* src/ds390/gen.c (opIsGptr, adjustArithmeticResult, genAddrOf, genAssign),
[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)
185     {
186       rtrackUpdate (lbp);
187
188       lineCurr = (lineCurr ?
189                   connectLine (lineCurr, newLineNode (lb)) :
190                   (lineHead = newLineNode (lb)));
191
192       lineCurr->isInline = _G.inLine;
193       lineCurr->isDebug = _G.debugLine;
194       lineCurr->ic = _G.current_iCode;
195       lineCurr->isComment = (*lbp==';');
196     }
197
198   va_end (ap);
199
200   dbuf_destroy(&dbuf);
201 }
202
203 static void
204 emitLabel (symbol *tlbl)
205 {
206   emitcode ("", "%05d$:", tlbl->key + 100);
207   lineCurr->isLabel = 1;
208 }
209
210 /*-----------------------------------------------------------------*/
211 /* mcs51_emitDebuggerSymbol - associate the current code location  */
212 /*   with a debugger symbol                                        */
213 /*-----------------------------------------------------------------*/
214 void
215 mcs51_emitDebuggerSymbol (char * debugSym)
216 {
217   _G.debugLine = 1;
218   emitcode ("", "%s ==.", debugSym);
219   _G.debugLine = 0;
220 }
221
222 /*-----------------------------------------------------------------*/
223 /* mova - moves specified value into accumulator                   */
224 /*-----------------------------------------------------------------*/
225 static void
226 mova (const char *x)
227 {
228   /* do some early peephole optimization */
229   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
230     return;
231
232   /* if it is a literal mov try to get it cheaper */
233   if (*x == '#' &&
234       rtrackMoveALit(x))
235     return;
236
237   emitcode("mov", "a,%s", x);
238 }
239
240 /*-----------------------------------------------------------------*/
241 /* movb - moves specified value into register b                    */
242 /*-----------------------------------------------------------------*/
243 static void
244 movb (const char *x)
245 {
246   /* do some early peephole optimization */
247   if (!strncmp(x, "b", 2))
248     return;
249
250   /* if it is a literal mov try to get it cheaper */
251   if (*x == '#')
252     {
253       emitcode("mov","b,%s", rtrackGetLit(x));
254       return;
255     }
256
257   emitcode("mov","b,%s", x);
258 }
259
260 /*-----------------------------------------------------------------*/
261 /* pushB - saves register B if necessary                           */
262 /*-----------------------------------------------------------------*/
263 static bool
264 pushB (void)
265 {
266   bool pushedB = FALSE;
267
268   if (BINUSE)
269     {
270       emitcode ("push", "b");
271 //    printf("B was in use !\n");
272       pushedB = TRUE;
273     }
274   else
275     {
276       OPINB++;
277     }
278   return pushedB;
279 }
280
281 /*-----------------------------------------------------------------*/
282 /* popB - restores value of register B if necessary                */
283 /*-----------------------------------------------------------------*/
284 static void
285 popB (bool pushedB)
286 {
287   if (pushedB)
288     {
289       emitcode ("pop", "b");
290     }
291   else
292     {
293       OPINB--;
294     }
295 }
296
297 /*-----------------------------------------------------------------*/
298 /* pushReg - saves register                                        */
299 /*-----------------------------------------------------------------*/
300 static bool
301 pushReg (int index, bool bits_pushed)
302 {
303   regs * reg = REG_WITH_INDEX (index);
304   if (reg->type == REG_BIT)
305     {
306       if (!bits_pushed)
307         emitcode ("push", "%s", reg->base);
308       return TRUE;
309     }
310   else
311     emitcode ("push", "%s", reg->dname);
312   return bits_pushed;
313 }
314
315 /*-----------------------------------------------------------------*/
316 /* popReg - restores register                                      */
317 /*-----------------------------------------------------------------*/
318 static bool
319 popReg (int index, bool bits_popped)
320 {
321   regs * reg = REG_WITH_INDEX (index);
322   if (reg->type == REG_BIT)
323     {
324       if (!bits_popped)
325         emitcode ("pop", "%s", reg->base);
326       return TRUE;
327     }
328   else
329     emitcode ("pop", "%s", reg->dname);
330   return bits_popped;
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
335 /*-----------------------------------------------------------------*/
336 static regs *
337 getFreePtr (iCode * ic, asmop ** aopp, bool result)
338 {
339   bool r0iu, r1iu;
340   bool r0ou, r1ou;
341
342   /* the logic: if r0 & r1 used in the instruction
343      then we are in trouble otherwise */
344
345   /* first check if r0 & r1 are used by this
346      instruction, in which case we are in trouble */
347   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
348   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
349   if (r0iu && r1iu) {
350       goto endOfWorld;
351     }
352
353   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
354   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
355
356   /* if no usage of r0 then return it */
357   if (!r0iu && !r0ou)
358     {
359       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
360       (*aopp)->type = AOP_R0;
361
362       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
363     }
364
365   /* if no usage of r1 then return it */
366   if (!r1iu && !r1ou)
367     {
368       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
369       (*aopp)->type = AOP_R1;
370
371       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
372     }
373
374   /* now we know they both have usage */
375   /* if r0 not used in this instruction */
376   if (!r0iu)
377     {
378       /* push it if not already pushed */
379       if (ic->op == IPUSH)
380         {
381           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
382           R0INB++;
383         }
384       else if (!_G.r0Pushed)
385         {
386           emitcode ("push", "%s",
387                     REG_WITH_INDEX (R0_IDX)->dname);
388           _G.r0Pushed++;
389         }
390
391       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
392       (*aopp)->type = AOP_R0;
393
394       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
395     }
396
397   /* if r1 not used then */
398
399   if (!r1iu)
400     {
401       /* push it if not already pushed */
402       if (ic->op == IPUSH)
403         {
404           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
405           R1INB++;
406         }
407       else if (!_G.r1Pushed)
408         {
409           emitcode ("push", "%s",
410                     REG_WITH_INDEX (R1_IDX)->dname);
411           _G.r1Pushed++;
412         }
413
414       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
415       (*aopp)->type = AOP_R1;
416       return REG_WITH_INDEX (R1_IDX);
417     }
418
419 endOfWorld:
420   /* I said end of world, but not quite end of world yet */
421   /* if this is a result then we can push it on the stack */
422   if (result)
423     {
424       (*aopp)->type = AOP_STK;
425       return NULL;
426     }
427   /* in the case that result AND left AND right needs a pointer reg
428      we can safely use the result's */
429   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
430     {
431       (*aopp)->type = AOP_R0;
432       return REG_WITH_INDEX (R0_IDX);
433     }
434   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
435     {
436       (*aopp)->type = AOP_R1;
437       return REG_WITH_INDEX (R1_IDX);
438     }
439
440   /* now this is REALLY the end of the world */
441   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
442           "getFreePtr should never reach here");
443   exit (1);
444 }
445
446
447 /*-----------------------------------------------------------------*/
448 /* getTempRegs - initialize an array of pointers to GPR registers */
449 /*               that are not in use. Returns 1 if the requested   */
450 /*               number of registers were available, 0 otherwise.  */
451 /*-----------------------------------------------------------------*/
452 int
453 getTempRegs(regs **tempRegs, int size, iCode *ic)
454 {
455   bitVect * freeRegs;
456   int i;
457   int offset;
458
459   if (!ic)
460     ic = _G.current_iCode;
461   if (!ic)
462     return 0;
463   if (!_G.currentFunc)
464     return 0;
465
466   freeRegs = newBitVect(8);
467   bitVectSetBit (freeRegs, R2_IDX);
468   bitVectSetBit (freeRegs, R3_IDX);
469   bitVectSetBit (freeRegs, R4_IDX);
470   bitVectSetBit (freeRegs, R5_IDX);
471   bitVectSetBit (freeRegs, R6_IDX);
472   bitVectSetBit (freeRegs, R7_IDX);
473
474   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
475     {
476       bitVect * newfreeRegs;
477       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
478       freeBitVect(freeRegs);
479       freeRegs = newfreeRegs;
480     }
481   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
482
483   offset = 0;
484   for (i=0; i<freeRegs->size; i++)
485     {
486       if (bitVectBitValue(freeRegs,i))
487         tempRegs[offset++] = REG_WITH_INDEX(i);
488       if (offset>=size)
489         {
490           freeBitVect(freeRegs);
491           return 1;
492         }
493     }
494
495   freeBitVect(freeRegs);
496   return 0;
497 }
498
499
500 /*-----------------------------------------------------------------*/
501 /* newAsmop - creates a new asmOp                                  */
502 /*-----------------------------------------------------------------*/
503 static asmop *
504 newAsmop (short type)
505 {
506   asmop *aop;
507
508   aop = Safe_calloc (1, sizeof (asmop));
509   aop->type = type;
510   aop->allocated = 1;
511   return aop;
512 }
513
514 /*-----------------------------------------------------------------*/
515 /* pointerCode - returns the code for a pointer type               */
516 /*-----------------------------------------------------------------*/
517 static int
518 pointerCode (sym_link * etype)
519 {
520
521   return PTR_TYPE (SPEC_OCLS (etype));
522
523 }
524
525 /*-----------------------------------------------------------------*/
526 /* leftRightUseAcc - returns size of accumulator use by operands   */
527 /*-----------------------------------------------------------------*/
528 static int
529 leftRightUseAcc(iCode *ic)
530 {
531   operand *op;
532   int size;
533   int accuseSize = 0;
534   int accuse = 0;
535
536   if (!ic)
537     {
538       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
539               "null iCode pointer");
540       return 0;
541     }
542
543   if (ic->op == IFX)
544     {
545       op = IC_COND (ic);
546       if (IS_OP_ACCUSE (op))
547         {
548           accuse = 1;
549           size = getSize (OP_SYMBOL (op)->type);
550           if (size>accuseSize)
551             accuseSize = size;
552         }
553     }
554   else if (ic->op == JUMPTABLE)
555     {
556       op = IC_JTCOND (ic);
557       if (IS_OP_ACCUSE (op))
558         {
559           accuse = 1;
560           size = getSize (OP_SYMBOL (op)->type);
561           if (size>accuseSize)
562             accuseSize = size;
563         }
564     }
565   else
566     {
567       op = IC_LEFT (ic);
568       if (IS_OP_ACCUSE (op))
569         {
570           accuse = 1;
571           size = getSize (OP_SYMBOL (op)->type);
572           if (size>accuseSize)
573             accuseSize = size;
574         }
575       op = IC_RIGHT (ic);
576       if (IS_OP_ACCUSE (op))
577         {
578           accuse = 1;
579           size = getSize (OP_SYMBOL (op)->type);
580           if (size>accuseSize)
581             accuseSize = size;
582         }
583     }
584
585   if (accuseSize)
586     return accuseSize;
587   else
588     return accuse;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* aopForSym - for a true symbol                                   */
593 /*-----------------------------------------------------------------*/
594 static asmop *
595 aopForSym (iCode * ic, symbol * sym, bool result)
596 {
597   asmop *aop;
598   memmap *space;
599   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
600
601   wassertl (ic != NULL, "Got a null iCode");
602   wassertl (sym != NULL, "Got a null symbol");
603
604   space = SPEC_OCLS (sym->etype);
605
606   /* if already has one */
607   if (sym->aop)
608     {
609       sym->aop->allocated++;
610       return sym->aop;
611     }
612
613   /* assign depending on the storage class */
614   /* if it is on the stack or indirectly addressable */
615   /* space we need to assign either r0 or r1 to it   */
616   if (sym->onStack || sym->iaccess)
617     {
618       sym->aop = aop = newAsmop (0);
619       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
620       aop->size = getSize (sym->type);
621
622       /* now assign the address of the variable to
623          the pointer register */
624       if (aop->type != AOP_STK)
625         {
626           if (sym->onStack)
627             {
628               signed char offset = ((sym->stack < 0) ?
629                          ((signed char) (sym->stack - _G.nRegsSaved)) :
630                          ((signed char) sym->stack)) & 0xff;
631
632               if ((abs(offset) <= 3) ||
633                   (accuse && (abs(offset) <= 7)))
634                 {
635                   emitcode ("mov", "%s,%s",
636                             aop->aopu.aop_ptr->name, SYM_BP (sym));
637                   while (offset < 0)
638                     {
639                       emitcode ("dec", aop->aopu.aop_ptr->name);
640                       offset++;
641                     }
642                   while (offset > 0)
643                     {
644                       emitcode ("inc", aop->aopu.aop_ptr->name);
645                       offset--;
646                     }
647                 }
648               else
649                 {
650                   if (accuse)
651                     emitcode ("push", "acc");
652                   emitcode ("mov", "a,%s", SYM_BP (sym));
653                   emitcode ("add", "a,#0x%02x", offset & 0xff);
654                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
655                   if (accuse)
656                     emitcode ("pop", "acc");
657                 }
658             }
659           else
660             {
661               emitcode ("mov", "%s,#%s",
662                         aop->aopu.aop_ptr->name,
663                         sym->rname);
664             }
665           aop->paged = space->paged;
666         }
667       else
668         aop->aopu.aop_stk = sym->stack;
669       return aop;
670     }
671
672   /* if in bit space */
673   if (IN_BITSPACE (space))
674     {
675       sym->aop = aop = newAsmop (AOP_CRY);
676       aop->aopu.aop_dir = sym->rname;
677       aop->size = getSize (sym->type);
678       return aop;
679     }
680   /* if it is in direct space */
681   if (IN_DIRSPACE (space))
682     {
683       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
684       //printTypeChainRaw(sym->type, NULL);
685       //printf("space = %s\n", space ? space->sname : "NULL");
686       sym->aop = aop = newAsmop (AOP_DIR);
687       aop->aopu.aop_dir = sym->rname;
688       aop->size = getSize (sym->type);
689       return aop;
690     }
691
692   /* special case for a function */
693   if (IS_FUNC (sym->type))
694     {
695       sym->aop = aop = newAsmop (AOP_IMMD);
696       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
697       aop->size = getSize (sym->type);
698       return aop;
699     }
700
701   /* only remaining is far space */
702   /* in which case DPTR gets the address */
703   sym->aop = aop = newAsmop (AOP_DPTR);
704   emitcode ("mov", "dptr,#%s", sym->rname);
705   aop->size = getSize (sym->type);
706
707   /* if it is in code space */
708   if (IN_CODESPACE (space))
709     aop->code = 1;
710
711   return aop;
712 }
713
714 /*-----------------------------------------------------------------*/
715 /* aopForRemat - rematerializes an object                          */
716 /*-----------------------------------------------------------------*/
717 static asmop *
718 aopForRemat (symbol * sym)
719 {
720   iCode *ic = sym->rematiCode;
721   asmop *aop = newAsmop (AOP_IMMD);
722   int ptr_type = 0;
723   int val = 0;
724
725   for (;;)
726     {
727       if (ic->op == '+')
728         val += (int) operandLitValue (IC_RIGHT (ic));
729       else if (ic->op == '-')
730         val -= (int) operandLitValue (IC_RIGHT (ic));
731       else if (IS_CAST_ICODE(ic))
732         {
733           sym_link *from_type = operandType(IC_RIGHT(ic));
734           aop->aopu.aop_immd.from_cast_remat = 1;
735           ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
736           ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
737           continue;
738         }
739       else break;
740
741       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
742     }
743
744   if (val)
745     {
746       SNPRINTF (buffer, sizeof(buffer),
747                 "(%s %c 0x%04x)",
748                 OP_SYMBOL (IC_LEFT (ic))->rname,
749                 val >= 0 ? '+' : '-',
750                 abs (val) & 0xffff);
751     }
752   else
753     {
754       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
755     }
756
757   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
758   /* set immd2 field if required */
759   if (aop->aopu.aop_immd.from_cast_remat)
760     {
761       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
762       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
763     }
764
765   return aop;
766 }
767
768 /*-----------------------------------------------------------------*/
769 /* regsInCommon - two operands have some registers in common       */
770 /*-----------------------------------------------------------------*/
771 static bool
772 regsInCommon (operand * op1, operand * op2)
773 {
774   symbol *sym1, *sym2;
775   int i;
776
777   /* if they have registers in common */
778   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
779     return FALSE;
780
781   sym1 = OP_SYMBOL (op1);
782   sym2 = OP_SYMBOL (op2);
783
784   if (sym1->nRegs == 0 || sym2->nRegs == 0)
785     return FALSE;
786
787   for (i = 0; i < sym1->nRegs; i++)
788     {
789       int j;
790       if (!sym1->regs[i])
791         continue;
792
793       for (j = 0; j < sym2->nRegs; j++)
794         {
795           if (!sym2->regs[j])
796             continue;
797
798           if (sym2->regs[j] == sym1->regs[i])
799             return TRUE;
800         }
801     }
802
803   return FALSE;
804 }
805
806 /*-----------------------------------------------------------------*/
807 /* operandsEqu - equivalent                                        */
808 /*-----------------------------------------------------------------*/
809 static bool
810 operandsEqu (operand * op1, operand * op2)
811 {
812   symbol *sym1, *sym2;
813
814   /* if they're not symbols */
815   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
816     return FALSE;
817
818   sym1 = OP_SYMBOL (op1);
819   sym2 = OP_SYMBOL (op2);
820
821   /* if both are itemps & one is spilt
822      and the other is not then false */
823   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
824       sym1->isspilt != sym2->isspilt)
825     return FALSE;
826
827   /* if they are the same */
828   if (sym1 == sym2)
829     return TRUE;
830
831   /* if they have the same rname */
832   if (sym1->rname[0] && sym2->rname[0] &&
833       strcmp (sym1->rname, sym2->rname) == 0 &&
834       !(IS_PARM (op2) && IS_ITEMP (op1)))
835     return TRUE;
836
837   /* if left is a tmp & right is not */
838   if (IS_ITEMP (op1) &&
839       !IS_ITEMP (op2) &&
840       sym1->isspilt &&
841       (sym1->usl.spillLoc == sym2))
842     return TRUE;
843
844   if (IS_ITEMP (op2) &&
845       !IS_ITEMP (op1) &&
846       sym2->isspilt &&
847       sym1->level > 0 &&
848       (sym2->usl.spillLoc == sym1))
849     return TRUE;
850
851   return FALSE;
852 }
853
854 /*-----------------------------------------------------------------*/
855 /* sameByte - two asmops have the same address at given offsets    */
856 /*-----------------------------------------------------------------*/
857 static bool
858 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
859 {
860   if (aop1 == aop2 && off1 == off2)
861     return TRUE;
862
863   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
864     return FALSE;
865
866   if (aop1->type != aop2->type)
867     return FALSE;
868
869   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
870     return FALSE;
871
872   return TRUE;
873 }
874
875 /*-----------------------------------------------------------------*/
876 /* sameRegs - two asmops have the same registers                   */
877 /*-----------------------------------------------------------------*/
878 static bool
879 sameRegs (asmop * aop1, asmop * aop2)
880 {
881   int i;
882
883   if (aop1 == aop2)
884     return TRUE;
885
886   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
887     return FALSE;
888
889   if (aop1->type != aop2->type)
890     return FALSE;
891
892   if (aop1->size != aop2->size)
893     return FALSE;
894
895   for (i = 0; i < aop1->size; i++)
896     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
897       return FALSE;
898
899   return TRUE;
900 }
901
902 /*-----------------------------------------------------------------*/
903 /* aopOp - allocates an asmop for an operand  :                    */
904 /*-----------------------------------------------------------------*/
905 static void
906 aopOp (operand * op, iCode * ic, bool result)
907 {
908   asmop *aop;
909   symbol *sym;
910   int i;
911
912   if (!op)
913     return;
914
915   /* if this a literal */
916   if (IS_OP_LITERAL (op))
917     {
918       op->aop = aop = newAsmop (AOP_LIT);
919       aop->aopu.aop_lit = op->operand.valOperand;
920       aop->size = getSize (operandType (op));
921       return;
922     }
923
924   /* if already has a asmop then continue */
925   if (op->aop)
926     {
927       op->aop->allocated++;
928       return;
929     }
930
931   /* if the underlying symbol has a aop */
932   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
933     {
934       op->aop = OP_SYMBOL (op)->aop;
935       op->aop->allocated++;
936       return;
937     }
938
939   /* if this is a true symbol */
940   if (IS_TRUE_SYMOP (op))
941     {
942       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
943       return;
944     }
945
946   /* this is a temporary : this has
947      only five choices :
948      a) register
949      b) spillocation
950      c) rematerialize
951      d) conditional
952      e) can be a return use only */
953
954   sym = OP_SYMBOL (op);
955
956   /* if the type is a conditional */
957   if (sym->regType == REG_CND)
958     {
959       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
960       aop->size = sym->ruonly ? 1 : 0;
961       return;
962     }
963
964   /* if it is spilt then two situations
965      a) is rematerialize
966      b) has a spill location */
967   if (sym->isspilt || sym->nRegs == 0)
968     {
969
970       /* rematerialize it NOW */
971       if (sym->remat)
972         {
973           sym->aop = op->aop = aop = aopForRemat (sym);
974           aop->size = operandSize (op);
975           return;
976         }
977
978       if (sym->accuse)
979         {
980           int i;
981           sym->aop = op->aop = aop = newAsmop (AOP_ACC);
982           aop->size = getSize (sym->type);
983           for (i = 0; i < 2; i++)
984             aop->aopu.aop_str[i] = accUse[i];
985           return;
986         }
987
988       if (sym->ruonly)
989         {
990           unsigned i;
991
992           sym->aop = op->aop = aop = newAsmop (AOP_STR);
993           aop->size = getSize (sym->type);
994           for (i = 0; i < fReturnSizeMCS51; i++)
995             aop->aopu.aop_str[i] = fReturn[i];
996           return;
997         }
998
999       if (sym->usl.spillLoc)
1000         {
1001           asmop *oldAsmOp = NULL;
1002
1003           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1004             {
1005               /* force a new aop if sizes differ */
1006               oldAsmOp = sym->usl.spillLoc->aop;
1007               sym->usl.spillLoc->aop = NULL;
1008             }
1009           sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1010           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1011             {
1012               /* Don't reuse the new aop, go with the last one */
1013               sym->usl.spillLoc->aop = oldAsmOp;
1014             }
1015           aop->size = getSize (sym->type);
1016           return;
1017         }
1018
1019       /* else must be a dummy iTemp */
1020       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1021       aop->size = getSize (sym->type);
1022       return;
1023     }
1024
1025   /* if the type is a bit register */
1026   if (sym->regType == REG_BIT)
1027     {
1028       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1029       aop->size = sym->nRegs;//1???
1030       aop->aopu.aop_reg[0] = sym->regs[0];
1031       aop->aopu.aop_dir = sym->regs[0]->name;
1032       return;
1033     }
1034
1035   /* must be in a register */
1036   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1037   aop->size = sym->nRegs;
1038   for (i = 0; i < sym->nRegs; i++)
1039     aop->aopu.aop_reg[i] = sym->regs[i];
1040 }
1041
1042 /*-----------------------------------------------------------------*/
1043 /* freeAsmop - free up the asmop given to an operand               */
1044 /*-----------------------------------------------------------------*/
1045 static void
1046 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1047 {
1048   asmop *aop;
1049
1050   if (!op)
1051     aop = aaop;
1052   else
1053     aop = op->aop;
1054
1055   if (!aop)
1056     return;
1057
1058   aop->allocated--;
1059
1060   if (aop->allocated)
1061     goto dealloc;
1062
1063   /* depending on the asmop type only three cases need work
1064      AOP_R0, AOP_R1 & AOP_STK */
1065   switch (aop->type)
1066     {
1067     case AOP_R0:
1068       if (R0INB)
1069         {
1070           emitcode ("mov", "r0,b");
1071           R0INB--;
1072         }
1073       else if (_G.r0Pushed)
1074         {
1075           if (pop)
1076             {
1077               emitcode ("pop", "ar0");
1078               _G.r0Pushed--;
1079             }
1080         }
1081       bitVectUnSetBit (ic->rUsed, R0_IDX);
1082       break;
1083
1084     case AOP_R1:
1085       if (R1INB)
1086         {
1087           emitcode ("mov", "r1,b");
1088           R1INB--;
1089         }
1090       else if (_G.r1Pushed)
1091         {
1092           if (pop)
1093             {
1094               emitcode ("pop", "ar1");
1095               _G.r1Pushed--;
1096             }
1097         }
1098       bitVectUnSetBit (ic->rUsed, R1_IDX);
1099       break;
1100
1101     case AOP_STK:
1102       {
1103         int sz = aop->size;
1104         int stk = aop->aopu.aop_stk + aop->size - 1;
1105         bitVectUnSetBit (ic->rUsed, R0_IDX);
1106         bitVectUnSetBit (ic->rUsed, R1_IDX);
1107
1108         getFreePtr (ic, &aop, FALSE);
1109
1110         if (stk)
1111           {
1112             emitcode ("mov", "a,_bp");
1113             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1114             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1115           }
1116         else
1117           {
1118             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1119           }
1120
1121         while (sz--)
1122           {
1123             emitcode ("pop", "acc");
1124             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1125             if (!sz)
1126               break;
1127             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1128           }
1129         op->aop = aop;
1130         freeAsmop (op, NULL, ic, TRUE);
1131         if (_G.r1Pushed)
1132           {
1133             emitcode ("pop", "ar1");
1134             _G.r1Pushed--;
1135           }
1136         if (_G.r0Pushed)
1137           {
1138             emitcode ("pop", "ar0");
1139             _G.r0Pushed--;
1140           }
1141       }
1142       break;
1143     }
1144
1145 dealloc:
1146   /* all other cases just dealloc */
1147   if (op)
1148     {
1149       op->aop = NULL;
1150       if (IS_SYMOP (op))
1151         {
1152           OP_SYMBOL (op)->aop = NULL;
1153           /* if the symbol has a spill */
1154           if (SPIL_LOC (op))
1155             SPIL_LOC (op)->aop = NULL;
1156         }
1157     }
1158 }
1159
1160 /*------------------------------------------------------------------*/
1161 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1162 /*                      pop r0 or r1 off stack if pushed            */
1163 /*------------------------------------------------------------------*/
1164 static void
1165 freeForBranchAsmop (operand * op)
1166 {
1167   asmop *aop;
1168
1169   if (!op)
1170     return;
1171
1172   aop = op->aop;
1173
1174   if (!aop)
1175     return;
1176
1177   if (!aop->allocated)
1178     return;
1179
1180   switch (aop->type)
1181     {
1182     case AOP_R0:
1183       if (R0INB)
1184         {
1185           emitcode ("mov", "r0,b");
1186         }
1187       else if (_G.r0Pushed)
1188         {
1189           emitcode ("pop", "ar0");
1190         }
1191       break;
1192
1193     case AOP_R1:
1194       if (R1INB)
1195         {
1196           emitcode ("mov", "r1,b");
1197         }
1198       else if (_G.r1Pushed)
1199         {
1200           emitcode ("pop", "ar1");
1201         }
1202       break;
1203
1204     case AOP_STK:
1205       {
1206         int sz = aop->size;
1207         int stk = aop->aopu.aop_stk + aop->size - 1;
1208
1209         emitcode ("mov", "b,r0");
1210         if (stk)
1211           {
1212             emitcode ("mov", "a,_bp");
1213             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1214             emitcode ("mov", "r0,a");
1215           }
1216         else
1217           {
1218             emitcode ("mov", "r0,_bp");
1219           }
1220
1221         while (sz--)
1222           {
1223             emitcode ("pop", "acc");
1224             emitcode ("mov", "@r0,a");
1225             if (!sz)
1226               break;
1227             emitcode ("dec", "r0");
1228           }
1229         emitcode ("mov", "r0,b");
1230       }
1231     }
1232
1233 }
1234
1235 /*-----------------------------------------------------------------*/
1236 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1237 /*                 clobber the accumulator                         */
1238 /*-----------------------------------------------------------------*/
1239 static bool
1240 aopGetUsesAcc (operand * oper, int offset)
1241 {
1242   asmop * aop = AOP (oper);
1243
1244   if (offset > (aop->size - 1))
1245     return FALSE;
1246
1247   switch (aop->type)
1248     {
1249
1250     case AOP_R0:
1251     case AOP_R1:
1252       if (aop->paged)
1253         return TRUE;
1254       return FALSE;
1255     case AOP_DPTR:
1256       return TRUE;
1257     case AOP_IMMD:
1258       return FALSE;
1259     case AOP_DIR:
1260       return FALSE;
1261     case AOP_REG:
1262       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1263       return FALSE;
1264     case AOP_CRY:
1265       return TRUE;
1266     case AOP_ACC:
1267       if (offset)
1268         return FALSE;
1269       return TRUE;
1270     case AOP_LIT:
1271       return FALSE;
1272     case AOP_STR:
1273       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1274         return TRUE;
1275       return FALSE;
1276     case AOP_DUMMY:
1277       return FALSE;
1278     default:
1279       /* Error case --- will have been caught already */
1280       wassert(0);
1281       return FALSE;
1282     }
1283 }
1284
1285 /*-------------------------------------------------------------------*/
1286 /* aopGet - for fetching value of the aop                            */
1287 /*-------------------------------------------------------------------*/
1288 static char *
1289 aopGet (operand * oper, int offset, bool bit16, bool dname)
1290 {
1291   asmop * aop = AOP (oper);
1292
1293   /* offset is greater than
1294      size then zero */
1295   if (offset > (aop->size - 1) &&
1296       aop->type != AOP_LIT)
1297     return zero;
1298
1299   /* depending on type */
1300   switch (aop->type)
1301     {
1302     case AOP_DUMMY:
1303       return zero;
1304
1305     case AOP_R0:
1306     case AOP_R1:
1307       /* if we need to increment it */
1308       while (offset > aop->coff)
1309         {
1310           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1311           aop->coff++;
1312         }
1313
1314       while (offset < aop->coff)
1315         {
1316           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1317           aop->coff--;
1318         }
1319
1320       aop->coff = offset;
1321       if (aop->paged)
1322         {
1323           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1324           return (dname ? "acc" : "a");
1325         }
1326       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1327       return Safe_strdup(buffer);
1328
1329     case AOP_DPTR:
1330       if (aop->code && aop->coff==0 && offset>=1) {
1331         emitcode ("mov", "a,#0x%02x", offset);
1332         emitcode ("movc", "a,@a+dptr");
1333         return (dname ? "acc" : "a");
1334       }
1335
1336       while (offset > aop->coff)
1337         {
1338           emitcode ("inc", "dptr");
1339           aop->coff++;
1340         }
1341
1342       while (offset < aop->coff)
1343         {
1344           emitcode ("lcall", "__decdptr");
1345           aop->coff--;
1346         }
1347
1348       aop->coff = offset;
1349       if (aop->code)
1350         {
1351           emitcode ("clr", "a");
1352           emitcode ("movc", "a,@a+dptr");
1353         }
1354       else
1355         {
1356           emitcode ("movx", "a,@dptr");
1357         }
1358       return (dname ? "acc" : "a");
1359
1360     case AOP_IMMD:
1361       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1362         {
1363           SNPRINTF(buffer, sizeof(buffer),
1364                    "%s",aop->aopu.aop_immd.aop_immd2);
1365         }
1366       else if (bit16)
1367         {
1368           SNPRINTF(buffer, sizeof(buffer),
1369                    "#%s", aop->aopu.aop_immd.aop_immd1);
1370         }
1371       else if (offset)
1372         {
1373           SNPRINTF (buffer, sizeof(buffer),
1374                     "#(%s >> %d)",
1375                     aop->aopu.aop_immd.aop_immd1,
1376                     offset * 8);
1377         }
1378       else
1379         {
1380           SNPRINTF (buffer, sizeof(buffer),
1381                     "#%s",
1382                     aop->aopu.aop_immd.aop_immd1);
1383         }
1384       return Safe_strdup(buffer);
1385
1386     case AOP_DIR:
1387       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1388         {
1389           SNPRINTF (buffer, sizeof(buffer),
1390                     "(%s >> %d)",
1391                     aop->aopu.aop_dir, offset * 8);
1392         }
1393       else if (offset)
1394         {
1395           SNPRINTF (buffer, sizeof(buffer),
1396                     "(%s + %d)",
1397                     aop->aopu.aop_dir,
1398                     offset);
1399         }
1400       else
1401         {
1402           SNPRINTF (buffer, sizeof(buffer),
1403                     "%s",
1404                     aop->aopu.aop_dir);
1405         }
1406
1407       return Safe_strdup(buffer);
1408
1409     case AOP_REG:
1410       if (dname)
1411         return aop->aopu.aop_reg[offset]->dname;
1412       else
1413         return aop->aopu.aop_reg[offset]->name;
1414
1415     case AOP_CRY:
1416       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1417       emitcode ("clr", "a");
1418       emitcode ("rlc", "a");
1419       return (dname ? "acc" : "a");
1420
1421     case AOP_ACC:
1422       if (!offset && dname)
1423         return "acc";
1424       return aop->aopu.aop_str[offset];
1425
1426     case AOP_LIT:
1427       return aopLiteral (aop->aopu.aop_lit, offset);
1428
1429     case AOP_STR:
1430       aop->coff = offset;
1431       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1432           dname)
1433         return "acc";
1434
1435       return aop->aopu.aop_str[offset];
1436
1437     }
1438
1439   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1440           "aopget got unsupported aop->type");
1441   exit (1);
1442 }
1443
1444 /*-----------------------------------------------------------------*/
1445 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1446 /*                 clobber the accumulator                         */
1447 /*-----------------------------------------------------------------*/
1448 static bool
1449 aopPutUsesAcc (operand * oper, const char *s, int offset)
1450 {
1451   asmop * aop = AOP (oper);
1452
1453   if (offset > (aop->size - 1))
1454     return FALSE;
1455
1456   switch (aop->type)
1457     {
1458     case AOP_DUMMY:
1459       return TRUE;
1460     case AOP_DIR:
1461       return FALSE;
1462     case AOP_REG:
1463       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1464       return FALSE;
1465     case AOP_DPTR:
1466       return TRUE;
1467     case AOP_R0:
1468     case AOP_R1:
1469       return ((aop->paged) || (*s == '@'));
1470     case AOP_STK:
1471       return (*s == '@');
1472     case AOP_CRY:
1473       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1474     case AOP_STR:
1475       return FALSE;
1476     case AOP_IMMD:
1477       return FALSE;
1478     case AOP_ACC:
1479       return FALSE;
1480     default:
1481       /* Error case --- will have been caught already */
1482       wassert(0);
1483       return FALSE;
1484     }
1485 }
1486
1487 /*-----------------------------------------------------------------*/
1488 /* aopPut - puts a string for a aop and indicates if acc is in use */
1489 /*-----------------------------------------------------------------*/
1490 static bool
1491 aopPut (operand * result, const char *s, int offset)
1492 {
1493   bool bvolatile = isOperandVolatile (result, FALSE);
1494   bool accuse = FALSE;
1495   asmop * aop = AOP (result);
1496   const char *d = NULL;
1497
1498   if (aop->size && offset > (aop->size - 1))
1499     {
1500       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1501               "aopPut got offset > aop->size");
1502       exit (1);
1503     }
1504
1505   /* will assign value to value */
1506   /* depending on where it is ofcourse */
1507   switch (aop->type)
1508     {
1509     case AOP_DUMMY:
1510       MOVA (s);         /* read s in case it was volatile */
1511       accuse = TRUE;
1512       break;
1513
1514     case AOP_DIR:
1515       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1516         {
1517           SNPRINTF (buffer, sizeof(buffer),
1518                     "(%s >> %d)",
1519                     aop->aopu.aop_dir, offset * 8);
1520         }
1521       else if (offset)
1522         {
1523           SNPRINTF (buffer, sizeof(buffer),
1524                     "(%s + %d)",
1525                     aop->aopu.aop_dir, offset);
1526         }
1527       else
1528         {
1529           SNPRINTF (buffer, sizeof(buffer),
1530                     "%s",
1531                     aop->aopu.aop_dir);
1532         }
1533
1534       if (strcmp (buffer, s) || bvolatile)
1535         {
1536           emitcode ("mov", "%s,%s", buffer, s);
1537         }
1538       if (!strcmp (buffer, "acc"))
1539         {
1540           accuse = TRUE;
1541         }
1542       break;
1543
1544     case AOP_REG:
1545       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1546           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1547         {
1548           if (*s == '@' ||
1549               strcmp (s, "r0") == 0 ||
1550               strcmp (s, "r1") == 0 ||
1551               strcmp (s, "r2") == 0 ||
1552               strcmp (s, "r3") == 0 ||
1553               strcmp (s, "r4") == 0 ||
1554               strcmp (s, "r5") == 0 ||
1555               strcmp (s, "r6") == 0 ||
1556               strcmp (s, "r7") == 0)
1557             {
1558               emitcode ("mov", "%s,%s",
1559                         aop->aopu.aop_reg[offset]->dname, s);
1560             }
1561           else
1562             {
1563               emitcode ("mov", "%s,%s",
1564                         aop->aopu.aop_reg[offset]->name, s);
1565             }
1566         }
1567       break;
1568
1569     case AOP_DPTR:
1570       if (aop->code)
1571         {
1572           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1573                   "aopPut writing to code space");
1574           exit (1);
1575         }
1576
1577       while (offset > aop->coff)
1578         {
1579           aop->coff++;
1580           emitcode ("inc", "dptr");
1581         }
1582
1583       while (offset < aop->coff)
1584         {
1585           aop->coff--;
1586           emitcode ("lcall", "__decdptr");
1587         }
1588
1589       aop->coff = offset;
1590
1591       /* if not in accumulator */
1592       MOVA (s);
1593
1594       emitcode ("movx", "@dptr,a");
1595       break;
1596
1597     case AOP_R0:
1598     case AOP_R1:
1599       while (offset > aop->coff)
1600         {
1601           aop->coff++;
1602           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1603         }
1604       while (offset < aop->coff)
1605         {
1606           aop->coff--;
1607           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1608         }
1609       aop->coff = offset;
1610
1611       if (aop->paged)
1612         {
1613           MOVA (s);
1614           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1615         }
1616       else if (*s == '@')
1617         {
1618           MOVA (s);
1619           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1620         }
1621       else if (strcmp (s, "r0") == 0 ||
1622                strcmp (s, "r1") == 0 ||
1623                strcmp (s, "r2") == 0 ||
1624                strcmp (s, "r3") == 0 ||
1625                strcmp (s, "r4") == 0 ||
1626                strcmp (s, "r5") == 0 ||
1627                strcmp (s, "r6") == 0 ||
1628                strcmp (s, "r7") == 0)
1629         {
1630           char buffer[10];
1631           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1632           emitcode ("mov", "@%s,%s",
1633                     aop->aopu.aop_ptr->name, buffer);
1634         }
1635       else
1636         {
1637           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1638         }
1639       break;
1640
1641     case AOP_STK:
1642       if (strcmp (s, "a") == 0)
1643         {
1644           emitcode ("push", "acc");
1645         }
1646       else if (*s=='@')
1647         {
1648           MOVA(s);
1649           emitcode ("push", "acc");
1650         }
1651       else if (strcmp (s, "r0") == 0 ||
1652                strcmp (s, "r1") == 0 ||
1653                strcmp (s, "r2") == 0 ||
1654                strcmp (s, "r3") == 0 ||
1655                strcmp (s, "r4") == 0 ||
1656                strcmp (s, "r5") == 0 ||
1657                strcmp (s, "r6") == 0 ||
1658                strcmp (s, "r7") == 0)
1659         {
1660           char buffer[10];
1661           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1662           emitcode ("push", buffer);
1663         }
1664       else
1665         {
1666           emitcode ("push", s);
1667         }
1668
1669       break;
1670
1671     case AOP_CRY:
1672       // destination is carry for return-use-only
1673       d = (IS_OP_RUONLY (result)) ? "c" : aop->aopu.aop_dir;
1674       // source is no literal and not in carry
1675       if ((s != zero) && (s != one) && strcmp (s, "c"))
1676         {
1677           MOVA (s);
1678           /* set C, if a >= 1 */
1679           emitcode ("add", "a,#0xff");
1680           s = "c";
1681         }
1682       // now source is zero, one or carry
1683
1684       /* if result no bit variable */
1685       if (!d)
1686         {
1687           if (!strcmp (s, "c"))
1688             {
1689               /* inefficient: move carry into A and use jz/jnz */
1690               emitcode ("clr", "a");
1691               emitcode ("rlc", "a");
1692               accuse = TRUE;
1693             }
1694           else
1695             {
1696               MOVA (s);
1697               accuse = TRUE;
1698             }
1699         }
1700       else if (s == zero)
1701           emitcode ("clr", "%s", d);
1702       else if (s == one)
1703           emitcode ("setb", "%s", d);
1704       else if (strcmp (s, d))
1705           emitcode ("mov", "%s,c", d);
1706       break;
1707
1708     case AOP_STR:
1709       aop->coff = offset;
1710       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1711         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1712       break;
1713
1714     case AOP_ACC:
1715       accuse = TRUE;
1716       aop->coff = offset;
1717       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1718         break;
1719
1720       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1721         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1722       break;
1723
1724     default:
1725       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1726               "aopPut got unsupported aop->type");
1727       exit (1);
1728     }
1729
1730     return accuse;
1731 }
1732
1733
1734 #if 0
1735 /*-----------------------------------------------------------------*/
1736 /* pointToEnd :- points to the last byte of the operand            */
1737 /*-----------------------------------------------------------------*/
1738 static void
1739 pointToEnd (asmop * aop)
1740 {
1741   int count;
1742   if (!aop)
1743     return;
1744
1745   aop->coff = count = (aop->size - 1);
1746   switch (aop->type)
1747     {
1748     case AOP_R0:
1749     case AOP_R1:
1750       while (count--)
1751         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1752       break;
1753     case AOP_DPTR:
1754       while (count--)
1755         emitcode ("inc", "dptr");
1756       break;
1757     }
1758
1759 }
1760 #endif
1761
1762 /*-----------------------------------------------------------------*/
1763 /* reAdjustPreg - points a register back to where it should        */
1764 /*-----------------------------------------------------------------*/
1765 static void
1766 reAdjustPreg (asmop * aop)
1767 {
1768   if ((aop->coff==0) || (aop->size <= 1))
1769     return;
1770
1771   switch (aop->type)
1772     {
1773     case AOP_R0:
1774     case AOP_R1:
1775       while (aop->coff--)
1776         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1777       break;
1778     case AOP_DPTR:
1779       while (aop->coff--)
1780         {
1781           emitcode ("lcall", "__decdptr");
1782         }
1783       break;
1784     }
1785   aop->coff = 0;
1786 }
1787
1788 /*-----------------------------------------------------------------*/
1789 /* opIsGptr: returns non-zero if the passed operand is             */
1790 /* a generic pointer type.                                         */
1791 /*-----------------------------------------------------------------*/
1792 static int
1793 opIsGptr (operand * op)
1794 {
1795   if (op && IS_GENPTR (operandType (op)) && (AOP_SIZE (op) == GPTRSIZE))
1796     {
1797       return 1;
1798     }
1799   return 0;
1800 }
1801
1802 /*-----------------------------------------------------------------*/
1803 /* getDataSize - get the operand data size                         */
1804 /*-----------------------------------------------------------------*/
1805 static int
1806 getDataSize (operand * op)
1807 {
1808   int size = AOP_SIZE (op);
1809
1810   if (size == GPTRSIZE)
1811     {
1812       sym_link *type = operandType (op);
1813       if (IS_GENPTR (type))
1814         {
1815           /* generic pointer; arithmetic operations
1816            * should ignore the high byte (pointer type).
1817            */
1818           size--;
1819         }
1820     }
1821   return size;
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* outAcc - output Acc                                             */
1826 /*-----------------------------------------------------------------*/
1827 static void
1828 outAcc (operand * result)
1829 {
1830   int size, offset;
1831   size = getDataSize (result);
1832   if (size)
1833     {
1834       aopPut (result, "a", 0);
1835       size--;
1836       offset = 1;
1837       /* unsigned or positive */
1838       while (size--)
1839         {
1840           aopPut (result, zero, offset++);
1841         }
1842     }
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* outBitC - output a bit C                                        */
1847 /*-----------------------------------------------------------------*/
1848 static void
1849 outBitC (operand * result)
1850 {
1851   /* if the result is bit */
1852   if (AOP_TYPE (result) == AOP_CRY)
1853     {
1854       if (!IS_OP_RUONLY (result))
1855         aopPut (result, "c", 0);
1856     }
1857   else if (AOP_TYPE (result) != AOP_DUMMY)
1858     {
1859       emitcode ("clr", "a");
1860       emitcode ("rlc", "a");
1861       outAcc (result);
1862     }
1863 }
1864
1865 /*-----------------------------------------------------------------*/
1866 /* toBoolean - emit code for orl a,operator(sizeop)                */
1867 /*-----------------------------------------------------------------*/
1868 static void
1869 toBoolean (operand * oper)
1870 {
1871   int size = AOP_SIZE (oper) - 1;
1872   int offset = 1;
1873   bool AccUsed = FALSE;
1874   bool pushedB;
1875
1876   while (!AccUsed && size--)
1877     {
1878       AccUsed |= aopGetUsesAcc(oper, offset++);
1879     }
1880
1881   size = AOP_SIZE (oper) - 1;
1882   offset = 1;
1883   MOVA (aopGet (oper, 0, FALSE, FALSE));
1884   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1885     {
1886       pushedB = pushB ();
1887       emitcode("mov", "b,a");
1888       while (--size)
1889         {
1890           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1891           emitcode ("orl", "b,a");
1892         }
1893       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1894       emitcode ("orl", "a,b");
1895       popB (pushedB);
1896     }
1897   else
1898     {
1899       while (size--)
1900         {
1901           emitcode ("orl", "a,%s",
1902                     aopGet (oper, offset++, FALSE, FALSE));
1903         }
1904     }
1905 }
1906
1907 /*-----------------------------------------------------------------*/
1908 /* toCarry - make boolean and move into carry                      */
1909 /*-----------------------------------------------------------------*/
1910 static void
1911 toCarry (operand * oper)
1912 {
1913   /* if the operand is a literal then
1914      we know what the value is */
1915   if (AOP_TYPE (oper) == AOP_LIT)
1916     {
1917       if ((int) operandLitValue (oper))
1918         SETC;
1919       else
1920         CLRC;
1921     }
1922   else if (AOP_TYPE (oper) == AOP_CRY)
1923     {
1924       emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1925     }
1926   else
1927     {
1928       /* or the operand into a */
1929       toBoolean (oper);
1930       /* set C, if a >= 1 */
1931       emitcode ("add", "a,#0xff");
1932     }
1933 }
1934
1935 /*-----------------------------------------------------------------*/
1936 /* assignBit - assign operand to bit operand                       */
1937 /*-----------------------------------------------------------------*/
1938 static void
1939 assignBit (operand * result, operand * right)
1940 {
1941   /* if the right side is a literal then
1942      we know what the value is */
1943   if (AOP_TYPE (right) == AOP_LIT)
1944     {
1945       if ((int) operandLitValue (right))
1946         aopPut (result, one, 0);
1947       else
1948         aopPut (result, zero, 0);
1949     }
1950   else
1951     {
1952       toCarry (right);
1953       aopPut (result, "c", 0);
1954     }
1955 }
1956
1957
1958 /*-------------------------------------------------------------------*/
1959 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1960 /*-------------------------------------------------------------------*/
1961 static char *
1962 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1963 {
1964   char * l;
1965
1966   if (aopGetUsesAcc (oper, offset))
1967     {
1968       emitcode("mov", "b,a");
1969       MOVA (aopGet (oper, offset, bit16, dname));
1970       emitcode("xch", "a,b");
1971       aopPut (oper, "a", offset);
1972       emitcode("xch", "a,b");
1973       l = "b";
1974     }
1975   else
1976     {
1977       l = aopGet (oper, offset, bit16, dname);
1978       emitcode("xch", "a,%s", l);
1979     }
1980   return l;
1981 }
1982
1983
1984 /*-----------------------------------------------------------------*/
1985 /* genNot - generate code for ! operation                          */
1986 /*-----------------------------------------------------------------*/
1987 static void
1988 genNot (iCode * ic)
1989 {
1990   symbol *tlbl;
1991
1992   D (emitcode (";", "genNot"));
1993
1994   /* assign asmOps to operand & result */
1995   aopOp (IC_LEFT (ic), ic, FALSE);
1996   aopOp (IC_RESULT (ic), ic, TRUE);
1997
1998   /* if in bit space then a special case */
1999   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2000     {
2001       /* if left==result then cpl bit */
2002       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2003         {
2004           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2005         }
2006       else
2007         {
2008           toCarry (IC_LEFT (ic));
2009           emitcode ("cpl", "c");
2010           outBitC (IC_RESULT (ic));
2011         }
2012       goto release;
2013     }
2014
2015   toBoolean (IC_LEFT (ic));
2016
2017   /* set C, if a == 0 */
2018   tlbl = newiTempLabel (NULL);
2019   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2020   emitLabel (tlbl);
2021   outBitC (IC_RESULT (ic));
2022
2023 release:
2024   /* release the aops */
2025   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2026   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2027 }
2028
2029
2030 /*-----------------------------------------------------------------*/
2031 /* genCpl - generate code for complement                           */
2032 /*-----------------------------------------------------------------*/
2033 static void
2034 genCpl (iCode * ic)
2035 {
2036   int offset = 0;
2037   int size;
2038   symbol *tlbl;
2039   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2040
2041   D(emitcode (";", "genCpl"));
2042
2043   /* assign asmOps to operand & result */
2044   aopOp (IC_LEFT (ic), ic, FALSE);
2045   aopOp (IC_RESULT (ic), ic, TRUE);
2046
2047   /* special case if in bit space */
2048   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2049     {
2050       char *l;
2051
2052       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2053           (SPEC_USIGN (letype) && IS_CHAR (letype)))
2054         {
2055           /* promotion rules are responsible for this strange result:
2056              bit -> int -> ~int -> bit
2057              uchar -> int -> ~int -> bit
2058           */
2059           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2060           goto release;
2061         }
2062
2063       tlbl=newiTempLabel(NULL);
2064       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2065       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2066           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2067           IS_AOP_PREG (IC_LEFT (ic)))
2068         {
2069           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2070         }
2071       else
2072         {
2073           MOVA (l);
2074           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2075         }
2076       emitLabel (tlbl);
2077       outBitC (IC_RESULT(ic));
2078       goto release;
2079     }
2080
2081   size = AOP_SIZE (IC_RESULT (ic));
2082   while (size--)
2083     {
2084       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2085       MOVA (l);
2086       emitcode ("cpl", "a");
2087       aopPut (IC_RESULT (ic), "a", offset++);
2088     }
2089
2090
2091 release:
2092   /* release the aops */
2093   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2094   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2095 }
2096
2097 /*-----------------------------------------------------------------*/
2098 /* genUminusFloat - unary minus for floating points                */
2099 /*-----------------------------------------------------------------*/
2100 static void
2101 genUminusFloat (operand * op, operand * result)
2102 {
2103   int size, offset = 0;
2104   char *l;
2105
2106   D (emitcode (";", "genUminusFloat"));
2107
2108   /* for this we just copy and then flip the bit */
2109
2110   size = AOP_SIZE (op) - 1;
2111
2112   while (size--)
2113     {
2114       aopPut (result,
2115               aopGet (op, offset, FALSE, FALSE),
2116               offset);
2117       offset++;
2118     }
2119
2120   l = aopGet (op, offset, FALSE, FALSE);
2121   MOVA (l);
2122
2123   emitcode ("cpl", "acc.7");
2124   aopPut (result, "a", offset);
2125 }
2126
2127 /*-----------------------------------------------------------------*/
2128 /* genUminus - unary minus code generation                         */
2129 /*-----------------------------------------------------------------*/
2130 static void
2131 genUminus (iCode * ic)
2132 {
2133   int offset, size;
2134   sym_link *optype;
2135
2136   D (emitcode (";", "genUminus"));
2137
2138   /* assign asmops */
2139   aopOp (IC_LEFT (ic), ic, FALSE);
2140   aopOp (IC_RESULT (ic), ic, TRUE);
2141
2142   /* if both in bit space then special
2143      case */
2144   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2145       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2146     {
2147
2148       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2149       emitcode ("cpl", "c");
2150       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2151       goto release;
2152     }
2153
2154   optype = operandType (IC_LEFT (ic));
2155
2156   /* if float then do float stuff */
2157   if (IS_FLOAT (optype))
2158     {
2159       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2160       goto release;
2161     }
2162
2163   /* otherwise subtract from zero */
2164   size = AOP_SIZE (IC_LEFT (ic));
2165   offset = 0;
2166   while (size--)
2167     {
2168       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2169       if (!strcmp (l, "a"))
2170         {
2171           if (offset == 0)
2172             SETC;
2173           emitcode ("cpl", "a");
2174           emitcode ("addc", "a,#0x00");
2175         }
2176       else
2177         {
2178           if (offset == 0)
2179             CLRC;
2180           emitcode ("clr", "a");
2181           emitcode ("subb", "a,%s", l);
2182         }
2183       aopPut (IC_RESULT (ic), "a", offset++);
2184     }
2185
2186   /* if any remaining bytes in the result */
2187   /* we just need to propagate the sign   */
2188   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2189     {
2190       emitcode ("rlc", "a");
2191       emitcode ("subb", "a,acc");
2192       while (size--)
2193         aopPut (IC_RESULT (ic), "a", offset++);
2194     }
2195
2196 release:
2197   /* release the aops */
2198   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2199   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2200 }
2201
2202 /*-----------------------------------------------------------------*/
2203 /* saveRegisters - will look for a call and save the registers     */
2204 /*-----------------------------------------------------------------*/
2205 static void
2206 saveRegisters (iCode * lic)
2207 {
2208   int i;
2209   iCode *ic;
2210   bitVect *rsave;
2211
2212   /* look for call */
2213   for (ic = lic; ic; ic = ic->next)
2214     if (ic->op == CALL || ic->op == PCALL)
2215       break;
2216
2217   if (!ic)
2218     {
2219       fprintf (stderr, "found parameter push with no function call\n");
2220       return;
2221     }
2222
2223   /* if the registers have been saved already or don't need to be then
2224      do nothing */
2225   if (ic->regsSaved)
2226     return;
2227   if (IS_SYMOP(IC_LEFT(ic)) &&
2228       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2229        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2230     return;
2231
2232   /* save the registers in use at this time but skip the
2233      ones for the result */
2234   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2235                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2236
2237   ic->regsSaved = 1;
2238   if (options.useXstack)
2239     {
2240       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2241       int nBits = bitVectnBitsOn (rsavebits);
2242       int count = bitVectnBitsOn (rsave);
2243
2244       if (nBits != 0)
2245         {
2246           count = count - nBits + 1;
2247           /* remove all but the first bits as they are pushed all at once */
2248           rsave = bitVectCplAnd (rsave, rsavebits);
2249           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2250         }
2251       freeBitVect (rsavebits);
2252
2253       if (count == 1)
2254         {
2255           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2256           if (reg->type == REG_BIT)
2257             {
2258               emitcode ("mov", "a,%s", reg->base);
2259             }
2260           else
2261             {
2262               emitcode ("mov", "a,%s", reg->name);
2263             }
2264           emitcode ("mov", "r0,%s", spname);
2265           emitcode ("inc", "%s", spname);// allocate before use
2266           emitcode ("movx", "@r0,a");
2267           if (bitVectBitValue (rsave, R0_IDX))
2268             emitcode ("mov", "r0,a");
2269         }
2270       else if (count != 0)
2271         {
2272           if (bitVectBitValue (rsave, R0_IDX))
2273             {
2274               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2275             }
2276           emitcode ("mov", "r0,%s", spname);
2277           MOVA ("r0");
2278           emitcode ("add", "a,#0x%02x", count);
2279           emitcode ("mov", "%s,a", spname);
2280           for (i = 0; i < mcs51_nRegs; i++)
2281             {
2282               if (bitVectBitValue (rsave, i))
2283                 {
2284                   regs * reg = REG_WITH_INDEX (i);
2285                   if (i == R0_IDX)
2286                     {
2287                       emitcode ("pop", "acc");
2288                       emitcode ("push", "acc");
2289                     }
2290                   else if (reg->type == REG_BIT)
2291                     {
2292                       emitcode ("mov", "a,%s", reg->base);
2293                     }
2294                   else
2295                     {
2296                       emitcode ("mov", "a,%s", reg->name);
2297                     }
2298                   emitcode ("movx", "@r0,a");
2299                   if (--count)
2300                     {
2301                       emitcode ("inc", "r0");
2302                     }
2303                 }
2304             }
2305           if (bitVectBitValue (rsave, R0_IDX))
2306             {
2307               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2308             }
2309         }
2310     }
2311   else
2312     {
2313       bool bits_pushed = FALSE;
2314       for (i = 0; i < mcs51_nRegs; i++)
2315         {
2316           if (bitVectBitValue (rsave, i))
2317             {
2318               bits_pushed = pushReg (i, bits_pushed);
2319             }
2320         }
2321     }
2322   freeBitVect (rsave);
2323 }
2324
2325 /*-----------------------------------------------------------------*/
2326 /* unsaveRegisters - pop the pushed registers                      */
2327 /*-----------------------------------------------------------------*/
2328 static void
2329 unsaveRegisters (iCode * ic)
2330 {
2331   int i;
2332   bitVect *rsave;
2333
2334   /* restore the registers in use at this time but skip the
2335      ones for the result */
2336   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2337                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2338
2339   if (options.useXstack)
2340     {
2341       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2342       int nBits = bitVectnBitsOn (rsavebits);
2343       int count = bitVectnBitsOn (rsave);
2344
2345       if (nBits != 0)
2346         {
2347           count = count - nBits + 1;
2348           /* remove all but the first bits as they are popped all at once */
2349           rsave = bitVectCplAnd (rsave, rsavebits);
2350           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2351         }
2352       freeBitVect (rsavebits);
2353
2354       if (count == 1)
2355         {
2356           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2357           emitcode ("mov", "r0,%s", spname);
2358           emitcode ("dec", "r0");
2359           emitcode ("movx", "a,@r0");
2360           if (reg->type == REG_BIT)
2361             {
2362               emitcode ("mov", "%s,a", reg->base);
2363             }
2364           else
2365             {
2366               emitcode ("mov", "%s,a", reg->name);
2367             }
2368           emitcode ("dec", "%s", spname);
2369         }
2370       else if (count != 0)
2371         {
2372           emitcode ("mov", "r0,%s", spname);
2373           for (i = mcs51_nRegs; i >= 0; i--)
2374             {
2375               if (bitVectBitValue (rsave, i))
2376                 {
2377                   regs * reg = REG_WITH_INDEX (i);
2378                   emitcode ("dec", "r0");
2379                   emitcode ("movx", "a,@r0");
2380                   if (i == R0_IDX)
2381                     {
2382                       emitcode ("push", "acc");
2383                     }
2384                   else if (reg->type == REG_BIT)
2385                     {
2386                       emitcode ("mov", "%s,a", reg->base);
2387                     }
2388                   else
2389                     {
2390                       emitcode ("mov", "%s,a", reg->name);
2391                     }
2392                 }
2393             }
2394           emitcode ("mov", "%s,r0", spname);
2395           if (bitVectBitValue (rsave, R0_IDX))
2396             {
2397               emitcode ("pop", "ar0");
2398             }
2399         }
2400     }
2401   else
2402     {
2403       bool bits_popped = FALSE;
2404       for (i = mcs51_nRegs; i >= 0; i--)
2405         {
2406           if (bitVectBitValue (rsave, i))
2407             {
2408               bits_popped = popReg (i, bits_popped);
2409             }
2410         }
2411     }
2412   freeBitVect (rsave);
2413 }
2414
2415
2416 /*-----------------------------------------------------------------*/
2417 /* pushSide -                                                      */
2418 /*-----------------------------------------------------------------*/
2419 static void
2420 pushSide (operand * oper, int size, iCode * ic)
2421 {
2422   int offset = 0;
2423   int nPushed = _G.r0Pushed + _G.r1Pushed;
2424
2425   aopOp (oper, ic, FALSE);
2426
2427   if (nPushed != _G.r0Pushed + _G.r1Pushed)
2428     {
2429       while (offset < size)
2430         {
2431           char *l = aopGet (oper, offset, FALSE, TRUE);
2432           emitcode ("mov", "%s,%s", fReturn[offset++], l);
2433         }
2434       freeAsmop (oper, NULL, ic, TRUE);
2435       offset = 0;
2436       while (offset < size)
2437         {
2438           emitcode ("push", "%s", fReturn[offset++]);
2439         }
2440       return;
2441     }
2442
2443   while (size--)
2444     {
2445       char *l = aopGet (oper, offset++, FALSE, TRUE);
2446       if (AOP_TYPE (oper) != AOP_REG &&
2447           AOP_TYPE (oper) != AOP_DIR &&
2448           strcmp (l, "a"))
2449         {
2450           MOVA (l);
2451           emitcode ("push", "acc");
2452         }
2453       else
2454         {
2455           emitcode ("push", "%s", l);
2456         }
2457     }
2458
2459   freeAsmop (oper, NULL, ic, TRUE);
2460 }
2461
2462 /*-----------------------------------------------------------------*/
2463 /* assignResultValue - also indicates if acc is in use afterwards  */
2464 /*-----------------------------------------------------------------*/
2465 static bool
2466 assignResultValue (operand * oper, operand * func)
2467 {
2468   int offset = 0;
2469   int size = AOP_SIZE (oper);
2470   bool accuse = FALSE;
2471   bool pushedA = FALSE;
2472
2473   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2474     {
2475       outBitC (oper);
2476       return FALSE;
2477     }
2478
2479   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2480     {
2481       emitcode ("push", "acc");
2482       pushedA = TRUE;
2483     }
2484   while (size--)
2485     {
2486       if ((offset == 3) && pushedA)
2487         emitcode ("pop", "acc");
2488       accuse |= aopPut (oper, fReturn[offset], offset);
2489       offset++;
2490     }
2491   return accuse;
2492 }
2493
2494
2495 /*-----------------------------------------------------------------*/
2496 /* genXpush - pushes onto the external stack                       */
2497 /*-----------------------------------------------------------------*/
2498 static void
2499 genXpush (iCode * ic)
2500 {
2501   asmop *aop = newAsmop (0);
2502   regs *r;
2503   int size, offset = 0;
2504
2505   D (emitcode (";", "genXpush"));
2506
2507   aopOp (IC_LEFT (ic), ic, FALSE);
2508   r = getFreePtr (ic, &aop, FALSE);
2509
2510   size = AOP_SIZE (IC_LEFT (ic));
2511
2512   if (size == 1)
2513     {
2514       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2515       emitcode ("mov", "%s,%s", r->name, spname);
2516       emitcode ("inc", "%s", spname); // allocate space first
2517       emitcode ("movx", "@%s,a", r->name);
2518     }
2519   else
2520     {
2521       // allocate space first
2522       emitcode ("mov", "%s,%s", r->name, spname);
2523       MOVA (r->name);
2524       emitcode ("add", "a,#0x%02x", size);
2525       emitcode ("mov", "%s,a", spname);
2526
2527       while (size--)
2528         {
2529           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2530           emitcode ("movx", "@%s,a", r->name);
2531           emitcode ("inc", "%s", r->name);
2532         }
2533     }
2534
2535   freeAsmop (NULL, aop, ic, TRUE);
2536   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2537 }
2538
2539 /*-----------------------------------------------------------------*/
2540 /* genIpush - generate code for pushing this gets a little complex */
2541 /*-----------------------------------------------------------------*/
2542 static void
2543 genIpush (iCode * ic)
2544 {
2545   int size, offset = 0;
2546   char *l;
2547   char *prev = "";
2548
2549   D (emitcode (";", "genIpush"));
2550
2551   /* if this is not a parm push : ie. it is spill push
2552      and spill push is always done on the local stack */
2553   if (!ic->parmPush)
2554     {
2555
2556       /* and the item is spilt then do nothing */
2557       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2558         return;
2559
2560       aopOp (IC_LEFT (ic), ic, FALSE);
2561       size = AOP_SIZE (IC_LEFT (ic));
2562       /* push it on the stack */
2563       while (size--)
2564         {
2565           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2566           if (*l == '#')
2567             {
2568               MOVA (l);
2569               l = "acc";
2570             }
2571           emitcode ("push", "%s", l);
2572         }
2573       return;
2574     }
2575
2576   /* this is a parameter push: in this case we call
2577      the routine to find the call and save those
2578      registers that need to be saved */
2579   saveRegisters (ic);
2580
2581   /* if use external stack then call the external
2582      stack pushing routine */
2583   if (options.useXstack)
2584     {
2585       genXpush (ic);
2586       return;
2587     }
2588
2589   /* then do the push */
2590   aopOp (IC_LEFT (ic), ic, FALSE);
2591
2592   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2593   size = AOP_SIZE (IC_LEFT (ic));
2594
2595   while (size--)
2596     {
2597       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2598       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2599           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2600         {
2601           if (strcmp (l, prev) || *l == '@')
2602             MOVA (l);
2603           emitcode ("push", "acc");
2604         }
2605       else
2606         {
2607           emitcode ("push", "%s", l);
2608         }
2609       prev = l;
2610     }
2611
2612   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2613 }
2614
2615 /*-----------------------------------------------------------------*/
2616 /* genIpop - recover the registers: can happen only for spilling   */
2617 /*-----------------------------------------------------------------*/
2618 static void
2619 genIpop (iCode * ic)
2620 {
2621   int size, offset;
2622
2623   D (emitcode (";", "genIpop"));
2624
2625   /* if the temp was not pushed then */
2626   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2627     return;
2628
2629   aopOp (IC_LEFT (ic), ic, FALSE);
2630   size = AOP_SIZE (IC_LEFT (ic));
2631   offset = (size - 1);
2632   while (size--)
2633     {
2634       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2635                                      FALSE, TRUE));
2636     }
2637
2638   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2639 }
2640
2641 /*-----------------------------------------------------------------*/
2642 /* saveRBank - saves an entire register bank on the stack          */
2643 /*-----------------------------------------------------------------*/
2644 static void
2645 saveRBank (int bank, iCode * ic, bool pushPsw)
2646 {
2647   int i;
2648   int count = 8 + (pushPsw ? 1 : 0);
2649   asmop *aop = NULL;
2650   regs *r = NULL;
2651
2652   if (options.useXstack)
2653     {
2654       if (!ic)
2655         {
2656           /* Assume r0 is available for use. */
2657           r = REG_WITH_INDEX (R0_IDX);
2658         }
2659       else
2660         {
2661           aop = newAsmop (0);
2662           r = getFreePtr (ic, &aop, FALSE);
2663         }
2664       // allocate space first
2665       emitcode ("mov", "%s,%s", r->name, spname);
2666       MOVA (r->name);
2667       emitcode ("add", "a,#0x%02x", count);
2668       emitcode ("mov", "%s,a", spname);
2669     }
2670
2671   for (i = 0; i < 8; i++)
2672     {
2673       if (options.useXstack)
2674         {
2675           emitcode ("mov", "a,(%s+%d)",
2676                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2677           emitcode ("movx", "@%s,a", r->name);
2678           if (--count)
2679             emitcode ("inc", "%s", r->name);
2680         }
2681       else
2682         emitcode ("push", "(%s+%d)",
2683                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2684     }
2685
2686   if (pushPsw)
2687     {
2688       if (options.useXstack)
2689         {
2690           emitcode ("mov", "a,psw");
2691           emitcode ("movx", "@%s,a", r->name);
2692         }
2693       else
2694         {
2695           emitcode ("push", "psw");
2696         }
2697
2698       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2699     }
2700
2701   if (aop)
2702     {
2703       freeAsmop (NULL, aop, ic, TRUE);
2704     }
2705
2706   if (ic)
2707     {
2708       ic->bankSaved = 1;
2709     }
2710 }
2711
2712 /*-----------------------------------------------------------------*/
2713 /* unsaveRBank - restores the register bank from stack             */
2714 /*-----------------------------------------------------------------*/
2715 static void
2716 unsaveRBank (int bank, iCode * ic, bool popPsw)
2717 {
2718   int i;
2719   asmop *aop = NULL;
2720   regs *r = NULL;
2721
2722   if (options.useXstack)
2723     {
2724       if (!ic)
2725         {
2726           /* Assume r0 is available for use. */
2727           r = REG_WITH_INDEX (R0_IDX);;
2728         }
2729       else
2730         {
2731           aop = newAsmop (0);
2732           r = getFreePtr (ic, &aop, FALSE);
2733         }
2734       emitcode ("mov", "%s,%s", r->name, spname);
2735     }
2736
2737   if (popPsw)
2738     {
2739       if (options.useXstack)
2740         {
2741           emitcode ("dec", "%s", r->name);
2742           emitcode ("movx", "a,@%s", r->name);
2743           emitcode ("mov", "psw,a");
2744         }
2745       else
2746         {
2747           emitcode ("pop", "psw");
2748         }
2749     }
2750
2751   for (i = 7; i >= 0; i--)
2752     {
2753       if (options.useXstack)
2754         {
2755           emitcode ("dec", "%s", r->name);
2756           emitcode ("movx", "a,@%s", r->name);
2757           emitcode ("mov", "(%s+%d),a",
2758                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2759         }
2760       else
2761         {
2762           emitcode ("pop", "(%s+%d)",
2763                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2764         }
2765     }
2766
2767   if (options.useXstack)
2768     {
2769       emitcode ("mov", "%s,%s", spname, r->name);
2770     }
2771
2772   if (aop)
2773     {
2774       freeAsmop (NULL, aop, ic, TRUE);
2775     }
2776 }
2777
2778 /*-----------------------------------------------------------------*/
2779 /* genSend - gen code for SEND                                     */
2780 /*-----------------------------------------------------------------*/
2781 static void genSend(set *sendSet)
2782 {
2783   iCode *sic;
2784   int bit_count = 0;
2785
2786   /* first we do all bit parameters */
2787   for (sic = setFirstItem (sendSet); sic;
2788        sic = setNextItem (sendSet))
2789     {
2790       if (sic->argreg > 12)
2791         {
2792           int bit = sic->argreg-13;
2793
2794           aopOp (IC_LEFT (sic), sic, FALSE);
2795
2796           /* if left is a literal then
2797              we know what the value is */
2798           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2799             {
2800               if (((int) operandLitValue (IC_LEFT (sic))))
2801                   emitcode ("setb", "b[%d]", bit);
2802               else
2803                   emitcode ("clr", "b[%d]", bit);
2804             }
2805           else
2806             {
2807               /* we need to or */
2808               toCarry (IC_LEFT (sic));
2809               emitcode ("mov", "b[%d],c", bit);
2810             }
2811           bit_count++;
2812           BitBankUsed = 1;
2813
2814           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2815         }
2816     }
2817
2818   if (bit_count)
2819     {
2820       saveRegisters (setFirstItem (sendSet));
2821       emitcode ("mov", "bits,b");
2822     }
2823
2824   /* then we do all other parameters */
2825   for (sic = setFirstItem (sendSet); sic;
2826        sic = setNextItem (sendSet))
2827     {
2828       if (sic->argreg <= 12)
2829         {
2830           int size, offset = 0;
2831           aopOp (IC_LEFT (sic), sic, FALSE);
2832           size = AOP_SIZE (IC_LEFT (sic));
2833
2834           if (sic->argreg == 1)
2835             {
2836               while (size--)
2837                 {
2838                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2839                   if (strcmp (l, fReturn[offset]))
2840                     {
2841                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2842                     }
2843                   offset++;
2844                 }
2845             }
2846           else
2847             {
2848               while (size--)
2849                 {
2850                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2851                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2852                   offset++;
2853                 }
2854             }
2855           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2856         }
2857     }
2858 }
2859
2860 /*-----------------------------------------------------------------*/
2861 /* selectRegBank - emit code to select the register bank           */
2862 /*-----------------------------------------------------------------*/
2863 static void
2864 selectRegBank (short bank, bool keepFlags)
2865 {
2866   /* if f.e. result is in carry */
2867   if (keepFlags)
2868     {
2869       emitcode ("anl", "psw,#0xE7");
2870       if (bank)
2871         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2872     }
2873   else
2874     {
2875       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2876     }
2877 }
2878
2879 /*-----------------------------------------------------------------*/
2880 /* genCall - generates a call statement                            */
2881 /*-----------------------------------------------------------------*/
2882 static void
2883 genCall (iCode * ic)
2884 {
2885   sym_link *dtype;
2886   sym_link *etype;
2887 //  bool restoreBank = FALSE;
2888   bool swapBanks = FALSE;
2889   bool accuse = FALSE;
2890   bool accPushed = FALSE;
2891   bool resultInF0 = FALSE;
2892   bool assignResultGenerated = FALSE;
2893
2894   D (emitcode (";", "genCall"));
2895
2896   dtype = operandType (IC_LEFT (ic));
2897   etype = getSpec(dtype);
2898   /* if send set is not empty then assign */
2899   if (_G.sendSet)
2900     {
2901         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2902             genSend(reverseSet(_G.sendSet));
2903         } else {
2904             genSend(_G.sendSet);
2905         }
2906       _G.sendSet = NULL;
2907     }
2908
2909   /* if we are calling a not _naked function that is not using
2910      the same register bank then we need to save the
2911      destination registers on the stack */
2912   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2913       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2914        !IFFUNC_ISISR (dtype))
2915     {
2916       swapBanks = TRUE;
2917     }
2918
2919   /* if caller saves & we have not saved then */
2920   if (!ic->regsSaved)
2921       saveRegisters (ic);
2922
2923   if (swapBanks)
2924     {
2925         emitcode ("mov", "psw,#0x%02x",
2926            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2927     }
2928
2929   /* make the call */
2930   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2931     {
2932       if (IFFUNC_CALLEESAVES(dtype))
2933         {
2934           werror (E_BANKED_WITH_CALLEESAVES);
2935         }
2936       else
2937         {
2938           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2939                      OP_SYMBOL (IC_LEFT (ic))->rname :
2940                      OP_SYMBOL (IC_LEFT (ic))->name);
2941
2942           emitcode ("mov", "r0,#%s", l);
2943           emitcode ("mov", "r1,#(%s >> 8)", l);
2944           emitcode ("mov", "r2,#(%s >> 16)", l);
2945           emitcode ("lcall", "__sdcc_banked_call");
2946         }
2947     }
2948   else
2949     {
2950       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2951                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2952                                 OP_SYMBOL (IC_LEFT (ic))->name));
2953     }
2954
2955   if (swapBanks)
2956     {
2957       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2958     }
2959
2960   /* if we need assign a result value */
2961   if ((IS_ITEMP (IC_RESULT (ic)) &&
2962        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2963        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2964         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2965         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2966       IS_TRUE_SYMOP (IC_RESULT (ic)))
2967     {
2968
2969       _G.accInUse++;
2970       aopOp (IC_RESULT (ic), ic, FALSE);
2971       _G.accInUse--;
2972
2973       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2974       assignResultGenerated = TRUE;
2975
2976       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2977     }
2978
2979   /* adjust the stack for parameters if required */
2980   if (ic->parmBytes)
2981     {
2982       int i;
2983       if (ic->parmBytes > 3)
2984         {
2985           if (accuse)
2986             {
2987               emitcode ("push", "acc");
2988               accPushed = TRUE;
2989             }
2990           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2991               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2992               !assignResultGenerated)
2993             {
2994               emitcode ("mov", "F0,c");
2995               resultInF0 = TRUE;
2996             }
2997
2998           emitcode ("mov", "a,%s", spname);
2999           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3000           emitcode ("mov", "%s,a", spname);
3001
3002           /* unsaveRegisters from xstack needs acc, but */
3003           /* unsaveRegisters from stack needs this popped */
3004           if (accPushed && !options.useXstack)
3005             {
3006               emitcode ("pop", "acc");
3007               accPushed = FALSE;
3008             }
3009         }
3010       else
3011         for (i = 0; i < ic->parmBytes; i++)
3012           emitcode ("dec", "%s", spname);
3013     }
3014
3015   /* if we had saved some registers then unsave them */
3016   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3017     {
3018       if (accuse && !accPushed && options.useXstack)
3019         {
3020           /* xstack needs acc, but doesn't touch normal stack */
3021           emitcode ("push", "acc");
3022           accPushed = TRUE;
3023         }
3024       unsaveRegisters (ic);
3025     }
3026
3027 //  /* if register bank was saved then pop them */
3028 //  if (restoreBank)
3029 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
3030
3031   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
3032     {
3033       if (resultInF0)
3034           emitcode ("mov", "c,F0");
3035
3036       aopOp (IC_RESULT (ic), ic, FALSE);
3037       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3038       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3039     }
3040
3041   if (accPushed)
3042     emitcode ("pop", "acc");
3043 }
3044
3045 /*-----------------------------------------------------------------*/
3046 /* genPcall - generates a call by pointer statement                */
3047 /*-----------------------------------------------------------------*/
3048 static void
3049 genPcall (iCode * ic)
3050 {
3051   sym_link *dtype;
3052   sym_link *etype;
3053   symbol *rlbl = newiTempLabel (NULL);
3054 //  bool restoreBank=FALSE;
3055   bool swapBanks = FALSE;
3056   bool resultInF0 = FALSE;
3057
3058   D (emitcode (";", "genPcall"));
3059
3060   dtype = operandType (IC_LEFT (ic))->next;
3061   etype = getSpec(dtype);
3062   /* if caller saves & we have not saved then */
3063   if (!ic->regsSaved)
3064     saveRegisters (ic);
3065
3066   /* if we are calling a not _naked function that is not using
3067      the same register bank then we need to save the
3068      destination registers on the stack */
3069   if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3070       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3071       !IFFUNC_ISISR (dtype))
3072     {
3073 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3074 //    restoreBank=TRUE;
3075       swapBanks = TRUE;
3076       // need caution message to user here
3077     }
3078
3079   if (IS_LITERAL (etype))
3080     {
3081       /* if send set is not empty then assign */
3082       if (_G.sendSet)
3083         {
3084           genSend(reverseSet(_G.sendSet));
3085           _G.sendSet = NULL;
3086         }
3087
3088       if (swapBanks)
3089         {
3090           emitcode ("mov", "psw,#0x%02x",
3091            ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3092         }
3093
3094       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3095         {
3096           if (IFFUNC_CALLEESAVES (dtype))
3097             {
3098               werror (E_BANKED_WITH_CALLEESAVES);
3099             }
3100           else
3101             {
3102               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3103
3104               emitcode ("mov", "r0,#%s", l);
3105               emitcode ("mov", "r1,#(%s >> 8)", l);
3106               emitcode ("mov", "r2,#(%s >> 16)", l);
3107               emitcode ("lcall", "__sdcc_banked_call");
3108             }
3109         }
3110       else
3111         {
3112           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3113         }
3114     }
3115   else
3116     {
3117       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3118         {
3119           if (IFFUNC_CALLEESAVES (dtype))
3120             {
3121               werror (E_BANKED_WITH_CALLEESAVES);
3122             }
3123           else
3124             {
3125               aopOp (IC_LEFT (ic), ic, FALSE);
3126
3127               if (!swapBanks)
3128                 {
3129                   /* what if aopGet needs r0 or r1 ??? */
3130                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3131                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3132                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3133                 }
3134               else
3135                 {
3136                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3137                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3138                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3139                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3140                 }
3141
3142               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3143
3144               /* if send set is not empty then assign */
3145               if (_G.sendSet)
3146                 {
3147                   genSend(reverseSet(_G.sendSet));
3148                   _G.sendSet = NULL;
3149                 }
3150
3151               if (swapBanks)
3152                 {
3153                   emitcode ("mov", "psw,#0x%02x",
3154                    ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3155                 }
3156
3157               /* make the call */
3158               emitcode ("lcall", "__sdcc_banked_call");
3159             }
3160         }
3161       else if (_G.sendSet)
3162         {
3163           /* push the return address on to the stack */
3164           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3165           emitcode ("push", "acc");
3166           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3167           emitcode ("push", "acc");
3168
3169           /* now push the function address */
3170           pushSide (IC_LEFT (ic), FPTRSIZE, ic);
3171
3172           /* if send set is not empty then assign */
3173           if (_G.sendSet)
3174             {
3175               genSend(reverseSet(_G.sendSet));
3176               _G.sendSet = NULL;
3177             }
3178
3179           if (swapBanks)
3180             {
3181               emitcode ("mov", "psw,#0x%02x",
3182                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3183             }
3184
3185           /* make the call */
3186           emitcode ("ret", "");
3187           emitLabel (rlbl);
3188         }
3189       else /* the send set is empty */
3190         {
3191           char *l;
3192           /* now get the calling address into dptr */
3193           aopOp (IC_LEFT (ic), ic, FALSE);
3194
3195           l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3196           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3197             {
3198               emitcode ("mov", "r0,%s", l);
3199               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3200               emitcode ("mov", "dph,%s", l);
3201               emitcode ("mov", "dpl,r0");
3202             }
3203           else
3204             {
3205               emitcode ("mov", "dpl,%s", l);
3206               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3207               emitcode ("mov", "dph,%s", l);
3208             }
3209
3210           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3211
3212           if (swapBanks)
3213             {
3214               emitcode ("mov", "psw,#0x%02x",
3215                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3216             }
3217
3218           /* make the call */
3219           emitcode ("lcall", "__sdcc_call_dptr");
3220         }
3221     }
3222   if (swapBanks)
3223     {
3224       selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3225     }
3226
3227   /* if we need assign a result value */
3228   if ((IS_ITEMP (IC_RESULT (ic)) &&
3229        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3230        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3231         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3232       IS_TRUE_SYMOP (IC_RESULT (ic)))
3233     {
3234
3235       _G.accInUse++;
3236       aopOp (IC_RESULT (ic), ic, FALSE);
3237       _G.accInUse--;
3238
3239       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3240
3241       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3242     }
3243
3244   /* adjust the stack for parameters if required */
3245   if (ic->parmBytes)
3246     {
3247       int i;
3248       if (ic->parmBytes > 3)
3249         {
3250           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3251               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3252             {
3253               emitcode ("mov", "F0,c");
3254               resultInF0 = TRUE;
3255             }
3256
3257           emitcode ("mov", "a,%s", spname);
3258           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3259           emitcode ("mov", "%s,a", spname);
3260         }
3261       else
3262         for (i = 0; i < ic->parmBytes; i++)
3263           emitcode ("dec", "%s", spname);
3264     }
3265
3266 //  /* if register bank was saved then unsave them */
3267 //  if (restoreBank)
3268 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3269
3270   /* if we had saved some registers then unsave them */
3271   if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3272     unsaveRegisters (ic);
3273
3274   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3275     {
3276       if (resultInF0)
3277           emitcode ("mov", "c,F0");
3278
3279       aopOp (IC_RESULT (ic), ic, FALSE);
3280       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3281       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3282     }
3283 }
3284
3285 /*-----------------------------------------------------------------*/
3286 /* resultRemat - result  is rematerializable                       */
3287 /*-----------------------------------------------------------------*/
3288 static int
3289 resultRemat (iCode * ic)
3290 {
3291   if (SKIP_IC (ic) || ic->op == IFX)
3292     return 0;
3293
3294   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3295     {
3296       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3297       if (sym->remat && !POINTER_SET (ic))
3298         return 1;
3299     }
3300
3301   return 0;
3302 }
3303
3304 /*-----------------------------------------------------------------*/
3305 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3306 /*-----------------------------------------------------------------*/
3307 static int
3308 regsCmp(void *p1, void *p2)
3309 {
3310   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3311 }
3312
3313 static bool
3314 inExcludeList (char *s)
3315 {
3316   const char *p = setFirstItem(options.excludeRegsSet);
3317
3318   if (p == NULL || STRCASECMP(p, "none") == 0)
3319     return FALSE;
3320
3321
3322   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3323 }
3324
3325 /*-----------------------------------------------------------------*/
3326 /* genFunction - generated code for function entry                 */
3327 /*-----------------------------------------------------------------*/
3328 static void
3329 genFunction (iCode * ic)
3330 {
3331   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3332   sym_link *ftype;
3333   bool     switchedPSW = FALSE;
3334   int      calleesaves_saved_register = -1;
3335   int      stackAdjust = sym->stack;
3336   int      accIsFree = sym->recvSize < 4;
3337   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3338   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3339
3340   _G.nRegsSaved = 0;
3341   /* create the function header */
3342   emitcode (";", "-----------------------------------------");
3343   emitcode (";", " function %s", sym->name);
3344   emitcode (";", "-----------------------------------------");
3345
3346   emitcode ("", "%s:", sym->rname);
3347   lineCurr->isLabel = 1;
3348   ftype = operandType (IC_LEFT (ic));
3349   _G.currentFunc = sym;
3350
3351   if (IFFUNC_ISNAKED(ftype))
3352   {
3353       emitcode(";", "naked function: no prologue.");
3354       return;
3355   }
3356
3357   /* here we need to generate the equates for the
3358      register bank if required */
3359   if (FUNC_REGBANK (ftype) != rbank)
3360     {
3361       int i;
3362
3363       rbank = FUNC_REGBANK (ftype);
3364       for (i = 0; i < mcs51_nRegs; i++)
3365         {
3366           if (regs8051[i].type != REG_BIT)
3367             {
3368               if (strcmp (regs8051[i].base, "0") == 0)
3369                 emitcode ("", "%s = 0x%02x",
3370                           regs8051[i].dname,
3371                           8 * rbank + regs8051[i].offset);
3372               else
3373                 emitcode ("", "%s = %s + 0x%02x",
3374                           regs8051[i].dname,
3375                           regs8051[i].base,
3376                           8 * rbank + regs8051[i].offset);
3377             }
3378         }
3379     }
3380
3381   /* if this is an interrupt service routine then
3382      save acc, b, dpl, dph  */
3383   if (IFFUNC_ISISR (sym->type))
3384     {
3385       bitVect *rsavebits;
3386
3387       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3388       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3389         {
3390           emitcode ("push", "bits");
3391           BitBankUsed = 1;
3392         }
3393       freeBitVect (rsavebits);
3394
3395       if (!inExcludeList ("acc"))
3396         emitcode ("push", "acc");
3397       if (!inExcludeList ("b"))
3398         emitcode ("push", "b");
3399       if (!inExcludeList ("dpl"))
3400         emitcode ("push", "dpl");
3401       if (!inExcludeList ("dph"))
3402         emitcode ("push", "dph");
3403       /* if this isr has no bank i.e. is going to
3404          run with bank 0 , then we need to save more
3405          registers :-) */
3406       if (!FUNC_REGBANK (sym->type))
3407         {
3408           int i;
3409
3410           /* if this function does not call any other
3411              function then we can be economical and
3412              save only those registers that are used */
3413           if (!IFFUNC_HASFCALL(sym->type))
3414             {
3415               /* if any registers used */
3416               if (sym->regsUsed)
3417                 {
3418                   /* save the registers used */
3419                   for (i = 0; i < sym->regsUsed->size; i++)
3420                     {
3421                       if (bitVectBitValue (sym->regsUsed, i))
3422                         pushReg (i, TRUE);
3423                     }
3424                 }
3425             }
3426           else
3427             {
3428               /* this function has a function call. We cannot
3429                  determine register usage so we will have to push the
3430                  entire bank */
3431                 saveRBank (0, ic, FALSE);
3432                 if (options.parms_in_bank1) {
3433                     for (i=0; i < 8 ; i++ ) {
3434                         emitcode ("push","%s",rb1regs[i]);
3435                     }
3436                 }
3437             }
3438         }
3439       else
3440         {
3441             /* This ISR uses a non-zero bank.
3442              *
3443              * We assume that the bank is available for our
3444              * exclusive use.
3445              *
3446              * However, if this ISR calls a function which uses some
3447              * other bank, we must save that bank entirely.
3448              */
3449             unsigned long banksToSave = 0;
3450
3451             if (IFFUNC_HASFCALL(sym->type))
3452             {
3453
3454 #define MAX_REGISTER_BANKS 4
3455
3456                 iCode *i;
3457                 int ix;
3458
3459                 for (i = ic; i; i = i->next)
3460                 {
3461                     if (i->op == ENDFUNCTION)
3462                     {
3463                         /* we got to the end OK. */
3464                         break;
3465                     }
3466
3467                     if (i->op == CALL)
3468                     {
3469                         sym_link *dtype;
3470
3471                         dtype = operandType (IC_LEFT(i));
3472                         if (dtype
3473                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3474                         {
3475                              /* Mark this bank for saving. */
3476                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3477                              {
3478                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3479                              }
3480                              else
3481                              {
3482                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3483                              }
3484
3485                              /* And note that we don't need to do it in
3486                               * genCall.
3487                               */
3488                              i->bankSaved = 1;
3489                         }
3490                     }
3491                     if (i->op == PCALL)
3492                     {
3493                         /* This is a mess; we have no idea what
3494                          * register bank the called function might
3495                          * use.
3496                          *
3497                          * The only thing I can think of to do is
3498                          * throw a warning and hope.
3499                          */
3500                         werror(W_FUNCPTR_IN_USING_ISR);
3501                     }
3502                 }
3503
3504                 if (banksToSave && options.useXstack)
3505                 {
3506                     /* Since we aren't passing it an ic,
3507                      * saveRBank will assume r0 is available to abuse.
3508                      *
3509                      * So switch to our (trashable) bank now, so
3510                      * the caller's R0 isn't trashed.
3511                      */
3512                     emitcode ("push", "psw");
3513                     emitcode ("mov", "psw,#0x%02x",
3514                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3515                     switchedPSW = TRUE;
3516                 }
3517
3518                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3519                 {
3520                      if (banksToSave & (1 << ix))
3521                      {
3522                          saveRBank(ix, NULL, FALSE);
3523                      }
3524                 }
3525             }
3526             // TODO: this needs a closer look
3527             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3528         }
3529
3530       /* Set the register bank to the desired value if nothing else */
3531       /* has done so yet. */
3532       if (!switchedPSW)
3533         {
3534           emitcode ("push", "psw");
3535           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3536         }
3537     }
3538   else
3539     {
3540       /* This is a non-ISR function. The caller has already switched register */
3541       /* banks, if necessary, so just handle the callee-saves option. */
3542
3543       /* if callee-save to be used for this function
3544          then save the registers being used in this function */
3545       if (IFFUNC_CALLEESAVES(sym->type))
3546         {
3547           int i;
3548
3549           /* if any registers used */
3550           if (sym->regsUsed)
3551             {
3552               bool bits_pushed = FALSE;
3553               /* save the registers used */
3554               for (i = 0; i < sym->regsUsed->size; i++)
3555                 {
3556                   if (bitVectBitValue (sym->regsUsed, i))
3557                     {
3558                       /* remember one saved register for later usage */
3559                       if (calleesaves_saved_register < 0)
3560                         calleesaves_saved_register = i;
3561                       bits_pushed = pushReg (i, bits_pushed);
3562                       _G.nRegsSaved++;
3563                     }
3564                 }
3565             }
3566         }
3567     }
3568
3569   if (fReentrant)
3570     {
3571       if (options.useXstack)
3572         {
3573           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3574             {
3575               emitcode ("mov", "r0,%s", spname);
3576               emitcode ("inc", "%s", spname);
3577               emitcode ("xch", "a,_bpx");
3578               emitcode ("movx", "@r0,a");
3579               emitcode ("inc", "r0");
3580               emitcode ("mov", "a,r0");
3581               emitcode ("xch", "a,_bpx");
3582             }
3583           if (sym->stack)
3584             {
3585               emitcode ("push", "_bp");     /* save the callers stack  */
3586               emitcode ("mov", "_bp,sp");
3587             }
3588         }
3589       else
3590         {
3591           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3592             {
3593               /* set up the stack */
3594               emitcode ("push", "_bp");     /* save the callers stack  */
3595               emitcode ("mov", "_bp,sp");
3596             }
3597         }
3598     }
3599
3600   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3601   /* before setting up the stack frame completely. */
3602   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3603     {
3604       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3605
3606       if (rsym->isitmp)
3607         {
3608           if (rsym && rsym->regType == REG_CND)
3609             rsym = NULL;
3610           if (rsym && (rsym->accuse || rsym->ruonly))
3611             rsym = NULL;
3612           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3613             rsym = rsym->usl.spillLoc;
3614         }
3615
3616       /* If the RECEIVE operand immediately spills to the first entry on the */
3617       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3618       /* rather than the usual @r0/r1 machinations. */
3619       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3620         {
3621           int ofs;
3622
3623           _G.current_iCode = ric;
3624           D(emitcode (";", "genReceive"));
3625           for (ofs=0; ofs < sym->recvSize; ofs++)
3626             {
3627               if (!strcmp (fReturn[ofs], "a"))
3628                 emitcode ("push", "acc");
3629               else
3630                 emitcode ("push", fReturn[ofs]);
3631             }
3632           stackAdjust -= sym->recvSize;
3633           if (stackAdjust<0)
3634             {
3635               assert (stackAdjust>=0);
3636               stackAdjust = 0;
3637             }
3638           _G.current_iCode = ic;
3639           ric->generated = 1;
3640           accIsFree = 1;
3641         }
3642       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3643       /* to free up the accumulator. */
3644       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3645         {
3646           int ofs;
3647
3648           _G.current_iCode = ric;
3649           D(emitcode (";", "genReceive"));
3650           for (ofs=0; ofs < sym->recvSize; ofs++)
3651             {
3652               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3653             }
3654           _G.current_iCode = ic;
3655           ric->generated = 1;
3656           accIsFree = 1;
3657         }
3658     }
3659
3660   /* adjust the stack for the function */
3661   if (stackAdjust)
3662     {
3663       int i = stackAdjust;
3664       if (i > 256)
3665         werror (W_STACK_OVERFLOW, sym->name);
3666
3667       if (i > 3 && accIsFree)
3668         {
3669           emitcode ("mov", "a,sp");
3670           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671           emitcode ("mov", "sp,a");
3672         }
3673       else if (i > 5)
3674         {
3675           /* The accumulator is not free, so we will need another register */
3676           /* to clobber. No need to worry about a possible conflict with */
3677           /* the above early RECEIVE optimizations since they would have */
3678           /* freed the accumulator if they were generated. */
3679
3680           if (IFFUNC_CALLEESAVES(sym->type))
3681             {
3682               /* if it's a callee-saves function we need a saved register */
3683               if (calleesaves_saved_register >= 0)
3684                 {
3685                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3686                   emitcode ("mov", "a,sp");
3687                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3688                   emitcode ("mov", "sp,a");
3689                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3690                 }
3691               else
3692                 /* do it the hard way */
3693                 while (i--)
3694                   emitcode ("inc", "sp");
3695             }
3696           else
3697             {
3698               /* not callee-saves, we can clobber r0 */
3699               emitcode ("mov", "r0,a");
3700               emitcode ("mov", "a,sp");
3701               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3702               emitcode ("mov", "sp,a");
3703               emitcode ("mov", "a,r0");
3704             }
3705         }
3706       else
3707         while (i--)
3708           emitcode ("inc", "sp");
3709     }
3710
3711   if (sym->xstack)
3712     {
3713       char i = ((char) sym->xstack & 0xff);
3714
3715       if (i > 3 && accIsFree)
3716         {
3717           emitcode ("mov", "a,_spx");
3718           emitcode ("add", "a,#0x%02x", i & 0xff);
3719           emitcode ("mov", "_spx,a");
3720         }
3721       else if (i > 5)
3722         {
3723           emitcode ("push", "acc");
3724           emitcode ("mov", "a,_spx");
3725           emitcode ("add", "a,#0x%02x", i & 0xff);
3726           emitcode ("mov", "_spx,a");
3727           emitcode ("pop", "acc");
3728         }
3729       else
3730         {
3731           while (i--)
3732             emitcode ("inc", "_spx");
3733         }
3734     }
3735
3736   /* if critical function then turn interrupts off */
3737   if (IFFUNC_ISCRITICAL (ftype))
3738     {
3739       symbol *tlbl = newiTempLabel (NULL);
3740       emitcode ("setb", "c");
3741       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3742       emitcode ("clr", "c");
3743       emitLabel (tlbl);
3744       emitcode ("push", "psw"); /* save old ea via c in psw */
3745     }
3746 }
3747
3748 /*-----------------------------------------------------------------*/
3749 /* genEndFunction - generates epilogue for functions               */
3750 /*-----------------------------------------------------------------*/
3751 static void
3752 genEndFunction (iCode * ic)
3753 {
3754   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3755   lineNode *lnp = lineCurr;
3756   bitVect  *regsUsed;
3757   bitVect  *regsUsedPrologue;
3758   bitVect  *regsUnneeded;
3759   int      idx;
3760
3761   _G.currentFunc = NULL;
3762   if (IFFUNC_ISNAKED(sym->type))
3763   {
3764       emitcode(";", "naked function: no epilogue.");
3765       if (options.debug && currFunc)
3766         debugFile->writeEndFunction (currFunc, ic, 0);
3767       return;
3768   }
3769
3770   if (IFFUNC_ISCRITICAL (sym->type))
3771     {
3772       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3773         {
3774           emitcode ("rlc", "a");   /* save c in a */
3775           emitcode ("pop", "psw"); /* restore ea via c in psw */
3776           emitcode ("mov", "ea,c");
3777           emitcode ("rrc", "a");   /* restore c from a */
3778         }
3779       else
3780         {
3781           emitcode ("pop", "psw"); /* restore ea via c in psw */
3782           emitcode ("mov", "ea,c");
3783         }
3784     }
3785
3786   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3787     {
3788       if (options.useXstack)
3789         {
3790           if (sym->stack)
3791             {
3792               emitcode ("mov", "sp,_bp");
3793               emitcode ("pop", "_bp");
3794             }
3795           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3796             {
3797               emitcode ("xch", "a,_bpx");
3798               emitcode ("mov", "r0,a");
3799               emitcode ("dec", "r0");
3800               emitcode ("movx", "a,@r0");
3801               emitcode ("xch", "a,_bpx");
3802               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3803             }
3804         }
3805       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3806         {
3807           if (sym->stack)
3808             emitcode ("mov", "sp,_bp");
3809           emitcode ("pop", "_bp");
3810         }
3811     }
3812
3813   /* restore the register bank  */
3814   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3815   {
3816     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3817      || !options.useXstack)
3818     {
3819         /* Special case of ISR using non-zero bank with useXstack
3820          * is handled below.
3821          */
3822         emitcode ("pop", "psw");
3823     }
3824   }
3825
3826   if (IFFUNC_ISISR (sym->type))
3827     {
3828       bitVect *rsavebits;
3829
3830       /* now we need to restore the registers */
3831       /* if this isr has no bank i.e. is going to
3832          run with bank 0 , then we need to save more
3833          registers :-) */
3834       if (!FUNC_REGBANK (sym->type))
3835         {
3836           int i;
3837           /* if this function does not call any other
3838              function then we can be economical and
3839              save only those registers that are used */
3840           if (!IFFUNC_HASFCALL(sym->type))
3841             {
3842               /* if any registers used */
3843               if (sym->regsUsed)
3844                 {
3845                   /* save the registers used */
3846                   for (i = sym->regsUsed->size; i >= 0; i--)
3847                     {
3848                       if (bitVectBitValue (sym->regsUsed, i))
3849                         popReg (i, TRUE);
3850                     }
3851                 }
3852             }
3853           else
3854             {
3855               if (options.parms_in_bank1) {
3856                   for (i = 7 ; i >= 0 ; i-- ) {
3857                       emitcode ("pop","%s",rb1regs[i]);
3858                   }
3859               }
3860               /* this function has a function call. We cannot
3861                  determine register usage so we will have to pop the
3862                  entire bank */
3863               unsaveRBank (0, ic, FALSE);
3864             }
3865         }
3866         else
3867         {
3868             /* This ISR uses a non-zero bank.
3869              *
3870              * Restore any register banks saved by genFunction
3871              * in reverse order.
3872              */
3873             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3874             int ix;
3875
3876             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3877             {
3878                 if (savedBanks & (1 << ix))
3879                 {
3880                     unsaveRBank(ix, NULL, FALSE);
3881                 }
3882             }
3883
3884             if (options.useXstack)
3885             {
3886                 /* Restore bank AFTER calling unsaveRBank,
3887                  * since it can trash r0.
3888                  */
3889                 emitcode ("pop", "psw");
3890             }
3891         }
3892
3893       if (!inExcludeList ("dph"))
3894         emitcode ("pop", "dph");
3895       if (!inExcludeList ("dpl"))
3896         emitcode ("pop", "dpl");
3897       if (!inExcludeList ("b"))
3898         emitcode ("pop", "b");
3899       if (!inExcludeList ("acc"))
3900         emitcode ("pop", "acc");
3901
3902       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3903       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3904         emitcode ("pop", "bits");
3905       freeBitVect (rsavebits);
3906
3907       /* if debug then send end of function */
3908       if (options.debug && currFunc)
3909         {
3910           debugFile->writeEndFunction (currFunc, ic, 1);
3911         }
3912
3913       emitcode ("reti", "");
3914     }
3915   else
3916     {
3917       if (IFFUNC_CALLEESAVES(sym->type))
3918         {
3919           int i;
3920
3921           /* if any registers used */
3922           if (sym->regsUsed)
3923             {
3924               /* save the registers used */
3925               for (i = sym->regsUsed->size; i >= 0; i--)
3926                 {
3927                   if (bitVectBitValue (sym->regsUsed, i) ||
3928                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3929                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3930                 }
3931             }
3932           else if (mcs51_ptrRegReq)
3933             {
3934               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3935               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3936             }
3937
3938         }
3939
3940       /* if debug then send end of function */
3941       if (options.debug && currFunc)
3942         {
3943           debugFile->writeEndFunction (currFunc, ic, 1);
3944         }
3945
3946       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3947         {
3948           emitcode ("ljmp", "__sdcc_banked_ret");
3949         }
3950       else
3951         {
3952           emitcode ("ret", "");
3953         }
3954     }
3955
3956   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3957     return;
3958
3959   /* If this was an interrupt handler using bank 0 that called another */
3960   /* function, then all registers must be saved; nothing to optimized. */
3961   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3962       && !FUNC_REGBANK(sym->type))
3963     return;
3964
3965   /* There are no push/pops to optimize if not callee-saves or ISR */
3966   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3967     return;
3968
3969   /* If there were stack parameters, we cannot optimize without also    */
3970   /* fixing all of the stack offsets; this is too dificult to consider. */
3971   if (FUNC_HASSTACKPARM(sym->type))
3972     return;
3973
3974   /* Compute the registers actually used */
3975   regsUsed = newBitVect (mcs51_nRegs);
3976   regsUsedPrologue = newBitVect (mcs51_nRegs);
3977   while (lnp)
3978     {
3979       if (lnp->ic && lnp->ic->op == FUNCTION)
3980         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3981       else
3982         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3983
3984       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3985           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3986         break;
3987       if (!lnp->prev)
3988         break;
3989       lnp = lnp->prev;
3990     }
3991
3992   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3993       && !bitVectBitValue (regsUsed, CND_IDX))
3994     {
3995       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3996       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3997           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3998         bitVectUnSetBit (regsUsed, CND_IDX);
3999     }
4000   else
4001     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
4002
4003   /* If this was an interrupt handler that called another function */
4004   /* function, then assume A, B, DPH, & DPL may be modified by it. */
4005   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
4006     {
4007       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
4008       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
4009       regsUsed = bitVectSetBit (regsUsed, B_IDX);
4010       regsUsed = bitVectSetBit (regsUsed, A_IDX);
4011       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
4012     }
4013
4014   /* Remove the unneeded push/pops */
4015   regsUnneeded = newBitVect (mcs51_nRegs);
4016   while (lnp)
4017     {
4018       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
4019         {
4020           if (!strncmp(lnp->line, "push", 4))
4021             {
4022               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
4023               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4024                 {
4025                   connectLine (lnp->prev, lnp->next);
4026                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4027                 }
4028             }
4029           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
4030             {
4031               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4032               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4033                 {
4034                   connectLine (lnp->prev, lnp->next);
4035                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4036                 }
4037             }
4038         }
4039       lnp = lnp->next;
4040     }
4041
4042   for (idx = 0; idx < regsUnneeded->size; idx++)
4043     if (bitVectBitValue (regsUnneeded, idx))
4044       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4045
4046   freeBitVect (regsUnneeded);
4047   freeBitVect (regsUsed);
4048   freeBitVect (regsUsedPrologue);
4049 }
4050
4051 /*-----------------------------------------------------------------*/
4052 /* genRet - generate code for return statement                     */
4053 /*-----------------------------------------------------------------*/
4054 static void
4055 genRet (iCode * ic)
4056 {
4057   int size, offset = 0, pushed = 0;
4058
4059   D (emitcode (";", "genRet"));
4060
4061   /* if we have no return value then
4062      just generate the "ret" */
4063   if (!IC_LEFT (ic))
4064     goto jumpret;
4065
4066   /* we have something to return then
4067      move the return value into place */
4068   aopOp (IC_LEFT (ic), ic, FALSE);
4069   size = AOP_SIZE (IC_LEFT (ic));
4070
4071   if (IS_BIT(_G.currentFunc->etype))
4072     {
4073       if (!IS_OP_RUONLY (IC_LEFT (ic)))
4074         toCarry (IC_LEFT (ic));
4075     }
4076   else
4077     {
4078       while (size--)
4079         {
4080           char *l;
4081           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4082             {
4083               /* #NOCHANGE */
4084               l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4085               emitcode ("push", "%s", l);
4086               pushed++;
4087             }
4088           else
4089             {
4090               l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4091               if (strcmp (fReturn[offset], l))
4092                 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4093             }
4094         }
4095
4096       while (pushed)
4097         {
4098           pushed--;
4099           if (strcmp (fReturn[pushed], "a"))
4100             emitcode ("pop", fReturn[pushed]);
4101           else
4102             emitcode ("pop", "acc");
4103         }
4104     }
4105   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4106
4107 jumpret:
4108   /* generate a jump to the return label
4109      if the next is not the return statement */
4110   if (!(ic->next && ic->next->op == LABEL &&
4111         IC_LABEL (ic->next) == returnLabel))
4112
4113     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4114
4115 }
4116
4117 /*-----------------------------------------------------------------*/
4118 /* genLabel - generates a label                                    */
4119 /*-----------------------------------------------------------------*/
4120 static void
4121 genLabel (iCode * ic)
4122 {
4123   /* special case never generate */
4124   if (IC_LABEL (ic) == entryLabel)
4125     return;
4126
4127   emitLabel (IC_LABEL (ic));
4128 }
4129
4130 /*-----------------------------------------------------------------*/
4131 /* genGoto - generates a ljmp                                      */
4132 /*-----------------------------------------------------------------*/
4133 static void
4134 genGoto (iCode * ic)
4135 {
4136   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4137 }
4138
4139 /*-----------------------------------------------------------------*/
4140 /* findLabelBackwards: walks back through the iCode chain looking  */
4141 /* for the given label. Returns number of iCode instructions     */
4142 /* between that label and given ic.          */
4143 /* Returns zero if label not found.          */
4144 /*-----------------------------------------------------------------*/
4145 static int
4146 findLabelBackwards (iCode * ic, int key)
4147 {
4148   int count = 0;
4149
4150   while (ic->prev)
4151     {
4152       ic = ic->prev;
4153       count++;
4154
4155       /* If we have any pushes or pops, we cannot predict the distance.
4156          I don't like this at all, this should be dealt with in the
4157          back-end */
4158       if (ic->op == IPUSH || ic->op == IPOP) {
4159         return 0;
4160       }
4161
4162       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4163         {
4164           return count;
4165         }
4166     }
4167
4168   return 0;
4169 }
4170
4171 /*-----------------------------------------------------------------*/
4172 /* genPlusIncr :- does addition with increment if possible         */
4173 /*-----------------------------------------------------------------*/
4174 static bool
4175 genPlusIncr (iCode * ic)
4176 {
4177   unsigned int icount;
4178   unsigned int size = getDataSize (IC_RESULT (ic));
4179
4180   /* will try to generate an increment */
4181   /* if the right side is not a literal
4182      we cannot */
4183   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4184     return FALSE;
4185
4186   icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4187
4188   D(emitcode (";","genPlusIncr"));
4189
4190   /* if increment >=16 bits in register or direct space */
4191   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4192         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4193         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4194       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4195       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4196       (size > 1) &&
4197       (icount == 1))
4198     {
4199       symbol *tlbl;
4200       int emitTlbl;
4201       int labelRange;
4202
4203       /* If the next instruction is a goto and the goto target
4204        * is < 10 instructions previous to this, we can generate
4205        * jumps straight to that target.
4206        */
4207       if (ic->next && ic->next->op == GOTO
4208           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4209           && labelRange <= 10)
4210         {
4211           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4212           tlbl = IC_LABEL (ic->next);
4213           emitTlbl = 0;
4214         }
4215       else
4216         {
4217           tlbl = newiTempLabel (NULL);
4218           emitTlbl = 1;
4219         }
4220       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4221       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4222           IS_AOP_PREG (IC_RESULT (ic)))
4223         emitcode ("cjne", "%s,#0x00,%05d$",
4224                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4225                   tlbl->key + 100);
4226       else
4227         {
4228           emitcode ("clr", "a");
4229           emitcode ("cjne", "a,%s,%05d$",
4230                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4231                     tlbl->key + 100);
4232         }
4233
4234       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4235       if (size > 2)
4236         {
4237           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4238               IS_AOP_PREG (IC_RESULT (ic)))
4239             emitcode ("cjne", "%s,#0x00,%05d$",
4240                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4241                       tlbl->key + 100);
4242           else
4243             emitcode ("cjne", "a,%s,%05d$",
4244                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4245                       tlbl->key + 100);
4246
4247           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4248         }
4249       if (size > 3)
4250         {
4251           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4252               IS_AOP_PREG (IC_RESULT (ic)))
4253             emitcode ("cjne", "%s,#0x00,%05d$",
4254                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4255                       tlbl->key + 100);
4256           else
4257             {
4258               emitcode ("cjne", "a,%s,%05d$",
4259                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4260                         tlbl->key + 100);
4261             }
4262           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4263         }
4264
4265       if (emitTlbl)
4266         {
4267           emitLabel (tlbl);
4268         }
4269       return TRUE;
4270     }
4271
4272   /* if result is dptr */
4273   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4274       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4275       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4276       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4277     {
4278       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4279         return FALSE;
4280
4281       if (icount > 9)
4282         return FALSE;
4283
4284       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4285         return FALSE;
4286
4287       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4288       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4289       while (icount--)
4290         emitcode ("inc", "dptr");
4291
4292       return TRUE;
4293     }
4294
4295   /* if the literal value of the right hand side
4296      is greater than 4 then it is not worth it */
4297   if (icount > 4)
4298     return FALSE;
4299
4300   /* if the sizes are greater than 1 then we cannot */
4301   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4302       AOP_SIZE (IC_LEFT (ic)) > 1)
4303     return FALSE;
4304
4305   /* we can if the aops of the left & result match or
4306      if they are in registers and the registers are the
4307      same */
4308   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4309     {
4310       if (icount > 3)
4311         {
4312           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4313           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4314           aopPut (IC_RESULT (ic), "a", 0);
4315         }
4316       else
4317         {
4318           while (icount--)
4319             {
4320               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4321             }
4322         }
4323
4324       return TRUE;
4325     }
4326
4327   if (icount == 1)
4328     {
4329       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4330       emitcode ("inc", "a");
4331       aopPut (IC_RESULT (ic), "a", 0);
4332       return TRUE;
4333     }
4334
4335   return FALSE;
4336 }
4337
4338 /*-----------------------------------------------------------------*/
4339 /* outBitAcc - output a bit in acc                                 */
4340 /*-----------------------------------------------------------------*/
4341 static void
4342 outBitAcc (operand * result)
4343 {
4344   symbol *tlbl = newiTempLabel (NULL);
4345   /* if the result is a bit */
4346   if (AOP_TYPE (result) == AOP_CRY)
4347     {
4348       aopPut (result, "a", 0);
4349     }
4350   else
4351     {
4352       emitcode ("jz", "%05d$", tlbl->key + 100);
4353       emitcode ("mov", "a,%s", one);
4354       emitLabel (tlbl);
4355       outAcc (result);
4356     }
4357 }
4358
4359 /*-----------------------------------------------------------------*/
4360 /* genPlusBits - generates code for addition of two bits           */
4361 /*-----------------------------------------------------------------*/
4362 static void
4363 genPlusBits (iCode * ic)
4364 {
4365   D (emitcode (";", "genPlusBits"));
4366
4367   emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4368   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4369     {
4370       symbol *lbl = newiTempLabel (NULL);
4371       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4372       emitcode ("cpl", "c");
4373       emitLabel (lbl);
4374       outBitC (IC_RESULT (ic));
4375     }
4376   else
4377     {
4378       emitcode ("clr", "a");
4379       emitcode ("rlc", "a");
4380       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381       emitcode ("addc", "a,%s", zero);
4382       outAcc (IC_RESULT (ic));
4383     }
4384 }
4385
4386 #if 0
4387 /* This is the original version of this code.
4388
4389  * This is being kept around for reference,
4390  * because I am not entirely sure I got it right...
4391  */
4392 static void
4393 adjustArithmeticResult (iCode * ic)
4394 {
4395   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4396       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4397       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4398     aopPut (IC_RESULT (ic),
4399             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4400             2);
4401
4402   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4403       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4404       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4405     aopPut (IC_RESULT (ic),
4406             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4407             2);
4408
4409   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4410       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4411       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4412       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4413       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4414     {
4415       char buffer[5];
4416       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4417       aopPut (IC_RESULT (ic), buffer, 2);
4418     }
4419 }
4420 #else
4421 /* This is the pure and virtuous version of this code.
4422  * I'm pretty certain it's right, but not enough to toss the old
4423  * code just yet...
4424  */
4425 static void
4426 adjustArithmeticResult (iCode * ic)
4427 {
4428   if (opIsGptr (IC_RESULT (ic)) &&
4429       opIsGptr (IC_LEFT (ic)) &&
4430       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4431     {
4432       aopPut (IC_RESULT (ic),
4433               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4434               GPTRSIZE - 1);
4435     }
4436
4437   if (opIsGptr (IC_RESULT (ic)) &&
4438       opIsGptr (IC_RIGHT (ic)) &&
4439       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4440     {
4441       aopPut (IC_RESULT (ic),
4442               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4443               GPTRSIZE - 1);
4444     }
4445
4446   if (opIsGptr (IC_RESULT (ic)) &&
4447       IC_LEFT (ic) && AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4448       IC_RIGHT (ic) && AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4449       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4450       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4451     {
4452       char buffer[10];
4453       SNPRINTF (buffer, sizeof(buffer),
4454                 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4455       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4456     }
4457 }
4458 #endif
4459
4460 /*-----------------------------------------------------------------*/
4461 /* genPlus - generates code for addition                           */
4462 /*-----------------------------------------------------------------*/
4463 static void
4464 genPlus (iCode * ic)
4465 {
4466   int size, offset = 0;
4467   int skip_bytes = 0;
4468   char *add = "add";
4469   bool swappedLR = FALSE;
4470   operand *leftOp, *rightOp;
4471   operand * op;
4472
4473   D (emitcode (";", "genPlus"));
4474
4475   /* special cases :- */
4476
4477   aopOp (IC_LEFT (ic), ic, FALSE);
4478   aopOp (IC_RIGHT (ic), ic, FALSE);
4479   aopOp (IC_RESULT (ic), ic, TRUE);
4480
4481   /* if literal, literal on the right or
4482      if left requires ACC or right is already
4483      in ACC */
4484   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4485       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4486       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4487     {
4488       operand *t = IC_RIGHT (ic);
4489       IC_RIGHT (ic) = IC_LEFT (ic);
4490       IC_LEFT (ic) = t;
4491       swappedLR = TRUE;
4492     }
4493
4494   /* if both left & right are in bit
4495      space */
4496   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4497       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4498     {
4499       genPlusBits (ic);
4500       goto release;
4501     }
4502
4503   /* if left in bit space & right literal */
4504   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4505       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4506     {
4507       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4508       /* if result in bit space */
4509       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4510         {
4511           if (ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4512             emitcode ("cpl", "c");
4513           outBitC (IC_RESULT (ic));
4514         }
4515       else
4516         {
4517           size = getDataSize (IC_RESULT (ic));
4518           while (size--)
4519             {
4520               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4521               emitcode ("addc", "a,%s", zero);
4522               aopPut (IC_RESULT (ic), "a", offset++);
4523             }
4524         }
4525       goto release;
4526     }
4527
4528   /* if I can do an increment instead
4529      of add then GOOD for ME */
4530   if (genPlusIncr (ic) == TRUE)
4531     goto release;
4532
4533   size = getDataSize (IC_RESULT (ic));
4534   leftOp = IC_LEFT(ic);
4535   rightOp = IC_RIGHT(ic);
4536   op = IC_LEFT(ic);
4537
4538   /* if this is an add for an array access
4539      at a 256 byte boundary */
4540   if ( 2 == size
4541        && AOP_TYPE (op) == AOP_IMMD
4542        && IS_SYMOP (op)
4543        && IS_SPEC (OP_SYM_ETYPE (op))
4544        && SPEC_ABSA (OP_SYM_ETYPE (op))
4545        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4546      )
4547     {
4548       D(emitcode (";", "genPlus aligned array"));
4549       aopPut (IC_RESULT (ic),
4550               aopGet (rightOp, 0, FALSE, FALSE),
4551               0);
4552
4553       if( 1 == getDataSize (IC_RIGHT (ic)) )
4554         {
4555           aopPut (IC_RESULT (ic),
4556                   aopGet (leftOp, 1, FALSE, FALSE),
4557                   1);
4558         }
4559       else
4560         {
4561           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4562           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4563           aopPut (IC_RESULT (ic), "a", 1);
4564         }
4565       goto release;
4566     }
4567
4568   /* if the lower bytes of a literal are zero skip the addition */
4569   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4570     {
4571        while ((0 == ((unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4572               (skip_bytes+1 < size))
4573          {
4574            skip_bytes++;
4575          }
4576        if (skip_bytes)
4577          D(emitcode (";", "genPlus shortcut"));
4578     }
4579
4580   while (size--)
4581     {
4582       if( offset >= skip_bytes )
4583         {
4584           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4585             {
4586               bool pushedB;
4587               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4588               pushedB = pushB ();
4589               emitcode("xch", "a,b");
4590               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4591               emitcode (add, "a,b");
4592               popB (pushedB);
4593             }
4594           else if (aopGetUsesAcc (leftOp, offset))
4595             {
4596               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4597               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4598             }
4599           else
4600             {
4601               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4602               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4603             }
4604           aopPut (IC_RESULT (ic), "a", offset);
4605           add = "addc";  /* further adds must propagate carry */
4606         }
4607       else
4608         {
4609           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4610               isOperandVolatile (IC_RESULT (ic), FALSE))
4611             {
4612               /* just move */
4613               aopPut (IC_RESULT (ic),
4614                       aopGet (leftOp, offset, FALSE, FALSE),
4615                       offset);
4616             }
4617         }
4618       offset++;
4619     }
4620
4621   adjustArithmeticResult (ic);
4622
4623 release:
4624   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4625   if (!swappedLR)
4626     {
4627       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4628       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4629     }
4630   else
4631     {
4632       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4633       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4634     }
4635 }
4636
4637 /*-----------------------------------------------------------------*/
4638 /* genMinusDec :- does subtraction with decrement if possible      */
4639 /*-----------------------------------------------------------------*/
4640 static bool
4641 genMinusDec (iCode * ic)
4642 {
4643   unsigned int icount;
4644   unsigned int size = getDataSize (IC_RESULT (ic));
4645
4646   /* will try to generate an increment */
4647   /* if the right side is not a literal
4648      we cannot */
4649   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4650     return FALSE;
4651
4652   /* if the literal value of the right hand side
4653      is greater than 4 then it is not worth it */
4654   if ((icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4655     return FALSE;
4656
4657   D (emitcode (";", "genMinusDec"));
4658
4659   /* if decrement >=16 bits in register or direct space */
4660   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG ||
4661         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4662         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4663       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4664       (size > 1) &&
4665       (icount == 1))
4666     {
4667       symbol *tlbl;
4668       int emitTlbl;
4669       int labelRange;
4670
4671       /* If the next instruction is a goto and the goto target
4672        * is <= 10 instructions previous to this, we can generate
4673        * jumps straight to that target.
4674        */
4675       if (ic->next && ic->next->op == GOTO
4676           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4677           && labelRange <= 10)
4678         {
4679           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4680           tlbl = IC_LABEL (ic->next);
4681           emitTlbl = 0;
4682         }
4683       else
4684         {
4685           tlbl = newiTempLabel (NULL);
4686           emitTlbl = 1;
4687         }
4688
4689       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4690       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4691           IS_AOP_PREG (IC_RESULT (ic)))
4692         emitcode ("cjne", "%s,#0xff,%05d$"
4693                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4694                   ,tlbl->key + 100);
4695       else
4696         {
4697           emitcode ("mov", "a,#0xff");
4698           emitcode ("cjne", "a,%s,%05d$"
4699                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4700                     ,tlbl->key + 100);
4701         }
4702       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4703       if (size > 2)
4704         {
4705           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4706               IS_AOP_PREG (IC_RESULT (ic)))
4707             emitcode ("cjne", "%s,#0xff,%05d$"
4708                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4709                       ,tlbl->key + 100);
4710           else
4711             {
4712               emitcode ("cjne", "a,%s,%05d$"
4713                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4714                         ,tlbl->key + 100);
4715             }
4716           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4717         }
4718       if (size > 3)
4719         {
4720           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4721               IS_AOP_PREG (IC_RESULT (ic)))
4722             emitcode ("cjne", "%s,#0xff,%05d$"
4723                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4724                       ,tlbl->key + 100);
4725           else
4726             {
4727               emitcode ("cjne", "a,%s,%05d$"
4728                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4729                         ,tlbl->key + 100);
4730             }
4731           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4732         }
4733       if (emitTlbl)
4734         {
4735           emitLabel (tlbl);
4736         }
4737       return TRUE;
4738     }
4739
4740   /* if the sizes are greater than 1 then we cannot */
4741   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4742       AOP_SIZE (IC_LEFT (ic)) > 1)
4743     return FALSE;
4744
4745   /* we can if the aops of the left & result match or
4746      if they are in registers and the registers are the
4747      same */
4748   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4749     {
4750       char *l;
4751
4752       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4753         {
4754           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4755           l = "a";
4756         }
4757       else
4758         {
4759           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4760         }
4761
4762       while (icount--)
4763         {
4764           emitcode ("dec", "%s", l);
4765         }
4766
4767       if (AOP_NEEDSACC (IC_RESULT (ic)))
4768         aopPut (IC_RESULT (ic), "a", 0);
4769
4770       return TRUE;
4771     }
4772
4773   if (icount == 1)
4774     {
4775       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4776       emitcode ("dec", "a");
4777       aopPut (IC_RESULT (ic), "a", 0);
4778       return TRUE;
4779     }
4780
4781   return FALSE;
4782 }
4783
4784 /*-----------------------------------------------------------------*/
4785 /* addSign - complete with sign                                    */
4786 /*-----------------------------------------------------------------*/
4787 static void
4788 addSign (operand * result, int offset, int sign)
4789 {
4790   int size = (getDataSize (result) - offset);
4791   if (size > 0)
4792     {
4793       if (sign)
4794         {
4795           emitcode ("rlc", "a");
4796           emitcode ("subb", "a,acc");
4797           while (size--)
4798             {
4799               aopPut (result, "a", offset++);
4800             }
4801         }
4802       else
4803         {
4804           while (size--)
4805             {
4806               aopPut (result, zero, offset++);
4807             }
4808         }
4809     }
4810 }
4811
4812 /*-----------------------------------------------------------------*/
4813 /* genMinusBits - generates code for subtraction  of two bits      */
4814 /*-----------------------------------------------------------------*/
4815 static void
4816 genMinusBits (iCode * ic)
4817 {
4818   symbol *lbl = newiTempLabel (NULL);
4819
4820   D (emitcode (";", "genMinusBits"));
4821
4822   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4823     {
4824       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4825       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4826       emitcode ("cpl", "c");
4827       emitLabel (lbl);
4828       outBitC (IC_RESULT (ic));
4829     }
4830   else
4831     {
4832       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4833       emitcode ("subb", "a,acc");
4834       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4835       emitcode ("inc", "a");
4836       emitLabel (lbl);
4837       aopPut (IC_RESULT (ic), "a", 0);
4838       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4839     }
4840 }
4841
4842 /*-----------------------------------------------------------------*/
4843 /* genMinus - generates code for subtraction                       */
4844 /*-----------------------------------------------------------------*/
4845 static void
4846 genMinus (iCode * ic)
4847 {
4848   int size, offset = 0;
4849
4850   D (emitcode (";", "genMinus"));
4851
4852   aopOp (IC_LEFT (ic), ic, FALSE);
4853   aopOp (IC_RIGHT (ic), ic, FALSE);
4854   aopOp (IC_RESULT (ic), ic, TRUE);
4855
4856   /* special cases :- */
4857   /* if both left & right are in bit space */
4858   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4859       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4860     {
4861       genMinusBits (ic);
4862       goto release;
4863     }
4864
4865   /* if I can do an decrement instead
4866      of subtract then GOOD for ME */
4867   if (genMinusDec (ic) == TRUE)
4868     goto release;
4869
4870   size = getDataSize (IC_RESULT (ic));
4871
4872   /* if literal, add a,#-lit, else normal subb */
4873   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4874     {
4875       unsigned long lit = 0L;
4876       bool useCarry = FALSE;
4877
4878       lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4879       lit = -(long) lit;
4880
4881       while (size--)
4882         {
4883           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4884             {
4885               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4886               if (!offset && !size && lit== (unsigned long) -1)
4887                 {
4888                   emitcode ("dec", "a");
4889                 }
4890               else if (!useCarry)
4891                 {
4892                   /* first add without previous c */
4893                   emitcode ("add", "a,#0x%02x",
4894                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4895                   useCarry = TRUE;
4896                 }
4897               else
4898                 {
4899                   emitcode ("addc", "a,#0x%02x",
4900                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4901                 }
4902               aopPut (IC_RESULT (ic), "a", offset++);
4903             }
4904           else
4905             {
4906               /* no need to add zeroes */
4907               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4908                 {
4909                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4910                           offset);
4911                 }
4912               offset++;
4913             }
4914         }
4915     }
4916   else
4917     {
4918       operand *leftOp, *rightOp;
4919
4920       leftOp = IC_LEFT(ic);
4921       rightOp = IC_RIGHT(ic);
4922
4923       while (size--)
4924         {
4925           if (aopGetUsesAcc(rightOp, offset)) {
4926             if (aopGetUsesAcc(leftOp, offset)) {
4927               bool pushedB;
4928
4929               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4930               pushedB = pushB ();
4931               emitcode ("mov", "b,a");
4932               if (offset == 0)
4933                 CLRC;
4934               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4935               emitcode ("subb", "a,b");
4936               popB (pushedB);
4937             } else {
4938               /* reverse subtraction with 2's complement */
4939               if (offset == 0)
4940                 emitcode( "setb", "c");
4941               else
4942                 emitcode( "cpl", "c");
4943               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4944               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4945               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4946               emitcode("cpl", "a");
4947               if (size) /* skip if last byte */
4948                 emitcode( "cpl", "c");
4949             }
4950           } else {
4951             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4952             if (offset == 0)
4953               CLRC;
4954             emitcode ("subb", "a,%s",
4955                       aopGet(rightOp, offset, FALSE, TRUE));
4956           }
4957
4958           aopPut (IC_RESULT (ic), "a", offset++);
4959         }
4960     }
4961
4962   adjustArithmeticResult (ic);
4963
4964 release:
4965   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4966   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4967   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4968 }
4969
4970
4971 /*-----------------------------------------------------------------*/
4972 /* genMultbits :- multiplication of bits                           */
4973 /*-----------------------------------------------------------------*/
4974 static void
4975 genMultbits (operand * left,
4976              operand * right,
4977              operand * result)
4978 {
4979   D (emitcode (";", "genMultbits"));
4980
4981   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4982   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4983   outBitC (result);
4984 }
4985
4986 /*-----------------------------------------------------------------*/
4987 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4988 /*-----------------------------------------------------------------*/
4989 static void
4990 genMultOneByte (operand * left,
4991                 operand * right,
4992                 operand * result)
4993 {
4994   symbol *lbl;
4995   int size = AOP_SIZE (result);
4996   bool runtimeSign, compiletimeSign;
4997   bool lUnsigned, rUnsigned, pushedB;
4998
4999   D (emitcode (";", "genMultOneByte"));
5000
5001   if (size < 1 || size > 2)
5002     {
5003       /* this should never happen */
5004       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
5005                AOP_SIZE(result), __FILE__, lineno);
5006       exit (1);
5007     }
5008
5009   /* (if two literals: the value is computed before) */
5010   /* if one literal, literal on the right */
5011   if (AOP_TYPE (left) == AOP_LIT)
5012     {
5013       operand *t = right;
5014       right = left;
5015       left = t;
5016       /* emitcode (";", "swapped left and right"); */
5017     }
5018   /* if no literal, unsigned on the right: shorter code */
5019   if (   AOP_TYPE (right) != AOP_LIT
5020       && SPEC_USIGN (getSpec (operandType (left))))
5021     {
5022       operand *t = right;
5023       right = left;
5024       left = t;
5025     }
5026
5027   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5028   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5029
5030   pushedB = pushB ();
5031
5032   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5033                    no need to take care about the signedness! */
5034       || (lUnsigned && rUnsigned))
5035     {
5036       /* just an unsigned 8 * 8 = 8 multiply
5037          or 8u * 8u = 16u */
5038       /* emitcode (";","unsigned"); */
5039       /* TODO: check for accumulator clash between left & right aops? */
5040
5041       if (AOP_TYPE (right) == AOP_LIT)
5042         {
5043           /* moving to accumulator first helps peepholes */
5044           MOVA (aopGet (left, 0, FALSE, FALSE));
5045           MOVB (aopGet (right, 0, FALSE, FALSE));
5046         }
5047       else
5048         {
5049           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5050           MOVA (aopGet (left, 0, FALSE, FALSE));
5051         }
5052
5053       emitcode ("mul", "ab");
5054       aopPut (result, "a", 0);
5055       if (size == 2)
5056         aopPut (result, "b", 1);
5057
5058       popB (pushedB);
5059       return;
5060     }
5061
5062   /* we have to do a signed multiply */
5063   /* emitcode (";", "signed"); */
5064
5065   /* now sign adjust for both left & right */
5066
5067   /* let's see what's needed: */
5068   /* apply negative sign during runtime */
5069   runtimeSign = FALSE;
5070   /* negative sign from literals */
5071   compiletimeSign = FALSE;
5072
5073   if (!lUnsigned)
5074     {
5075       if (AOP_TYPE(left) == AOP_LIT)
5076         {
5077           /* signed literal */
5078           signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5079           if (val < 0)
5080             compiletimeSign = TRUE;
5081         }
5082       else
5083         /* signed but not literal */
5084         runtimeSign = TRUE;
5085     }
5086
5087   if (!rUnsigned)
5088     {
5089       if (AOP_TYPE(right) == AOP_LIT)
5090         {
5091           /* signed literal */
5092           signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5093           if (val < 0)
5094             compiletimeSign ^= TRUE;
5095         }
5096       else
5097         /* signed but not literal */
5098         runtimeSign = TRUE;
5099     }
5100
5101   /* initialize F0, which stores the runtime sign */
5102   if (runtimeSign)
5103     {
5104       if (compiletimeSign)
5105         emitcode ("setb", "F0"); /* set sign flag */
5106       else
5107         emitcode ("clr", "F0"); /* reset sign flag */
5108     }
5109
5110   /* save the signs of the operands */
5111   if (AOP_TYPE(right) == AOP_LIT)
5112     {
5113       signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5114
5115       if (!rUnsigned && val < 0)
5116         emitcode ("mov", "b,#0x%02x", -val);
5117       else
5118         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5119     }
5120   else /* ! literal */
5121     {
5122       if (rUnsigned)  /* emitcode (";", "signed"); */
5123         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5124       else
5125         {
5126           MOVA (aopGet (right, 0, FALSE, FALSE));
5127           lbl = newiTempLabel (NULL);
5128           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5129           emitcode ("cpl", "F0"); /* complement sign flag */
5130           emitcode ("cpl", "a");  /* 2's complement */
5131           emitcode ("inc", "a");
5132           emitLabel (lbl);
5133           emitcode ("mov", "b,a");
5134         }
5135     }
5136
5137   if (AOP_TYPE(left) == AOP_LIT)
5138     {
5139       signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5140
5141       if (!lUnsigned && val < 0)
5142         emitcode ("mov", "a,#0x%02x", -val);
5143       else
5144         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5145     }
5146   else /* ! literal */
5147     {
5148       MOVA (aopGet (left, 0, FALSE, FALSE));
5149
5150       if (!lUnsigned)
5151         {
5152           lbl = newiTempLabel (NULL);
5153           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5154           emitcode ("cpl", "F0"); /* complement sign flag */
5155           emitcode ("cpl", "a"); /* 2's complement */
5156           emitcode ("inc", "a");
5157           emitLabel (lbl);
5158         }
5159     }
5160
5161   /* now the multiplication */
5162   emitcode ("mul", "ab");
5163   if (runtimeSign || compiletimeSign)
5164     {
5165       lbl = newiTempLabel (NULL);
5166       if (runtimeSign)
5167         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5168       emitcode ("cpl", "a"); /* lsb 2's complement */
5169       if (size != 2)
5170         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5171       else
5172         {
5173           emitcode ("add", "a,#0x01"); /* this sets carry flag */
5174           emitcode ("xch", "a,b");
5175           emitcode ("cpl", "a"); /* msb 2's complement */
5176           emitcode ("addc", "a,#0x00");
5177           emitcode ("xch", "a,b");
5178         }
5179       emitLabel (lbl);
5180     }
5181   aopPut (result, "a", 0);
5182   if (size == 2)
5183     aopPut (result, "b", 1);
5184
5185   popB (pushedB);
5186 }
5187
5188 /*-----------------------------------------------------------------*/
5189 /* genMult - generates code for multiplication                     */
5190 /*-----------------------------------------------------------------*/
5191 static void
5192 genMult (iCode * ic)
5193 {
5194   operand *left = IC_LEFT (ic);
5195   operand *right = IC_RIGHT (ic);
5196   operand *result = IC_RESULT (ic);
5197
5198   D (emitcode (";", "genMult"));
5199
5200   /* assign the asmops */
5201   aopOp (left, ic, FALSE);
5202   aopOp (right, ic, FALSE);
5203   aopOp (result, ic, TRUE);
5204
5205   /* special cases first */
5206   /* both are bits */
5207   if (AOP_TYPE (left) == AOP_CRY &&
5208       AOP_TYPE (right) == AOP_CRY)
5209     {
5210       genMultbits (left, right, result);
5211       goto release;
5212     }
5213
5214   /* if both are of size == 1 */
5215 #if 0 // one of them can be a sloc shared with the result
5216     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5217 #else
5218   if (getSize(operandType(left)) == 1 &&
5219       getSize(operandType(right)) == 1)
5220 #endif
5221     {
5222       genMultOneByte (left, right, result);
5223       goto release;
5224     }
5225
5226   /* should have been converted to function call */
5227     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5228              getSize(OP_SYMBOL(right)->type));
5229   assert (0);
5230
5231 release:
5232   freeAsmop (result, NULL, ic, TRUE);
5233   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5234   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5235 }
5236
5237 /*-----------------------------------------------------------------*/
5238 /* genDivbits :- division of bits                                  */
5239 /*-----------------------------------------------------------------*/
5240 static void
5241 genDivbits (operand * left,
5242             operand * right,
5243             operand * result)
5244 {
5245   char *l;
5246   bool pushedB;
5247
5248   D(emitcode (";", "genDivbits"));
5249
5250   pushedB = pushB ();
5251
5252   /* the result must be bit */
5253   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5254   l = aopGet (left, 0, FALSE, FALSE);
5255
5256   MOVA (l);
5257
5258   emitcode ("div", "ab");
5259   emitcode ("rrc", "a");
5260
5261   popB (pushedB);
5262
5263   aopPut (result, "c", 0);
5264 }
5265
5266 /*-----------------------------------------------------------------*/
5267 /* genDivOneByte : 8 bit division                                  */
5268 /*-----------------------------------------------------------------*/
5269 static void
5270 genDivOneByte (operand * left,
5271                operand * right,
5272                operand * result)
5273 {
5274   bool lUnsigned, rUnsigned, pushedB;
5275   bool runtimeSign, compiletimeSign;
5276   bool accuse = FALSE;
5277   bool pushedA = FALSE;
5278   symbol *lbl;
5279   int size, offset;
5280
5281   D(emitcode (";", "genDivOneByte"));
5282
5283   /* Why is it necessary that genDivOneByte() can return an int result?
5284      Have a look at:
5285
5286         volatile unsigned char uc;
5287         volatile signed char sc1, sc2;
5288         volatile int i;
5289
5290         uc  = 255;
5291         sc1 = -1;
5292         i = uc / sc1;
5293
5294      Or:
5295
5296         sc1 = -128;
5297         sc2 = -1;
5298         i = sc1 / sc2;
5299
5300      In all cases a one byte result would overflow, the following cast to int
5301      would return the wrong result.
5302
5303      Two possible solution:
5304         a) cast operands to int, if ((unsigned) / (signed)) or
5305            ((signed) / (signed))
5306         b) return an 16 bit signed int; this is what we're doing here!
5307   */
5308
5309   size = AOP_SIZE (result) - 1;
5310   offset = 1;
5311   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5312   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5313
5314   pushedB = pushB ();
5315
5316   /* signed or unsigned */
5317   if (lUnsigned && rUnsigned)
5318     {
5319       /* unsigned is easy */
5320       MOVB (aopGet (right, 0, FALSE, FALSE));
5321       MOVA (aopGet (left, 0, FALSE, FALSE));
5322       emitcode ("div", "ab");
5323       aopPut (result, "a", 0);
5324       while (size--)
5325         aopPut (result, zero, offset++);
5326
5327       popB (pushedB);
5328       return;
5329     }
5330
5331   /* signed is a little bit more difficult */
5332
5333   /* now sign adjust for both left & right */
5334
5335   /* let's see what's needed: */
5336   /* apply negative sign during runtime */
5337   runtimeSign = FALSE;
5338   /* negative sign from literals */
5339   compiletimeSign = FALSE;
5340
5341   if (!lUnsigned)
5342     {
5343       if (AOP_TYPE(left) == AOP_LIT)
5344         {
5345           /* signed literal */
5346           signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5347           if (val < 0)
5348             compiletimeSign = TRUE;
5349         }
5350       else
5351         /* signed but not literal */
5352         runtimeSign = TRUE;
5353     }
5354
5355   if (!rUnsigned)
5356     {
5357       if (AOP_TYPE(right) == AOP_LIT)
5358         {
5359           /* signed literal */
5360           signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5361           if (val < 0)
5362             compiletimeSign ^= TRUE;
5363         }
5364       else
5365         /* signed but not literal */
5366         runtimeSign = TRUE;
5367     }
5368
5369   /* initialize F0, which stores the runtime sign */
5370   if (runtimeSign)
5371     {
5372       if (compiletimeSign)
5373         emitcode ("setb", "F0"); /* set sign flag */
5374       else
5375         emitcode ("clr", "F0"); /* reset sign flag */
5376     }
5377
5378   /* save the signs of the operands */
5379   if (AOP_TYPE(right) == AOP_LIT)
5380     {
5381       signed char val = (char) ulFromVal (AOP (right)->aopu.aop_lit);
5382
5383       if (!rUnsigned && val < 0)
5384         emitcode ("mov", "b,#0x%02x", -val);
5385       else
5386         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5387     }
5388   else /* ! literal */
5389     {
5390       if (rUnsigned)
5391         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5392       else
5393         {
5394           MOVA (aopGet (right, 0, FALSE, FALSE));
5395           lbl = newiTempLabel (NULL);
5396           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5397           emitcode ("cpl", "F0"); /* complement sign flag */
5398           emitcode ("cpl", "a");  /* 2's complement */
5399           emitcode ("inc", "a");
5400           emitLabel (lbl);
5401           emitcode ("mov", "b,a");
5402         }
5403     }
5404
5405   if (AOP_TYPE(left) == AOP_LIT)
5406     {
5407       signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5408
5409       if (!lUnsigned && val < 0)
5410         emitcode ("mov", "a,#0x%02x", -val);
5411       else
5412         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5413     }
5414   else /* ! literal */
5415     {
5416       MOVA (aopGet (left, 0, FALSE, FALSE));
5417
5418       if (!lUnsigned)
5419         {
5420           lbl = newiTempLabel (NULL);
5421           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5422           emitcode ("cpl", "F0"); /* complement sign flag */
5423           emitcode ("cpl", "a");  /* 2's complement */
5424           emitcode ("inc", "a");
5425           emitLabel (lbl);
5426         }
5427     }
5428
5429   /* now the division */
5430   emitcode ("div", "ab");
5431
5432   if (runtimeSign || compiletimeSign)
5433     {
5434       lbl = newiTempLabel (NULL);
5435       if (runtimeSign)
5436         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5437       emitcode ("cpl", "a"); /* lsb 2's complement */
5438       emitcode ("inc", "a");
5439       emitLabel (lbl);
5440
5441       accuse = aopPut (result, "a", 0);
5442       if (size > 0)
5443         {
5444           /* msb is 0x00 or 0xff depending on the sign */
5445           if (runtimeSign)
5446             {
5447               if (accuse)
5448                 {
5449                   emitcode ("push", "acc");
5450                   pushedA = TRUE;
5451                 }
5452               emitcode ("mov", "c,F0");
5453               emitcode ("subb", "a,acc");
5454               while (size--)
5455                 aopPut (result, "a", offset++);
5456             }
5457           else /* compiletimeSign */
5458             {
5459               if (aopPutUsesAcc (result, "#0xff", offset))
5460                 {
5461                   emitcode ("push", "acc");
5462                   pushedA = TRUE;
5463                 }
5464               while (size--)
5465                 aopPut (result, "#0xff", offset++);
5466             }
5467         }
5468     }
5469   else
5470     {
5471       aopPut (result, "a", 0);
5472       while (size--)
5473         aopPut (result, zero, offset++);
5474     }
5475
5476   if (pushedA)
5477     emitcode ("pop", "acc");
5478   popB (pushedB);
5479 }
5480
5481 /*-----------------------------------------------------------------*/
5482 /* genDiv - generates code for division                            */
5483 /*-----------------------------------------------------------------*/
5484 static void
5485 genDiv (iCode * ic)
5486 {
5487   operand *left = IC_LEFT (ic);
5488   operand *right = IC_RIGHT (ic);
5489   operand *result = IC_RESULT (ic);
5490
5491   D (emitcode (";", "genDiv"));
5492
5493   /* assign the asmops */
5494   aopOp (left, ic, FALSE);
5495   aopOp (right, ic, FALSE);
5496   aopOp (result, ic, TRUE);
5497
5498   /* special cases first */
5499   /* both are bits */
5500   if (AOP_TYPE (left) == AOP_CRY &&
5501       AOP_TYPE (right) == AOP_CRY)
5502     {
5503       genDivbits (left, right, result);
5504       goto release;
5505     }
5506
5507   /* if both are of size == 1 */
5508   if (AOP_SIZE (left) == 1 &&
5509       AOP_SIZE (right) == 1)
5510     {
5511       genDivOneByte (left, right, result);
5512       goto release;
5513     }
5514
5515   /* should have been converted to function call */
5516   assert (0);
5517 release:
5518   freeAsmop (result, NULL, ic, TRUE);
5519   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5520   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5521 }
5522
5523 /*-----------------------------------------------------------------*/
5524 /* genModbits :- modulus of bits                                   */
5525 /*-----------------------------------------------------------------*/
5526 static void
5527 genModbits (operand * left,
5528             operand * right,
5529             operand * result)
5530 {
5531   char *l;
5532   bool pushedB;
5533
5534   D (emitcode (";", "genModbits"));
5535
5536   pushedB = pushB ();
5537
5538   /* the result must be bit */
5539   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5540   l = aopGet (left, 0, FALSE, FALSE);
5541
5542   MOVA (l);
5543
5544   emitcode ("div", "ab");
5545   emitcode ("mov", "a,b");
5546   emitcode ("rrc", "a");
5547
5548   popB (pushedB);
5549
5550   aopPut (result, "c", 0);
5551 }
5552
5553 /*-----------------------------------------------------------------*/
5554 /* genModOneByte : 8 bit modulus                                   */
5555 /*-----------------------------------------------------------------*/
5556 static void
5557 genModOneByte (operand * left,
5558                operand * right,
5559                operand * result)
5560 {
5561   bool lUnsigned, rUnsigned, pushedB;
5562   bool runtimeSign, compiletimeSign;
5563   symbol *lbl;
5564   int size, offset;
5565
5566   D (emitcode (";", "genModOneByte"));
5567
5568   size = AOP_SIZE (result) - 1;
5569   offset = 1;
5570   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5571   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5572
5573   /* if right is a literal, check it for 2^n */
5574   if (AOP_TYPE(right) == AOP_LIT)
5575     {
5576       unsigned char val = abs((int) operandLitValue(right));
5577       symbol *lbl2 = NULL;
5578
5579       switch (val)
5580         {
5581           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5582           case 2:
5583           case 4:
5584           case 8:
5585           case 16:
5586           case 32:
5587           case 64:
5588           case 128:
5589             if (lUnsigned)
5590               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5591                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5592               /* because iCode should have been changed to genAnd  */
5593               /* see file "SDCCopt.c", function "convertToFcall()" */
5594
5595             MOVA (aopGet (left, 0, FALSE, FALSE));
5596             emitcode ("mov", "c,acc.7");
5597             emitcode ("anl", "a,#0x%02x", val - 1);
5598             lbl = newiTempLabel (NULL);
5599             emitcode ("jz", "%05d$", (lbl->key + 100));
5600             emitcode ("jnc", "%05d$", (lbl->key + 100));
5601             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5602             if (size)
5603               {
5604                 int size2 = size;
5605                 int offs2 = offset;
5606
5607                 aopPut (result, "a", 0);
5608                 while (size2--)
5609                   aopPut (result, "#0xff", offs2++);
5610                 lbl2 = newiTempLabel (NULL);
5611                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5612               }
5613             emitLabel (lbl);
5614             aopPut (result, "a", 0);
5615             while (size--)
5616               aopPut (result, zero, offset++);
5617             if (lbl2)
5618               {
5619                 emitLabel (lbl2);
5620               }
5621             return;
5622
5623           default:
5624             break;
5625         }
5626     }
5627
5628   pushedB = pushB ();
5629
5630   /* signed or unsigned */
5631   if (lUnsigned && rUnsigned)
5632     {
5633       /* unsigned is easy */
5634       MOVB (aopGet (right, 0, FALSE, FALSE));
5635       MOVA (aopGet (left, 0, FALSE, FALSE));
5636       emitcode ("div", "ab");
5637       aopPut (result, "b", 0);
5638       while (size--)
5639         aopPut (result, zero, offset++);
5640
5641       popB (pushedB);
5642       return;
5643     }
5644
5645   /* signed is a little bit more difficult */
5646
5647   /* now sign adjust for both left & right */
5648
5649   /* modulus: sign of the right operand has no influence on the result! */
5650   if (AOP_TYPE(right) == AOP_LIT)
5651     {
5652       signed char val = (char) operandLitValue(right);
5653
5654       if (!rUnsigned && val < 0)
5655         emitcode ("mov", "b,#0x%02x", -val);
5656       else
5657         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5658     }
5659   else /* not literal */
5660     {
5661       if (rUnsigned)
5662         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5663       else
5664         {
5665           MOVA (aopGet (right, 0, FALSE, FALSE));
5666           lbl = newiTempLabel (NULL);
5667           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5668           emitcode ("cpl", "a"); /* 2's complement */
5669           emitcode ("inc", "a");
5670           emitLabel (lbl);
5671           emitcode ("mov", "b,a");
5672         }
5673     }
5674
5675   /* let's see what's needed: */
5676   /* apply negative sign during runtime */
5677   runtimeSign = FALSE;
5678   /* negative sign from literals */
5679   compiletimeSign = FALSE;
5680
5681   /* sign adjust left side */
5682   if (AOP_TYPE(left) == AOP_LIT)
5683     {
5684       signed char val = (char) ulFromVal (AOP (left)->aopu.aop_lit);
5685
5686       if (!lUnsigned && val < 0)
5687         {
5688           compiletimeSign = TRUE; /* set sign flag */
5689           emitcode ("mov", "a,#0x%02x", -val);
5690         }
5691       else
5692         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5693     }
5694   else /* ! literal */
5695     {
5696       MOVA (aopGet (left, 0, FALSE, FALSE));
5697
5698       if (!lUnsigned)
5699         {
5700           runtimeSign = TRUE;
5701           emitcode ("clr", "F0"); /* clear sign flag */
5702
5703           lbl = newiTempLabel (NULL);
5704           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5705           emitcode ("setb", "F0"); /* set sign flag */
5706           emitcode ("cpl", "a");   /* 2's complement */
5707           emitcode ("inc", "a");
5708           emitLabel (lbl);
5709         }
5710     }
5711
5712   /* now the modulus */
5713   emitcode ("div", "ab");
5714
5715   if (runtimeSign || compiletimeSign)
5716     {
5717       emitcode ("mov", "a,b");
5718       lbl = newiTempLabel (NULL);
5719       if (runtimeSign)
5720         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5721       emitcode ("cpl", "a"); /* 2's complement */
5722       emitcode ("inc", "a");
5723       emitLabel (lbl);
5724
5725       aopPut (result, "a", 0);
5726       if (size > 0)
5727         {
5728           /* msb is 0x00 or 0xff depending on the sign */
5729           if (runtimeSign)
5730             {
5731               emitcode ("mov", "c,F0");
5732               emitcode ("subb", "a,acc");
5733               while (size--)
5734                 aopPut (result, "a", offset++);
5735             }
5736           else /* compiletimeSign */
5737             while (size--)
5738               aopPut (result, "#0xff", offset++);
5739         }
5740     }
5741   else
5742     {
5743       aopPut (result, "b", 0);
5744       while (size--)
5745         aopPut (result, zero, offset++);
5746     }
5747
5748   popB (pushedB);
5749 }
5750
5751 /*-----------------------------------------------------------------*/
5752 /* genMod - generates code for division                            */
5753 /*-----------------------------------------------------------------*/
5754 static void
5755 genMod (iCode * ic)
5756 {
5757   operand *left = IC_LEFT (ic);
5758   operand *right = IC_RIGHT (ic);
5759   operand *result = IC_RESULT (ic);
5760
5761   D (emitcode (";", "genMod"));
5762
5763   /* assign the asmops */
5764   aopOp (left, ic, FALSE);
5765   aopOp (right, ic, FALSE);
5766   aopOp (result, ic, TRUE);
5767
5768   /* special cases first */
5769   /* both are bits */
5770   if (AOP_TYPE (left) == AOP_CRY &&
5771       AOP_TYPE (right) == AOP_CRY)
5772     {
5773       genModbits (left, right, result);
5774       goto release;
5775     }
5776
5777   /* if both are of size == 1 */
5778   if (AOP_SIZE (left) == 1 &&
5779       AOP_SIZE (right) == 1)
5780     {
5781       genModOneByte (left, right, result);
5782       goto release;
5783     }
5784
5785   /* should have been converted to function call */
5786   assert (0);
5787
5788 release:
5789   freeAsmop (result, NULL, ic, TRUE);
5790   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5791   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5792 }
5793
5794 /*-----------------------------------------------------------------*/
5795 /* genIfxJump :- will create a jump depending on the ifx           */
5796 /*-----------------------------------------------------------------*/
5797 static void
5798 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5799 {
5800   symbol *jlbl;
5801   symbol *tlbl = newiTempLabel (NULL);
5802   char *inst;
5803
5804   D (emitcode (";", "genIfxJump"));
5805
5806   /* if true label then we jump if condition
5807      supplied is true */
5808   if (IC_TRUE (ic))
5809     {
5810       jlbl = IC_TRUE (ic);
5811       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5812                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5813     }
5814   else
5815     {
5816       /* false label is present */
5817       jlbl = IC_FALSE (ic);
5818       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5819                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5820     }
5821   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5822     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5823   else
5824     emitcode (inst, "%05d$", tlbl->key + 100);
5825   freeForBranchAsmop (result);
5826   freeForBranchAsmop (right);
5827   freeForBranchAsmop (left);
5828   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5829   emitLabel (tlbl);
5830
5831   /* mark the icode as generated */
5832   ic->generated = 1;
5833 }
5834
5835 /*-----------------------------------------------------------------*/
5836 /* genCmp :- greater or less than comparison                       */
5837 /*-----------------------------------------------------------------*/
5838 static void
5839 genCmp (operand * left, operand * right,
5840         operand * result, iCode * ifx, int sign, iCode *ic)
5841 {
5842   int size, offset = 0;
5843   unsigned long lit = 0L;
5844   bool rightInB;
5845
5846   D (emitcode (";", "genCmp"));
5847
5848   /* if left & right are bit variables */
5849   if (AOP_TYPE (left) == AOP_CRY &&
5850       AOP_TYPE (right) == AOP_CRY)
5851     {
5852       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5853       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5854     }
5855   else
5856     {
5857       /* subtract right from left if at the
5858          end the carry flag is set then we know that
5859          left is greater than right */
5860       size = max (AOP_SIZE (left), AOP_SIZE (right));
5861
5862       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5863       if ((size == 1) && !sign &&
5864           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5865         {
5866           symbol *lbl = newiTempLabel (NULL);
5867           emitcode ("cjne", "%s,%s,%05d$",
5868                     aopGet (left, offset, FALSE, FALSE),
5869                     aopGet (right, offset, FALSE, FALSE),
5870                     lbl->key + 100);
5871           emitLabel (lbl);
5872         }
5873       else
5874         {
5875           if (AOP_TYPE (right) == AOP_LIT)
5876             {
5877               lit = ulFromVal (AOP (right)->aopu.aop_lit);
5878               /* optimize if(x < 0) or if(x >= 0) */
5879               if (lit == 0L)
5880                 {
5881                   if (!sign)
5882                     {
5883                       CLRC;
5884                     }
5885                   else
5886                     {
5887                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5888                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5889                         {
5890                           genIfxJump (ifx, "acc.7", left, right, result);
5891                           freeAsmop (right, NULL, ic, TRUE);
5892                           freeAsmop (left, NULL, ic, TRUE);
5893
5894                           return;
5895                         }
5896                       else
5897                         {
5898                           emitcode ("rlc", "a");
5899                         }
5900                     }
5901                   goto release;
5902                 }
5903               else
5904                 {//nonzero literal
5905                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5906                   while (size && (bytelit == 0))
5907                     {
5908                       offset++;
5909                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5910                       size--;
5911                     }
5912                   CLRC;
5913                   while (size--)
5914                     {
5915                       MOVA (aopGet (left, offset, FALSE, FALSE));
5916                       if (sign && size == 0)
5917                         {
5918                           emitcode ("xrl", "a,#0x80");
5919                           emitcode ("subb", "a,#0x%02x",
5920                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5921                         }
5922                       else
5923                         {
5924                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5925                         }
5926                       offset++;
5927                     }
5928                   goto release;
5929                 }
5930             }
5931           CLRC;
5932           while (size--)
5933             {
5934               bool pushedB = FALSE;
5935               rightInB = aopGetUsesAcc(right, offset);
5936               if (rightInB)
5937                 {
5938                   pushedB = pushB ();
5939                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5940                 }
5941               MOVA (aopGet (left, offset, FALSE, FALSE));
5942               if (sign && size == 0)
5943                 {
5944                   emitcode ("xrl", "a,#0x80");
5945                   if (!rightInB)
5946                     {
5947                       pushedB = pushB ();
5948                       rightInB++;
5949                       MOVB (aopGet (right, offset, FALSE, FALSE));
5950                     }
5951                   emitcode ("xrl", "b,#0x80");
5952                   emitcode ("subb", "a,b");
5953                 }
5954               else
5955                 {
5956                   if (rightInB)
5957                     emitcode ("subb", "a,b");
5958                   else
5959                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5960                 }
5961               if (rightInB)
5962                 popB (pushedB);
5963               offset++;
5964             }
5965         }
5966     }
5967
5968 release:
5969   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5970   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5971   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5972     {
5973       outBitC (result);
5974     }
5975   else
5976     {
5977       /* if the result is used in the next
5978          ifx conditional branch then generate
5979          code a little differently */
5980       if (ifx)
5981         {
5982           genIfxJump (ifx, "c", NULL, NULL, result);
5983         }
5984       else
5985         {
5986           outBitC (result);
5987         }
5988       /* leave the result in acc */
5989     }
5990 }
5991
5992 /*-----------------------------------------------------------------*/
5993 /* genCmpGt :- greater than comparison                             */
5994 /*-----------------------------------------------------------------*/
5995 static void
5996 genCmpGt (iCode * ic, iCode * ifx)
5997 {
5998   operand *left, *right, *result;
5999   sym_link *letype, *retype;
6000   int sign;
6001
6002   D (emitcode (";", "genCmpGt"));
6003
6004   left = IC_LEFT (ic);
6005   right = IC_RIGHT (ic);
6006   result = IC_RESULT (ic);
6007
6008   letype = getSpec (operandType (left));
6009   retype = getSpec (operandType (right));
6010   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6011            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6012   /* assign the asmops */
6013   aopOp (result, ic, TRUE);
6014   aopOp (left, ic, FALSE);
6015   aopOp (right, ic, FALSE);
6016
6017   genCmp (right, left, result, ifx, sign, ic);
6018
6019   freeAsmop (result, NULL, ic, TRUE);
6020 }
6021
6022 /*-----------------------------------------------------------------*/
6023 /* genCmpLt - less than comparisons                                */
6024 /*-----------------------------------------------------------------*/
6025 static void
6026 genCmpLt (iCode * ic, iCode * ifx)
6027 {
6028   operand *left, *right, *result;
6029   sym_link *letype, *retype;
6030   int sign;
6031
6032   D (emitcode (";", "genCmpLt"));
6033
6034   left = IC_LEFT (ic);
6035   right = IC_RIGHT (ic);
6036   result = IC_RESULT (ic);
6037
6038   letype = getSpec (operandType (left));
6039   retype = getSpec (operandType (right));
6040   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6041            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6042   /* assign the asmops */
6043   aopOp (result, ic, TRUE);
6044   aopOp (left, ic, FALSE);
6045   aopOp (right, ic, FALSE);
6046
6047   genCmp (left, right, result, ifx, sign, ic);
6048
6049   freeAsmop (result, NULL, ic, TRUE);
6050 }
6051
6052 /*-----------------------------------------------------------------*/
6053 /* gencjneshort - compare and jump if not equal                    */
6054 /*-----------------------------------------------------------------*/
6055 static void
6056 gencjneshort (operand * left, operand * right, symbol * lbl)
6057 {
6058   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6059   int offset = 0;
6060   unsigned long lit = 0L;
6061
6062   D (emitcode (";", "gencjneshort"));
6063
6064   /* if the left side is a literal or
6065      if the right is in a pointer register and left
6066      is not */
6067   if ((AOP_TYPE (left) == AOP_LIT)  ||
6068       (AOP_TYPE (left) == AOP_IMMD) ||
6069       (AOP_TYPE (left) == AOP_DIR)  ||
6070       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6071     {
6072       operand *t = right;
6073       right = left;
6074       left = t;
6075     }
6076
6077   if (AOP_TYPE (right) == AOP_LIT)
6078     lit = ulFromVal (AOP (right)->aopu.aop_lit);
6079
6080   /* if the right side is a literal then anything goes */
6081   if (AOP_TYPE (right) == AOP_LIT &&
6082       AOP_TYPE (left) != AOP_DIR  &&
6083       AOP_TYPE (left) != AOP_IMMD)
6084     {
6085       while (size--)
6086         {
6087           emitcode ("cjne", "%s,%s,%05d$",
6088                     aopGet (left, offset, FALSE, FALSE),
6089                     aopGet (right, offset, FALSE, FALSE),
6090                     lbl->key + 100);
6091           offset++;
6092         }
6093     }
6094
6095   /* if the right side is in a register or in direct space or
6096      if the left is a pointer register & right is not */
6097   else if (AOP_TYPE (right) == AOP_REG ||
6098            AOP_TYPE (right) == AOP_DIR ||
6099            AOP_TYPE (right) == AOP_LIT ||
6100            AOP_TYPE (right) == AOP_IMMD ||
6101            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6102            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6103     {
6104       while (size--)
6105         {
6106           MOVA (aopGet (left, offset, FALSE, FALSE));
6107           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6108               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6109             emitcode ("jnz", "%05d$", lbl->key + 100);
6110           else
6111             emitcode ("cjne", "a,%s,%05d$",
6112                       aopGet (right, offset, FALSE, TRUE),
6113                       lbl->key + 100);
6114           offset++;
6115         }
6116     }
6117   else
6118     {
6119       /* right is a pointer reg need both a & b */
6120       while (size--)
6121         {
6122           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6123           wassertl(!BINUSE, "B was in use");
6124           MOVB (aopGet (left, offset, FALSE, FALSE));
6125           MOVA (aopGet (right, offset, FALSE, FALSE));
6126           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6127           offset++;
6128         }
6129     }
6130 }
6131
6132 /*-----------------------------------------------------------------*/
6133 /* gencjne - compare and jump if not equal                         */
6134 /*-----------------------------------------------------------------*/
6135 static void
6136 gencjne (operand * left, operand * right, symbol * lbl, bool useCarry)
6137 {
6138   symbol *tlbl = newiTempLabel (NULL);
6139
6140   D (emitcode (";", "gencjne"));
6141
6142   gencjneshort (left, right, lbl);
6143
6144   if (useCarry)
6145       SETC;
6146   else
6147       MOVA (one);
6148   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6149   emitLabel (lbl);
6150   if (useCarry)
6151       CLRC;
6152   else
6153       MOVA (zero);
6154   emitLabel (tlbl);
6155 }
6156
6157 /*-----------------------------------------------------------------*/
6158 /* genCmpEq - generates code for equal to                          */
6159 /*-----------------------------------------------------------------*/
6160 static void
6161 genCmpEq (iCode * ic, iCode * ifx)
6162 {
6163   bool swappedLR = FALSE;
6164   operand *left, *right, *result;
6165
6166   D (emitcode (";", "genCmpEq"));
6167
6168   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6169   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6170   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6171
6172   /* if literal, literal on the right or
6173      if the right is in a pointer register and left
6174      is not */
6175   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6176       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6177     {
6178       operand *t = IC_RIGHT (ic);
6179       IC_RIGHT (ic) = IC_LEFT (ic);
6180       IC_LEFT (ic) = t;
6181       swappedLR = TRUE;
6182     }
6183
6184   if (ifx && !AOP_SIZE (result))
6185     {
6186       symbol *tlbl;
6187       /* if they are both bit variables */
6188       if (AOP_TYPE (left) == AOP_CRY &&
6189           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6190         {
6191           if (AOP_TYPE (right) == AOP_LIT)
6192             {
6193               unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6194               if (lit == 0L)
6195                 {
6196                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6197                   emitcode ("cpl", "c");
6198                 }
6199               else if (lit == 1L)
6200                 {
6201                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6202                 }
6203               else
6204                 {
6205                   emitcode ("clr", "c");
6206                 }
6207               /* AOP_TYPE(right) == AOP_CRY */
6208             }
6209           else
6210             {
6211               symbol *lbl = newiTempLabel (NULL);
6212               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6213               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6214               emitcode ("cpl", "c");
6215               emitLabel (lbl);
6216             }
6217           /* if true label then we jump if condition
6218              supplied is true */
6219           tlbl = newiTempLabel (NULL);
6220           if (IC_TRUE (ifx))
6221             {
6222               emitcode ("jnc", "%05d$", tlbl->key + 100);
6223               freeForBranchAsmop (result);
6224               freeForBranchAsmop (right);
6225               freeForBranchAsmop (left);
6226               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6227             }
6228           else
6229             {
6230               emitcode ("jc", "%05d$", tlbl->key + 100);
6231               freeForBranchAsmop (result);
6232               freeForBranchAsmop (right);
6233               freeForBranchAsmop (left);
6234               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6235             }
6236           emitLabel (tlbl);
6237         }
6238       else
6239         {
6240           tlbl = newiTempLabel (NULL);
6241           gencjneshort (left, right, tlbl);
6242           if (IC_TRUE (ifx))
6243             {
6244               freeForBranchAsmop (result);
6245               freeForBranchAsmop (right);
6246               freeForBranchAsmop (left);
6247               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6248               emitLabel (tlbl);
6249             }
6250           else
6251             {
6252               symbol *lbl = newiTempLabel (NULL);
6253               emitcode ("sjmp", "%05d$", lbl->key + 100);
6254               emitLabel (tlbl);
6255               freeForBranchAsmop (result);
6256               freeForBranchAsmop (right);
6257               freeForBranchAsmop (left);
6258               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6259               emitLabel (lbl);
6260             }
6261         }
6262       /* mark the icode as generated */
6263       ifx->generated = 1;
6264       goto release;
6265     }
6266
6267   /* if they are both bit variables */
6268   if (AOP_TYPE (left) == AOP_CRY &&
6269       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6270     {
6271       if (AOP_TYPE (right) == AOP_LIT)
6272         {
6273           unsigned long lit = ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6274           if (lit == 0L)
6275             {
6276               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6277               emitcode ("cpl", "c");
6278             }
6279           else if (lit == 1L)
6280             {
6281               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6282             }
6283           else
6284             {
6285               emitcode ("clr", "c");
6286             }
6287           /* AOP_TYPE(right) == AOP_CRY */
6288         }
6289       else
6290         {
6291           symbol *lbl = newiTempLabel (NULL);
6292           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6293           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6294           emitcode ("cpl", "c");
6295           emitLabel (lbl);
6296         }
6297       /* c = 1 if egal */
6298       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6299         {
6300           outBitC (result);
6301           goto release;
6302         }
6303       if (ifx)
6304         {
6305           genIfxJump (ifx, "c", left, right, result);
6306           goto release;
6307         }
6308       /* if the result is used in an arithmetic operation
6309          then put the result in place */
6310       outBitC (result);
6311     }
6312   else
6313     {
6314       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6315         {
6316           gencjne (left, right, newiTempLabel (NULL), TRUE);
6317           aopPut (result, "c", 0);
6318           goto release;
6319         }
6320       gencjne (left, right, newiTempLabel (NULL), FALSE);
6321       if (ifx)
6322         {
6323           genIfxJump (ifx, "a", left, right, result);
6324           goto release;
6325         }
6326       /* if the result is used in an arithmetic operation
6327          then put the result in place */
6328       if (AOP_TYPE (result) != AOP_CRY)
6329         outAcc (result);
6330       /* leave the result in acc */
6331     }
6332
6333 release:
6334   freeAsmop (result, NULL, ic, TRUE);
6335   if (!swappedLR)
6336     {
6337       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6338       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6339     }
6340   else
6341     {
6342       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6343       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6344     }
6345 }
6346
6347 /*-----------------------------------------------------------------*/
6348 /* ifxForOp - returns the icode containing the ifx for operand     */
6349 /*-----------------------------------------------------------------*/
6350 static iCode *
6351 ifxForOp (operand * op, iCode * ic)
6352 {
6353   /* if true symbol then needs to be assigned */
6354   if (IS_TRUE_SYMOP (op))
6355     return NULL;
6356
6357   /* if this has register type condition and
6358      the next instruction is ifx with the same operand
6359      and live to of the operand is upto the ifx only then */
6360   if (ic->next &&
6361       ic->next->op == IFX &&
6362       IC_COND (ic->next)->key == op->key &&
6363       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6364     return ic->next;
6365
6366   return NULL;
6367 }
6368
6369 /*-----------------------------------------------------------------*/
6370 /* hasInc - operand is incremented before any other use            */
6371 /*-----------------------------------------------------------------*/
6372 static iCode *
6373 hasInc (operand *op, iCode *ic, int osize)
6374 {
6375   sym_link *type = operandType(op);
6376   sym_link *retype = getSpec (type);
6377   iCode *lic = ic->next;
6378   int isize ;
6379
6380   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6381   if (!IS_SYMOP(op)) return NULL;
6382
6383   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6384   if (IS_AGGREGATE(type->next)) return NULL;
6385   if (osize != (isize = getSize(type->next))) return NULL;
6386
6387   while (lic) {
6388     /* if operand of the form op = op + <sizeof *op> */
6389     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6390         isOperandEqual(IC_RESULT(lic),op) &&
6391         isOperandLiteral(IC_RIGHT(lic)) &&
6392         operandLitValue(IC_RIGHT(lic)) == isize) {
6393       return lic;
6394     }
6395     /* if the operand used or deffed */
6396     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6397       return NULL;
6398     }
6399     /* if GOTO or IFX */
6400     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6401     lic = lic->next;
6402   }
6403   return NULL;
6404 }
6405
6406 /*-----------------------------------------------------------------*/
6407 /* genAndOp - for && operation                                     */
6408 /*-----------------------------------------------------------------*/
6409 static void
6410 genAndOp (iCode * ic)
6411 {
6412   operand *left, *right, *result;
6413   symbol *tlbl;
6414
6415   D (emitcode (";", "genAndOp"));
6416
6417   /* note here that && operations that are in an
6418      if statement are taken away by backPatchLabels
6419      only those used in arthmetic operations remain */
6420   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6421   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6422   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6423
6424   /* if both are bit variables */
6425   if (AOP_TYPE (left) == AOP_CRY &&
6426       AOP_TYPE (right) == AOP_CRY)
6427     {
6428       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6429       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6430       outBitC (result);
6431     }
6432   else
6433     {
6434       tlbl = newiTempLabel (NULL);
6435       toBoolean (left);
6436       emitcode ("jz", "%05d$", tlbl->key + 100);
6437       toBoolean (right);
6438       emitLabel (tlbl);
6439       outBitAcc (result);
6440     }
6441
6442   freeAsmop (result, NULL, ic, TRUE);
6443   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6444   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6445 }
6446
6447
6448 /*-----------------------------------------------------------------*/
6449 /* genOrOp - for || operation                                      */
6450 /*-----------------------------------------------------------------*/
6451 static void
6452 genOrOp (iCode * ic)
6453 {
6454   operand *left, *right, *result;
6455   symbol *tlbl;
6456
6457   D (emitcode (";", "genOrOp"));
6458
6459   /* note here that || operations that are in an
6460      if statement are taken away by backPatchLabels
6461      only those used in arthmetic operations remain */
6462   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6463   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6464   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6465
6466   /* if both are bit variables */
6467   if (AOP_TYPE (left) == AOP_CRY &&
6468       AOP_TYPE (right) == AOP_CRY)
6469     {
6470       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6471       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6472       outBitC (result);
6473     }
6474   else
6475     {
6476       tlbl = newiTempLabel (NULL);
6477       toBoolean (left);
6478       emitcode ("jnz", "%05d$", tlbl->key + 100);
6479       toBoolean (right);
6480       emitLabel (tlbl);
6481       outBitAcc (result);
6482     }
6483
6484   freeAsmop (result, NULL, ic, TRUE);
6485   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6486   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6487 }
6488
6489 /*-----------------------------------------------------------------*/
6490 /* isLiteralBit - test if lit == 2^n                               */
6491 /*-----------------------------------------------------------------*/
6492 static int
6493 isLiteralBit (unsigned long lit)
6494 {
6495   unsigned long pw[32] =
6496   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6497    0x100L, 0x200L, 0x400L, 0x800L,
6498    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6499    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6500    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6501    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6502    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6503   int idx;
6504
6505   for (idx = 0; idx < 32; idx++)
6506     if (lit == pw[idx])
6507       return idx + 1;
6508   return 0;
6509 }
6510
6511 /*-----------------------------------------------------------------*/
6512 /* continueIfTrue -                                                */
6513 /*-----------------------------------------------------------------*/
6514 static void
6515 continueIfTrue (iCode * ic)
6516 {
6517   if (IC_TRUE (ic))
6518     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6519   ic->generated = 1;
6520 }
6521
6522 /*-----------------------------------------------------------------*/
6523 /* jmpIfTrue -                                                     */
6524 /*-----------------------------------------------------------------*/
6525 static void
6526 jumpIfTrue (iCode * ic)
6527 {
6528   if (!IC_TRUE (ic))
6529     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6530   ic->generated = 1;
6531 }
6532
6533 /*-----------------------------------------------------------------*/
6534 /* jmpTrueOrFalse -                                                */
6535 /*-----------------------------------------------------------------*/
6536 static void
6537 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6538 {
6539   // ugly but optimized by peephole
6540   if (IC_TRUE (ic))
6541     {
6542       symbol *nlbl = newiTempLabel (NULL);
6543       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6544       emitLabel (tlbl);
6545       freeForBranchAsmop (result);
6546       freeForBranchAsmop (right);
6547       freeForBranchAsmop (left);
6548       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6549       emitLabel (nlbl);
6550     }
6551   else
6552     {
6553       freeForBranchAsmop (result);
6554       freeForBranchAsmop (right);
6555       freeForBranchAsmop (left);
6556       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6557       emitLabel (tlbl);
6558     }
6559   ic->generated = 1;
6560 }
6561
6562 /*-----------------------------------------------------------------*/
6563 /* genAnd  - code for and                                          */
6564 /*-----------------------------------------------------------------*/
6565 static void
6566 genAnd (iCode * ic, iCode * ifx)
6567 {
6568   operand *left, *right, *result;
6569   int size, offset = 0;
6570   unsigned long lit = 0L;
6571   int bytelit = 0;
6572   char buffer[10];
6573
6574   D (emitcode (";", "genAnd"));
6575
6576   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6577   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6578   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6579
6580 #ifdef DEBUG_TYPE
6581   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
6582             AOP_TYPE (result),
6583             AOP_TYPE (left), AOP_TYPE (right));
6584   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
6585             AOP_SIZE (result),
6586             AOP_SIZE (left), AOP_SIZE (right));
6587 #endif
6588
6589   /* if left is a literal & right is not then exchange them */
6590   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6591       AOP_NEEDSACC (left))
6592     {
6593       operand *tmp = right;
6594       right = left;
6595       left = tmp;
6596     }
6597
6598   /* if result = right then exchange left and right */
6599   if (sameRegs (AOP (result), AOP (right)))
6600     {
6601       operand *tmp = right;
6602       right = left;
6603       left = tmp;
6604     }
6605
6606   /* if right is bit then exchange them */
6607   if (AOP_TYPE (right) == AOP_CRY &&
6608       AOP_TYPE (left) != AOP_CRY)
6609     {
6610       operand *tmp = right;
6611       right = left;
6612       left = tmp;
6613     }
6614   if (AOP_TYPE (right) == AOP_LIT)
6615     lit = ulFromVal (AOP (right)->aopu.aop_lit);
6616
6617   size = AOP_SIZE (result);
6618
6619   // if(bit & yy)
6620   // result = bit & yy;
6621   if (AOP_TYPE (left) == AOP_CRY)
6622     {
6623       // c = bit & literal;
6624       if (AOP_TYPE (right) == AOP_LIT)
6625         {
6626           if (lit & 1)
6627             {
6628               if (size && sameRegs (AOP (result), AOP (left)))
6629                 // no change
6630                 goto release;
6631               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6632             }
6633           else
6634             {
6635               // bit(result) = 0;
6636               if (size && (AOP_TYPE (result) == AOP_CRY))
6637                 {
6638                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6639                   goto release;
6640                 }
6641               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6642                 {
6643                   jumpIfTrue (ifx);
6644                   goto release;
6645                 }
6646               emitcode ("clr", "c");
6647             }
6648         }
6649       else
6650         {
6651           if (AOP_TYPE (right) == AOP_CRY)
6652             {
6653               // c = bit & bit;
6654               if (IS_OP_ACCUSE (left))
6655                 {
6656                   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6657                 }
6658               else
6659                 {
6660                   emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6661                   emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6662                 }
6663             }
6664           else
6665             {
6666               // c = bit & val;
6667               MOVA (aopGet (right, 0, FALSE, FALSE));
6668               // c = lsb
6669               emitcode ("rrc", "a");
6670               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6671             }
6672         }
6673       // bit = c
6674       // val = c
6675       if (size)
6676         outBitC (result);
6677       // if(bit & ...)
6678       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6679         genIfxJump (ifx, "c", left, right, result);
6680       goto release;
6681     }
6682
6683   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6684   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6685   if ((AOP_TYPE (right) == AOP_LIT) &&
6686       (AOP_TYPE (result) == AOP_CRY) &&
6687       (AOP_TYPE (left) != AOP_CRY))
6688     {
6689       int posbit = isLiteralBit (lit);
6690       /* left &  2^n */
6691       if (posbit)
6692         {
6693           posbit--;
6694           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6695           // bit = left & 2^n
6696           if (size)
6697             {
6698               switch (posbit & 0x07)
6699                 {
6700                   case 0: emitcode ("rrc", "a");
6701                           break;
6702                   case 7: emitcode ("rlc", "a");
6703                           break;
6704                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6705                           break;
6706                 }
6707             }
6708           // if(left &  2^n)
6709           else
6710             {
6711               if (ifx)
6712                 {
6713                   SNPRINTF (buffer, sizeof(buffer),
6714                             "acc.%d", posbit & 0x07);
6715                   genIfxJump (ifx, buffer, left, right, result);
6716                 }
6717               else
6718                 {// what is this case? just found it in ds390/gen.c
6719                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6720                 }
6721               goto release;
6722             }
6723         }
6724       else
6725         {
6726           symbol *tlbl = newiTempLabel (NULL);
6727           int sizel = AOP_SIZE (left);
6728           if (size)
6729             emitcode ("setb", "c");
6730           while (sizel--)
6731             {
6732               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6733                 {
6734                   MOVA (aopGet (left, offset, FALSE, FALSE));
6735                   // byte ==  2^n ?
6736                   if ((posbit = isLiteralBit (bytelit)) != 0)
6737                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6738                   else
6739                     {
6740                       if (bytelit != 0x0FFL)
6741                         emitcode ("anl", "a,%s",
6742                                   aopGet (right, offset, FALSE, TRUE));
6743                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6744                     }
6745                 }
6746               offset++;
6747             }
6748           // bit = left & literal
6749           if (size)
6750             {
6751               emitcode ("clr", "c");
6752               emitLabel (tlbl);
6753             }
6754           // if(left & literal)
6755           else
6756             {
6757               if (ifx)
6758                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6759               else
6760                 emitLabel (tlbl);
6761               goto release;
6762             }
6763         }
6764       outBitC (result);
6765       goto release;
6766     }
6767
6768   /* if left is same as result */
6769   if (sameRegs (AOP (result), AOP (left)))
6770     {
6771       for (; size--; offset++)
6772         {
6773           if (AOP_TYPE (right) == AOP_LIT)
6774             {
6775               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6776               if (bytelit == 0x0FF)
6777                 {
6778                   /* dummy read of volatile operand */
6779                   if (isOperandVolatile (left, FALSE))
6780                     MOVA (aopGet (left, offset, FALSE, FALSE));
6781                   else
6782                     continue;
6783                 }
6784               else if (bytelit == 0)
6785                 {
6786                   aopPut (result, zero, offset);
6787                 }
6788               else if (IS_AOP_PREG (result))
6789                 {
6790                   MOVA (aopGet (left, offset, FALSE, TRUE));
6791                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6792                   aopPut (result, "a", offset);
6793                 }
6794               else
6795                 emitcode ("anl", "%s,%s",
6796                           aopGet (left, offset, FALSE, TRUE),
6797                           aopGet (right, offset, FALSE, FALSE));
6798             }
6799           else
6800             {
6801               if (AOP_TYPE (left) == AOP_ACC)
6802                 {
6803                   if (offset)
6804                     emitcode("mov", "a,b");
6805                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6806                 }
6807               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6808                 {
6809                   MOVB (aopGet (left, offset, FALSE, FALSE));
6810                   MOVA (aopGet (right, offset, FALSE, FALSE));
6811                   emitcode ("anl", "a,b");
6812                   aopPut (result, "a", offset);
6813                 }
6814               else if (aopGetUsesAcc (left, offset))
6815                 {
6816                   MOVA (aopGet (left, offset, FALSE, FALSE));
6817                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6818                   aopPut (result, "a", offset);
6819                 }
6820               else
6821                 {
6822                   MOVA (aopGet (right, offset, FALSE, FALSE));
6823                   if (IS_AOP_PREG (result))
6824                     {
6825                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6826                       aopPut (result, "a", offset);
6827                     }
6828                   else
6829                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6830                 }
6831             }
6832         }
6833     }
6834   else
6835     {
6836       // left & result in different registers
6837       if (AOP_TYPE (result) == AOP_CRY)
6838         {
6839           // result = bit
6840           // if(size), result in bit
6841           // if(!size && ifx), conditional oper: if(left & right)
6842           symbol *tlbl = newiTempLabel (NULL);
6843           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6844           if (size)
6845             emitcode ("setb", "c");
6846           while (sizer--)
6847             {
6848               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6849                   && AOP_TYPE(left)==AOP_ACC)
6850                 {
6851                   if (offset)
6852                     emitcode("mov", "a,b");
6853                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6854                 }
6855               else if (AOP_TYPE(left)==AOP_ACC)
6856                 {
6857                   if (!offset)
6858                     {
6859                       bool pushedB = pushB ();
6860                       emitcode("mov", "b,a");
6861                       MOVA (aopGet (right, offset, FALSE, FALSE));
6862                       emitcode("anl", "a,b");
6863                       popB (pushedB);
6864                     }
6865                   else
6866                     {
6867                       MOVA (aopGet (right, offset, FALSE, FALSE));
6868                       emitcode("anl", "a,b");
6869                     }
6870                 }
6871               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6872                 {
6873                   MOVB (aopGet (left, offset, FALSE, FALSE));
6874                   MOVA (aopGet (right, offset, FALSE, FALSE));
6875                   emitcode ("anl", "a,b");
6876                 }
6877               else if (aopGetUsesAcc (left, offset))
6878                 {
6879                   MOVA (aopGet (left, offset, FALSE, FALSE));
6880                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6881                     }
6882               else
6883                 {
6884                   MOVA (aopGet (right, offset, FALSE, FALSE));
6885                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6886                 }
6887
6888               emitcode ("jnz", "%05d$", tlbl->key + 100);
6889               offset++;
6890             }
6891           if (size)
6892             {
6893               CLRC;
6894               emitLabel (tlbl);
6895               outBitC (result);
6896             }
6897           else if (ifx)
6898             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6899           else
6900             emitLabel (tlbl);
6901         }
6902       else
6903         {
6904           for (; (size--); offset++)
6905             {
6906               // normal case
6907               // result = left & right
6908               if (AOP_TYPE (right) == AOP_LIT)
6909                 {
6910                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6911                   if (bytelit == 0x0FF)
6912                     {
6913                       aopPut (result,
6914                               aopGet (left, offset, FALSE, FALSE),
6915                               offset);
6916                       continue;
6917                     }
6918                   else if (bytelit == 0)
6919                     {
6920                       /* dummy read of volatile operand */
6921                       if (isOperandVolatile (left, FALSE))
6922                         MOVA (aopGet (left, offset, FALSE, FALSE));
6923                       aopPut (result, zero, offset);
6924                       continue;
6925                     }
6926                   else if (AOP_TYPE (left) == AOP_ACC)
6927                     {
6928                       if (!offset)
6929                         {
6930                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6931                           aopPut (result, "a", offset);
6932                           continue;
6933                         }
6934                       else
6935                         {
6936                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6937                           aopPut (result, "b", offset);
6938                           continue;
6939                         }
6940                     }
6941                 }
6942               // faster than result <- left, anl result,right
6943               // and better if result is SFR
6944               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6945                   && AOP_TYPE(left)==AOP_ACC)
6946                 {
6947                   if (offset)
6948                     emitcode("mov", "a,b");
6949                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6950                 }
6951               else if (AOP_TYPE(left)==AOP_ACC)
6952                 {
6953                   if (!offset)
6954                     {
6955                       bool pushedB = pushB ();
6956                       emitcode("mov", "b,a");
6957                       MOVA (aopGet (right, offset, FALSE, FALSE));
6958                       emitcode("anl", "a,b");
6959                       popB (pushedB);
6960                     }
6961                   else
6962                     {
6963                       MOVA (aopGet (right, offset, FALSE, FALSE));
6964                       emitcode("anl", "a,b");
6965                     }
6966                 }
6967               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6968                 {
6969                   MOVB (aopGet (left, offset, FALSE, FALSE));
6970                   MOVA (aopGet (right, offset, FALSE, FALSE));
6971                   emitcode ("anl", "a,b");
6972                 }
6973               else if (aopGetUsesAcc (left, offset))
6974                 {
6975                   MOVA (aopGet (left, offset, FALSE, FALSE));
6976                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6977                 }
6978               else
6979                 {
6980                   MOVA (aopGet (right, offset, FALSE, FALSE));
6981                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6982                 }
6983               aopPut (result, "a", offset);
6984             }
6985         }
6986     }
6987
6988 release:
6989   freeAsmop (result, NULL, ic, TRUE);
6990   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6991   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6992 }
6993
6994 /*-----------------------------------------------------------------*/
6995 /* genOr  - code for or                                            */
6996 /*-----------------------------------------------------------------*/
6997 static void
6998 genOr (iCode * ic, iCode * ifx)
6999 {
7000   operand *left, *right, *result;
7001   int size, offset = 0;
7002   unsigned long lit = 0L;
7003   int bytelit = 0;
7004
7005   D (emitcode (";", "genOr"));
7006
7007   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7008   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7009   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7010
7011 #ifdef DEBUG_TYPE
7012   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7013             AOP_TYPE (result),
7014             AOP_TYPE (left), AOP_TYPE (right));
7015   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7016             AOP_SIZE (result),
7017             AOP_SIZE (left), AOP_SIZE (right));
7018 #endif
7019
7020   /* if left is a literal & right is not then exchange them */
7021   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7022       AOP_NEEDSACC (left))
7023     {
7024       operand *tmp = right;
7025       right = left;
7026       left = tmp;
7027     }
7028
7029   /* if result = right then exchange them */
7030   if (sameRegs (AOP (result), AOP (right)))
7031     {
7032       operand *tmp = right;
7033       right = left;
7034       left = tmp;
7035     }
7036
7037   /* if right is bit then exchange them */
7038   if (AOP_TYPE (right) == AOP_CRY &&
7039       AOP_TYPE (left) != AOP_CRY)
7040     {
7041       operand *tmp = right;
7042       right = left;
7043       left = tmp;
7044     }
7045   if (AOP_TYPE (right) == AOP_LIT)
7046     lit = ulFromVal (AOP (right)->aopu.aop_lit);
7047
7048   size = AOP_SIZE (result);
7049
7050   // if(bit | yy)
7051   // xx = bit | yy;
7052   if (AOP_TYPE (left) == AOP_CRY)
7053     {
7054       if (AOP_TYPE (right) == AOP_LIT)
7055         {
7056           // c = bit | literal;
7057           if (lit)
7058             {
7059               // lit != 0 => result = 1
7060               if (AOP_TYPE (result) == AOP_CRY)
7061                 {
7062                   if (size)
7063                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7064                   else if (ifx)
7065                     continueIfTrue (ifx);
7066                   goto release;
7067                 }
7068               emitcode ("setb", "c");
7069             }
7070           else
7071             {
7072               // lit == 0 => result = left
7073               if (size && sameRegs (AOP (result), AOP (left)))
7074                 goto release;
7075               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7076             }
7077         }
7078       else
7079         {
7080           if (AOP_TYPE (right) == AOP_CRY)
7081             {
7082               // c = bit | bit;
7083               if (IS_OP_ACCUSE (left))
7084                 {
7085                   emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
7086                 }
7087               else
7088                 {
7089                   emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7090                   emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7091                 }
7092             }
7093           else
7094             {
7095               // c = bit | val;
7096               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7097                 {
7098                   symbol *tlbl = newiTempLabel (NULL);
7099                   emitcode ("jb", "%s,%05d$",
7100                             AOP (left)->aopu.aop_dir, tlbl->key + 100);
7101                   toBoolean (right);
7102                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7103                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
7104                   goto release;
7105                 }
7106               else
7107                 {
7108                   toCarry (right);
7109                   emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7110                 }
7111             }
7112         }
7113       // bit = c
7114       // val = c
7115       if (size)
7116         outBitC (result);
7117       // if(bit | ...)
7118       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7119         genIfxJump (ifx, "c", left, right, result);
7120       goto release;
7121     }
7122
7123   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7124   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7125   if ((AOP_TYPE (right) == AOP_LIT) &&
7126       (AOP_TYPE (result) == AOP_CRY) &&
7127       (AOP_TYPE (left) != AOP_CRY))
7128     {
7129       if (lit)
7130         {
7131           // result = 1
7132           if (size)
7133             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7134           else
7135             continueIfTrue (ifx);
7136           goto release;
7137         }
7138       else
7139         {
7140           // lit = 0, result = boolean(left)
7141           if (size)
7142             emitcode ("setb", "c");
7143           toBoolean (right);
7144           if (size)
7145             {
7146               symbol *tlbl = newiTempLabel (NULL);
7147               emitcode ("jnz", "%05d$", tlbl->key + 100);
7148               CLRC;
7149               emitLabel (tlbl);
7150             }
7151           else
7152             {
7153               genIfxJump (ifx, "a", left, right, result);
7154               goto release;
7155             }
7156         }
7157       outBitC (result);
7158       goto release;
7159     }
7160
7161   /* if left is same as result */
7162   if (sameRegs (AOP (result), AOP (left)))
7163     {
7164       for (; size--; offset++)
7165         {
7166           if (AOP_TYPE (right) == AOP_LIT)
7167             {
7168               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7169               if (bytelit == 0)
7170                 {
7171                   /* dummy read of volatile operand */
7172                   if (isOperandVolatile (left, FALSE))
7173                     MOVA (aopGet (left, offset, FALSE, FALSE));
7174                   else
7175                     continue;
7176                 }
7177               else if (bytelit == 0x0FF)
7178                 {
7179                   aopPut (result, "#0xff", offset);
7180                 }
7181               else if (IS_AOP_PREG (left))
7182                 {
7183                   MOVA (aopGet (left, offset, FALSE, TRUE));
7184                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7185                   aopPut (result, "a", offset);
7186                 }
7187               else
7188                 {
7189                   emitcode ("orl", "%s,%s",
7190                             aopGet (left, offset, FALSE, TRUE),
7191                             aopGet (right, offset, FALSE, FALSE));
7192                 }
7193             }
7194           else
7195             {
7196               if (AOP_TYPE (left) == AOP_ACC)
7197                 {
7198                   if (offset)
7199                     emitcode("mov", "a,b");
7200                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7201                 }
7202               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7203                 {
7204                   MOVB (aopGet (left, offset, FALSE, FALSE));
7205                   MOVA (aopGet (right, offset, FALSE, FALSE));
7206                   emitcode ("orl", "a,b");
7207                   aopPut (result, "a", offset);
7208                 }
7209               else if (aopGetUsesAcc (left, offset))
7210                 {
7211                   MOVA (aopGet (left, offset, FALSE, FALSE));
7212                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7213                   aopPut (result, "a", offset);
7214                 }
7215               else
7216                 {
7217                   MOVA (aopGet (right, offset, FALSE, FALSE));
7218                   if (IS_AOP_PREG (left))
7219                     {
7220                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7221                       aopPut (result, "a", offset);
7222                     }
7223                   else
7224                     {
7225                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7226                     }
7227                 }
7228             }
7229         }
7230     }
7231   else
7232     {
7233       // left & result in different registers
7234       if (AOP_TYPE (result) == AOP_CRY)
7235         {
7236           // result = bit
7237           // if(size), result in bit
7238           // if(!size && ifx), conditional oper: if(left | right)
7239           symbol *tlbl = newiTempLabel (NULL);
7240           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7241           if (size)
7242             emitcode ("setb", "c");
7243           while (sizer--)
7244             {
7245               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7246                   && AOP_TYPE(left)==AOP_ACC)
7247                 {
7248                   if (offset)
7249                     emitcode("mov", "a,b");
7250                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7251                 }
7252               else if (AOP_TYPE(left)==AOP_ACC)
7253                 {
7254                   if (!offset)
7255                     {
7256                       bool pushedB = pushB ();
7257                       emitcode("mov", "b,a");
7258                       MOVA (aopGet (right, offset, FALSE, FALSE));
7259                       emitcode("orl", "a,b");
7260                       popB (pushedB);
7261                     }
7262                   else
7263                     {
7264                       MOVA (aopGet (right, offset, FALSE, FALSE));
7265                       emitcode("orl", "a,b");
7266                     }
7267                 }
7268               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7269                 {
7270                   MOVB (aopGet (left, offset, FALSE, FALSE));
7271                   MOVA (aopGet (right, offset, FALSE, FALSE));
7272                   emitcode ("orl", "a,b");
7273                 }
7274               else if (aopGetUsesAcc (left, offset))
7275                 {
7276                   MOVA (aopGet (left, offset, FALSE, FALSE));
7277                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7278                 }
7279               else
7280                 {
7281                   MOVA (aopGet (right, offset, FALSE, FALSE));
7282                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7283               }
7284
7285               emitcode ("jnz", "%05d$", tlbl->key + 100);
7286               offset++;
7287             }
7288           if (size)
7289             {
7290               CLRC;
7291               emitLabel (tlbl);
7292               outBitC (result);
7293             }
7294           else if (ifx)
7295             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7296           else
7297             emitLabel (tlbl);
7298         }
7299       else
7300         {
7301           for (; (size--); offset++)
7302             {
7303               // normal case
7304               // result = left | right
7305               if (AOP_TYPE (right) == AOP_LIT)
7306                 {
7307                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7308                   if (bytelit == 0)
7309                     {
7310                       aopPut (result,
7311                               aopGet (left, offset, FALSE, FALSE),
7312                               offset);
7313                       continue;
7314                     }
7315                   else if (bytelit == 0x0FF)
7316                     {
7317                       /* dummy read of volatile operand */
7318                       if (isOperandVolatile (left, FALSE))
7319                         MOVA (aopGet (left, offset, FALSE, FALSE));
7320                       aopPut (result, "#0xff", offset);
7321                       continue;
7322                     }
7323                 }
7324               // faster than result <- left, orl result,right
7325               // and better if result is SFR
7326               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7327                   && AOP_TYPE(left)==AOP_ACC)
7328                 {
7329                   if (offset)
7330                     emitcode("mov", "a,b");
7331                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7332                 }
7333               else if (AOP_TYPE(left)==AOP_ACC)
7334                 {
7335                   if (!offset)
7336                     {
7337                       bool pushedB = pushB ();
7338                       emitcode("mov", "b,a");
7339                       MOVA (aopGet (right, offset, FALSE, FALSE));
7340                       emitcode("orl", "a,b");
7341                       popB (pushedB);
7342                     }
7343                   else
7344                     {
7345                       MOVA (aopGet (right, offset, FALSE, FALSE));
7346                       emitcode("orl", "a,b");
7347                     }
7348                 }
7349               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7350                 {
7351                   MOVB (aopGet (left, offset, FALSE, FALSE));
7352                   MOVA (aopGet (right, offset, FALSE, FALSE));
7353                   emitcode ("orl", "a,b");
7354                 }
7355               else if (aopGetUsesAcc (left, offset))
7356                 {
7357                   MOVA (aopGet (left, offset, FALSE, FALSE));
7358                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7359                 }
7360               else
7361                 {
7362                   MOVA (aopGet (right, offset, FALSE, FALSE));
7363                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7364                 }
7365               aopPut (result, "a", offset);
7366             }
7367         }
7368     }
7369
7370 release:
7371   freeAsmop (result, NULL, ic, TRUE);
7372   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7373   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7374 }
7375
7376 /*-----------------------------------------------------------------*/
7377 /* genXor - code for xclusive or                                   */
7378 /*-----------------------------------------------------------------*/
7379 static void
7380 genXor (iCode * ic, iCode * ifx)
7381 {
7382   operand *left, *right, *result;
7383   int size, offset = 0;
7384   unsigned long lit = 0L;
7385   int bytelit = 0;
7386
7387   D (emitcode (";", "genXor"));
7388
7389   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7390   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7391   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7392
7393 #ifdef DEBUG_TYPE
7394   emitcode (";", "Type res[%d] = l[%d]&r[%d]",
7395             AOP_TYPE (result),
7396             AOP_TYPE (left), AOP_TYPE (right));
7397   emitcode (";", "Size res[%d] = l[%d]&r[%d]",
7398             AOP_SIZE (result),
7399             AOP_SIZE (left), AOP_SIZE (right));
7400 #endif
7401
7402   /* if left is a literal & right is not ||
7403      if left needs acc & right does not */
7404   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7405       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7406     {
7407       operand *tmp = right;
7408       right = left;
7409       left = tmp;
7410     }
7411
7412   /* if result = right then exchange them */
7413   if (sameRegs (AOP (result), AOP (right)))
7414     {
7415       operand *tmp = right;
7416       right = left;
7417       left = tmp;
7418     }
7419
7420   /* if right is bit then exchange them */
7421   if (AOP_TYPE (right) == AOP_CRY &&
7422       AOP_TYPE (left) != AOP_CRY)
7423     {
7424       operand *tmp = right;
7425       right = left;
7426       left = tmp;
7427     }
7428
7429   if (AOP_TYPE (right) == AOP_LIT)
7430     lit = ulFromVal (AOP (right)->aopu.aop_lit);
7431
7432   size = AOP_SIZE (result);
7433
7434   // if(bit ^ yy)
7435   // xx = bit ^ yy;
7436   if (AOP_TYPE (left) == AOP_CRY)
7437     {
7438       if (AOP_TYPE (right) == AOP_LIT)
7439         {
7440           // c = bit & literal;
7441           if (lit >> 1)
7442             {
7443               // lit>>1  != 0 => result = 1
7444               if (AOP_TYPE (result) == AOP_CRY)
7445                 {
7446                   if (size)
7447                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7448                   else if (ifx)
7449                     continueIfTrue (ifx);
7450                   goto release;
7451                 }
7452               emitcode ("setb", "c");
7453             }
7454           else
7455             {
7456               // lit == (0 or 1)
7457               if (lit == 0)
7458                 {
7459                   // lit == 0, result = left
7460                   if (size && sameRegs (AOP (result), AOP (left)))
7461                     goto release;
7462                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7463                 }
7464               else
7465                 {
7466                   // lit == 1, result = not(left)
7467                   if (size && sameRegs (AOP (result), AOP (left)))
7468                     {
7469                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7470                       goto release;
7471                     }
7472                   else
7473                     {
7474                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7475                       emitcode ("cpl", "c");
7476                     }
7477                 }
7478             }
7479         }
7480       else
7481         {
7482           // right != literal
7483           symbol *tlbl = newiTempLabel (NULL);
7484           if (AOP_TYPE (right) == AOP_CRY)
7485             {
7486               // c = bit ^ bit;
7487               if (IS_OP_ACCUSE (left))
7488                 {// left already is in the carry
7489                   operand *tmp = right;
7490                   right = left;
7491                   left = tmp;
7492                 }
7493               else
7494                 {
7495                   toCarry (right);
7496                 }
7497             }
7498           else
7499             {
7500               // c = bit ^ val
7501               toCarry (right);
7502             }
7503           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7504           emitcode ("cpl", "c");
7505           emitLabel (tlbl);
7506         }
7507       // bit = c
7508       // val = c
7509       if (size)
7510         outBitC (result);
7511       // if(bit ^ ...)
7512       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7513         genIfxJump (ifx, "c", left, right, result);
7514       goto release;
7515     }
7516
7517   /* if left is same as result */
7518   if (sameRegs (AOP (result), AOP (left)))
7519     {
7520       for (; size--; offset++)
7521         {
7522           if (AOP_TYPE (right) == AOP_LIT)
7523             {
7524               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7525               if (bytelit == 0)
7526                 {
7527                   /* dummy read of volatile operand */
7528                   if (isOperandVolatile (left, FALSE))
7529                     MOVA (aopGet (left, offset, FALSE, FALSE));
7530                   else
7531                     continue;
7532                 }
7533               else if (IS_AOP_PREG (left))
7534                 {
7535                   MOVA (aopGet (left, offset, FALSE, TRUE));
7536                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7537                   aopPut (result, "a", offset);
7538                 }
7539               else
7540                 {
7541                   emitcode ("xrl", "%s,%s",
7542                             aopGet (left, offset, FALSE, TRUE),
7543                             aopGet (right, offset, FALSE, FALSE));
7544                 }
7545             }
7546           else
7547             {
7548               if (AOP_TYPE (left) == AOP_ACC)
7549                 {
7550                   if (offset)
7551                     emitcode("mov", "a,b");
7552                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7553                 }
7554               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7555                 {
7556                   MOVB (aopGet (left, offset, FALSE, FALSE));
7557                   MOVA (aopGet (right, offset, FALSE, FALSE));
7558                   emitcode ("xrl", "a,b");
7559                   aopPut (result, "a", offset);
7560                 }
7561               else if (aopGetUsesAcc (left, offset))
7562                 {
7563                   MOVA (aopGet (left, offset, FALSE, FALSE));
7564                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7565                   aopPut (result, "a", offset);
7566                 }
7567               else
7568                 {
7569                   MOVA (aopGet (right, offset, FALSE, FALSE));
7570                   if (IS_AOP_PREG (left))
7571                     {
7572                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7573                       aopPut (result, "a", offset);
7574                     }
7575                   else
7576                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7577                 }
7578             }
7579         }
7580     }
7581   else
7582     {
7583       // left & result in different registers
7584       if (AOP_TYPE (result) == AOP_CRY)
7585         {
7586           // result = bit
7587           // if(size), result in bit
7588           // if(!size && ifx), conditional oper: if(left ^ right)
7589           symbol *tlbl = newiTempLabel (NULL);
7590           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7591
7592           if (size)
7593             emitcode ("setb", "c");
7594           while (sizer--)
7595             {
7596               if ((AOP_TYPE (right) == AOP_LIT) &&
7597                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7598                 {
7599                   MOVA (aopGet (left, offset, FALSE, FALSE));
7600                 }
7601               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7602                   && AOP_TYPE(left)==AOP_ACC)
7603                 {
7604                   if (offset)
7605                     emitcode("mov", "a,b");
7606                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7607                 }
7608               else if (AOP_TYPE(left)==AOP_ACC)
7609                 {
7610                   if (!offset)
7611                     {
7612                       bool pushedB = pushB ();
7613                       emitcode("mov", "b,a");
7614                       MOVA (aopGet (right, offset, FALSE, FALSE));
7615                       emitcode("xrl", "a,b");
7616                       popB (pushedB);
7617                     }
7618                   else
7619                     {
7620                       MOVA (aopGet (right, offset, FALSE, FALSE));
7621                       emitcode("xrl", "a,b");
7622                     }
7623                 }
7624               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7625                 {
7626                   MOVB (aopGet (left, offset, FALSE, FALSE));
7627                   MOVA (aopGet (right, offset, FALSE, FALSE));
7628                   emitcode ("xrl", "a,b");
7629                 }
7630               else if (aopGetUsesAcc (left, offset))
7631                 {
7632                   MOVA (aopGet (left, offset, FALSE, FALSE));
7633                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7634                 }
7635               else
7636                 {
7637                   MOVA (aopGet (right, offset, FALSE, FALSE));
7638                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7639                 }
7640
7641               emitcode ("jnz", "%05d$", tlbl->key + 100);
7642               offset++;
7643             }
7644           if (size)
7645             {
7646               CLRC;
7647               emitLabel (tlbl);
7648               outBitC (result);
7649             }
7650           else if (ifx)
7651             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7652         }
7653       else
7654         {
7655           for (; (size--); offset++)
7656             {
7657               // normal case
7658               // result = left ^ right
7659               if (AOP_TYPE (right) == AOP_LIT)
7660                 {
7661                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7662                   if (bytelit == 0)
7663                     {
7664                       aopPut (result,
7665                               aopGet (left, offset, FALSE, FALSE),
7666                               offset);
7667                       continue;
7668                     }
7669                 }
7670               // faster than result <- left, xrl result,right
7671               // and better if result is SFR
7672               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7673                   && AOP_TYPE(left)==AOP_ACC)
7674                 {
7675                   if (offset)
7676                     emitcode("mov", "a,b");
7677                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7678                 }
7679               else if (AOP_TYPE(left)==AOP_ACC)
7680                 {
7681                   if (!offset)
7682                     {
7683                       bool pushedB = pushB ();
7684                       emitcode("mov", "b,a");
7685                       MOVA (aopGet (right, offset, FALSE, FALSE));
7686                       emitcode("xrl", "a,b");
7687                       popB (pushedB);
7688                     }
7689                   else
7690                     {
7691                       MOVA (aopGet (right, offset, FALSE, FALSE));
7692                       emitcode("xrl", "a,b");
7693                     }
7694                 }
7695               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7696                 {
7697                   MOVB (aopGet (left, offset, FALSE, FALSE));
7698                   MOVA (aopGet (right, offset, FALSE, FALSE));
7699                   emitcode ("xrl", "a,b");
7700                 }
7701               else if (aopGetUsesAcc (left, offset))
7702                 {
7703                   MOVA (aopGet (left, offset, FALSE, FALSE));
7704                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7705                 }
7706               else
7707                 {
7708                   MOVA (aopGet (right, offset, FALSE, FALSE));
7709                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7710                 }
7711               aopPut (result, "a", offset);
7712             }
7713         }
7714     }
7715
7716 release:
7717   freeAsmop (result, NULL, ic, TRUE);
7718   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7719   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7720 }
7721
7722 /*-----------------------------------------------------------------*/
7723 /* genInline - write the inline code out                           */
7724 /*-----------------------------------------------------------------*/
7725 static void
7726 genInline (iCode * ic)
7727 {
7728   char *buffer, *bp, *bp1;
7729   bool inComment = FALSE;
7730
7731   D (emitcode (";", "genInline"));
7732
7733   _G.inLine += (!options.asmpeep);
7734
7735   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
7736
7737   /* emit each line as a code */
7738   while (*bp)
7739     {
7740       switch (*bp)
7741         {
7742         case ';':
7743           inComment = TRUE;
7744           ++bp;
7745           break;
7746
7747         case '\n':
7748           inComment = FALSE;
7749           *bp++ = '\0';
7750           emitcode (bp1, "");
7751           bp1 = bp;
7752           break;
7753
7754         default:
7755           /* Add \n for labels, not dirs such as c:\mydir */
7756           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
7757             {
7758               ++bp;
7759               *bp = '\0';
7760               ++bp;
7761               emitcode (bp1, "");
7762               bp1 = bp;
7763             }
7764           else
7765             ++bp;
7766           break;
7767         }
7768     }
7769   if (bp1 != bp)
7770     emitcode (bp1, "");
7771
7772   Safe_free (buffer);
7773
7774   _G.inLine -= (!options.asmpeep);
7775 }
7776
7777 /*-----------------------------------------------------------------*/
7778 /* genRRC - rotate right with carry                                */
7779 /*-----------------------------------------------------------------*/
7780 static void
7781 genRRC (iCode * ic)
7782 {
7783   operand *left, *result;
7784   int size, offset;
7785   char *l;
7786
7787   D (emitcode (";", "genRRC"));
7788
7789   /* rotate right with carry */
7790   left = IC_LEFT (ic);
7791   result = IC_RESULT (ic);
7792   aopOp (left, ic, FALSE);
7793   aopOp (result, ic, FALSE);
7794
7795   /* move it to the result */
7796   size = AOP_SIZE (result);
7797   offset = size - 1;
7798   if (size == 1) { /* special case for 1 byte */
7799       l = aopGet (left, offset, FALSE, FALSE);
7800       MOVA (l);
7801       emitcode ("rr", "a");
7802       goto release;
7803   }
7804   /* no need to clear carry, bit7 will be written later */
7805   while (size--)
7806     {
7807       l = aopGet (left, offset, FALSE, FALSE);
7808       MOVA (l);
7809       emitcode ("rrc", "a");
7810       if (AOP_SIZE (result) > 1)
7811         aopPut (result, "a", offset--);
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, AOP_SIZE (result) - 1, FALSE, FALSE);
7818       MOVA (l);
7819     }
7820   emitcode ("mov", "acc.7,c");
7821  release:
7822   aopPut (result, "a", AOP_SIZE (result) - 1);
7823   freeAsmop (result, NULL, ic, TRUE);
7824   freeAsmop (left, NULL, ic, TRUE);
7825 }
7826
7827 /*-----------------------------------------------------------------*/
7828 /* genRLC - generate code for rotate left with carry               */
7829 /*-----------------------------------------------------------------*/
7830 static void
7831 genRLC (iCode * ic)
7832 {
7833   operand *left, *result;
7834   int size, offset;
7835   char *l;
7836
7837   D (emitcode (";", "genRLC"));
7838
7839   /* rotate right with carry */
7840   left = IC_LEFT (ic);
7841   result = IC_RESULT (ic);
7842   aopOp (left, ic, FALSE);
7843   aopOp (result, ic, FALSE);
7844
7845   /* move it to the result */
7846   size = AOP_SIZE (result);
7847   offset = 0;
7848   if (size--)
7849     {
7850       l = aopGet (left, offset, FALSE, FALSE);
7851       MOVA (l);
7852       if (size == 0) { /* special case for 1 byte */
7853               emitcode("rl","a");
7854               goto release;
7855       }
7856       emitcode("rlc","a"); /* bit0 will be written later */
7857       if (AOP_SIZE (result) > 1)
7858         {
7859           aopPut (result, "a", offset++);
7860         }
7861
7862       while (size--)
7863         {
7864           l = aopGet (left, offset, FALSE, FALSE);
7865           MOVA (l);
7866           emitcode ("rlc", "a");
7867           if (AOP_SIZE (result) > 1)
7868             aopPut (result, "a", offset++);
7869         }
7870     }
7871   /* now we need to put the carry into the
7872      highest order byte of the result */
7873   if (AOP_SIZE (result) > 1)
7874     {
7875       l = aopGet (result, 0, FALSE, FALSE);
7876       MOVA (l);
7877     }
7878   emitcode ("mov", "acc.0,c");
7879  release:
7880   aopPut (result, "a", 0);
7881   freeAsmop (result, NULL, ic, TRUE);
7882   freeAsmop (left, NULL, ic, TRUE);
7883 }
7884
7885 /*-----------------------------------------------------------------*/
7886 /* genGetHbit - generates code get highest order bit               */
7887 /*-----------------------------------------------------------------*/
7888 static void
7889 genGetHbit (iCode * ic)
7890 {
7891   operand *left, *result;
7892
7893   D (emitcode (";", "genGetHbit"));
7894
7895   left = IC_LEFT (ic);
7896   result = IC_RESULT (ic);
7897   aopOp (left, ic, FALSE);
7898   aopOp (result, ic, FALSE);
7899
7900   /* get the highest order byte into a */
7901   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7902   if (AOP_TYPE (result) == AOP_CRY)
7903     {
7904       emitcode ("rlc", "a");
7905       outBitC (result);
7906     }
7907   else
7908     {
7909       emitcode ("rl", "a");
7910       emitcode ("anl", "a,#0x01");
7911       outAcc (result);
7912     }
7913
7914   freeAsmop (result, NULL, ic, TRUE);
7915   freeAsmop (left, NULL, ic, TRUE);
7916 }
7917
7918 /*-----------------------------------------------------------------*/
7919 /* genGetAbit - generates code get a single bit                    */
7920 /*-----------------------------------------------------------------*/
7921 static void
7922 genGetAbit (iCode * ic)
7923 {
7924   operand *left, *right, *result;
7925   int shCount;
7926
7927   D (emitcode (";", "genGetAbit"));
7928
7929   left = IC_LEFT (ic);
7930   right = IC_RIGHT (ic);
7931   result = IC_RESULT (ic);
7932   aopOp (left, ic, FALSE);
7933   aopOp (right, ic, FALSE);
7934   aopOp (result, ic, FALSE);
7935
7936   shCount = (int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7937
7938   /* get the needed byte into a */
7939   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7940   shCount %= 8;
7941   if (AOP_TYPE (result) == AOP_CRY)
7942     {
7943       if ((shCount) == 7)
7944           emitcode ("rlc", "a");
7945       else if ((shCount) == 0)
7946           emitcode ("rrc", "a");
7947       else
7948           emitcode ("mov", "c,acc[%d]", shCount);
7949       outBitC (result);
7950     }
7951   else
7952     {
7953       switch (shCount)
7954         {
7955         case 2:
7956           emitcode ("rr", "a");
7957           //fallthrough
7958         case 1:
7959           emitcode ("rr", "a");
7960           //fallthrough
7961         case 0:
7962           emitcode ("anl", "a,#0x01");
7963           break;
7964         case 3:
7965         case 5:
7966           emitcode ("mov", "c,acc[%d]", shCount);
7967           emitcode ("clr", "a");
7968           emitcode ("rlc", "a");
7969           break;
7970         case 4:
7971           emitcode ("swap", "a");
7972           emitcode ("anl", "a,#0x01");
7973           break;
7974         case 6:
7975           emitcode ("rl", "a");
7976           //fallthrough
7977         case 7:
7978           emitcode ("rl", "a");
7979           emitcode ("anl", "a,#0x01");
7980           break;
7981         }
7982       outAcc (result);
7983     }
7984
7985   freeAsmop (result, NULL, ic, TRUE);
7986   freeAsmop (right, NULL, ic, TRUE);
7987   freeAsmop (left, NULL, ic, TRUE);
7988 }
7989
7990 /*-----------------------------------------------------------------*/
7991 /* genGetByte - generates code get a single byte                   */
7992 /*-----------------------------------------------------------------*/
7993 static void
7994 genGetByte (iCode * ic)
7995 {
7996   operand *left, *right, *result;
7997   int offset;
7998
7999   D (emitcode (";", "genGetByte"));
8000
8001   left = IC_LEFT (ic);
8002   right = IC_RIGHT (ic);
8003   result = IC_RESULT (ic);
8004   aopOp (left, ic, FALSE);
8005   aopOp (right, ic, FALSE);
8006   aopOp (result, ic, FALSE);
8007
8008   offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8009   aopPut (result,
8010           aopGet (left, offset, FALSE, FALSE),
8011           0);
8012
8013   freeAsmop (result, NULL, ic, TRUE);
8014   freeAsmop (right, NULL, ic, TRUE);
8015   freeAsmop (left, NULL, ic, TRUE);
8016 }
8017
8018 /*-----------------------------------------------------------------*/
8019 /* genGetWord - generates code get two bytes                       */
8020 /*-----------------------------------------------------------------*/
8021 static void
8022 genGetWord (iCode * ic)
8023 {
8024   operand *left, *right, *result;
8025   int offset;
8026
8027   D (emitcode (";", "genGetWord"));
8028
8029   left = IC_LEFT (ic);
8030   right = IC_RIGHT (ic);
8031   result = IC_RESULT (ic);
8032   aopOp (left, ic, FALSE);
8033   aopOp (right, ic, FALSE);
8034   aopOp (result, ic, FALSE);
8035
8036   offset = (int) ulFromVal (AOP (right)->aopu.aop_lit) / 8;
8037   aopPut (result,
8038           aopGet (left, offset, FALSE, FALSE),
8039           0);
8040   aopPut (result,
8041           aopGet (left, offset+1, FALSE, FALSE),
8042           1);
8043
8044   freeAsmop (result, NULL, ic, TRUE);
8045   freeAsmop (right, NULL, ic, TRUE);
8046   freeAsmop (left, NULL, ic, TRUE);
8047 }
8048
8049 /*-----------------------------------------------------------------*/
8050 /* genSwap - generates code to swap nibbles or bytes               */
8051 /*-----------------------------------------------------------------*/
8052 static void
8053 genSwap (iCode * ic)
8054 {
8055   operand *left, *result;
8056
8057   D(emitcode (";", "genSwap"));
8058
8059   left = IC_LEFT (ic);
8060   result = IC_RESULT (ic);
8061   aopOp (left, ic, FALSE);
8062   aopOp (result, ic, FALSE);
8063
8064   switch (AOP_SIZE (left))
8065     {
8066     case 1: /* swap nibbles in byte */
8067       MOVA (aopGet (left, 0, FALSE, FALSE));
8068       emitcode ("swap", "a");
8069       aopPut (result, "a", 0);
8070       break;
8071     case 2: /* swap bytes in word */
8072       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8073         {
8074           MOVA (aopGet (left, 0, FALSE, FALSE));
8075           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8076           aopPut (result, "a", 1);
8077         }
8078       else if (operandsEqu (left, result))
8079         {
8080           char * reg = "a";
8081           bool pushedB = FALSE, leftInB = FALSE;
8082
8083           MOVA (aopGet (left, 0, FALSE, FALSE));
8084           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8085             {
8086               pushedB = pushB ();
8087               emitcode ("mov", "b,a");
8088               reg = "b";
8089               leftInB = TRUE;
8090             }
8091           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8092           aopPut (result, reg, 1);
8093
8094           if (leftInB)
8095             popB (pushedB);
8096         }
8097       else
8098         {
8099           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8100           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8101         }
8102       break;
8103     default:
8104       wassertl(FALSE, "unsupported SWAP operand size");
8105     }
8106
8107   freeAsmop (result, NULL, ic, TRUE);
8108   freeAsmop (left, NULL, ic, TRUE);
8109 }
8110
8111 /*-----------------------------------------------------------------*/
8112 /* AccRol - rotate left accumulator by known count                 */
8113 /*-----------------------------------------------------------------*/
8114 static void
8115 AccRol (int shCount)
8116 {
8117   shCount &= 0x0007;            // shCount : 0..7
8118
8119   switch (shCount)
8120     {
8121     case 0:
8122       break;
8123     case 1:
8124       emitcode ("rl", "a");
8125       break;
8126     case 2:
8127       emitcode ("rl", "a");
8128       emitcode ("rl", "a");
8129       break;
8130     case 3:
8131       emitcode ("swap", "a");
8132       emitcode ("rr", "a");
8133       break;
8134     case 4:
8135       emitcode ("swap", "a");
8136       break;
8137     case 5:
8138       emitcode ("swap", "a");
8139       emitcode ("rl", "a");
8140       break;
8141     case 6:
8142       emitcode ("rr", "a");
8143       emitcode ("rr", "a");
8144       break;
8145     case 7:
8146       emitcode ("rr", "a");
8147       break;
8148     }
8149 }
8150
8151 /*-----------------------------------------------------------------*/
8152 /* AccLsh - left shift accumulator by known count                  */
8153 /*-----------------------------------------------------------------*/
8154 static void
8155 AccLsh (int shCount)
8156 {
8157   if (shCount != 0)
8158     {
8159       if (shCount == 1)
8160         emitcode ("add", "a,acc");
8161       else if (shCount == 2)
8162         {
8163           emitcode ("add", "a,acc");
8164           emitcode ("add", "a,acc");
8165         }
8166       else
8167         {
8168           /* rotate left accumulator */
8169           AccRol (shCount);
8170           /* and kill the lower order bits */
8171           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8172         }
8173     }
8174 }
8175
8176 /*-----------------------------------------------------------------*/
8177 /* AccRsh - right shift accumulator by known count                 */
8178 /*-----------------------------------------------------------------*/
8179 static void
8180 AccRsh (int shCount)
8181 {
8182   if (shCount != 0)
8183     {
8184       if (shCount == 1)
8185         {
8186           CLRC;
8187           emitcode ("rrc", "a");
8188         }
8189       else
8190         {
8191           /* rotate right accumulator */
8192           AccRol (8 - shCount);
8193           /* and kill the higher order bits */
8194           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8195         }
8196     }
8197 }
8198
8199 /*-----------------------------------------------------------------*/
8200 /* AccSRsh - signed right shift accumulator by known count                 */
8201 /*-----------------------------------------------------------------*/
8202 static void
8203 AccSRsh (int shCount)
8204 {
8205   symbol *tlbl;
8206   if (shCount != 0)
8207     {
8208       if (shCount == 1)
8209         {
8210           emitcode ("mov", "c,acc.7");
8211           emitcode ("rrc", "a");
8212         }
8213       else if (shCount == 2)
8214         {
8215           emitcode ("mov", "c,acc.7");
8216           emitcode ("rrc", "a");
8217           emitcode ("mov", "c,acc.7");
8218           emitcode ("rrc", "a");
8219         }
8220       else
8221         {
8222           tlbl = newiTempLabel (NULL);
8223           /* rotate right accumulator */
8224           AccRol (8 - shCount);
8225           /* and kill the higher order bits */
8226           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8227           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8228           emitcode ("orl", "a,#0x%02x",
8229                     (unsigned char) ~SRMask[shCount]);
8230           emitLabel (tlbl);
8231         }
8232     }
8233 }
8234
8235 /*-----------------------------------------------------------------*/
8236 /* shiftR1Left2Result - shift right one byte from left to result   */
8237 /*-----------------------------------------------------------------*/
8238 static void
8239 shiftR1Left2Result (operand * left, int offl,
8240                     operand * result, int offr,
8241                     int shCount, int sign)
8242 {
8243   MOVA (aopGet (left, offl, FALSE, FALSE));
8244   /* shift right accumulator */
8245   if (sign)
8246     AccSRsh (shCount);
8247   else
8248     AccRsh (shCount);
8249   aopPut (result, "a", offr);
8250 }
8251
8252 /*-----------------------------------------------------------------*/
8253 /* shiftL1Left2Result - shift left one byte from left to result    */
8254 /*-----------------------------------------------------------------*/
8255 static void
8256 shiftL1Left2Result (operand * left, int offl,
8257                     operand * result, int offr, int shCount)
8258 {
8259   char *l;
8260   l = aopGet (left, offl, FALSE, FALSE);
8261   MOVA (l);
8262   /* shift left accumulator */
8263   AccLsh (shCount);
8264   aopPut (result, "a", offr);
8265 }
8266
8267 /*-----------------------------------------------------------------*/
8268 /* movLeft2Result - move byte from left to result                  */
8269 /*-----------------------------------------------------------------*/
8270 static void
8271 movLeft2Result (operand * left, int offl,
8272                 operand * result, int offr, int sign)
8273 {
8274   char *l;
8275   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8276     {
8277       l = aopGet (left, offl, FALSE, FALSE);
8278
8279       if (*l == '@' && (IS_AOP_PREG (result)))
8280         {
8281           emitcode ("mov", "a,%s", l);
8282           aopPut (result, "a", offr);
8283         }
8284       else
8285         {
8286           if (!sign)
8287             {
8288               aopPut (result, l, offr);
8289             }
8290           else
8291             {
8292               /* MSB sign in acc.7 ! */
8293               if (getDataSize (left) == offl + 1)
8294                 {
8295                   MOVA (l);
8296                   aopPut (result, "a", offr);
8297                 }
8298             }
8299         }
8300     }
8301 }
8302
8303 /*-----------------------------------------------------------------*/
8304 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8305 /*-----------------------------------------------------------------*/
8306 static void
8307 AccAXRrl1 (char *x)
8308 {
8309   emitcode ("rrc", "a");
8310   emitcode ("xch", "a,%s", x);
8311   emitcode ("rrc", "a");
8312   emitcode ("xch", "a,%s", x);
8313 }
8314
8315 /*-----------------------------------------------------------------*/
8316 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8317 /*-----------------------------------------------------------------*/
8318 static void
8319 AccAXLrl1 (char *x)
8320 {
8321   emitcode ("xch", "a,%s", x);
8322   emitcode ("rlc", "a");
8323   emitcode ("xch", "a,%s", x);
8324   emitcode ("rlc", "a");
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8329 /*-----------------------------------------------------------------*/
8330 static void
8331 AccAXLsh1 (char *x)
8332 {
8333   emitcode ("xch", "a,%s", x);
8334   emitcode ("add", "a,acc");
8335   emitcode ("xch", "a,%s", x);
8336   emitcode ("rlc", "a");
8337 }
8338
8339 /*-----------------------------------------------------------------*/
8340 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8341 /*-----------------------------------------------------------------*/
8342 static void
8343 AccAXLsh (char *x, int shCount)
8344 {
8345   switch (shCount)
8346     {
8347     case 0:
8348       break;
8349     case 1:
8350       AccAXLsh1 (x);
8351       break;
8352     case 2:
8353       AccAXLsh1 (x);
8354       AccAXLsh1 (x);
8355       break;
8356     case 3:
8357     case 4:
8358     case 5:                     // AAAAABBB:CCCCCDDD
8359
8360       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8361
8362       emitcode ("anl", "a,#0x%02x",
8363                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8364
8365       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8366
8367       AccRol (shCount);         // DDDCCCCC:BBB00000
8368
8369       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8370
8371       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8372
8373       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8374
8375       emitcode ("anl", "a,#0x%02x",
8376                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8377
8378       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8379
8380       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8381
8382       break;
8383     case 6:                     // AAAAAABB:CCCCCCDD
8384       emitcode ("anl", "a,#0x%02x",
8385                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8386       emitcode ("mov", "c,acc.0");      // c = B
8387       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8388 #if 0 // REMOVE ME
8389       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8390       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8391 #else
8392       emitcode("rrc","a");
8393       emitcode("xch","a,%s", x);
8394       emitcode("rrc","a");
8395       emitcode("mov","c,acc.0"); //<< get correct bit
8396       emitcode("xch","a,%s", x);
8397
8398       emitcode("rrc","a");
8399       emitcode("xch","a,%s", x);
8400       emitcode("rrc","a");
8401       emitcode("xch","a,%s", x);
8402 #endif
8403       break;
8404     case 7:                     // a:x <<= 7
8405
8406       emitcode ("anl", "a,#0x%02x",
8407                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8408
8409       emitcode ("mov", "c,acc.0");      // c = B
8410
8411       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8412
8413       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8414
8415       break;
8416     default:
8417       break;
8418     }
8419 }
8420
8421 /*-----------------------------------------------------------------*/
8422 /* AccAXRsh - right shift a:x known count (0..7)                   */
8423 /*-----------------------------------------------------------------*/
8424 static void
8425 AccAXRsh (char *x, int shCount)
8426 {
8427   switch (shCount)
8428     {
8429     case 0:
8430       break;
8431     case 1:
8432       CLRC;
8433       AccAXRrl1 (x);            // 0->a:x
8434
8435       break;
8436     case 2:
8437       CLRC;
8438       AccAXRrl1 (x);            // 0->a:x
8439
8440       CLRC;
8441       AccAXRrl1 (x);            // 0->a:x
8442
8443       break;
8444     case 3:
8445     case 4:
8446     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8447
8448       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8449
8450       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8451
8452       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8453
8454       emitcode ("anl", "a,#0x%02x",
8455                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8456
8457       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8458
8459       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8460
8461       emitcode ("anl", "a,#0x%02x",
8462                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8463
8464       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8465
8466       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8467
8468       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8469
8470       break;
8471     case 6:                     // AABBBBBB:CCDDDDDD
8472
8473       emitcode ("mov", "c,acc.7");
8474       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8475
8476       emitcode ("mov", "c,acc.7");
8477       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8478
8479       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8480
8481       emitcode ("anl", "a,#0x%02x",
8482                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8483
8484       break;
8485     case 7:                     // ABBBBBBB:CDDDDDDD
8486
8487       emitcode ("mov", "c,acc.7");      // c = A
8488
8489       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8490
8491       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8492
8493       emitcode ("anl", "a,#0x%02x",
8494                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8495
8496       break;
8497     default:
8498       break;
8499     }
8500 }
8501
8502 /*-----------------------------------------------------------------*/
8503 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8504 /*-----------------------------------------------------------------*/
8505 static void
8506 AccAXRshS (char *x, int shCount)
8507 {
8508   symbol *tlbl;
8509   switch (shCount)
8510     {
8511     case 0:
8512       break;
8513     case 1:
8514       emitcode ("mov", "c,acc.7");
8515       AccAXRrl1 (x);            // s->a:x
8516
8517       break;
8518     case 2:
8519       emitcode ("mov", "c,acc.7");
8520       AccAXRrl1 (x);            // s->a:x
8521
8522       emitcode ("mov", "c,acc.7");
8523       AccAXRrl1 (x);            // s->a:x
8524
8525       break;
8526     case 3:
8527     case 4:
8528     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8529
8530       tlbl = newiTempLabel (NULL);
8531       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8532
8533       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8534
8535       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8536
8537       emitcode ("anl", "a,#0x%02x",
8538                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8539
8540       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8541
8542       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8543
8544       emitcode ("anl", "a,#0x%02x",
8545                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8546
8547       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8548
8549       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8550
8551       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8552
8553       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8554       emitcode ("orl", "a,#0x%02x",
8555                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8556
8557       emitLabel (tlbl);
8558       break;                    // SSSSAAAA:BBBCCCCC
8559
8560     case 6:                     // AABBBBBB:CCDDDDDD
8561
8562       tlbl = newiTempLabel (NULL);
8563       emitcode ("mov", "c,acc.7");
8564       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8565
8566       emitcode ("mov", "c,acc.7");
8567       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8568
8569       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8570
8571       emitcode ("anl", "a,#0x%02x",
8572                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8573
8574       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8575       emitcode ("orl", "a,#0x%02x",
8576                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8577
8578       emitLabel (tlbl);
8579       break;
8580     case 7:                     // ABBBBBBB:CDDDDDDD
8581
8582       tlbl = newiTempLabel (NULL);
8583       emitcode ("mov", "c,acc.7");      // c = A
8584
8585       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8586
8587       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8588
8589       emitcode ("anl", "a,#0x%02x",
8590                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8591
8592       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8593       emitcode ("orl", "a,#0x%02x",
8594                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8595
8596       emitLabel (tlbl);
8597       break;
8598     default:
8599       break;
8600     }
8601 }
8602
8603 /*-----------------------------------------------------------------*/
8604 /* shiftL2Left2Result - shift left two bytes from left to result   */
8605 /*-----------------------------------------------------------------*/
8606 static void
8607 shiftL2Left2Result (operand * left, int offl,
8608                     operand * result, int offr, int shCount)
8609 {
8610   char * x;
8611   bool pushedB = FALSE;
8612   bool usedB = FALSE;
8613
8614   if (sameRegs (AOP (result), AOP (left)) &&
8615       ((offl + MSB16) == offr))
8616     {
8617       /* don't crash result[offr] */
8618       MOVA (aopGet (left, offl, FALSE, FALSE));
8619       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8620       usedB = !strncmp(x, "b", 1);
8621     }
8622   else if (aopGetUsesAcc (result, offr))
8623     {
8624       movLeft2Result (left, offl, result, offr, 0);
8625       pushedB = pushB ();
8626       usedB = TRUE;
8627       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8628       MOVA (aopGet (result, offr, FALSE, FALSE));
8629       emitcode ("xch", "a,b");
8630       x = "b";
8631     }
8632   else
8633     {
8634       movLeft2Result (left, offl, result, offr, 0);
8635       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8636       x = aopGet (result, offr, FALSE, FALSE);
8637     }
8638   /* ax << shCount (x = lsb(result)) */
8639   AccAXLsh (x, shCount);
8640   if (usedB)
8641     {
8642       emitcode ("xch", "a,b");
8643       aopPut (result, "a", offr);
8644       aopPut (result, "b", offr + MSB16);
8645       popB (pushedB);
8646     }
8647   else
8648     {
8649       aopPut (result, "a", offr + MSB16);
8650     }
8651 }
8652
8653
8654 /*-----------------------------------------------------------------*/
8655 /* shiftR2Left2Result - shift right two bytes from left to result  */
8656 /*-----------------------------------------------------------------*/
8657 static void
8658 shiftR2Left2Result (operand * left, int offl,
8659                     operand * result, int offr,
8660                     int shCount, int sign)
8661 {
8662   char * x;
8663   bool pushedB = FALSE;
8664   bool usedB = FALSE;
8665
8666   if (sameRegs (AOP (result), AOP (left)) &&
8667       ((offl + MSB16) == offr))
8668     {
8669       /* don't crash result[offr] */
8670       MOVA (aopGet (left, offl, FALSE, FALSE));
8671       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8672       usedB = !strncmp(x, "b", 1);
8673     }
8674   else if (aopGetUsesAcc (result, offr))
8675     {
8676       movLeft2Result (left, offl, result, offr, 0);
8677       pushedB = pushB ();
8678       usedB = TRUE;
8679       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8680       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8681       x = "b";
8682     }
8683   else
8684     {
8685       movLeft2Result (left, offl, result, offr, 0);
8686       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8687       x = aopGet (result, offr, FALSE, FALSE);
8688     }
8689   /* a:x >> shCount (x = lsb(result)) */
8690   if (sign)
8691     AccAXRshS (x, shCount);
8692   else
8693     AccAXRsh (x, shCount);
8694   if (usedB)
8695     {
8696       emitcode ("xch", "a,b");
8697       aopPut (result, "a", offr);
8698       emitcode ("xch", "a,b");
8699       popB (pushedB);
8700     }
8701   if (getDataSize (result) > 1)
8702     aopPut (result, "a", offr + MSB16);
8703 }
8704
8705 /*-----------------------------------------------------------------*/
8706 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8707 /*-----------------------------------------------------------------*/
8708 static void
8709 shiftLLeftOrResult (operand * left, int offl,
8710                     operand * result, int offr, int shCount)
8711 {
8712   MOVA (aopGet (left, offl, FALSE, FALSE));
8713   /* shift left accumulator */
8714   AccLsh (shCount);
8715   /* or with result */
8716   if (aopGetUsesAcc (result, offr))
8717     {
8718       emitcode ("xch", "a,b");
8719       MOVA (aopGet (result, offr, FALSE, FALSE));
8720       emitcode ("orl", "a,b");
8721     }
8722   else
8723     {
8724       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8725     }
8726   /* back to result */
8727   aopPut (result, "a", offr);
8728 }
8729
8730 /*-----------------------------------------------------------------*/
8731 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8732 /*-----------------------------------------------------------------*/
8733 static void
8734 shiftRLeftOrResult (operand * left, int offl,
8735                     operand * result, int offr, int shCount)
8736 {
8737   MOVA (aopGet (left, offl, FALSE, FALSE));
8738   /* shift right accumulator */
8739   AccRsh (shCount);
8740   /* or with result */
8741   if (aopGetUsesAcc(result, offr))
8742     {
8743       emitcode ("xch", "a,b");
8744       MOVA (aopGet (result, offr, FALSE, FALSE));
8745       emitcode ("orl", "a,b");
8746     }
8747   else
8748     {
8749       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8750     }
8751   /* back to result */
8752   aopPut (result, "a", offr);
8753 }
8754
8755 /*-----------------------------------------------------------------*/
8756 /* genlshOne - left shift a one byte quantity by known count       */
8757 /*-----------------------------------------------------------------*/
8758 static void
8759 genlshOne (operand * result, operand * left, int shCount)
8760 {
8761   D (emitcode (";", "genlshOne"));
8762
8763   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8764 }
8765
8766 /*-----------------------------------------------------------------*/
8767 /* genlshTwo - left shift two bytes by known amount != 0           */
8768 /*-----------------------------------------------------------------*/
8769 static void
8770 genlshTwo (operand * result, operand * left, int shCount)
8771 {
8772   int size;
8773
8774   D (emitcode (";", "genlshTwo"));
8775
8776   size = getDataSize (result);
8777
8778   /* if shCount >= 8 */
8779   if (shCount >= 8)
8780     {
8781       shCount -= 8;
8782
8783       if (size > 1)
8784         {
8785           if (shCount)
8786             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8787           else
8788             movLeft2Result (left, LSB, result, MSB16, 0);
8789         }
8790       aopPut (result, zero, LSB);
8791     }
8792
8793   /*  1 <= shCount <= 7 */
8794   else
8795     {
8796       if (size == 1)
8797         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8798       else
8799         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8800     }
8801 }
8802
8803 /*-----------------------------------------------------------------*/
8804 /* shiftLLong - shift left one long from left to result            */
8805 /* offl = LSB or MSB16                                             */
8806 /*-----------------------------------------------------------------*/
8807 static void
8808 shiftLLong (operand * left, operand * result, int offr)
8809 {
8810   char *l;
8811   int size = AOP_SIZE (result);
8812
8813   if (size >= LSB + offr)
8814     {
8815       l = aopGet (left, LSB, FALSE, FALSE);
8816       MOVA (l);
8817       emitcode ("add", "a,acc");
8818       if (sameRegs (AOP (left), AOP (result)) &&
8819           size >= MSB16 + offr && offr != LSB)
8820         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8821       else
8822         aopPut (result, "a", LSB + offr);
8823     }
8824
8825   if (size >= MSB16 + offr)
8826     {
8827       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8828         {
8829           l = aopGet (left, MSB16, FALSE, FALSE);
8830           MOVA (l);
8831         }
8832       emitcode ("rlc", "a");
8833       if (sameRegs (AOP (left), AOP (result)) &&
8834           size >= MSB24 + offr && offr != LSB)
8835         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8836       else
8837         aopPut (result, "a", MSB16 + offr);
8838     }
8839
8840   if (size >= MSB24 + offr)
8841     {
8842       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8843         {
8844           l = aopGet (left, MSB24, FALSE, FALSE);
8845           MOVA (l);
8846         }
8847       emitcode ("rlc", "a");
8848       if (sameRegs (AOP (left), AOP (result)) &&
8849           size >= MSB32 + offr && offr != LSB)
8850         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8851       else
8852         aopPut (result, "a", MSB24 + offr);
8853     }
8854
8855   if (size > MSB32 + offr)
8856     {
8857       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8858         {
8859           l = aopGet (left, MSB32, FALSE, FALSE);
8860           MOVA (l);
8861         }
8862       emitcode ("rlc", "a");
8863       aopPut (result, "a", MSB32 + offr);
8864     }
8865   if (offr != LSB)
8866     aopPut (result, zero, LSB);
8867 }
8868
8869 /*-----------------------------------------------------------------*/
8870 /* genlshFour - shift four byte by a known amount != 0             */
8871 /*-----------------------------------------------------------------*/
8872 static void
8873 genlshFour (operand * result, operand * left, int shCount)
8874 {
8875   int size;
8876
8877   D (emitcode (";", "genlshFour"));
8878
8879   size = AOP_SIZE (result);
8880
8881   /* if shifting more that 3 bytes */
8882   if (shCount >= 24)
8883     {
8884       shCount -= 24;
8885       if (shCount)
8886         /* lowest order of left goes to the highest
8887            order of the destination */
8888         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8889       else
8890         movLeft2Result (left, LSB, result, MSB32, 0);
8891       aopPut (result, zero, LSB);
8892       aopPut (result, zero, MSB16);
8893       aopPut (result, zero, MSB24);
8894       return;
8895     }
8896
8897   /* more than two bytes */
8898   else if (shCount >= 16)
8899     {
8900       /* lower order two bytes goes to higher order two bytes */
8901       shCount -= 16;
8902       /* if some more remaining */
8903       if (shCount)
8904         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8905       else
8906         {
8907           movLeft2Result (left, MSB16, result, MSB32, 0);
8908           movLeft2Result (left, LSB, result, MSB24, 0);
8909         }
8910       aopPut (result, zero, MSB16);
8911       aopPut (result, zero, LSB);
8912       return;
8913     }
8914
8915   /* if more than 1 byte */
8916   else if (shCount >= 8)
8917     {
8918       /* lower order three bytes goes to higher order  three bytes */
8919       shCount -= 8;
8920       if (size == 2)
8921         {
8922           if (shCount)
8923             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8924           else
8925             movLeft2Result (left, LSB, result, MSB16, 0);
8926         }
8927       else
8928         {                       /* size = 4 */
8929           if (shCount == 0)
8930             {
8931               movLeft2Result (left, MSB24, result, MSB32, 0);
8932               movLeft2Result (left, MSB16, result, MSB24, 0);
8933               movLeft2Result (left, LSB, result, MSB16, 0);
8934               aopPut (result, zero, LSB);
8935             }
8936           else if (shCount == 1)
8937             shiftLLong (left, result, MSB16);
8938           else
8939             {
8940               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8941               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8942               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8943               aopPut (result, zero, LSB);
8944             }
8945         }
8946     }
8947
8948   /* 1 <= shCount <= 7 */
8949   else if (shCount <= 2)
8950     {
8951       shiftLLong (left, result, LSB);
8952       if (shCount == 2)
8953         shiftLLong (result, result, LSB);
8954     }
8955   /* 3 <= shCount <= 7, optimize */
8956   else
8957     {
8958       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8959       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8960       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8961     }
8962 }
8963
8964 /*-----------------------------------------------------------------*/
8965 /* genLeftShiftLiteral - left shifting by known count              */
8966 /*-----------------------------------------------------------------*/
8967 static void
8968 genLeftShiftLiteral (operand * left,
8969                      operand * right,
8970                      operand * result,
8971                      iCode * ic)
8972 {
8973   int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
8974   int size;
8975
8976   D (emitcode (";", "genLeftShiftLiteral"));
8977
8978   freeAsmop (right, NULL, ic, TRUE);
8979
8980   aopOp (left, ic, FALSE);
8981   aopOp (result, ic, FALSE);
8982
8983   size = getSize (operandType (result));
8984
8985 #if VIEW_SIZE
8986   emitcode ("; shift left ", "result %d, left %d", size,
8987             AOP_SIZE (left));
8988 #endif
8989
8990   /* I suppose that the left size >= result size */
8991   if (shCount == 0)
8992     {
8993       while (size--)
8994         {
8995           movLeft2Result (left, size, result, size, 0);
8996         }
8997     }
8998   else if (shCount >= (size * 8))
8999     {
9000       while (size--)
9001         {
9002           aopPut (result, zero, size);
9003         }
9004     }
9005   else
9006     {
9007       switch (size)
9008         {
9009         case 1:
9010           genlshOne (result, left, shCount);
9011           break;
9012
9013         case 2:
9014           genlshTwo (result, left, shCount);
9015           break;
9016
9017         case 4:
9018           genlshFour (result, left, shCount);
9019           break;
9020         default:
9021           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9022                   "*** ack! mystery literal shift!\n");
9023           break;
9024         }
9025     }
9026   freeAsmop (result, NULL, ic, TRUE);
9027   freeAsmop (left, NULL, ic, TRUE);
9028 }
9029
9030 /*-----------------------------------------------------------------*/
9031 /* genLeftShift - generates code for left shifting                 */
9032 /*-----------------------------------------------------------------*/
9033 static void
9034 genLeftShift (iCode * ic)
9035 {
9036   operand *left, *right, *result;
9037   int size, offset;
9038   char *l;
9039   symbol *tlbl, *tlbl1;
9040   bool pushedB;
9041
9042   D (emitcode (";", "genLeftShift"));
9043
9044   right = IC_RIGHT (ic);
9045   left = IC_LEFT (ic);
9046   result = IC_RESULT (ic);
9047
9048   aopOp (right, ic, FALSE);
9049
9050   /* if the shift count is known then do it
9051      as efficiently as possible */
9052   if (AOP_TYPE (right) == AOP_LIT)
9053     {
9054       genLeftShiftLiteral (left, right, result, ic);
9055       return;
9056     }
9057
9058   /* shift count is unknown then we have to form
9059      a loop get the loop count in B : Note: we take
9060      only the lower order byte since shifting
9061      more that 32 bits make no sense anyway, ( the
9062      largest size of an object can be only 32 bits ) */
9063
9064   pushedB = pushB ();
9065   MOVB (aopGet (right, 0, FALSE, FALSE));
9066   emitcode ("inc", "b");
9067   freeAsmop (right, NULL, ic, TRUE);
9068   aopOp (left, ic, FALSE);
9069   aopOp (result, ic, FALSE);
9070
9071   /* now move the left to the result if they are not the same */
9072   if (!sameRegs (AOP (left), AOP (result)) &&
9073       AOP_SIZE (result) > 1)
9074     {
9075
9076       size = AOP_SIZE (result);
9077       offset = 0;
9078       while (size--)
9079         {
9080           l = aopGet (left, offset, FALSE, TRUE);
9081           if (*l == '@' && (IS_AOP_PREG (result)))
9082             {
9083
9084               emitcode ("mov", "a,%s", l);
9085               aopPut (result, "a", offset);
9086             }
9087           else
9088             aopPut (result, l, offset);
9089           offset++;
9090         }
9091     }
9092
9093   tlbl = newiTempLabel (NULL);
9094   size = AOP_SIZE (result);
9095   offset = 0;
9096   tlbl1 = newiTempLabel (NULL);
9097
9098   /* if it is only one byte then */
9099   if (size == 1)
9100     {
9101       symbol *tlbl1 = newiTempLabel (NULL);
9102
9103       l = aopGet (left, 0, FALSE, FALSE);
9104       MOVA (l);
9105       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9106       emitLabel (tlbl);
9107       emitcode ("add", "a,acc");
9108       emitLabel (tlbl1);
9109       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9110       popB (pushedB);
9111       aopPut (result, "a", 0);
9112       goto release;
9113     }
9114
9115   reAdjustPreg (AOP (result));
9116
9117   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9118   emitLabel (tlbl);
9119   l = aopGet (result, offset, FALSE, FALSE);
9120   MOVA (l);
9121   emitcode ("add", "a,acc");
9122   aopPut (result, "a", offset++);
9123   while (--size)
9124     {
9125       l = aopGet (result, offset, FALSE, FALSE);
9126       MOVA (l);
9127       emitcode ("rlc", "a");
9128       aopPut (result, "a", offset++);
9129     }
9130   reAdjustPreg (AOP (result));
9131
9132   emitLabel (tlbl1);
9133   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9134   popB (pushedB);
9135 release:
9136   freeAsmop (result, NULL, ic, TRUE);
9137   freeAsmop (left, NULL, ic, TRUE);
9138 }
9139
9140 /*-----------------------------------------------------------------*/
9141 /* genrshOne - right shift a one byte quantity by known count      */
9142 /*-----------------------------------------------------------------*/
9143 static void
9144 genrshOne (operand * result, operand * left,
9145            int shCount, int sign)
9146 {
9147   D (emitcode (";", "genrshOne"));
9148
9149   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* genrshTwo - right shift two bytes by known amount != 0          */
9154 /*-----------------------------------------------------------------*/
9155 static void
9156 genrshTwo (operand * result, operand * left,
9157            int shCount, int sign)
9158 {
9159   D (emitcode (";", "genrshTwo"));
9160
9161   /* if shCount >= 8 */
9162   if (shCount >= 8)
9163     {
9164       shCount -= 8;
9165       if (shCount)
9166         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9167       else
9168         movLeft2Result (left, MSB16, result, LSB, sign);
9169       addSign (result, MSB16, sign);
9170     }
9171
9172   /*  1 <= shCount <= 7 */
9173   else
9174     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9175 }
9176
9177 /*-----------------------------------------------------------------*/
9178 /* shiftRLong - shift right one long from left to result           */
9179 /* offl = LSB or MSB16                                             */
9180 /*-----------------------------------------------------------------*/
9181 static void
9182 shiftRLong (operand * left, int offl,
9183             operand * result, int sign)
9184 {
9185   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9186
9187   if (overlapping && offl>1)
9188     {
9189       // we are in big trouble, but this shouldn't happen
9190       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9191     }
9192
9193   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9194
9195   if (offl==MSB16)
9196     {
9197       // shift is > 8
9198       if (sign)
9199         {
9200           emitcode ("rlc", "a");
9201           emitcode ("subb", "a,acc");
9202           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9203             {
9204               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9205             }
9206           else
9207             {
9208               aopPut (result, "a", MSB32);
9209               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9210             }
9211         }
9212       else
9213         {
9214           if (aopPutUsesAcc (result, zero, MSB32))
9215             {
9216               emitcode("xch", "a,b");
9217               aopPut (result, zero, MSB32);
9218               emitcode("xch", "a,b");
9219             }
9220           else
9221             {
9222               aopPut (result, zero, MSB32);
9223             }
9224         }
9225     }
9226
9227   if (!sign)
9228     {
9229       emitcode ("clr", "c");
9230     }
9231   else
9232     {
9233       emitcode ("mov", "c,acc.7");
9234     }
9235
9236   emitcode ("rrc", "a");
9237
9238   if (overlapping && offl==MSB16 &&
9239       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9240     {
9241       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9242     }
9243   else
9244     {
9245       aopPut (result, "a", MSB32 - offl);
9246       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9247     }
9248
9249   emitcode ("rrc", "a");
9250   if (overlapping && offl==MSB16 &&
9251       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9252     {
9253       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9254     }
9255   else
9256     {
9257       aopPut (result, "a", MSB24 - offl);
9258       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9259     }
9260
9261   emitcode ("rrc", "a");
9262   if (offl != LSB)
9263     {
9264       aopPut (result, "a", MSB16 - offl);
9265     }
9266   else
9267     {
9268       if (overlapping &&
9269           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9270         {
9271           xch_a_aopGet (left, LSB, FALSE, FALSE);
9272         }
9273       else
9274         {
9275           aopPut (result, "a", MSB16 - offl);
9276           MOVA (aopGet (left, LSB, FALSE, FALSE));
9277         }
9278       emitcode ("rrc", "a");
9279       aopPut (result, "a", LSB);
9280     }
9281 }
9282
9283 /*-----------------------------------------------------------------*/
9284 /* genrshFour - shift four byte by a known amount != 0             */
9285 /*-----------------------------------------------------------------*/
9286 static void
9287 genrshFour (operand * result, operand * left,
9288             int shCount, int sign)
9289 {
9290   D (emitcode (";", "genrshFour"));
9291
9292   /* if shifting more that 3 bytes */
9293   if (shCount >= 24)
9294     {
9295       shCount -= 24;
9296       if (shCount)
9297         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9298       else
9299         movLeft2Result (left, MSB32, result, LSB, sign);
9300       addSign (result, MSB16, sign);
9301     }
9302   else if (shCount >= 16)
9303     {
9304       shCount -= 16;
9305       if (shCount)
9306         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9307       else
9308         {
9309           movLeft2Result (left, MSB24, result, LSB, 0);
9310           movLeft2Result (left, MSB32, result, MSB16, sign);
9311         }
9312       addSign (result, MSB24, sign);
9313     }
9314   else if (shCount >= 8)
9315     {
9316       shCount -= 8;
9317       if (shCount == 1)
9318         {
9319           shiftRLong (left, MSB16, result, sign);
9320         }
9321       else if (shCount == 0)
9322         {
9323           movLeft2Result (left, MSB16, result, LSB, 0);
9324           movLeft2Result (left, MSB24, result, MSB16, 0);
9325           movLeft2Result (left, MSB32, result, MSB24, sign);
9326           addSign (result, MSB32, sign);
9327         }
9328       else
9329         {
9330           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9331           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9332           /* the last shift is signed */
9333           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9334           addSign (result, MSB32, sign);
9335         }
9336     }
9337   else
9338     {
9339       /* 1 <= shCount <= 7 */
9340       if (shCount <= 2)
9341         {
9342           shiftRLong (left, LSB, result, sign);
9343           if (shCount == 2)
9344             shiftRLong (result, LSB, result, sign);
9345         }
9346       else
9347         {
9348           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9349           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9350           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9351         }
9352     }
9353 }
9354
9355 /*-----------------------------------------------------------------*/
9356 /* genRightShiftLiteral - right shifting by known count            */
9357 /*-----------------------------------------------------------------*/
9358 static void
9359 genRightShiftLiteral (operand * left,
9360                       operand * right,
9361                       operand * result,
9362                       iCode * ic,
9363                       int sign)
9364 {
9365   int shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
9366   int size;
9367
9368   D (emitcode (";", "genRightShiftLiteral"));
9369
9370   freeAsmop (right, NULL, ic, TRUE);
9371
9372   aopOp (left, ic, FALSE);
9373   aopOp (result, ic, FALSE);
9374
9375 #if VIEW_SIZE
9376   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9377             AOP_SIZE (left));
9378 #endif
9379
9380   size = getDataSize (left);
9381   /* test the LEFT size !!! */
9382
9383   /* I suppose that the left size >= result size */
9384   if (shCount == 0)
9385     {
9386       size = getDataSize (result);
9387       while (size--)
9388         movLeft2Result (left, size, result, size, 0);
9389     }
9390
9391   else if (shCount >= (size * 8))
9392     {
9393       if (sign)
9394         {
9395           /* get sign in acc.7 */
9396           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9397         }
9398       addSign (result, LSB, sign);
9399     }
9400   else
9401     {
9402       switch (size)
9403         {
9404         case 1:
9405           genrshOne (result, left, shCount, sign);
9406           break;
9407
9408         case 2:
9409           genrshTwo (result, left, shCount, sign);
9410           break;
9411
9412         case 4:
9413           genrshFour (result, left, shCount, sign);
9414           break;
9415         default:
9416           break;
9417         }
9418     }
9419   freeAsmop (result, NULL, ic, TRUE);
9420   freeAsmop (left, NULL, ic, TRUE);
9421 }
9422
9423 /*-----------------------------------------------------------------*/
9424 /* genSignedRightShift - right shift of signed number              */
9425 /*-----------------------------------------------------------------*/
9426 static void
9427 genSignedRightShift (iCode * ic)
9428 {
9429   operand *right, *left, *result;
9430   int size, offset;
9431   char *l;
9432   symbol *tlbl, *tlbl1;
9433   bool pushedB;
9434
9435   D (emitcode (";", "genSignedRightShift"));
9436
9437   /* we do it the hard way put the shift count in b
9438      and loop thru preserving the sign */
9439
9440   right = IC_RIGHT (ic);
9441   left = IC_LEFT (ic);
9442   result = IC_RESULT (ic);
9443
9444   aopOp (right, ic, FALSE);
9445
9446
9447   if (AOP_TYPE (right) == AOP_LIT)
9448     {
9449       genRightShiftLiteral (left, right, result, ic, 1);
9450       return;
9451     }
9452   /* shift count is unknown then we have to form
9453      a loop get the loop count in B : Note: we take
9454      only the lower order byte since shifting
9455      more that 32 bits make no sense anyway, ( the
9456      largest size of an object can be only 32 bits ) */
9457
9458   pushedB = pushB ();
9459   MOVB (aopGet (right, 0, FALSE, FALSE));
9460   emitcode ("inc", "b");
9461   freeAsmop (right, NULL, ic, TRUE);
9462   aopOp (left, ic, FALSE);
9463   aopOp (result, ic, FALSE);
9464
9465   /* now move the left to the result if they are not the
9466      same */
9467   if (!sameRegs (AOP (left), AOP (result)) &&
9468       AOP_SIZE (result) > 1)
9469     {
9470
9471       size = AOP_SIZE (result);
9472       offset = 0;
9473       while (size--)
9474         {
9475           l = aopGet (left, offset, FALSE, TRUE);
9476           if (*l == '@' && IS_AOP_PREG (result))
9477             {
9478
9479               emitcode ("mov", "a,%s", l);
9480               aopPut (result, "a", offset);
9481             }
9482           else
9483             aopPut (result, l, offset);
9484           offset++;
9485         }
9486     }
9487
9488   /* mov the highest order bit to OVR */
9489   tlbl = newiTempLabel (NULL);
9490   tlbl1 = newiTempLabel (NULL);
9491
9492   size = AOP_SIZE (result);
9493   offset = size - 1;
9494   MOVA (aopGet (left, offset, FALSE, FALSE));
9495   emitcode ("rlc", "a");
9496   emitcode ("mov", "ov,c");
9497   /* if it is only one byte then */
9498   if (size == 1)
9499     {
9500       l = aopGet (left, 0, FALSE, FALSE);
9501       MOVA (l);
9502       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9503       emitLabel (tlbl);
9504       emitcode ("mov", "c,ov");
9505       emitcode ("rrc", "a");
9506       emitLabel (tlbl1);
9507       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9508       popB (pushedB);
9509       aopPut (result, "a", 0);
9510       goto release;
9511     }
9512
9513   reAdjustPreg (AOP (result));
9514   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9515   emitLabel (tlbl);
9516   emitcode ("mov", "c,ov");
9517   while (size--)
9518     {
9519       l = aopGet (result, offset, FALSE, FALSE);
9520       MOVA (l);
9521       emitcode ("rrc", "a");
9522       aopPut (result, "a", offset--);
9523     }
9524   reAdjustPreg (AOP (result));
9525   emitLabel (tlbl1);
9526   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9527   popB (pushedB);
9528
9529 release:
9530   freeAsmop (result, NULL, ic, TRUE);
9531   freeAsmop (left, NULL, ic, TRUE);
9532 }
9533
9534 /*-----------------------------------------------------------------*/
9535 /* genRightShift - generate code for right shifting                */
9536 /*-----------------------------------------------------------------*/
9537 static void
9538 genRightShift (iCode * ic)
9539 {
9540   operand *right, *left, *result;
9541   sym_link *letype;
9542   int size, offset;
9543   char *l;
9544   symbol *tlbl, *tlbl1;
9545   bool pushedB;
9546
9547   D (emitcode (";", "genRightShift"));
9548
9549   /* if signed then we do it the hard way preserve the
9550      sign bit moving it inwards */
9551   letype = getSpec (operandType (IC_LEFT (ic)));
9552
9553   if (!SPEC_USIGN (letype))
9554     {
9555       genSignedRightShift (ic);
9556       return;
9557     }
9558
9559   /* signed & unsigned types are treated the same : i.e. the
9560      signed is NOT propagated inwards : quoting from the
9561      ANSI - standard : "for E1 >> E2, is equivalent to division
9562      by 2**E2 if unsigned or if it has a non-negative value,
9563      otherwise the result is implementation defined ", MY definition
9564      is that the sign does not get propagated */
9565
9566   right = IC_RIGHT (ic);
9567   left = IC_LEFT (ic);
9568   result = IC_RESULT (ic);
9569
9570   aopOp (right, ic, FALSE);
9571
9572   /* if the shift count is known then do it
9573      as efficiently as possible */
9574   if (AOP_TYPE (right) == AOP_LIT)
9575     {
9576       genRightShiftLiteral (left, right, result, ic, 0);
9577       return;
9578     }
9579
9580   /* shift count is unknown then we have to form
9581      a loop get the loop count in B : Note: we take
9582      only the lower order byte since shifting
9583      more that 32 bits make no sense anyway, ( the
9584      largest size of an object can be only 32 bits ) */
9585
9586   pushedB = pushB ();
9587   MOVB (aopGet (right, 0, FALSE, FALSE));
9588   emitcode ("inc", "b");
9589   freeAsmop (right, NULL, ic, TRUE);
9590   aopOp (left, ic, FALSE);
9591   aopOp (result, ic, FALSE);
9592
9593   /* now move the left to the result if they are not the
9594      same */
9595   if (!sameRegs (AOP (left), AOP (result)) &&
9596       AOP_SIZE (result) > 1)
9597     {
9598       size = AOP_SIZE (result);
9599       offset = 0;
9600       while (size--)
9601         {
9602           l = aopGet (left, offset, FALSE, TRUE);
9603           if (*l == '@' && IS_AOP_PREG (result))
9604             {
9605
9606               emitcode ("mov", "a,%s", l);
9607               aopPut (result, "a", offset);
9608             }
9609           else
9610             aopPut (result, l, offset);
9611           offset++;
9612         }
9613     }
9614
9615   tlbl = newiTempLabel (NULL);
9616   tlbl1 = newiTempLabel (NULL);
9617   size = AOP_SIZE (result);
9618   offset = size - 1;
9619
9620   /* if it is only one byte then */
9621   if (size == 1)
9622     {
9623       l = aopGet (left, 0, FALSE, FALSE);
9624       MOVA (l);
9625       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9626       emitLabel (tlbl);
9627       CLRC;
9628       emitcode ("rrc", "a");
9629       emitLabel (tlbl1);
9630       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9631       popB (pushedB);
9632       aopPut (result, "a", 0);
9633       goto release;
9634     }
9635
9636   reAdjustPreg (AOP (result));
9637   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9638   emitLabel (tlbl);
9639   CLRC;
9640   while (size--)
9641     {
9642       l = aopGet (result, offset, FALSE, FALSE);
9643       MOVA (l);
9644       emitcode ("rrc", "a");
9645       aopPut (result, "a", offset--);
9646     }
9647   reAdjustPreg (AOP (result));
9648
9649   emitLabel (tlbl1);
9650   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9651   popB (pushedB);
9652
9653 release:
9654   freeAsmop (result, NULL, ic, TRUE);
9655   freeAsmop (left, NULL, ic, TRUE);
9656 }
9657
9658 /*-----------------------------------------------------------------*/
9659 /* emitPtrByteGet - emits code to get a byte into A through a      */
9660 /*                  pointer register (R0, R1, or DPTR). The        */
9661 /*                  original value of A can be preserved in B.     */
9662 /*-----------------------------------------------------------------*/
9663 static void
9664 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9665 {
9666   switch (p_type)
9667     {
9668     case IPOINTER:
9669     case POINTER:
9670       if (preserveAinB)
9671         emitcode ("mov", "b,a");
9672       emitcode ("mov", "a,@%s", rname);
9673       break;
9674
9675     case PPOINTER:
9676       if (preserveAinB)
9677         emitcode ("mov", "b,a");
9678       emitcode ("movx", "a,@%s", rname);
9679       break;
9680
9681     case FPOINTER:
9682       if (preserveAinB)
9683         emitcode ("mov", "b,a");
9684       emitcode ("movx", "a,@dptr");
9685       break;
9686
9687     case CPOINTER:
9688       if (preserveAinB)
9689         emitcode ("mov", "b,a");
9690       emitcode ("clr", "a");
9691       emitcode ("movc", "a,@a+dptr");
9692       break;
9693
9694     case GPOINTER:
9695       if (preserveAinB)
9696         {
9697           emitcode ("push", "b");
9698           emitcode ("push", "acc");
9699         }
9700       emitcode ("lcall", "__gptrget");
9701       if (preserveAinB)
9702         emitcode ("pop", "b");
9703       break;
9704     }
9705 }
9706
9707 /*-----------------------------------------------------------------*/
9708 /* emitPtrByteSet - emits code to set a byte from src through a    */
9709 /*                  pointer register (R0, R1, or DPTR).            */
9710 /*-----------------------------------------------------------------*/
9711 static void
9712 emitPtrByteSet (char *rname, int p_type, char *src)
9713 {
9714   switch (p_type)
9715     {
9716     case IPOINTER:
9717     case POINTER:
9718       if (*src=='@')
9719         {
9720           MOVA (src);
9721           emitcode ("mov", "@%s,a", rname);
9722         }
9723       else
9724         emitcode ("mov", "@%s,%s", rname, src);
9725       break;
9726
9727     case PPOINTER:
9728       MOVA (src);
9729       emitcode ("movx", "@%s,a", rname);
9730       break;
9731
9732     case FPOINTER:
9733       MOVA (src);
9734       emitcode ("movx", "@dptr,a");
9735       break;
9736
9737     case GPOINTER:
9738       MOVA (src);
9739       emitcode ("lcall", "__gptrput");
9740       break;
9741     }
9742 }
9743
9744 /*-----------------------------------------------------------------*/
9745 /* genUnpackBits - generates code for unpacking bits               */
9746 /*-----------------------------------------------------------------*/
9747 static char*
9748 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9749 {
9750   int offset = 0;       /* result byte offset */
9751   int rsize;            /* result size */
9752   int rlen = 0;         /* remaining bitfield length */
9753   sym_link *etype;      /* bitfield type information */
9754   int blen;             /* bitfield length */
9755   int bstr;             /* bitfield starting bit within byte */
9756   static char* const accBits[] = {"acc.0", "acc.1", "acc.2", "acc.3",
9757                                   "acc.4", "acc.5", "acc.6", "acc.7"};
9758
9759   D(emitcode (";", "genUnpackBits"));
9760
9761   etype = getSpec (operandType (result));
9762   rsize = getSize (operandType (result));
9763   blen = SPEC_BLEN (etype);
9764   bstr = SPEC_BSTR (etype);
9765
9766   if (ifx && blen <= 8)
9767     {
9768       emitPtrByteGet (rname, ptype, FALSE);
9769       if (blen == 1)
9770         {
9771           return accBits[bstr];;
9772         }
9773       else
9774         {
9775           if (blen < 8)
9776             emitcode ("anl", "a,#0x%02x",
9777                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9778           return "a";
9779         }
9780     }
9781   wassert (!ifx);
9782
9783   /* If the bitfield length is less than a byte */
9784   if (blen < 8)
9785     {
9786       emitPtrByteGet (rname, ptype, FALSE);
9787       AccRol (8 - bstr);
9788       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9789       if (!SPEC_USIGN (etype))
9790         {
9791           /* signed bitfield */
9792           symbol *tlbl = newiTempLabel (NULL);
9793
9794           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9795           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9796           emitLabel (tlbl);
9797         }
9798       aopPut (result, "a", offset++);
9799       goto finish;
9800     }
9801
9802   /* Bit field did not fit in a byte. Copy all
9803      but the partial byte at the end.  */
9804   for (rlen=blen;rlen>=8;rlen-=8)
9805     {
9806       emitPtrByteGet (rname, ptype, FALSE);
9807       aopPut (result, "a", offset++);
9808       if (rlen>8)
9809         emitcode ("inc", "%s", rname);
9810     }
9811
9812   /* Handle the partial byte at the end */
9813   if (rlen)
9814     {
9815       emitPtrByteGet (rname, ptype, FALSE);
9816       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9817       if (!SPEC_USIGN (etype))
9818         {
9819           /* signed bitfield */
9820           symbol *tlbl = newiTempLabel (NULL);
9821
9822           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9823           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9824           emitLabel (tlbl);
9825         }
9826       aopPut (result, "a", offset++);
9827     }
9828
9829 finish:
9830   if (offset < rsize)
9831     {
9832       char *source;
9833
9834       if (SPEC_USIGN (etype))
9835         source = zero;
9836       else
9837         {
9838           /* signed bitfield: sign extension with 0x00 or 0xff */
9839           emitcode ("rlc", "a");
9840           emitcode ("subb", "a,acc");
9841
9842           source = "a";
9843         }
9844       rsize -= offset;
9845       while (rsize--)
9846         aopPut (result, source, offset++);
9847     }
9848   return NULL;
9849 }
9850
9851
9852 /*-----------------------------------------------------------------*/
9853 /* genDataPointerGet - generates code when ptr offset is known     */
9854 /*-----------------------------------------------------------------*/
9855 static void
9856 genDataPointerGet (operand * left,
9857                    operand * result,
9858                    iCode * ic)
9859 {
9860   char *l;
9861   char buffer[256];
9862   int size, offset = 0;
9863
9864   D (emitcode (";", "genDataPointerGet"));
9865
9866   aopOp (result, ic, TRUE);
9867
9868   /* get the string representation of the name */
9869   l = aopGet (left, 0, FALSE, TRUE);
9870   l++; // remove #
9871   size = AOP_SIZE (result);
9872   while (size--)
9873     {
9874       if (offset)
9875         {
9876           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9877         }
9878       else
9879         {
9880           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9881         }
9882       aopPut (result, buffer, offset++);
9883     }
9884
9885   freeAsmop (result, NULL, ic, TRUE);
9886   freeAsmop (left, NULL, ic, TRUE);
9887 }
9888
9889 /*-----------------------------------------------------------------*/
9890 /* genNearPointerGet - emitcode for near pointer fetch             */
9891 /*-----------------------------------------------------------------*/
9892 static void
9893 genNearPointerGet (operand * left,
9894                    operand * result,
9895                    iCode * ic,
9896                    iCode * pi,
9897                    iCode * ifx)
9898 {
9899   asmop *aop = NULL;
9900   regs *preg = NULL;
9901   char *rname;
9902   char *ifxCond = "a";
9903   sym_link *rtype, *retype;
9904   sym_link *ltype = operandType (left);
9905
9906   D (emitcode (";", "genNearPointerGet"));
9907
9908   rtype = operandType (result);
9909   retype = getSpec (rtype);
9910
9911   aopOp (left, ic, FALSE);
9912
9913   /* if left is rematerialisable and
9914      result is not bitfield variable type and
9915      the left is pointer to data space i.e
9916      lower 128 bytes of space */
9917   if (AOP_TYPE (left) == AOP_IMMD &&
9918       !IS_BITFIELD (retype) &&
9919       DCL_TYPE (ltype) == POINTER)
9920     {
9921       genDataPointerGet (left, result, ic);
9922       return;
9923     }
9924
9925   //aopOp (result, ic, FALSE);
9926   aopOp (result, ic, result?TRUE:FALSE);
9927
9928  /* if the value is already in a pointer register
9929      then don't need anything more */
9930   if (!AOP_INPREG (AOP (left)))
9931     {
9932       if (IS_AOP_PREG (left))
9933         {
9934           // Aha, it is a pointer, just in disguise.
9935           rname = aopGet (left, 0, FALSE, FALSE);
9936           if (*rname != '@')
9937             {
9938               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9939                       __FILE__, __LINE__);
9940             }
9941           else
9942             {
9943               // Expected case.
9944               emitcode ("mov", "a%s,%s", rname + 1, rname);
9945               rname++;  // skip the '@'.
9946             }
9947         }
9948       else
9949         {
9950           /* otherwise get a free pointer register */
9951           aop = newAsmop (0);
9952           preg = getFreePtr (ic, &aop, FALSE);
9953           emitcode ("mov", "%s,%s",
9954                     preg->name,
9955                     aopGet (left, 0, FALSE, TRUE));
9956           rname = preg->name;
9957         }
9958     }
9959   else
9960     rname = aopGet (left, 0, FALSE, FALSE);
9961
9962   /* if bitfield then unpack the bits */
9963   if (IS_BITFIELD (retype))
9964     ifxCond = genUnpackBits (result, rname, POINTER, ifx);
9965   else
9966     {
9967       /* we have can just get the values */
9968       int size = AOP_SIZE (result);
9969       int offset = 0;
9970
9971       while (size--)
9972         {
9973           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9974             {
9975
9976               emitcode ("mov", "a,@%s", rname);
9977               if (!ifx)
9978                 aopPut (result, "a", offset);
9979             }
9980           else
9981             {
9982               char buffer[80];
9983
9984               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9985               aopPut (result, buffer, offset);
9986             }
9987           offset++;
9988           if (size || pi)
9989             emitcode ("inc", "%s", rname);
9990         }
9991     }
9992
9993   /* now some housekeeping stuff */
9994   if (aop)       /* we had to allocate for this iCode */
9995     {
9996       if (pi) { /* post increment present */
9997         aopPut (left, rname, 0);
9998       }
9999       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10000     }
10001   else
10002     {
10003       /* we did not allocate which means left
10004          already in a pointer register, then
10005          if size > 0 && this could be used again
10006          we have to point it back to where it
10007          belongs */
10008       if ((AOP_SIZE (result) > 1 &&
10009            !OP_SYMBOL (left)->remat &&
10010            (OP_SYMBOL (left)->liveTo > ic->seq ||
10011             ic->depth)) &&
10012           !pi)
10013         {
10014           int size = AOP_SIZE (result) - 1;
10015           while (size--)
10016             emitcode ("dec", "%s", rname);
10017         }
10018     }
10019
10020   if (ifx && !ifx->generated)
10021     {
10022       genIfxJump (ifx, ifxCond, left, NULL, result);
10023     }
10024
10025   /* done */
10026   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
10027   freeAsmop (left, NULL, ic, TRUE);
10028   if (pi) pi->generated = 1;
10029 }
10030
10031 /*-----------------------------------------------------------------*/
10032 /* genPagedPointerGet - emitcode for paged pointer fetch           */
10033 /*-----------------------------------------------------------------*/
10034 static void
10035 genPagedPointerGet (operand * left,
10036                     operand * result,
10037                     iCode * ic,
10038                     iCode *pi,
10039                     iCode *ifx)
10040 {
10041   asmop *aop = NULL;
10042   regs *preg = NULL;
10043   char *rname;
10044   char *ifxCond = "a";
10045   sym_link *rtype, *retype;
10046
10047   D (emitcode (";", "genPagedPointerGet"));
10048
10049   rtype = operandType (result);
10050   retype = getSpec (rtype);
10051
10052   aopOp (left, ic, FALSE);
10053
10054   aopOp (result, ic, FALSE);
10055
10056   /* if the value is already in a pointer register
10057      then don't need anything more */
10058   if (!AOP_INPREG (AOP (left)))
10059     {
10060       /* otherwise get a free pointer register */
10061       aop = newAsmop (0);
10062       preg = getFreePtr (ic, &aop, FALSE);
10063       emitcode ("mov", "%s,%s",
10064                 preg->name,
10065                 aopGet (left, 0, FALSE, TRUE));
10066       rname = preg->name;
10067     }
10068   else
10069     rname = aopGet (left, 0, FALSE, FALSE);
10070
10071   /* if bitfield then unpack the bits */
10072   if (IS_BITFIELD (retype))
10073     ifxCond = genUnpackBits (result, rname, PPOINTER, ifx);
10074   else
10075     {
10076       /* we have can just get the values */
10077       int size = AOP_SIZE (result);
10078       int offset = 0;
10079
10080       while (size--)
10081         {
10082
10083           emitcode ("movx", "a,@%s", rname);
10084           if (!ifx)
10085             aopPut (result, "a", offset);
10086
10087           offset++;
10088
10089           if (size || pi)
10090             emitcode ("inc", "%s", rname);
10091         }
10092     }
10093
10094   /* now some housekeeping stuff */
10095   if (aop) /* we had to allocate for this iCode */
10096     {
10097       if (pi)
10098         aopPut (left, rname, 0);
10099       freeAsmop (NULL, aop, ic, TRUE);
10100     }
10101   else
10102     {
10103       /* we did not allocate which means left
10104          already in a pointer register, then
10105          if size > 0 && this could be used again
10106          we have to point it back to where it
10107          belongs */
10108       if ((AOP_SIZE (result) > 1 &&
10109            !OP_SYMBOL (left)->remat &&
10110            (OP_SYMBOL (left)->liveTo > ic->seq ||
10111             ic->depth)) &&
10112           !pi)
10113         {
10114           int size = AOP_SIZE (result) - 1;
10115           while (size--)
10116             emitcode ("dec", "%s", rname);
10117         }
10118     }
10119
10120   if (ifx && !ifx->generated)
10121     {
10122       genIfxJump (ifx, ifxCond, left, NULL, result);
10123     }
10124
10125   /* done */
10126   freeAsmop (result, NULL, ic, TRUE);
10127   freeAsmop (left, NULL, ic, TRUE);
10128   if (pi) pi->generated = 1;
10129 }
10130
10131 /*--------------------------------------------------------------------*/
10132 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10133 /*--------------------------------------------------------------------*/
10134 static void
10135 loadDptrFromOperand (operand *op, bool loadBToo)
10136 {
10137   if (AOP_TYPE (op) != AOP_STR)
10138     {
10139       /* if this is rematerializable */
10140       if (AOP_TYPE (op) == AOP_IMMD)
10141         {
10142           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10143           if (loadBToo)
10144             {
10145               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10146                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10147               else
10148                 {
10149                   wassertl(FALSE, "need pointerCode");
10150                   emitcode (";", "mov b,???");
10151                   /* genPointerGet and genPointerSet originally did different
10152                   ** things for this case. Both seem wrong.
10153                   ** from genPointerGet:
10154                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10155                   ** from genPointerSet:
10156                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10157                   */
10158                 }
10159             }
10160         }
10161       else if (AOP_TYPE (op) == AOP_DPTR)
10162         {
10163           if (loadBToo)
10164             {
10165               MOVA (aopGet (op, 0, FALSE, FALSE));
10166               emitcode ("push", "acc");
10167               MOVA (aopGet (op, 1, FALSE, FALSE));
10168               emitcode ("push", "acc");
10169               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10170               emitcode ("pop", "dph");
10171               emitcode ("pop", "dpl");
10172             }
10173           else
10174             {
10175               MOVA (aopGet (op, 0, FALSE, FALSE));
10176               emitcode ("push", "acc");
10177               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10178               emitcode ("pop", "dpl");
10179             }
10180         }
10181       else
10182         {                       /* we need to get it byte by byte */
10183           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10184           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10185           if (loadBToo)
10186             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10187         }
10188     }
10189 }
10190
10191 /*-----------------------------------------------------------------*/
10192 /* genFarPointerGet - get value from far space                     */
10193 /*-----------------------------------------------------------------*/
10194 static void
10195 genFarPointerGet (operand * left,
10196                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10197 {
10198   int size, offset;
10199   char *ifxCond = "a";
10200   sym_link *retype = getSpec (operandType (result));
10201
10202   D (emitcode (";", "genFarPointerGet"));
10203
10204   aopOp (left, ic, FALSE);
10205   loadDptrFromOperand (left, FALSE);
10206
10207   /* so dptr now contains the address */
10208   aopOp (result, ic, FALSE);
10209
10210   /* if bit then unpack */
10211   if (IS_BITFIELD (retype))
10212     ifxCond = genUnpackBits (result, "dptr", FPOINTER, ifx);
10213   else
10214     {
10215       size = AOP_SIZE (result);
10216       offset = 0;
10217
10218       while (size--)
10219         {
10220           emitcode ("movx", "a,@dptr");
10221           if (!ifx)
10222             aopPut (result, "a", offset++);
10223           if (size || pi)
10224             emitcode ("inc", "dptr");
10225         }
10226     }
10227
10228   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10229     {
10230       aopPut (left, "dpl", 0);
10231       aopPut (left, "dph", 1);
10232       pi->generated = 1;
10233     }
10234
10235   if (ifx && !ifx->generated)
10236     {
10237       genIfxJump (ifx, ifxCond, left, NULL, result);
10238     }
10239
10240   freeAsmop (result, NULL, ic, TRUE);
10241   freeAsmop (left, NULL, ic, TRUE);
10242 }
10243
10244 /*-----------------------------------------------------------------*/
10245 /* genCodePointerGet - get value from code space                   */
10246 /*-----------------------------------------------------------------*/
10247 static void
10248 genCodePointerGet (operand * left,
10249                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10250 {
10251   int size, offset;
10252   char *ifxCond = "a";
10253   sym_link *retype = getSpec (operandType (result));
10254
10255   D (emitcode (";", "genCodePointerGet"));
10256
10257   aopOp (left, ic, FALSE);
10258   loadDptrFromOperand (left, FALSE);
10259
10260   /* so dptr now contains the address */
10261   aopOp (result, ic, FALSE);
10262
10263   /* if bit then unpack */
10264   if (IS_BITFIELD (retype))
10265     ifxCond = genUnpackBits (result, "dptr", CPOINTER, ifx);
10266   else
10267     {
10268       size = AOP_SIZE (result);
10269       offset = 0;
10270
10271       while (size--)
10272         {
10273           emitcode ("clr", "a");
10274           emitcode ("movc", "a,@a+dptr");
10275           if (!ifx)
10276             aopPut (result, "a", offset++);
10277           if (size || pi)
10278             emitcode ("inc", "dptr");
10279         }
10280     }
10281
10282   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10283     {
10284       aopPut (left, "dpl", 0);
10285       aopPut (left, "dph", 1);
10286       pi->generated = 1;
10287     }
10288
10289   if (ifx && !ifx->generated)
10290     {
10291       genIfxJump (ifx, ifxCond, left, NULL, result);
10292     }
10293
10294   freeAsmop (result, NULL, ic, TRUE);
10295   freeAsmop (left, NULL, ic, TRUE);
10296 }
10297
10298 /*-----------------------------------------------------------------*/
10299 /* genGenPointerGet - get value from generic pointer space         */
10300 /*-----------------------------------------------------------------*/
10301 static void
10302 genGenPointerGet (operand * left,
10303                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10304 {
10305   int size, offset;
10306   char *ifxCond = "a";
10307   sym_link *retype = getSpec (operandType (result));
10308
10309   D (emitcode (";", "genGenPointerGet"));
10310
10311   aopOp (left, ic, FALSE);
10312   loadDptrFromOperand (left, TRUE);
10313
10314   /* so dptr now contains the address */
10315   aopOp (result, ic, FALSE);
10316
10317   /* if bit then unpack */
10318   if (IS_BITFIELD (retype))
10319     {
10320       ifxCond = genUnpackBits (result, "dptr", GPOINTER, ifx);
10321     }
10322   else
10323     {
10324       size = AOP_SIZE (result);
10325       offset = 0;
10326
10327       while (size--)
10328         {
10329           emitcode ("lcall", "__gptrget");
10330           if (!ifx)
10331             aopPut (result, "a", offset++);
10332           if (size || pi)
10333             emitcode ("inc", "dptr");
10334         }
10335     }
10336
10337   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10338     {
10339       aopPut (left, "dpl", 0);
10340       aopPut (left, "dph", 1);
10341       pi->generated = 1;
10342     }
10343
10344   if (ifx && !ifx->generated)
10345     {
10346       genIfxJump (ifx, ifxCond, left, NULL, result);
10347     }
10348
10349   freeAsmop (result, NULL, ic, TRUE);
10350   freeAsmop (left, NULL, ic, TRUE);
10351 }
10352
10353 /*-----------------------------------------------------------------*/
10354 /* genPointerGet - generate code for pointer get                   */
10355 /*-----------------------------------------------------------------*/
10356 static void
10357 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10358 {
10359   operand *left, *result;
10360   sym_link *type, *etype;
10361   int p_type;
10362
10363   D (emitcode (";", "genPointerGet"));
10364
10365   left = IC_LEFT (ic);
10366   result = IC_RESULT (ic);
10367
10368   if (getSize (operandType (result))>1)
10369     ifx = NULL;
10370
10371   /* depending on the type of pointer we need to
10372      move it to the correct pointer register */
10373   type = operandType (left);
10374   etype = getSpec (type);
10375   /* if left is of type of pointer then it is simple */
10376   if (IS_PTR (type) && !IS_FUNC (type->next))
10377     {
10378       p_type = DCL_TYPE (type);
10379     }
10380   else
10381     {
10382       /* we have to go by the storage class */
10383       p_type = PTR_TYPE (SPEC_OCLS (etype));
10384     }
10385
10386   /* special case when cast remat */
10387   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10388       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10389     {
10390       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10391       type = operandType (left);
10392       p_type = DCL_TYPE (type);
10393     }
10394   /* now that we have the pointer type we assign
10395      the pointer values */
10396   switch (p_type)
10397     {
10398
10399     case POINTER:
10400     case IPOINTER:
10401       genNearPointerGet (left, result, ic, pi, ifx);
10402       break;
10403
10404     case PPOINTER:
10405       genPagedPointerGet (left, result, ic, pi, ifx);
10406       break;
10407
10408     case FPOINTER:
10409       genFarPointerGet (left, result, ic, pi, ifx);
10410       break;
10411
10412     case CPOINTER:
10413       genCodePointerGet (left, result, ic, pi, ifx);
10414       break;
10415
10416     case GPOINTER:
10417       genGenPointerGet (left, result, ic, pi, ifx);
10418       break;
10419     }
10420 }
10421
10422
10423 /*-----------------------------------------------------------------*/
10424 /* genPackBits - generates code for packed bit storage             */
10425 /*-----------------------------------------------------------------*/
10426 static void
10427 genPackBits (sym_link * etype,
10428              operand * right,
10429              char *rname, int p_type)
10430 {
10431   int offset = 0;       /* source byte offset */
10432   int rlen = 0;         /* remaining bitfield length */
10433   int blen;             /* bitfield length */
10434   int bstr;             /* bitfield starting bit within byte */
10435   int litval;           /* source literal value (if AOP_LIT) */
10436   unsigned char mask;   /* bitmask within current byte */
10437
10438   D(emitcode (";", "genPackBits"));
10439
10440   blen = SPEC_BLEN (etype);
10441   bstr = SPEC_BSTR (etype);
10442
10443   /* If the bitfield length is less than a byte */
10444   if (blen < 8)
10445     {
10446       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10447               (unsigned char) (0xFF >> (8 - bstr)));
10448
10449       if (AOP_TYPE (right) == AOP_LIT)
10450         {
10451           /* Case with a bitfield length <8 and literal source
10452           */
10453           litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10454           litval <<= bstr;
10455           litval &= (~mask) & 0xff;
10456           emitPtrByteGet (rname, p_type, FALSE);
10457           if ((mask|litval)!=0xff)
10458             emitcode ("anl","a,#0x%02x", mask);
10459           if (litval)
10460             emitcode ("orl","a,#0x%02x", litval);
10461         }
10462       else
10463         {
10464           if ((blen==1) && (p_type!=GPOINTER))
10465             {
10466               /* Case with a bitfield length == 1 and no generic pointer
10467               */
10468               if (AOP_TYPE (right) == AOP_CRY)
10469                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10470               else
10471                 {
10472                   MOVA (aopGet (right, 0, FALSE, FALSE));
10473                   emitcode ("rrc","a");
10474                 }
10475               emitPtrByteGet (rname, p_type, FALSE);
10476               emitcode ("mov","acc.%d,c",bstr);
10477             }
10478           else
10479             {
10480               bool pushedB;
10481               /* Case with a bitfield length < 8 and arbitrary source
10482               */
10483               MOVA (aopGet (right, 0, FALSE, FALSE));
10484               /* shift and mask source value */
10485               AccLsh (bstr);
10486               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10487
10488               pushedB = pushB ();
10489               /* transfer A to B and get next byte */
10490               emitPtrByteGet (rname, p_type, TRUE);
10491
10492               emitcode ("anl", "a,#0x%02x", mask);
10493               emitcode ("orl", "a,b");
10494               if (p_type == GPOINTER)
10495                 emitcode ("pop", "b");
10496
10497               popB (pushedB);
10498            }
10499         }
10500
10501       emitPtrByteSet (rname, p_type, "a");
10502       return;
10503     }
10504
10505   /* Bit length is greater than 7 bits. In this case, copy  */
10506   /* all except the partial byte at the end                 */
10507   for (rlen=blen;rlen>=8;rlen-=8)
10508     {
10509       emitPtrByteSet (rname, p_type,
10510                       aopGet (right, offset++, FALSE, TRUE) );
10511       if (rlen>8)
10512         emitcode ("inc", "%s", rname);
10513     }
10514
10515   /* If there was a partial byte at the end */
10516   if (rlen)
10517     {
10518       mask = (((unsigned char) -1 << rlen) & 0xff);
10519
10520       if (AOP_TYPE (right) == AOP_LIT)
10521         {
10522           /* Case with partial byte and literal source
10523           */
10524           litval = (int) ulFromVal (AOP (right)->aopu.aop_lit);
10525           litval >>= (blen-rlen);
10526           litval &= (~mask) & 0xff;
10527           emitPtrByteGet (rname, p_type, FALSE);
10528           if ((mask|litval)!=0xff)
10529             emitcode ("anl","a,#0x%02x", mask);
10530           if (litval)
10531             emitcode ("orl","a,#0x%02x", litval);
10532         }
10533       else
10534         {
10535           bool pushedB;
10536           /* Case with partial byte and arbitrary source
10537           */
10538           MOVA (aopGet (right, offset++, FALSE, FALSE));
10539           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10540
10541           pushedB = pushB ();
10542           /* transfer A to B and get next byte */
10543           emitPtrByteGet (rname, p_type, TRUE);
10544
10545           emitcode ("anl", "a,#0x%02x", mask);
10546           emitcode ("orl", "a,b");
10547           if (p_type == GPOINTER)
10548             emitcode ("pop", "b");
10549
10550           popB (pushedB);
10551         }
10552       emitPtrByteSet (rname, p_type, "a");
10553     }
10554 }
10555
10556
10557 /*-----------------------------------------------------------------*/
10558 /* genDataPointerSet - remat pointer to data space                 */
10559 /*-----------------------------------------------------------------*/
10560 static void
10561 genDataPointerSet (operand * right,
10562                    operand * result,
10563                    iCode * ic)
10564 {
10565   int size, offset = 0;
10566   char *l, buffer[256];
10567
10568   D (emitcode (";", "genDataPointerSet"));
10569
10570   aopOp (right, ic, FALSE);
10571
10572   l = aopGet (result, 0, FALSE, TRUE);
10573   l++; //remove #
10574   size = max (AOP_SIZE (right), AOP_SIZE (result));
10575   while (size--)
10576     {
10577       if (offset)
10578         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10579       else
10580         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10581       emitcode ("mov", "%s,%s", buffer,
10582                 aopGet (right, offset++, FALSE, FALSE));
10583     }
10584
10585   freeAsmop (right, NULL, ic, TRUE);
10586   freeAsmop (result, NULL, ic, TRUE);
10587 }
10588
10589 /*-----------------------------------------------------------------*/
10590 /* genNearPointerSet - emitcode for near pointer put               */
10591 /*-----------------------------------------------------------------*/
10592 static void
10593 genNearPointerSet (operand * right,
10594                    operand * result,
10595                    iCode * ic,
10596                    iCode * pi)
10597 {
10598   asmop *aop = NULL;
10599   regs *preg = NULL;
10600   char *rname, *l;
10601   sym_link *retype, *letype;
10602   sym_link *ptype = operandType (result);
10603
10604   D (emitcode (";", "genNearPointerSet"));
10605
10606   retype = getSpec (operandType (right));
10607   letype = getSpec (ptype);
10608
10609   aopOp (result, ic, FALSE);
10610
10611   /* if the result is rematerializable &
10612      in data space & not a bit variable */
10613   if (AOP_TYPE (result) == AOP_IMMD &&
10614       DCL_TYPE (ptype) == POINTER &&
10615       !IS_BITVAR (retype) &&
10616       !IS_BITVAR (letype))
10617     {
10618       genDataPointerSet (right, result, ic);
10619       return;
10620     }
10621
10622   /* if the value is already in a pointer register
10623      then don't need anything more */
10624   if (!AOP_INPREG (AOP (result)))
10625     {
10626       if (IS_AOP_PREG (result))
10627         {
10628           // Aha, it is a pointer, just in disguise.
10629           rname = aopGet (result, 0, FALSE, FALSE);
10630           if (*rname != '@')
10631             {
10632               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10633                       __FILE__, __LINE__);
10634             }
10635           else
10636             {
10637               // Expected case.
10638               emitcode ("mov", "a%s,%s", rname + 1, rname);
10639               rname++;  // skip the '@'.
10640             }
10641         }
10642       else
10643         {
10644           /* otherwise get a free pointer register */
10645           aop = newAsmop (0);
10646           preg = getFreePtr (ic, &aop, FALSE);
10647           emitcode ("mov", "%s,%s",
10648                     preg->name,
10649                     aopGet (result, 0, FALSE, TRUE));
10650           rname = preg->name;
10651         }
10652     }
10653   else
10654     {
10655       rname = aopGet (result, 0, FALSE, FALSE);
10656     }
10657
10658   aopOp (right, ic, FALSE);
10659
10660   /* if bitfield then unpack the bits */
10661   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10662     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10663   else
10664     {
10665       /* we can just get the values */
10666       int size = AOP_SIZE (right);
10667       int offset = 0;
10668
10669       while (size--)
10670         {
10671           l = aopGet (right, offset, FALSE, TRUE);
10672           if ((*l == '@') || (strcmp (l, "acc") == 0))
10673             {
10674               MOVA (l);
10675               emitcode ("mov", "@%s,a", rname);
10676             }
10677           else
10678             emitcode ("mov", "@%s,%s", rname, l);
10679           if (size || pi)
10680             emitcode ("inc", "%s", rname);
10681           offset++;
10682         }
10683     }
10684
10685   /* now some housekeeping stuff */
10686   if (aop) /* we had to allocate for this iCode */
10687     {
10688       if (pi)
10689         aopPut (result, rname, 0);
10690       freeAsmop (NULL, aop, ic, TRUE);
10691     }
10692   else
10693     {
10694       /* we did not allocate which means left
10695          already in a pointer register, then
10696          if size > 0 && this could be used again
10697          we have to point it back to where it
10698          belongs */
10699       if ((AOP_SIZE (right) > 1 &&
10700            !OP_SYMBOL (result)->remat &&
10701            (OP_SYMBOL (result)->liveTo > ic->seq ||
10702             ic->depth)) &&
10703           !pi)
10704         {
10705           int size = AOP_SIZE (right) - 1;
10706           while (size--)
10707             emitcode ("dec", "%s", rname);
10708         }
10709     }
10710
10711   /* done */
10712   if (pi)
10713     pi->generated = 1;
10714   freeAsmop (right, NULL, ic, TRUE);
10715   freeAsmop (result, NULL, ic, TRUE);
10716 }
10717
10718 /*-----------------------------------------------------------------*/
10719 /* genPagedPointerSet - emitcode for Paged pointer put             */
10720 /*-----------------------------------------------------------------*/
10721 static void
10722 genPagedPointerSet (operand * right,
10723                     operand * result,
10724                     iCode * ic,
10725                     iCode * pi)
10726 {
10727   asmop *aop = NULL;
10728   regs *preg = NULL;
10729   char *rname, *l;
10730   sym_link *retype, *letype;
10731
10732   D (emitcode (";", "genPagedPointerSet"));
10733
10734   retype = getSpec (operandType (right));
10735   letype = getSpec (operandType (result));
10736
10737   aopOp (result, ic, FALSE);
10738
10739   /* if the value is already in a pointer register
10740      then don't need anything more */
10741   if (!AOP_INPREG (AOP (result)))
10742     {
10743       if (IS_AOP_PREG (result))
10744         {
10745           // Aha, it is a pointer, just in disguise.
10746           rname = aopGet (result, 0, FALSE, FALSE);
10747           if (*rname != '@')
10748             {
10749               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10750                       __FILE__, __LINE__);
10751             }
10752           else
10753             {
10754               // Expected case.
10755               emitcode ("mov", "a%s,%s", rname + 1, rname);
10756               rname++;  // skip the '@'.
10757             }
10758         }
10759       else
10760         {
10761           /* otherwise get a free pointer register */
10762           aop = newAsmop (0);
10763           preg = getFreePtr (ic, &aop, FALSE);
10764           emitcode ("mov", "%s,%s",
10765                     preg->name,
10766                     aopGet (result, 0, FALSE, TRUE));
10767           rname = preg->name;
10768         }
10769     }
10770   else
10771     {
10772       rname = aopGet (result, 0, FALSE, FALSE);
10773     }
10774
10775   aopOp (right, ic, FALSE);
10776
10777   /* if bitfield then unpack the bits */
10778   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10779     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10780   else
10781     {
10782       /* we can just get the values */
10783       int size = AOP_SIZE (right);
10784       int offset = 0;
10785
10786       while (size--)
10787         {
10788           l = aopGet (right, offset, FALSE, TRUE);
10789           MOVA (l);
10790           emitcode ("movx", "@%s,a", rname);
10791           if (size || pi)
10792             emitcode ("inc", "%s", rname);
10793           offset++;
10794         }
10795     }
10796
10797   /* now some housekeeping stuff */
10798   if (aop) /* we had to allocate for this iCode */
10799     {
10800       if (pi)
10801         aopPut (result, rname, 0);
10802       freeAsmop (NULL, aop, ic, TRUE);
10803     }
10804   else
10805     {
10806       /* we did not allocate which means left
10807          already in a pointer register, then
10808          if size > 0 && this could be used again
10809          we have to point it back to where it
10810          belongs */
10811       if (AOP_SIZE (right) > 1 &&
10812           !OP_SYMBOL (result)->remat &&
10813           (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth) &&
10814           !pi)
10815         {
10816           int size = AOP_SIZE (right) - 1;
10817           while (size--)
10818             emitcode ("dec", "%s", rname);
10819         }
10820     }
10821
10822   /* done */
10823   if (pi)
10824     pi->generated = 1;
10825   freeAsmop (right, NULL, ic, TRUE);
10826   freeAsmop (result, NULL, ic, TRUE);
10827 }
10828
10829 /*-----------------------------------------------------------------*/
10830 /* genFarPointerSet - set value from far space                     */
10831 /*-----------------------------------------------------------------*/
10832 static void
10833 genFarPointerSet (operand * right,
10834                   operand * result, iCode * ic, iCode * pi)
10835 {
10836   int size, offset;
10837   sym_link *retype = getSpec (operandType (right));
10838   sym_link *letype = getSpec (operandType (result));
10839
10840   D(emitcode (";", "genFarPointerSet"));
10841
10842   aopOp (result, ic, FALSE);
10843   loadDptrFromOperand (result, FALSE);
10844
10845   /* so dptr now contains the address */
10846   aopOp (right, ic, FALSE);
10847
10848   /* if bit then unpack */
10849   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10850     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10851   else
10852     {
10853       size = AOP_SIZE (right);
10854       offset = 0;
10855
10856       while (size--)
10857         {
10858           char *l = aopGet (right, offset++, FALSE, FALSE);
10859           MOVA (l);
10860           emitcode ("movx", "@dptr,a");
10861           if (size || pi)
10862             emitcode ("inc", "dptr");
10863         }
10864     }
10865   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10866     aopPut (result, "dpl", 0);
10867     aopPut (result, "dph", 1);
10868     pi->generated=1;
10869   }
10870   freeAsmop (result, NULL, ic, TRUE);
10871   freeAsmop (right, NULL, ic, TRUE);
10872 }
10873
10874 /*-----------------------------------------------------------------*/
10875 /* genGenPointerSet - set value from generic pointer space         */
10876 /*-----------------------------------------------------------------*/
10877 static void
10878 genGenPointerSet (operand * right,
10879                   operand * result, iCode * ic, iCode * pi)
10880 {
10881   int size, offset;
10882   sym_link *retype = getSpec (operandType (right));
10883   sym_link *letype = getSpec (operandType (result));
10884
10885   D (emitcode (";", "genGenPointerSet"));
10886
10887   aopOp (result, ic, FALSE);
10888   loadDptrFromOperand (result, TRUE);
10889
10890   /* so dptr now contains the address */
10891   aopOp (right, ic, FALSE);
10892
10893   /* if bit then unpack */
10894   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10895     {
10896       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10897     }
10898   else
10899     {
10900       size = AOP_SIZE (right);
10901       offset = 0;
10902
10903       while (size--)
10904         {
10905           char *l = aopGet (right, offset++, FALSE, FALSE);
10906           MOVA (l);
10907           emitcode ("lcall", "__gptrput");
10908           if (size || pi)
10909             emitcode ("inc", "dptr");
10910         }
10911     }
10912
10913   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10914     aopPut (result, "dpl", 0);
10915     aopPut (result, "dph", 1);
10916     pi->generated=1;
10917   }
10918   freeAsmop (result, NULL, ic, TRUE);
10919   freeAsmop (right, NULL, ic, TRUE);
10920 }
10921
10922 /*-----------------------------------------------------------------*/
10923 /* genPointerSet - stores the value into a pointer location        */
10924 /*-----------------------------------------------------------------*/
10925 static void
10926 genPointerSet (iCode * ic, iCode *pi)
10927 {
10928   operand *right, *result;
10929   sym_link *type, *etype;
10930   int p_type;
10931
10932   D (emitcode (";", "genPointerSet"));
10933
10934   right = IC_RIGHT (ic);
10935   result = IC_RESULT (ic);
10936
10937   /* depending on the type of pointer we need to
10938      move it to the correct pointer register */
10939   type = operandType (result);
10940   etype = getSpec (type);
10941   /* if left is of type of pointer then it is simple */
10942   if (IS_PTR (type) && !IS_FUNC (type->next))
10943     {
10944       p_type = DCL_TYPE (type);
10945     }
10946   else
10947     {
10948       /* we have to go by the storage class */
10949       p_type = PTR_TYPE (SPEC_OCLS (etype));
10950     }
10951
10952   /* special case when cast remat */
10953   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10954       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10955           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10956           type = operandType (result);
10957           p_type = DCL_TYPE (type);
10958   }
10959
10960   /* now that we have the pointer type we assign
10961      the pointer values */
10962   switch (p_type)
10963     {
10964
10965     case POINTER:
10966     case IPOINTER:
10967       genNearPointerSet (right, result, ic, pi);
10968       break;
10969
10970     case PPOINTER:
10971       genPagedPointerSet (right, result, ic, pi);
10972       break;
10973
10974     case FPOINTER:
10975       genFarPointerSet (right, result, ic, pi);
10976       break;
10977
10978     case GPOINTER:
10979       genGenPointerSet (right, result, ic, pi);
10980       break;
10981
10982     default:
10983       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10984               "genPointerSet: illegal pointer type");
10985     }
10986 }
10987
10988 /*-----------------------------------------------------------------*/
10989 /* genIfx - generate code for Ifx statement                        */
10990 /*-----------------------------------------------------------------*/
10991 static void
10992 genIfx (iCode * ic, iCode * popIc)
10993 {
10994   operand *cond = IC_COND (ic);
10995   int isbit = 0;
10996   char *dup = NULL;
10997
10998   D (emitcode (";", "genIfx"));
10999
11000   aopOp (cond, ic, FALSE);
11001
11002   /* get the value into acc */
11003   if (AOP_TYPE (cond) != AOP_CRY)
11004     {
11005       toBoolean (cond);
11006     }
11007   else
11008     {
11009       isbit = 1;
11010       if (AOP(cond)->aopu.aop_dir)
11011         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
11012     }
11013
11014   /* the result is now in the accumulator or a directly addressable bit */
11015   freeAsmop (cond, NULL, ic, TRUE);
11016
11017   /* if there was something to be popped then do it */
11018   if (popIc)
11019       genIpop (popIc);
11020
11021   /* if the condition is a bit variable */
11022   if (isbit && dup)
11023     genIfxJump(ic, dup, NULL, NULL, NULL);
11024   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
11025     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
11026   else if (isbit && !IS_ITEMP (cond))
11027     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
11028   else
11029     genIfxJump (ic, "a", NULL, NULL, NULL);
11030
11031   ic->generated = 1;
11032 }
11033
11034 /*-----------------------------------------------------------------*/
11035 /* genAddrOf - generates code for address of                       */
11036 /*-----------------------------------------------------------------*/
11037 static void
11038 genAddrOf (iCode * ic)
11039 {
11040   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
11041   int size, offset;
11042
11043   D (emitcode (";", "genAddrOf"));
11044
11045   aopOp (IC_RESULT (ic), ic, FALSE);
11046
11047   /* if the operand is on the stack then we
11048      need to get the stack offset of this
11049      variable */
11050   if (sym->onStack)
11051     {
11052       /* if it has an offset then we need to compute it */
11053       if (sym->stack)
11054         {
11055           int stack_offset = ((sym->stack < 0) ?
11056                               ((char) (sym->stack - _G.nRegsSaved)) :
11057                               ((char) sym->stack)) & 0xff;
11058           if ((abs(stack_offset) == 1) &&
11059               !AOP_NEEDSACC(IC_RESULT (ic)) &&
11060               !isOperandVolatile (IC_RESULT (ic), FALSE))
11061             {
11062               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11063               if (stack_offset > 0)
11064                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11065               else
11066                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
11067             }
11068           else
11069             {
11070               emitcode ("mov", "a,%s", SYM_BP (sym));
11071               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
11072               aopPut (IC_RESULT (ic), "a", 0);
11073             }
11074         }
11075       else
11076         {
11077           /* we can just move _bp */
11078           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
11079         }
11080       /* fill the result with zero */
11081       size = AOP_SIZE (IC_RESULT (ic)) - 1;
11082
11083       offset = 1;
11084       while (size--)
11085         {
11086           aopPut (IC_RESULT (ic), zero, offset++);
11087         }
11088       goto release;
11089     }
11090
11091   /* object not on stack then we need the name */
11092   size = getDataSize (IC_RESULT (ic));
11093   offset = 0;
11094
11095   while (size--)
11096     {
11097       char s[SDCC_NAME_MAX];
11098       if (offset)
11099         sprintf (s, "#(%s >> %d)",
11100                  sym->rname,
11101                  offset * 8);
11102       else
11103         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11104       aopPut (IC_RESULT (ic), s, offset++);
11105     }
11106   if (opIsGptr (IC_RESULT (ic)))
11107     {
11108       char buffer[10];
11109       SNPRINTF (buffer, sizeof(buffer),
11110                 "#0x%02x", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
11111       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
11112     }
11113
11114 release:
11115   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11116
11117 }
11118
11119 /*-----------------------------------------------------------------*/
11120 /* genFarFarAssign - assignment when both are in far space         */
11121 /*-----------------------------------------------------------------*/
11122 static void
11123 genFarFarAssign (operand * result, operand * right, iCode * ic)
11124 {
11125   int size = AOP_SIZE (right);
11126   int offset = 0;
11127   char *l;
11128
11129   D (emitcode (";", "genFarFarAssign"));
11130
11131   /* first push the right side on to the stack */
11132   while (size--)
11133     {
11134       l = aopGet (right, offset++, FALSE, FALSE);
11135       MOVA (l);
11136       emitcode ("push", "acc");
11137     }
11138
11139   freeAsmop (right, NULL, ic, FALSE);
11140   /* now assign DPTR to result */
11141   aopOp (result, ic, FALSE);
11142   size = AOP_SIZE (result);
11143   while (size--)
11144     {
11145       emitcode ("pop", "acc");
11146       aopPut (result, "a", --offset);
11147     }
11148   freeAsmop (result, NULL, ic, FALSE);
11149 }
11150
11151 /*-----------------------------------------------------------------*/
11152 /* genAssign - generate code for assignment                        */
11153 /*-----------------------------------------------------------------*/
11154 static void
11155 genAssign (iCode * ic)
11156 {
11157   operand *result, *right;
11158   int size, offset;
11159   unsigned long lit = 0L;
11160
11161   D (emitcode (";", "genAssign"));
11162
11163   result = IC_RESULT (ic);
11164   right = IC_RIGHT (ic);
11165
11166   /* if they are the same */
11167   if (operandsEqu (result, right) &&
11168       !isOperandVolatile (result, FALSE) &&
11169       !isOperandVolatile (right, FALSE))
11170     return;
11171
11172   aopOp (right, ic, FALSE);
11173
11174   /* special case both in far space */
11175   if (AOP_TYPE (right) == AOP_DPTR &&
11176       IS_TRUE_SYMOP (result) &&
11177       isOperandInFarSpace (result))
11178     {
11179       genFarFarAssign (result, right, ic);
11180       return;
11181     }
11182
11183   aopOp (result, ic, TRUE);
11184
11185   /* if they are the same registers */
11186   if (sameRegs (AOP (right), AOP (result)) &&
11187       !isOperandVolatile (result, FALSE) &&
11188       !isOperandVolatile (right, FALSE))
11189     goto release;
11190
11191   /* if the result is a bit */
11192   if (AOP_TYPE (result) == AOP_CRY)
11193     {
11194       assignBit (result, right);
11195       goto release;
11196     }
11197
11198   /* bit variables done */
11199   /* general case */
11200   size = getDataSize (result);
11201   offset = 0;
11202   if (AOP_TYPE (right) == AOP_LIT)
11203     lit = ulFromVal (AOP (right)->aopu.aop_lit);
11204
11205   if ((size > 1) &&
11206       (AOP_TYPE (result) != AOP_REG) &&
11207       (AOP_TYPE (right) == AOP_LIT) &&
11208       !IS_FLOAT (operandType (right)) &&
11209       (lit < 256L))
11210     {
11211       while ((size) && (lit))
11212         {
11213           aopPut (result,
11214                   aopGet (right, offset, FALSE, FALSE),
11215                   offset);
11216           lit >>= 8;
11217           offset++;
11218           size--;
11219         }
11220       /* And now fill the rest with zeros. */
11221       if (size)
11222         {
11223           emitcode ("clr", "a");
11224         }
11225       while (size--)
11226         {
11227           aopPut (result, "a", offset);
11228           offset++;
11229         }
11230     }
11231   else
11232     {
11233       while (size--)
11234         {
11235           aopPut (result,
11236                   aopGet (right, offset, FALSE, FALSE),
11237                   offset);
11238           offset++;
11239         }
11240     }
11241   adjustArithmeticResult (ic);
11242
11243 release:
11244   freeAsmop (result, NULL, ic, TRUE);
11245   freeAsmop (right, NULL, ic, TRUE);
11246 }
11247
11248 /*-----------------------------------------------------------------*/
11249 /* genJumpTab - generates code for jump table                      */
11250 /*-----------------------------------------------------------------*/
11251 static void
11252 genJumpTab (iCode * ic)
11253 {
11254   symbol *jtab,*jtablo,*jtabhi;
11255   char *l;
11256   unsigned int count;
11257
11258   D (emitcode (";", "genJumpTab"));
11259
11260   count = elementsInSet( IC_JTLABELS (ic) );
11261
11262   if( count <= 16 )
11263     {
11264       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11265          if the switch argument is in a register.
11266          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11267       /* Peephole may not convert ljmp to sjmp or ret
11268          labelIsReturnOnly & labelInRange must check
11269          currPl->ic->op != JUMPTABLE */
11270       aopOp (IC_JTCOND (ic), ic, FALSE);
11271       /* get the condition into accumulator */
11272       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11273       MOVA (l);
11274       /* multiply by three */
11275       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11276         {
11277           emitcode ("mov", "b,#0x03");
11278           emitcode ("mul", "ab");
11279         }
11280       else
11281         {
11282           emitcode ("add", "a,acc");
11283           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11284         }
11285       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11286
11287       jtab = newiTempLabel (NULL);
11288       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11289       emitcode ("jmp", "@a+dptr");
11290       emitLabel (jtab);
11291       /* now generate the jump labels */
11292       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11293            jtab = setNextItem (IC_JTLABELS (ic)))
11294         emitcode ("ljmp", "%05d$", jtab->key + 100);
11295     }
11296   else
11297     {
11298       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11299          if the switch argument is in a register.
11300          For n>6 this algorithm may be more compact */
11301       jtablo = newiTempLabel (NULL);
11302       jtabhi = newiTempLabel (NULL);
11303
11304       /* get the condition into accumulator.
11305          Using b as temporary storage, if register push/pop is needed */
11306       aopOp (IC_JTCOND (ic), ic, FALSE);
11307       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11308       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11309           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11310         {
11311           // (MB) what if B is in use???
11312           wassertl(!BINUSE, "B was in use");
11313           emitcode ("mov", "b,%s", l);
11314           l = "b";
11315         }
11316       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11317       MOVA (l);
11318       if( count <= 112 )
11319         {
11320           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11321           emitcode ("movc", "a,@a+pc");
11322           emitcode ("push", "acc");
11323
11324           MOVA (l);
11325           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11326           emitcode ("movc", "a,@a+pc");
11327           emitcode ("push", "acc");
11328         }
11329       else
11330         {
11331           /* this scales up to n<=255, but needs two more bytes
11332              and changes dptr */
11333           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11334           emitcode ("movc", "a,@a+dptr");
11335           emitcode ("push", "acc");
11336
11337           MOVA (l);
11338           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11339           emitcode ("movc", "a,@a+dptr");
11340           emitcode ("push", "acc");
11341         }
11342
11343       emitcode ("ret", "");
11344
11345       /* now generate jump table, LSB */
11346       emitLabel (jtablo);
11347       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11348            jtab = setNextItem (IC_JTLABELS (ic)))
11349         emitcode (".db", "%05d$", jtab->key + 100);
11350
11351       /* now generate jump table, MSB */
11352       emitLabel (jtabhi);
11353       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11354            jtab = setNextItem (IC_JTLABELS (ic)))
11355          emitcode (".db", "%05d$>>8", jtab->key + 100);
11356     }
11357 }
11358
11359 /*-----------------------------------------------------------------*/
11360 /* genCast - gen code for casting                                  */
11361 /*-----------------------------------------------------------------*/
11362 static void
11363 genCast (iCode * ic)
11364 {
11365   operand *result = IC_RESULT (ic);
11366   sym_link *ctype = operandType (IC_LEFT (ic));
11367   sym_link *rtype = operandType (IC_RIGHT (ic));
11368   operand *right = IC_RIGHT (ic);
11369   int size, offset;
11370
11371   D (emitcode (";", "genCast"));
11372
11373   /* if they are equivalent then do nothing */
11374   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11375     return;
11376
11377   aopOp (right, ic, FALSE);
11378   aopOp (result, ic, FALSE);
11379
11380   /* if the result is a bit (and not a bitfield) */
11381   if (IS_BIT (OP_SYMBOL (result)->type))
11382     {
11383       assignBit (result, right);
11384       goto release;
11385     }
11386
11387   /* if they are the same size : or less */
11388   if (AOP_SIZE (result) <= AOP_SIZE (right))
11389     {
11390
11391       /* if they are in the same place */
11392       if (sameRegs (AOP (right), AOP (result)))
11393         goto release;
11394
11395       /* if they in different places then copy */
11396       size = AOP_SIZE (result);
11397       offset = 0;
11398       while (size--)
11399         {
11400           aopPut (result,
11401                   aopGet (right, offset, FALSE, FALSE),
11402                   offset);
11403           offset++;
11404         }
11405       goto release;
11406     }
11407
11408   /* if the result is of type pointer */
11409   if (IS_PTR (ctype))
11410     {
11411
11412       int p_type;
11413       sym_link *type = operandType (right);
11414       sym_link *etype = getSpec (type);
11415
11416       /* pointer to generic pointer */
11417       if (IS_GENPTR (ctype))
11418         {
11419           if (IS_PTR (type))
11420             {
11421               p_type = DCL_TYPE (type);
11422             }
11423           else
11424             {
11425               if (SPEC_SCLS(etype)==S_REGISTER) {
11426                 // let's assume it is a generic pointer
11427                 p_type=GPOINTER;
11428               } else {
11429                 /* we have to go by the storage class */
11430                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11431               }
11432             }
11433
11434           /* the first two bytes are known */
11435           size = GPTRSIZE - 1;
11436           offset = 0;
11437           while (size--)
11438             {
11439               aopPut (result,
11440                       aopGet (right, offset, FALSE, FALSE),
11441                       offset);
11442               offset++;
11443             }
11444           /* the last byte depending on type */
11445             {
11446                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11447                 char gpValStr[10];
11448
11449                 if (gpVal == -1)
11450                 {
11451                     // pointerTypeToGPByte will have bitched.
11452                     exit(1);
11453                 }
11454
11455                 sprintf(gpValStr, "#0x%02x", gpVal);
11456                 aopPut (result, gpValStr, GPTRSIZE - 1);
11457             }
11458           goto release;
11459         }
11460
11461       /* just copy the pointers */
11462       size = AOP_SIZE (result);
11463       offset = 0;
11464       while (size--)
11465         {
11466           aopPut (result,
11467                   aopGet (right, offset, FALSE, FALSE),
11468                   offset);
11469           offset++;
11470         }
11471       goto release;
11472     }
11473
11474   /* so we now know that the size of destination is greater
11475      than the size of the source */
11476   /* we move to result for the size of source */
11477   size = AOP_SIZE (right);
11478   offset = 0;
11479   while (size--)
11480     {
11481       aopPut (result,
11482               aopGet (right, offset, FALSE, FALSE),
11483               offset);
11484       offset++;
11485     }
11486
11487   /* now depending on the sign of the source && destination */
11488   size = AOP_SIZE (result) - AOP_SIZE (right);
11489   /* if unsigned or not an integral type */
11490   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11491     {
11492       while (size--)
11493         aopPut (result, zero, offset++);
11494     }
11495   else
11496     {
11497       /* we need to extend the sign :{ */
11498       char *l = aopGet (right, AOP_SIZE (right) - 1,
11499                         FALSE, FALSE);
11500       MOVA (l);
11501       emitcode ("rlc", "a");
11502       emitcode ("subb", "a,acc");
11503       while (size--)
11504         aopPut (result, "a", offset++);
11505     }
11506
11507   /* we are done hurray !!!! */
11508
11509 release:
11510   freeAsmop (result, NULL, ic, TRUE);
11511   freeAsmop (right, NULL, ic, TRUE);
11512 }
11513
11514 /*-----------------------------------------------------------------*/
11515 /* genDjnz - generate decrement & jump if not zero instrucion      */
11516 /*-----------------------------------------------------------------*/
11517 static int
11518 genDjnz (iCode * ic, iCode * ifx)
11519 {
11520   symbol *lbl, *lbl1;
11521   if (!ifx)
11522     return 0;
11523
11524   /* if the if condition has a false label
11525      then we cannot save */
11526   if (IC_FALSE (ifx))
11527     return 0;
11528
11529   /* if the minus is not of the form a = a - 1 */
11530   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11531       !IS_OP_LITERAL (IC_RIGHT (ic)))
11532     return 0;
11533
11534   if (operandLitValue (IC_RIGHT (ic)) != 1)
11535     return 0;
11536
11537   /* if the size of this greater than one then no
11538      saving */
11539   if (getSize (operandType (IC_RESULT (ic))) > 1)
11540     return 0;
11541
11542   /* otherwise we can save BIG */
11543
11544   D (emitcode (";", "genDjnz"));
11545
11546   lbl = newiTempLabel (NULL);
11547   lbl1 = newiTempLabel (NULL);
11548
11549   aopOp (IC_RESULT (ic), ic, FALSE);
11550
11551   if (AOP_NEEDSACC(IC_RESULT(ic)))
11552   {
11553       /* If the result is accessed indirectly via
11554        * the accumulator, we must explicitly write
11555        * it back after the decrement.
11556        */
11557       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11558
11559       if (strcmp(rByte, "a"))
11560       {
11561            /* Something is hopelessly wrong */
11562            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11563                    __FILE__, __LINE__);
11564            /* We can just give up; the generated code will be inefficient,
11565             * but what the hey.
11566             */
11567            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11568            return 0;
11569       }
11570       emitcode ("dec", "%s", rByte);
11571       aopPut (IC_RESULT (ic), rByte, 0);
11572       emitcode ("jnz", "%05d$", lbl->key + 100);
11573   }
11574   else if (IS_AOP_PREG (IC_RESULT (ic)))
11575     {
11576       emitcode ("dec", "%s",
11577                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11578       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11579       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11580       ifx->generated = 1;
11581       emitcode ("jnz", "%05d$", lbl->key + 100);
11582     }
11583   else
11584     {
11585       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11586                 lbl->key + 100);
11587     }
11588   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11589   emitLabel (lbl);
11590   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11591   emitLabel (lbl1);
11592
11593   if (!ifx->generated)
11594       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11595   ifx->generated = 1;
11596   return 1;
11597 }
11598
11599 /*-----------------------------------------------------------------*/
11600 /* genReceive - generate code for a receive iCode                  */
11601 /*-----------------------------------------------------------------*/
11602 static void
11603 genReceive (iCode * ic)
11604 {
11605   int size = getSize (operandType (IC_RESULT (ic)));
11606   int offset = 0;
11607
11608   D (emitcode (";", "genReceive"));
11609
11610   if (ic->argreg == 1)
11611     { /* first parameter */
11612       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11613            isOperandInPagedSpace (IC_RESULT (ic))) &&
11614           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11615            IS_TRUE_SYMOP (IC_RESULT (ic))))
11616         {
11617           regs *tempRegs[4];
11618           int receivingA = 0;
11619           int roffset = 0;
11620
11621           for (offset = 0; offset<size; offset++)
11622             if (!strcmp (fReturn[offset], "a"))
11623               receivingA = 1;
11624
11625           if (!receivingA)
11626             {
11627               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11628                 {
11629                   for (offset = size-1; offset>0; offset--)
11630                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11631                   emitcode("mov","a,%s", fReturn[0]);
11632                   _G.accInUse++;
11633                   aopOp (IC_RESULT (ic), ic, FALSE);
11634                   _G.accInUse--;
11635                   aopPut (IC_RESULT (ic), "a", offset);
11636                   for (offset = 1; offset<size; offset++)
11637                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11638                   goto release;
11639                 }
11640             }
11641           else
11642             {
11643               if (getTempRegs(tempRegs, size, ic))
11644                 {
11645                   for (offset = 0; offset<size; offset++)
11646                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11647                   aopOp (IC_RESULT (ic), ic, FALSE);
11648                   for (offset = 0; offset<size; offset++)
11649                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11650                   goto release;
11651                 }
11652             }
11653
11654           offset = fReturnSizeMCS51 - size;
11655           while (size--)
11656             {
11657               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11658                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11659               offset++;
11660             }
11661           aopOp (IC_RESULT (ic), ic, FALSE);
11662           size = AOP_SIZE (IC_RESULT (ic));
11663           offset = 0;
11664           while (size--)
11665             {
11666               emitcode ("pop", "acc");
11667               aopPut (IC_RESULT (ic), "a", offset++);
11668             }
11669         }
11670       else
11671         {
11672           _G.accInUse++;
11673           aopOp (IC_RESULT (ic), ic, FALSE);
11674           _G.accInUse--;
11675           assignResultValue (IC_RESULT (ic), NULL);
11676         }
11677     }
11678   else if (ic->argreg > 12)
11679     { /* bit parameters */
11680       regs *reg = OP_SYMBOL (IC_RESULT (ic))->regs[0];
11681
11682       BitBankUsed = 1;
11683       if (!reg || reg->rIdx != ic->argreg-5)
11684         {
11685           aopOp (IC_RESULT (ic), ic, FALSE);
11686           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11687           outBitC(IC_RESULT (ic));
11688         }
11689     }
11690   else
11691     { /* other parameters */
11692       int rb1off ;
11693       aopOp (IC_RESULT (ic), ic, FALSE);
11694       rb1off = ic->argreg;
11695       while (size--)
11696         {
11697           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11698         }
11699     }
11700
11701 release:
11702   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11703 }
11704
11705 /*-----------------------------------------------------------------*/
11706 /* genDummyRead - generate code for dummy read of volatiles        */
11707 /*-----------------------------------------------------------------*/
11708 static void
11709 genDummyRead (iCode * ic)
11710 {
11711   operand *op;
11712   int size, offset;
11713
11714   D (emitcode(";", "genDummyRead"));
11715
11716   op = IC_RIGHT (ic);
11717   if (op && IS_SYMOP (op))
11718     {
11719       aopOp (op, ic, FALSE);
11720
11721       /* if the result is a bit */
11722       if (AOP_TYPE (op) == AOP_CRY)
11723         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11724       else
11725         {
11726           /* bit variables done */
11727           /* general case */
11728           size = AOP_SIZE (op);
11729           offset = 0;
11730           while (size--)
11731           {
11732             MOVA (aopGet (op, offset, FALSE, FALSE));
11733             offset++;
11734           }
11735         }
11736
11737       freeAsmop (op, NULL, ic, TRUE);
11738     }
11739
11740   op = IC_LEFT (ic);
11741   if (op && IS_SYMOP (op))
11742     {
11743       aopOp (op, ic, FALSE);
11744
11745       /* if the result is a bit */
11746       if (AOP_TYPE (op) == AOP_CRY)
11747         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11748       else
11749         {
11750           /* bit variables done */
11751           /* general case */
11752           size = AOP_SIZE (op);
11753           offset = 0;
11754           while (size--)
11755           {
11756             MOVA (aopGet (op, offset, FALSE, FALSE));
11757             offset++;
11758           }
11759         }
11760
11761       freeAsmop (op, NULL, ic, TRUE);
11762     }
11763 }
11764
11765 /*-----------------------------------------------------------------*/
11766 /* genCritical - generate code for start of a critical sequence    */
11767 /*-----------------------------------------------------------------*/
11768 static void
11769 genCritical (iCode *ic)
11770 {
11771   symbol *tlbl = newiTempLabel (NULL);
11772
11773   D (emitcode(";", "genCritical"));
11774
11775   if (IC_RESULT (ic))
11776     {
11777       aopOp (IC_RESULT (ic), ic, TRUE);
11778       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11779       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11780       aopPut (IC_RESULT (ic), zero, 0);
11781       emitLabel (tlbl);
11782       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11783     }
11784   else
11785     {
11786       emitcode ("setb", "c");
11787       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11788       emitcode ("clr", "c");
11789       emitLabel (tlbl);
11790       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11791     }
11792 }
11793
11794 /*-----------------------------------------------------------------*/
11795 /* genEndCritical - generate code for end of a critical sequence   */
11796 /*-----------------------------------------------------------------*/
11797 static void
11798 genEndCritical (iCode *ic)
11799 {
11800   D(emitcode(";", "genEndCritical"));
11801
11802   if (IC_RIGHT (ic))
11803     {
11804       aopOp (IC_RIGHT (ic), ic, FALSE);
11805       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11806         {
11807           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11808           emitcode ("mov", "ea,c");
11809         }
11810       else
11811         {
11812           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11813             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11814           emitcode ("rrc", "a");
11815           emitcode ("mov", "ea,c");
11816         }
11817       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11818     }
11819   else
11820     {
11821       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11822       emitcode ("mov", "ea,c");
11823     }
11824 }
11825
11826 /*-----------------------------------------------------------------*/
11827 /* gen51Code - generate code for 8051 based controllers            */
11828 /*-----------------------------------------------------------------*/
11829 void
11830 gen51Code (iCode * lic)
11831 {
11832   iCode *ic;
11833   int cln = 0;
11834   /* int cseq = 0; */
11835
11836   _G.currentFunc = NULL;
11837   lineHead = lineCurr = NULL;
11838
11839   /* print the allocation information */
11840   if (allocInfo && currFunc)
11841     printAllocInfo (currFunc, codeOutBuf);
11842   /* if debug information required */
11843   if (options.debug && currFunc)
11844     {
11845       debugFile->writeFunction (currFunc, lic);
11846     }
11847   /* stack pointer name */
11848   if (options.useXstack)
11849     spname = "_spx";
11850   else
11851     spname = "sp";
11852
11853
11854   for (ic = lic; ic; ic = ic->next)
11855     {
11856       _G.current_iCode = ic;
11857
11858       if (ic->lineno && cln != ic->lineno)
11859         {
11860           if (options.debug)
11861             {
11862               debugFile->writeCLine (ic);
11863             }
11864           if (!options.noCcodeInAsm) {
11865             emitcode (";", "%s:%d: %s", ic->filename, ic->lineno,
11866                       printCLine(ic->filename, ic->lineno));
11867           }
11868           cln = ic->lineno;
11869         }
11870       #if 0
11871       if (ic->seqPoint && ic->seqPoint != cseq)
11872         {
11873           emitcode (";", "sequence point %d", ic->seqPoint);
11874           cseq = ic->seqPoint;
11875         }
11876       #endif
11877       if (options.iCodeInAsm) {
11878         char regsInUse[80];
11879         int i;
11880         const char *iLine;
11881
11882         #if 0
11883         for (i=0; i<8; i++) {
11884           sprintf (&regsInUse[i],
11885                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11886         regsInUse[i]=0;
11887         #else
11888         strcpy (regsInUse, "--------");
11889         for (i=0; i < 8; i++) {
11890           if (bitVectBitValue (ic->rMask, i))
11891             {
11892               int offset = regs8051[i].offset;
11893               regsInUse[offset] = offset + '0'; /* show rMask */
11894             }
11895         #endif
11896         }
11897         iLine = printILine(ic);
11898         emitcode(";", "[%s] ic:%d: %s", regsInUse, ic->seq, iLine);
11899         dbuf_free(iLine);
11900       }
11901       /* if the result is marked as
11902          spilt and rematerializable or code for
11903          this has already been generated then
11904          do nothing */
11905       if (resultRemat (ic) || ic->generated)
11906         continue;
11907
11908       /* depending on the operation */
11909       switch (ic->op)
11910         {
11911         case '!':
11912           genNot (ic);
11913           break;
11914
11915         case '~':
11916           genCpl (ic);
11917           break;
11918
11919         case UNARYMINUS:
11920           genUminus (ic);
11921           break;
11922
11923         case IPUSH:
11924           genIpush (ic);
11925           break;
11926
11927         case IPOP:
11928             /* IPOP happens only when trying to restore a
11929                spilt live range, if there is an ifx statement
11930              following this pop then the if statement might
11931                be using some of the registers being popped which
11932                would destory the contents of the register so
11933                we need to check for this condition and handle it */
11934           if (ic->next &&
11935               ic->next->op == IFX &&
11936               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11937             genIfx (ic->next, ic);
11938             else
11939               genIpop (ic);
11940           break;
11941
11942         case CALL:
11943           genCall (ic);
11944           break;
11945
11946         case PCALL:
11947           genPcall (ic);
11948           break;
11949
11950         case FUNCTION:
11951           genFunction (ic);
11952           break;
11953
11954         case ENDFUNCTION:
11955           genEndFunction (ic);
11956           break;
11957
11958         case RETURN:
11959           genRet (ic);
11960           break;
11961
11962         case LABEL:
11963           genLabel (ic);
11964           break;
11965
11966         case GOTO:
11967           genGoto (ic);
11968           break;
11969
11970         case '+':
11971           genPlus (ic);
11972           break;
11973
11974         case '-':
11975           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11976             genMinus (ic);
11977           break;
11978
11979         case '*':
11980           genMult (ic);
11981           break;
11982
11983         case '/':
11984           genDiv (ic);
11985           break;
11986
11987         case '%':
11988           genMod (ic);
11989           break;
11990
11991         case '>':
11992           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11993           break;
11994
11995         case '<':
11996           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11997           break;
11998
11999         case LE_OP:
12000         case GE_OP:
12001         case NE_OP:
12002
12003           /* note these two are xlated by algebraic equivalence
12004              in decorateType() in SDCCast.c */
12005           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12006                   "got '>=' or '<=' shouldn't have come here");
12007           break;
12008
12009         case EQ_OP:
12010           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12011           break;
12012
12013         case AND_OP:
12014           genAndOp (ic);
12015           break;
12016
12017         case OR_OP:
12018           genOrOp (ic);
12019           break;
12020
12021         case '^':
12022           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12023           break;
12024
12025         case '|':
12026           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12027           break;
12028
12029         case BITWISEAND:
12030           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12031           break;
12032
12033         case INLINEASM:
12034           genInline (ic);
12035           break;
12036
12037         case RRC:
12038           genRRC (ic);
12039           break;
12040
12041         case RLC:
12042           genRLC (ic);
12043           break;
12044
12045         case GETHBIT:
12046           genGetHbit (ic);
12047           break;
12048
12049         case GETABIT:
12050           genGetAbit (ic);
12051           break;
12052
12053         case GETBYTE:
12054           genGetByte (ic);
12055           break;
12056
12057         case GETWORD:
12058           genGetWord (ic);
12059           break;
12060
12061         case LEFT_OP:
12062           genLeftShift (ic);
12063           break;
12064
12065         case RIGHT_OP:
12066           genRightShift (ic);
12067           break;
12068
12069         case GET_VALUE_AT_ADDRESS:
12070           genPointerGet (ic,
12071                          hasInc (IC_LEFT (ic), ic,
12072                                  getSize (operandType (IC_RESULT (ic)))),
12073                          ifxForOp (IC_RESULT (ic), ic) );
12074           break;
12075
12076         case '=':
12077           if (POINTER_SET (ic))
12078             genPointerSet (ic,
12079                            hasInc (IC_RESULT (ic), ic,
12080                                    getSize (operandType (IC_RIGHT (ic)))));
12081           else
12082             genAssign (ic);
12083           break;
12084
12085         case IFX:
12086           genIfx (ic, NULL);
12087           break;
12088
12089         case ADDRESS_OF:
12090           genAddrOf (ic);
12091           break;
12092
12093         case JUMPTABLE:
12094           genJumpTab (ic);
12095           break;
12096
12097         case CAST:
12098           genCast (ic);
12099           break;
12100
12101         case RECEIVE:
12102           genReceive (ic);
12103           break;
12104
12105         case SEND:
12106           addSet (&_G.sendSet, ic);
12107           break;
12108
12109         case DUMMY_READ_VOLATILE:
12110           genDummyRead (ic);
12111           break;
12112
12113         case CRITICAL:
12114           genCritical (ic);
12115           break;
12116
12117         case ENDCRITICAL:
12118           genEndCritical (ic);
12119           break;
12120
12121         case SWAP:
12122           genSwap (ic);
12123           break;
12124
12125         default:
12126           ic = ic;
12127         }
12128     }
12129
12130   _G.current_iCode = NULL;
12131
12132   /* now we are ready to call the
12133      peep hole optimizer */
12134   if (!options.nopeep)
12135     peepHole (&lineHead);
12136
12137   /* now do the actual printing */
12138   printLine (lineHead, codeOutBuf);
12139   return;
12140 }