* as/mcs51/asdata.c: changed ctype['['] to BINOP
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
48 extern int allocInfo;
49
50 /* this is the down and dirty file with all kinds of
51    kludgy & hacky stuff. This is what it is all about
52    CODE GENERATION for a specific MCU . some of the
53    routines may be reusable, will have to see */
54
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
57 static char *spname;
58
59 char *fReturn8051[] =
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
64 {"a", "b"};
65
66 static unsigned short rbank = -1;
67
68 #define AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72                        AOP_TYPE(x) == AOP_R0))
73
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
75                         AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
76
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
78                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
80
81
82 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
83
84 #define R0INB   _G.bu.bs.r0InB
85 #define R1INB   _G.bu.bs.r1InB
86 #define OPINB   _G.bu.bs.OpInB
87 #define BINUSE  _G.bu.BInUse
88
89 static struct
90   {
91     short r0Pushed;
92     short r1Pushed;
93     union
94       {
95         struct
96           {
97             short r0InB : 2;//2 so we can see it overflow
98             short r1InB : 2;//2 so we can see it overflow
99             short OpInB : 2;//2 so we can see it overflow
100           } bs;
101         short BInUse;
102       } bu;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108     iCode *current_iCode;
109     symbol *currentFunc;
110   }
111 _G;
112
113 static char *rb1regs[] = {
114     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
115     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
116 };
117
118 extern int mcs51_ptrRegReq;
119 extern int mcs51_nRegs;
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define CLRC     emitcode("clr","c")
129 #define SETC     emitcode("setb","c")
130
131 static lineNode *lineHead = NULL;
132 static lineNode *lineCurr = NULL;
133
134 static unsigned char SLMask[] =
135 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
136  0xE0, 0xC0, 0x80, 0x00};
137 static unsigned char SRMask[] =
138 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
139  0x07, 0x03, 0x01, 0x00};
140
141 #define LSB     0
142 #define MSB16   1
143 #define MSB24   2
144 #define MSB32   3
145
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple    */
148 /*-----------------------------------------------------------------*/
149 static void
150 emitcode (char *inst, const char *fmt,...)
151 {
152   va_list ap;
153   char lb[INITIAL_INLINEASM];
154   char *lbp = lb;
155
156   va_start (ap, fmt);
157
158   if (inst && *inst)
159     {
160       if (fmt && *fmt)
161           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
162       else
163           SNPRINTF (lb, sizeof(lb), "%s", inst);
164       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
165     }
166   else
167       tvsprintf (lb, sizeof(lb), fmt, ap);
168
169   while (isspace (*lbp))
170       lbp++;
171
172   if (lbp && *lbp)
173       lineCurr = (lineCurr ?
174                   connectLine (lineCurr, newLineNode (lb)) :
175                   (lineHead = newLineNode (lb)));
176   lineCurr->isInline = _G.inLine;
177   lineCurr->isDebug = _G.debugLine;
178   lineCurr->ic = _G.current_iCode;
179   lineCurr->isComment = (*lbp==';');
180   va_end (ap);
181 }
182
183 /*-----------------------------------------------------------------*/
184 /* mcs51_emitDebuggerSymbol - associate the current code location  */
185 /*   with a debugger symbol                                        */
186 /*-----------------------------------------------------------------*/
187 void
188 mcs51_emitDebuggerSymbol (char * debugSym)
189 {
190   _G.debugLine = 1;
191   emitcode ("", "%s ==.", debugSym);
192   _G.debugLine = 0;
193 }
194
195 /*-----------------------------------------------------------------*/
196 /* mova - moves specified value into accumulator                   */
197 /*-----------------------------------------------------------------*/
198 static void
199 mova (const char *x)
200 {
201   /* do some early peephole optimization */
202   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
203     return;
204
205   emitcode("mov","a,%s", x);
206 }
207
208 /*-----------------------------------------------------------------*/
209 /* movc - moves specified value into the carry                     */
210 /*-----------------------------------------------------------------*/
211 static void
212 movc (const char *s)
213 {
214   if (s == zero)
215     CLRC;
216   else if (s == one)
217     SETC;
218   else if (strcmp (s, "c"))
219     {/* it's not in carry already */
220       MOVA (s);
221       /* set C, if a >= 1 */
222       emitcode ("add", "a,#0xff");
223     }
224 }
225
226 /*-----------------------------------------------------------------*/
227 /* pushB - saves register B if necessary                           */
228 /*-----------------------------------------------------------------*/
229 static bool
230 pushB (void)
231 {
232   bool pushedB = FALSE;
233
234   if (BINUSE)
235     {
236       emitcode ("push", "b");
237 //    printf("B was in use !\n");
238       pushedB = TRUE;
239     }
240   else
241     {
242       OPINB++;
243     }
244   return pushedB;
245 }
246
247 /*-----------------------------------------------------------------*/
248 /* popB - restores value of register B if necessary                */
249 /*-----------------------------------------------------------------*/
250 static void
251 popB (bool pushedB)
252 {
253   if (pushedB)
254     {
255       emitcode ("pop", "b");
256     }
257   else
258     {
259       OPINB--;
260     }
261 }
262
263 /*-----------------------------------------------------------------*/
264 /* pushReg - saves register                                        */
265 /*-----------------------------------------------------------------*/
266 static bool
267 pushReg (int index, bool bits_pushed)
268 {
269   regs * reg = mcs51_regWithIdx (index);
270   if (reg->type == REG_BIT)
271     {
272       if (!bits_pushed)
273         emitcode ("push", "%s", reg->base);
274       return TRUE;
275     }
276   else
277     emitcode ("push", "%s", reg->dname);
278   return bits_pushed;
279 }
280
281 /*-----------------------------------------------------------------*/
282 /* popReg - restores register                                      */
283 /*-----------------------------------------------------------------*/
284 static bool
285 popReg (int index, bool bits_popped)
286 {
287   regs * reg = mcs51_regWithIdx (index);
288   if (reg->type == REG_BIT)
289     {
290       if (!bits_popped)
291         emitcode ("pop", "%s", reg->base);
292       return TRUE;
293     }
294   else
295     emitcode ("pop", "%s", reg->dname);
296   return bits_popped;
297 }
298
299 /*-----------------------------------------------------------------*/
300 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
301 /*-----------------------------------------------------------------*/
302 static regs *
303 getFreePtr (iCode * ic, asmop ** aopp, bool result)
304 {
305   bool r0iu, r1iu;
306   bool r0ou, r1ou;
307
308   /* the logic: if r0 & r1 used in the instruction
309      then we are in trouble otherwise */
310
311   /* first check if r0 & r1 are used by this
312      instruction, in which case we are in trouble */
313   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
314   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
315   if (r0iu && r1iu) {
316       goto endOfWorld;
317     }
318
319   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
320   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
321
322   /* if no usage of r0 then return it */
323   if (!r0iu && !r0ou)
324     {
325       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
326       (*aopp)->type = AOP_R0;
327
328       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
329     }
330
331   /* if no usage of r1 then return it */
332   if (!r1iu && !r1ou)
333     {
334       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
335       (*aopp)->type = AOP_R1;
336
337       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
338     }
339
340   /* now we know they both have usage */
341   /* if r0 not used in this instruction */
342   if (!r0iu)
343     {
344       /* push it if not already pushed */
345       if (ic->op == IPUSH)
346         {
347           emitcode ("mov", "b,%s",
348                     mcs51_regWithIdx (R0_IDX)->dname);
349           R0INB++;
350         }
351       else if (!_G.r0Pushed)
352         {
353           emitcode ("push", "%s",
354                     mcs51_regWithIdx (R0_IDX)->dname);
355           _G.r0Pushed++;
356         }
357
358       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359       (*aopp)->type = AOP_R0;
360
361       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
362     }
363
364   /* if r1 not used then */
365
366   if (!r1iu)
367     {
368       /* push it if not already pushed */
369       if (ic->op == IPUSH)
370         {
371           emitcode ("mov", "b,%s",
372                     mcs51_regWithIdx (R1_IDX)->dname);
373           R1INB++;
374         }
375       else if (!_G.r1Pushed)
376         {
377           emitcode ("push", "%s",
378                     mcs51_regWithIdx (R1_IDX)->dname);
379           _G.r1Pushed++;
380         }
381
382       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
383       (*aopp)->type = AOP_R1;
384       return mcs51_regWithIdx (R1_IDX);
385     }
386 endOfWorld:
387   /* I said end of world, but not quite end of world yet */
388   if (result) {
389     /* we can push it on the stack */
390     (*aopp)->type = AOP_STK;
391     return NULL;
392   } else {
393     /* in the case that result AND left AND right needs a pointer reg
394        we can safely use the result's */
395     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
396       (*aopp)->type = AOP_R0;
397       return mcs51_regWithIdx (R0_IDX);
398     }
399     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
400       (*aopp)->type = AOP_R1;
401       return mcs51_regWithIdx (R1_IDX);
402     }
403   }
404
405   /* now this is REALLY the end of the world */
406   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
407           "getFreePtr should never reach here");
408   exit (1);
409 }
410
411
412 /*-----------------------------------------------------------------*/
413 /* getTempRegs - initialize an array of pointers to GPR registers */
414 /*               that are not in use. Returns 1 if the requested   */
415 /*               number of registers were available, 0 otherwise.  */
416 /*-----------------------------------------------------------------*/
417 int
418 getTempRegs(regs **tempRegs, int size, iCode *ic)
419 {
420   bitVect * freeRegs;
421   int i;
422   int offset;
423
424   if (!ic)
425     ic = _G.current_iCode;
426   if (!ic)
427     return 0;
428   if (!_G.currentFunc)
429     return 0;
430
431   freeRegs = newBitVect(8);
432   bitVectSetBit (freeRegs, R2_IDX);
433   bitVectSetBit (freeRegs, R3_IDX);
434   bitVectSetBit (freeRegs, R4_IDX);
435   bitVectSetBit (freeRegs, R5_IDX);
436   bitVectSetBit (freeRegs, R6_IDX);
437   bitVectSetBit (freeRegs, R7_IDX);
438
439   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
440     {
441       bitVect * newfreeRegs;
442       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
443       freeBitVect(freeRegs);
444       freeRegs = newfreeRegs;
445     }
446   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
447
448   offset = 0;
449   for (i=0; i<freeRegs->size; i++)
450     {
451       if (bitVectBitValue(freeRegs,i))
452         tempRegs[offset++] = mcs51_regWithIdx(i);
453       if (offset>=size)
454         {
455           freeBitVect(freeRegs);
456           return 1;
457         }
458     }
459
460   freeBitVect(freeRegs);
461   return 1;
462 }
463
464
465 /*-----------------------------------------------------------------*/
466 /* newAsmop - creates a new asmOp                                  */
467 /*-----------------------------------------------------------------*/
468 static asmop *
469 newAsmop (short type)
470 {
471   asmop *aop;
472
473   aop = Safe_calloc (1, sizeof (asmop));
474   aop->type = type;
475   return aop;
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* pointerCode - returns the code for a pointer type               */
480 /*-----------------------------------------------------------------*/
481 static int
482 pointerCode (sym_link * etype)
483 {
484
485   return PTR_TYPE (SPEC_OCLS (etype));
486
487 }
488
489 /*-----------------------------------------------------------------*/
490 /* leftRightUseAcc - returns size of accumulator use by operands   */
491 /*-----------------------------------------------------------------*/
492 static int
493 leftRightUseAcc(iCode *ic)
494 {
495   operand *op;
496   int size;
497   int accuseSize = 0;
498   int accuse = 0;
499
500   if (!ic)
501     {
502       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
503               "null iCode pointer");
504       return 0;
505     }
506
507   if (ic->op == IFX)
508     {
509       op = IC_COND (ic);
510       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
511         {
512           accuse = 1;
513           size = getSize (OP_SYMBOL (op)->type);
514           if (size>accuseSize)
515             accuseSize = size;
516         }
517     }
518   else if (ic->op == JUMPTABLE)
519     {
520       op = IC_JTCOND (ic);
521       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
522         {
523           accuse = 1;
524           size = getSize (OP_SYMBOL (op)->type);
525           if (size>accuseSize)
526             accuseSize = size;
527         }
528     }
529   else
530     {
531       op = IC_LEFT (ic);
532       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
533         {
534           accuse = 1;
535           size = getSize (OP_SYMBOL (op)->type);
536           if (size>accuseSize)
537             accuseSize = size;
538         }
539       op = IC_RIGHT (ic);
540       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
541         {
542           accuse = 1;
543           size = getSize (OP_SYMBOL (op)->type);
544           if (size>accuseSize)
545             accuseSize = size;
546         }
547     }
548
549   if (accuseSize)
550     return accuseSize;
551   else
552     return accuse;
553 }
554
555 /*-----------------------------------------------------------------*/
556 /* aopForSym - for a true symbol                                   */
557 /*-----------------------------------------------------------------*/
558 static asmop *
559 aopForSym (iCode * ic, symbol * sym, bool result)
560 {
561   asmop *aop;
562   memmap *space;
563
564   wassertl (ic != NULL, "Got a null iCode");
565   wassertl (sym != NULL, "Got a null symbol");
566
567   space = SPEC_OCLS (sym->etype);
568
569   /* if already has one */
570   if (sym->aop)
571     return sym->aop;
572
573   /* assign depending on the storage class */
574   /* if it is on the stack or indirectly addressable */
575   /* space we need to assign either r0 or r1 to it   */
576   if (sym->onStack || sym->iaccess)
577     {
578       sym->aop = aop = newAsmop (0);
579       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
580       aop->size = getSize (sym->type);
581
582       /* now assign the address of the variable to
583          the pointer register */
584       if (aop->type != AOP_STK)
585         {
586
587           if (sym->onStack)
588             {
589               char offset = ((sym->stack < 0) ?
590                          ((char) (sym->stack - _G.nRegsSaved)) :
591                          ((char) sym->stack)) & 0xff;
592
593               if ((offset >= -3) && (offset <= 3))
594                 {
595                   emitcode ("mov", "%s,%s",
596                             aop->aopu.aop_ptr->name, SYM_BP (sym));
597                   while (offset < 0)
598                     {
599                       emitcode ("dec", aop->aopu.aop_ptr->name);
600                       offset++;
601                     }
602                   while (offset > 0)
603                     {
604                       emitcode ("inc", aop->aopu.aop_ptr->name);
605                       offset--;
606                     }
607                 }
608               else
609                 {
610                   if (_G.accInUse || leftRightUseAcc (ic))
611                     emitcode ("push", "acc");
612                   emitcode ("mov", "a,%s", SYM_BP (sym));
613                   emitcode ("add", "a,#0x%02x", offset);
614                   emitcode ("mov", "%s,a",
615                             aop->aopu.aop_ptr->name);
616                   if (_G.accInUse || leftRightUseAcc (ic))
617                     emitcode ("pop", "acc");
618                 }
619             }
620           else
621             emitcode ("mov", "%s,#%s",
622                       aop->aopu.aop_ptr->name,
623                       sym->rname);
624           aop->paged = space->paged;
625         }
626       else
627         aop->aopu.aop_stk = sym->stack;
628       return aop;
629     }
630
631   /* if in bit space */
632   if (IN_BITSPACE (space))
633     {
634       sym->aop = aop = newAsmop (AOP_CRY);
635       aop->aopu.aop_dir = sym->rname;
636       aop->size = getSize (sym->type);
637       return aop;
638     }
639   /* if it is in direct space */
640   if (IN_DIRSPACE (space))
641     {
642       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
643       //printTypeChainRaw(sym->type, NULL);
644       //printf("space = %s\n", space ? space->sname : "NULL");
645       sym->aop = aop = newAsmop (AOP_DIR);
646       aop->aopu.aop_dir = sym->rname;
647       aop->size = getSize (sym->type);
648       return aop;
649     }
650
651   /* special case for a function */
652   if (IS_FUNC (sym->type))
653     {
654       sym->aop = aop = newAsmop (AOP_IMMD);
655       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
656       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
657       aop->size = getSize (sym->type);
658       return aop;
659     }
660
661   /* only remaining is far space */
662   /* in which case DPTR gets the address */
663   sym->aop = aop = newAsmop (AOP_DPTR);
664   emitcode ("mov", "dptr,#%s", sym->rname);
665   aop->size = getSize (sym->type);
666
667   /* if it is in code space */
668   if (IN_CODESPACE (space))
669     aop->code = 1;
670
671   return aop;
672 }
673
674 /*-----------------------------------------------------------------*/
675 /* aopForRemat - rematerialzes an object                           */
676 /*-----------------------------------------------------------------*/
677 static asmop *
678 aopForRemat (symbol * sym)
679 {
680   iCode *ic = sym->rematiCode;
681   asmop *aop = newAsmop (AOP_IMMD);
682   int ptr_type = 0;
683   int val = 0;
684
685   for (;;)
686     {
687       if (ic->op == '+')
688         val += (int) operandLitValue (IC_RIGHT (ic));
689       else if (ic->op == '-')
690         val -= (int) operandLitValue (IC_RIGHT (ic));
691       else if (IS_CAST_ICODE(ic)) {
692               sym_link *from_type = operandType(IC_RIGHT(ic));
693               aop->aopu.aop_immd.from_cast_remat = 1;
694               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
695               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
696               continue ;
697       } else break;
698
699       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
700     }
701
702   if (val)
703     sprintf (buffer, "(%s %c 0x%04x)",
704              OP_SYMBOL (IC_LEFT (ic))->rname,
705              val >= 0 ? '+' : '-',
706              abs (val) & 0xffff);
707   else
708     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
709
710   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
711   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
712   /* set immd2 field if required */
713   if (aop->aopu.aop_immd.from_cast_remat) {
714           sprintf(buffer,"#0x%02x",ptr_type);
715           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
716           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
717   }
718
719   return aop;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common       */
724 /*-----------------------------------------------------------------*/
725 static bool
726 regsInCommon (operand * op1, operand * op2)
727 {
728   symbol *sym1, *sym2;
729   int i;
730
731   /* if they have registers in common */
732   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
733     return FALSE;
734
735   sym1 = OP_SYMBOL (op1);
736   sym2 = OP_SYMBOL (op2);
737
738   if (sym1->nRegs == 0 || sym2->nRegs == 0)
739     return FALSE;
740
741   for (i = 0; i < sym1->nRegs; i++)
742     {
743       int j;
744       if (!sym1->regs[i])
745         continue;
746
747       for (j = 0; j < sym2->nRegs; j++)
748         {
749           if (!sym2->regs[j])
750             continue;
751
752           if (sym2->regs[j] == sym1->regs[i])
753             return TRUE;
754         }
755     }
756
757   return FALSE;
758 }
759
760 /*-----------------------------------------------------------------*/
761 /* operandsEqu - equivalent                                        */
762 /*-----------------------------------------------------------------*/
763 static bool
764 operandsEqu (operand * op1, operand * op2)
765 {
766   symbol *sym1, *sym2;
767
768   /* if they're not symbols */
769   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
770     return FALSE;
771
772   sym1 = OP_SYMBOL (op1);
773   sym2 = OP_SYMBOL (op2);
774
775   /* if both are itemps & one is spilt
776      and the other is not then false */
777   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
778       sym1->isspilt != sym2->isspilt)
779     return FALSE;
780
781   /* if they are the same */
782   if (sym1 == sym2)
783     return TRUE;
784
785   /* if they have the same rname */
786   if (sym1->rname[0] && sym2->rname[0] &&
787       strcmp (sym1->rname, sym2->rname) == 0 &&
788       !(IS_PARM (op2) && IS_ITEMP (op1)))
789     return TRUE;
790
791   /* if left is a tmp & right is not */
792   if (IS_ITEMP (op1) &&
793       !IS_ITEMP (op2) &&
794       sym1->isspilt &&
795       (sym1->usl.spillLoc == sym2))
796     return TRUE;
797
798   if (IS_ITEMP (op2) &&
799       !IS_ITEMP (op1) &&
800       sym2->isspilt &&
801       sym1->level > 0 &&
802       (sym2->usl.spillLoc == sym1))
803     return TRUE;
804
805   return FALSE;
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* sameRegs - two asmops have the same registers                   */
810 /*-----------------------------------------------------------------*/
811 static bool
812 sameRegs (asmop * aop1, asmop * aop2)
813 {
814   int i;
815
816   if (aop1 == aop2)
817     return TRUE;
818
819   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
820     return FALSE;
821
822   if (aop1->type != aop2->type)
823     return FALSE;
824
825   if (aop1->size != aop2->size)
826     return FALSE;
827
828   for (i = 0; i < aop1->size; i++)
829     if (aop1->aopu.aop_reg[i] !=
830         aop2->aopu.aop_reg[i])
831       return FALSE;
832
833   return TRUE;
834 }
835
836 /*-----------------------------------------------------------------*/
837 /* aopOp - allocates an asmop for an operand  :                    */
838 /*-----------------------------------------------------------------*/
839 static void
840 aopOp (operand * op, iCode * ic, bool result)
841 {
842   asmop *aop;
843   symbol *sym;
844   int i;
845
846   if (!op)
847     return;
848
849   /* if this a literal */
850   if (IS_OP_LITERAL (op))
851     {
852       op->aop = aop = newAsmop (AOP_LIT);
853       aop->aopu.aop_lit = op->operand.valOperand;
854       aop->size = getSize (operandType (op));
855       return;
856     }
857
858   /* if already has a asmop then continue */
859   if (op->aop )
860     return;
861
862   /* if the underlying symbol has a aop */
863   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
864     {
865       op->aop = OP_SYMBOL (op)->aop;
866       return;
867     }
868
869   /* if this is a true symbol */
870   if (IS_TRUE_SYMOP (op))
871     {
872       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
873       return;
874     }
875
876   /* this is a temporary : this has
877      only five choices :
878      a) register
879      b) spillocation
880      c) rematerialize
881      d) conditional
882      e) can be a return use only */
883
884   sym = OP_SYMBOL (op);
885
886   /* if the type is a conditional */
887   if (sym->regType == REG_CND)
888     {
889       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
890       aop->size = 0;
891       return;
892     }
893
894   /* if it is spilt then two situations
895      a) is rematerialize
896      b) has a spill location */
897   if (sym->isspilt || sym->nRegs == 0)
898     {
899
900       /* rematerialize it NOW */
901       if (sym->remat)
902         {
903           sym->aop = op->aop = aop =
904             aopForRemat (sym);
905           aop->size = getSize (sym->type);
906           return;
907         }
908
909       if (sym->accuse)
910         {
911           int i;
912           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
913           aop->size = getSize (sym->type);
914           for (i = 0; i < 2; i++)
915             aop->aopu.aop_str[i] = accUse[i];
916           return;
917         }
918
919       if (sym->ruonly)
920         {
921           unsigned i;
922
923           aop = op->aop = sym->aop = newAsmop (AOP_STR);
924           aop->size = getSize (sym->type);
925           for (i = 0; i < fReturnSizeMCS51; i++)
926             aop->aopu.aop_str[i] = fReturn[i];
927           return;
928         }
929
930       if (sym->usl.spillLoc)
931         {
932           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
933             {
934               /* force a new aop if sizes differ */
935               sym->usl.spillLoc->aop = NULL;
936             }
937           sym->aop = op->aop = aop =
938                      aopForSym (ic, sym->usl.spillLoc, result);
939           aop->size = getSize (sym->type);
940           return;
941         }
942
943       /* else must be a dummy iTemp */
944       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
945       aop->size = getSize (sym->type);
946       return;
947     }
948
949   /* if the type is a bit register */
950   if (sym->regType == REG_BIT)
951     {
952       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
953       aop->size = sym->nRegs;//1???
954       aop->aopu.aop_reg[0] = sym->regs[0];
955       aop->aopu.aop_dir = sym->regs[0]->name;
956       return;
957     }
958
959   /* must be in a register */
960   sym->aop = op->aop = aop = newAsmop (AOP_REG);
961   aop->size = sym->nRegs;
962   for (i = 0; i < sym->nRegs; i++)
963     aop->aopu.aop_reg[i] = sym->regs[i];
964 }
965
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand               */
968 /*----------------------------------------------------------------*/
969 static void
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
971 {
972   asmop *aop;
973
974   if (!op)
975     aop = aaop;
976   else
977     aop = op->aop;
978
979   if (!aop)
980     return;
981
982   if (aop->freed)
983     goto dealloc;
984
985   aop->freed = 1;
986
987   /* depending on the asmop type only three cases need work AOP_RO
988      , AOP_R1 && AOP_STK */
989   switch (aop->type)
990     {
991     case AOP_R0:
992       if (R0INB)
993         {
994           emitcode ("mov", "r0,b");
995           R0INB--;
996         }
997       else if (_G.r0Pushed)
998         {
999           if (pop)
1000             {
1001               emitcode ("pop", "ar0");
1002               _G.r0Pushed--;
1003             }
1004         }
1005       bitVectUnSetBit (ic->rUsed, R0_IDX);
1006       break;
1007
1008     case AOP_R1:
1009       if (R1INB)
1010         {
1011           emitcode ("mov", "r1,b");
1012           R1INB--;
1013         }
1014       if (_G.r1Pushed)
1015         {
1016           if (pop)
1017             {
1018               emitcode ("pop", "ar1");
1019               _G.r1Pushed--;
1020             }
1021         }
1022       bitVectUnSetBit (ic->rUsed, R1_IDX);
1023       break;
1024
1025     case AOP_STK:
1026       {
1027         int sz = aop->size;
1028         int stk = aop->aopu.aop_stk + aop->size - 1;
1029         bitVectUnSetBit (ic->rUsed, R0_IDX);
1030         bitVectUnSetBit (ic->rUsed, R1_IDX);
1031
1032         getFreePtr (ic, &aop, FALSE);
1033
1034         if (stk)
1035           {
1036             emitcode ("mov", "a,_bp");
1037             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1038             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1039           }
1040         else
1041           {
1042             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1043           }
1044
1045         while (sz--)
1046           {
1047             emitcode ("pop", "acc");
1048             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1049             if (!sz)
1050               break;
1051             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1052           }
1053         op->aop = aop;
1054         freeAsmop (op, NULL, ic, TRUE);
1055         if (_G.r1Pushed)
1056           {
1057             emitcode ("pop", "ar1");
1058             _G.r1Pushed--;
1059           }
1060
1061         if (_G.r0Pushed)
1062           {
1063             emitcode ("pop", "ar0");
1064             _G.r0Pushed--;
1065           }
1066       }
1067     }
1068
1069 dealloc:
1070   /* all other cases just dealloc */
1071   if (op)
1072     {
1073       op->aop = NULL;
1074       if (IS_SYMOP (op))
1075         {
1076           OP_SYMBOL (op)->aop = NULL;
1077           /* if the symbol has a spill */
1078           if (SPIL_LOC (op))
1079             SPIL_LOC (op)->aop = NULL;
1080         }
1081     }
1082 }
1083
1084 /*------------------------------------------------------------------*/
1085 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1086 /*                      pop r0 or r1 off stack if pushed            */
1087 /*------------------------------------------------------------------*/
1088 static void
1089 freeForBranchAsmop (operand * op)
1090 {
1091   asmop *aop;
1092
1093   if (!op)
1094     return;
1095
1096   aop = op->aop;
1097
1098   if (!aop)
1099     return;
1100
1101   if (aop->freed)
1102     return;
1103
1104   switch (aop->type)
1105     {
1106     case AOP_R0:
1107       if (R0INB)
1108         {
1109           emitcode ("mov", "r0,b");
1110         }
1111       else if (_G.r0Pushed)
1112         {
1113           emitcode ("pop", "ar0");
1114         }
1115       break;
1116
1117     case AOP_R1:
1118       if (R1INB)
1119         {
1120           emitcode ("mov", "r1,b");
1121         }
1122       else if (_G.r1Pushed)
1123         {
1124           emitcode ("pop", "ar1");
1125         }
1126       break;
1127
1128     case AOP_STK:
1129       {
1130         int sz = aop->size;
1131         int stk = aop->aopu.aop_stk + aop->size - 1;
1132
1133         emitcode ("mov", "b,r0");
1134         if (stk)
1135           {
1136             emitcode ("mov", "a,_bp");
1137             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1138             emitcode ("mov", "r0,a");
1139           }
1140         else
1141           {
1142             emitcode ("mov", "r0,_bp");
1143           }
1144
1145         while (sz--)
1146           {
1147             emitcode ("pop", "acc");
1148             emitcode ("mov", "@r0,a");
1149             if (!sz)
1150               break;
1151             emitcode ("dec", "r0");
1152           }
1153         emitcode ("mov", "r0,b");
1154       }
1155     }
1156
1157 }
1158
1159 /*-----------------------------------------------------------------*/
1160 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1161 /*                 clobber the accumulator                         */
1162 /*-----------------------------------------------------------------*/
1163 static bool
1164 aopGetUsesAcc (operand * oper, int offset)
1165 {
1166   asmop * aop = AOP (oper);
1167
1168   if (offset > (aop->size - 1))
1169     return FALSE;
1170
1171   switch (aop->type)
1172     {
1173
1174     case AOP_R0:
1175     case AOP_R1:
1176       if (aop->paged)
1177         return TRUE;
1178       return FALSE;
1179     case AOP_DPTR:
1180       return TRUE;
1181     case AOP_IMMD:
1182       return FALSE;
1183     case AOP_DIR:
1184       return FALSE;
1185     case AOP_REG:
1186       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1187       return FALSE;
1188     case AOP_CRY:
1189       return TRUE;
1190     case AOP_ACC:
1191       if (offset)
1192         return FALSE;
1193       return TRUE;
1194     case AOP_LIT:
1195       return FALSE;
1196     case AOP_STR:
1197       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1198         return TRUE;
1199       return FALSE;
1200     case AOP_DUMMY:
1201       return FALSE;
1202     default:
1203       /* Error case --- will have been caught already */
1204       wassert(0);
1205       return FALSE;
1206     }
1207 }
1208
1209 /*-----------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop                          */
1211 /*-----------------------------------------------------------------*/
1212 static char *
1213 aopGet (operand * oper, int offset, bool bit16, bool dname)
1214 {
1215   char *s = buffer;
1216   char *rs;
1217   asmop * aop = AOP (oper);
1218
1219   /* offset is greater than
1220      size then zero */
1221   if (offset > (aop->size - 1) &&
1222       aop->type != AOP_LIT)
1223     return zero;
1224
1225   /* depending on type */
1226   switch (aop->type)
1227     {
1228     case AOP_DUMMY:
1229       return zero;
1230
1231     case AOP_R0:
1232     case AOP_R1:
1233       /* if we need to increment it */
1234       while (offset > aop->coff)
1235         {
1236           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1237           aop->coff++;
1238         }
1239
1240       while (offset < aop->coff)
1241         {
1242           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1243           aop->coff--;
1244         }
1245
1246       aop->coff = offset;
1247       if (aop->paged)
1248         {
1249           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1250           return (dname ? "acc" : "a");
1251         }
1252       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1253       rs = Safe_calloc (1, strlen (s) + 1);
1254       strcpy (rs, s);
1255       return rs;
1256
1257     case AOP_DPTR:
1258       if (aop->code && aop->coff==0 && offset>=1) {
1259         emitcode ("mov", "a,#0x%02x", offset);
1260         emitcode ("movc", "a,@a+dptr");
1261         return (dname ? "acc" : "a");
1262       }
1263
1264       while (offset > aop->coff)
1265         {
1266           emitcode ("inc", "dptr");
1267           aop->coff++;
1268         }
1269
1270       while (offset < aop->coff)
1271         {
1272           emitcode ("lcall", "__decdptr");
1273           aop->coff--;
1274         }
1275
1276       aop->coff = offset;
1277       if (aop->code)
1278         {
1279           emitcode ("clr", "a");
1280           emitcode ("movc", "a,@a+dptr");
1281         }
1282       else
1283         {
1284           emitcode ("movx", "a,@dptr");
1285         }
1286       return (dname ? "acc" : "a");
1287
1288
1289     case AOP_IMMD:
1290       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1291               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1292       } else if (bit16)
1293         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1294       else if (offset)
1295         sprintf (s, "#(%s >> %d)",
1296                  aop->aopu.aop_immd.aop_immd1,
1297                  offset * 8);
1298       else
1299         sprintf (s, "#%s",
1300                  aop->aopu.aop_immd.aop_immd1);
1301       rs = Safe_calloc (1, strlen (s) + 1);
1302       strcpy (rs, s);
1303       return rs;
1304
1305     case AOP_DIR:
1306       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1307         sprintf (s, "(%s >> %d)",
1308                  aop->aopu.aop_dir, offset * 8);
1309       else if (offset)
1310         sprintf (s, "(%s + %d)",
1311                  aop->aopu.aop_dir,
1312                  offset);
1313       else
1314         sprintf (s, "%s", aop->aopu.aop_dir);
1315       rs = Safe_calloc (1, strlen (s) + 1);
1316       strcpy (rs, s);
1317       return rs;
1318
1319     case AOP_REG:
1320       if (dname)
1321         return aop->aopu.aop_reg[offset]->dname;
1322       else
1323         return aop->aopu.aop_reg[offset]->name;
1324
1325     case AOP_CRY:
1326       emitcode ("clr", "a");
1327       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1328       emitcode ("rlc", "a");
1329       return (dname ? "acc" : "a");
1330
1331     case AOP_ACC:
1332       if (!offset && dname)
1333         return "acc";
1334       return aop->aopu.aop_str[offset];
1335
1336     case AOP_LIT:
1337       return aopLiteral (aop->aopu.aop_lit, offset);
1338
1339     case AOP_STR:
1340       aop->coff = offset;
1341       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1342           dname)
1343         return "acc";
1344
1345       return aop->aopu.aop_str[offset];
1346
1347     }
1348
1349   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1350           "aopget got unsupported aop->type");
1351   exit (1);
1352 }
1353 /*-----------------------------------------------------------------*/
1354 /* aopPut - puts a string for a aop and indicates if acc is in use */
1355 /*-----------------------------------------------------------------*/
1356 static bool
1357 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1358 {
1359   char *d = buffer;
1360   bool accuse = FALSE;
1361   asmop * aop = AOP (result);
1362
1363   if (aop->size && offset > (aop->size - 1))
1364     {
1365       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1366               "aopPut got offset > aop->size");
1367       exit (1);
1368     }
1369
1370   /* will assign value to value */
1371   /* depending on where it is ofcourse */
1372   switch (aop->type)
1373     {
1374     case AOP_DUMMY:
1375       MOVA (s);         /* read s in case it was volatile */
1376       accuse = TRUE;
1377       break;
1378
1379     case AOP_DIR:
1380       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1381         sprintf (d, "(%s >> %d)",
1382                  aop->aopu.aop_dir, offset * 8);
1383       else if (offset)
1384         sprintf (d, "(%s + %d)",
1385                  aop->aopu.aop_dir, offset);
1386       else
1387         sprintf (d, "%s", aop->aopu.aop_dir);
1388
1389       if (strcmp (d, s) ||
1390           bvolatile)
1391           emitcode ("mov", "%s,%s", d, s);
1392       if (!strcmp (d, "acc"))
1393           accuse = TRUE;
1394
1395       break;
1396
1397     case AOP_REG:
1398       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1399           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1400         {
1401           if (*s == '@' ||
1402               strcmp (s, "r0") == 0 ||
1403               strcmp (s, "r1") == 0 ||
1404               strcmp (s, "r2") == 0 ||
1405               strcmp (s, "r3") == 0 ||
1406               strcmp (s, "r4") == 0 ||
1407               strcmp (s, "r5") == 0 ||
1408               strcmp (s, "r6") == 0 ||
1409               strcmp (s, "r7") == 0)
1410             emitcode ("mov", "%s,%s",
1411                       aop->aopu.aop_reg[offset]->dname, s);
1412           else
1413             emitcode ("mov", "%s,%s",
1414                       aop->aopu.aop_reg[offset]->name, s);
1415         }
1416       break;
1417
1418     case AOP_DPTR:
1419       if (aop->code)
1420         {
1421           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422                   "aopPut writing to code space");
1423           exit (1);
1424         }
1425
1426       while (offset > aop->coff)
1427         {
1428           aop->coff++;
1429           emitcode ("inc", "dptr");
1430         }
1431
1432       while (offset < aop->coff)
1433         {
1434           aop->coff--;
1435           emitcode ("lcall", "__decdptr");
1436         }
1437
1438       aop->coff = offset;
1439
1440       /* if not in accumulator */
1441       MOVA (s);
1442
1443       emitcode ("movx", "@dptr,a");
1444       break;
1445
1446     case AOP_R0:
1447     case AOP_R1:
1448       while (offset > aop->coff)
1449         {
1450           aop->coff++;
1451           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1452         }
1453       while (offset < aop->coff)
1454         {
1455           aop->coff--;
1456           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1457         }
1458       aop->coff = offset;
1459
1460       if (aop->paged)
1461         {
1462           MOVA (s);
1463           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1464
1465         }
1466       else if (*s == '@')
1467         {
1468           MOVA (s);
1469           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1470         }
1471       else if (strcmp (s, "r0") == 0 ||
1472                strcmp (s, "r1") == 0 ||
1473                strcmp (s, "r2") == 0 ||
1474                strcmp (s, "r3") == 0 ||
1475                strcmp (s, "r4") == 0 ||
1476                strcmp (s, "r5") == 0 ||
1477                strcmp (s, "r6") == 0 ||
1478                strcmp (s, "r7") == 0)
1479         {
1480           char buffer[10];
1481           sprintf (buffer, "a%s", s);
1482           emitcode ("mov", "@%s,%s",
1483                     aop->aopu.aop_ptr->name, buffer);
1484         }
1485       else
1486         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1487
1488       break;
1489
1490     case AOP_STK:
1491       if (strcmp (s, "a") == 0)
1492         emitcode ("push", "acc");
1493       else
1494         if (*s=='@') {
1495           MOVA(s);
1496           emitcode ("push", "acc");
1497         } else {
1498           emitcode ("push", s);
1499         }
1500
1501       break;
1502
1503     case AOP_CRY:
1504       /* if not bit variable */
1505       if (!aop->aopu.aop_dir)
1506         {
1507           /* inefficient: move carry into A and use jz/jnz */
1508           emitcode ("clr", "a");
1509           emitcode ("rlc", "a");
1510           accuse = TRUE;
1511         }
1512       else
1513         {
1514           if (s == zero)
1515             emitcode ("clr", "%s", aop->aopu.aop_dir);
1516           else if (s == one)
1517             emitcode ("setb", "%s", aop->aopu.aop_dir);
1518           else if (!strcmp (s, "c"))
1519             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1520           else if (strcmp (s, aop->aopu.aop_dir))
1521             {
1522               MOVA (s);
1523               /* set C, if a >= 1 */
1524               emitcode ("add", "a,#0xff");
1525               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1526             }
1527         }
1528       break;
1529
1530     case AOP_STR:
1531       aop->coff = offset;
1532       if (strcmp (aop->aopu.aop_str[offset], s) ||
1533           bvolatile)
1534         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1535       break;
1536
1537     case AOP_ACC:
1538       accuse = TRUE;
1539       aop->coff = offset;
1540       if (!offset && (strcmp (s, "acc") == 0) &&
1541           !bvolatile)
1542         break;
1543
1544       if (strcmp (aop->aopu.aop_str[offset], s) &&
1545           !bvolatile)
1546         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1547       break;
1548
1549     default:
1550       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1551               "aopPut got unsupported aop->type");
1552       exit (1);
1553     }
1554
1555     return accuse;
1556 }
1557
1558
1559 #if 0
1560 /*-----------------------------------------------------------------*/
1561 /* pointToEnd :- points to the last byte of the operand            */
1562 /*-----------------------------------------------------------------*/
1563 static void
1564 pointToEnd (asmop * aop)
1565 {
1566   int count;
1567   if (!aop)
1568     return;
1569
1570   aop->coff = count = (aop->size - 1);
1571   switch (aop->type)
1572     {
1573     case AOP_R0:
1574     case AOP_R1:
1575       while (count--)
1576         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1577       break;
1578     case AOP_DPTR:
1579       while (count--)
1580         emitcode ("inc", "dptr");
1581       break;
1582     }
1583
1584 }
1585 #endif
1586
1587 /*-----------------------------------------------------------------*/
1588 /* reAdjustPreg - points a register back to where it should        */
1589 /*-----------------------------------------------------------------*/
1590 static void
1591 reAdjustPreg (asmop * aop)
1592 {
1593   if ((aop->coff==0) || aop->size <= 1)
1594     return;
1595
1596   switch (aop->type)
1597     {
1598     case AOP_R0:
1599     case AOP_R1:
1600       while (aop->coff--)
1601         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1602       break;
1603     case AOP_DPTR:
1604       while (aop->coff--)
1605         {
1606           emitcode ("lcall", "__decdptr");
1607         }
1608       break;
1609     }
1610   aop->coff = 0;
1611 }
1612
1613 /*-----------------------------------------------------------------*/
1614 /* opIsGptr: returns non-zero if the passed operand is       */
1615 /* a generic pointer type.             */
1616 /*-----------------------------------------------------------------*/
1617 static int
1618 opIsGptr (operand * op)
1619 {
1620   sym_link *type = operandType (op);
1621
1622   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1623     {
1624       return 1;
1625     }
1626   return 0;
1627 }
1628
1629 /*-----------------------------------------------------------------*/
1630 /* getDataSize - get the operand data size                         */
1631 /*-----------------------------------------------------------------*/
1632 static int
1633 getDataSize (operand * op)
1634 {
1635   int size;
1636   size = AOP_SIZE (op);
1637   if (size == GPTRSIZE)
1638     {
1639       sym_link *type = operandType (op);
1640       if (IS_GENPTR (type))
1641         {
1642           /* generic pointer; arithmetic operations
1643            * should ignore the high byte (pointer type).
1644            */
1645           size--;
1646         }
1647     }
1648   return size;
1649 }
1650
1651 /*-----------------------------------------------------------------*/
1652 /* outAcc - output Acc                                             */
1653 /*-----------------------------------------------------------------*/
1654 static void
1655 outAcc (operand * result)
1656 {
1657   int size, offset;
1658   size = getDataSize (result);
1659   if (size)
1660     {
1661       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1662       size--;
1663       offset = 1;
1664       /* unsigned or positive */
1665       while (size--)
1666         {
1667           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1668         }
1669     }
1670 }
1671
1672 /*-----------------------------------------------------------------*/
1673 /* outBitC - output a bit C                                        */
1674 /*-----------------------------------------------------------------*/
1675 static void
1676 outBitC (operand * result)
1677 {
1678   /* if the result is bit */
1679   if (AOP_TYPE (result) == AOP_CRY)
1680     aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1681   else
1682     {
1683       emitcode ("clr", "a");
1684       emitcode ("rlc", "a");
1685       outAcc (result);
1686     }
1687 }
1688
1689 /*-----------------------------------------------------------------*/
1690 /* toBoolean - emit code for orl a,operator(sizeop)                */
1691 /*-----------------------------------------------------------------*/
1692 static void
1693 toBoolean (operand * oper)
1694 {
1695   int size = AOP_SIZE (oper) - 1;
1696   int offset = 1;
1697   bool AccUsed = FALSE;
1698   bool pushedB;
1699
1700   while (!AccUsed && size--)
1701     {
1702       AccUsed |= aopGetUsesAcc(oper, offset++);
1703     }
1704
1705   size = AOP_SIZE (oper) - 1;
1706   offset = 1;
1707   MOVA (aopGet (oper, 0, FALSE, FALSE));
1708   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1709     {
1710       pushedB = pushB ();
1711       emitcode("mov", "b,a");
1712       while (--size)
1713         {
1714           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1715           emitcode ("orl", "b,a");
1716         }
1717       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1718       emitcode ("orl", "a,b");
1719       popB (pushedB);
1720     }
1721   else
1722     {
1723       while (size--)
1724         {
1725           emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1726         }
1727     }
1728 }
1729
1730
1731 /*-----------------------------------------------------------------*/
1732 /* genNot - generate code for ! operation                          */
1733 /*-----------------------------------------------------------------*/
1734 static void
1735 genNot (iCode * ic)
1736 {
1737   symbol *tlbl;
1738
1739   D(emitcode (";     genNot",""));
1740
1741   /* assign asmOps to operand & result */
1742   aopOp (IC_LEFT (ic), ic, FALSE);
1743   aopOp (IC_RESULT (ic), ic, TRUE);
1744
1745   /* if in bit space then a special case */
1746   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1747     {
1748       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1749       emitcode ("cpl", "c");
1750       outBitC (IC_RESULT (ic));
1751       goto release;
1752     }
1753
1754   toBoolean (IC_LEFT (ic));
1755
1756   tlbl = newiTempLabel (NULL);
1757   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1758   emitcode ("", "%05d$:", tlbl->key + 100);
1759   outBitC (IC_RESULT (ic));
1760
1761 release:
1762   /* release the aops */
1763   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1764   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1765 }
1766
1767
1768 /*-----------------------------------------------------------------*/
1769 /* genCpl - generate code for complement                           */
1770 /*-----------------------------------------------------------------*/
1771 static void
1772 genCpl (iCode * ic)
1773 {
1774   int offset = 0;
1775   int size;
1776   symbol *tlbl;
1777   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1778
1779   D(emitcode (";", "genCpl"));
1780
1781   /* assign asmOps to operand & result */
1782   aopOp (IC_LEFT (ic), ic, FALSE);
1783   aopOp (IC_RESULT (ic), ic, TRUE);
1784
1785   /* special case if in bit space */
1786   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1787     {
1788       char *l;
1789
1790       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1791           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1792         {
1793           /* promotion rules are responsible for this strange result:
1794              bit -> int -> ~int -> bit
1795              uchar -> int -> ~int -> bit
1796           */
1797           werror(W_COMPLEMENT);
1798           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1799           goto release;
1800         }
1801
1802       tlbl=newiTempLabel(NULL);
1803       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1804       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1805           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1806           IS_AOP_PREG (IC_LEFT (ic)))
1807         {
1808           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1809         }
1810       else
1811         {
1812           MOVA (l);
1813           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1814         }
1815       emitcode ("", "%05d$:", tlbl->key + 100);
1816       outBitC (IC_RESULT(ic));
1817       goto release;
1818     }
1819
1820   size = AOP_SIZE (IC_RESULT (ic));
1821   while (size--)
1822     {
1823       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1824       MOVA (l);
1825       emitcode ("cpl", "a");
1826       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1827     }
1828
1829
1830 release:
1831   /* release the aops */
1832   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1833   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1834 }
1835
1836 /*-----------------------------------------------------------------*/
1837 /* genUminusFloat - unary minus for floating points                */
1838 /*-----------------------------------------------------------------*/
1839 static void
1840 genUminusFloat (operand * op, operand * result)
1841 {
1842   int size, offset = 0;
1843   char *l;
1844
1845   D(emitcode (";     genUminusFloat",""));
1846
1847   /* for this we just copy and then flip the bit */
1848
1849   size = AOP_SIZE (op) - 1;
1850
1851   while (size--)
1852     {
1853       aopPut (result,
1854               aopGet (op, offset, FALSE, FALSE),
1855               offset,
1856               isOperandVolatile (result, FALSE));
1857       offset++;
1858     }
1859
1860   l = aopGet (op, offset, FALSE, FALSE);
1861
1862   MOVA (l);
1863
1864   emitcode ("cpl", "acc.7");
1865   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1866 }
1867
1868 /*-----------------------------------------------------------------*/
1869 /* genUminus - unary minus code generation                         */
1870 /*-----------------------------------------------------------------*/
1871 static void
1872 genUminus (iCode * ic)
1873 {
1874   int offset, size;
1875   sym_link *optype, *rtype;
1876
1877
1878   D(emitcode (";     genUminus",""));
1879
1880   /* assign asmops */
1881   aopOp (IC_LEFT (ic), ic, FALSE);
1882   aopOp (IC_RESULT (ic), ic, TRUE);
1883
1884   /* if both in bit space then special
1885      case */
1886   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1887       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1888     {
1889
1890       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1891       emitcode ("cpl", "c");
1892       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1893       goto release;
1894     }
1895
1896   optype = operandType (IC_LEFT (ic));
1897   rtype = operandType (IC_RESULT (ic));
1898
1899   /* if float then do float stuff */
1900   if (IS_FLOAT (optype))
1901     {
1902       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1903       goto release;
1904     }
1905
1906   /* otherwise subtract from zero */
1907   size = AOP_SIZE (IC_LEFT (ic));
1908   offset = 0;
1909   //CLRC ;
1910   while (size--)
1911     {
1912       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1913       if (!strcmp (l, "a"))
1914         {
1915           if (offset == 0)
1916             SETC;
1917           emitcode ("cpl", "a");
1918           emitcode ("addc", "a,#0");
1919         }
1920       else
1921         {
1922           if (offset == 0)
1923             CLRC;
1924           emitcode ("clr", "a");
1925           emitcode ("subb", "a,%s", l);
1926         }
1927       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1928     }
1929
1930   /* if any remaining bytes in the result */
1931   /* we just need to propagate the sign   */
1932   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1933     {
1934       emitcode ("rlc", "a");
1935       emitcode ("subb", "a,acc");
1936       while (size--)
1937         aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1938     }
1939
1940 release:
1941   /* release the aops */
1942   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1943   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1944 }
1945
1946 /*-----------------------------------------------------------------*/
1947 /* saveRegisters - will look for a call and save the registers     */
1948 /*-----------------------------------------------------------------*/
1949 static void
1950 saveRegisters (iCode * lic)
1951 {
1952   int i;
1953   iCode *ic;
1954   bitVect *rsave;
1955
1956   /* look for call */
1957   for (ic = lic; ic; ic = ic->next)
1958     if (ic->op == CALL || ic->op == PCALL)
1959       break;
1960
1961   if (!ic)
1962     {
1963       fprintf (stderr, "found parameter push with no function call\n");
1964       return;
1965     }
1966
1967   /* if the registers have been saved already or don't need to be then
1968      do nothing */
1969   if (ic->regsSaved)
1970     return;
1971   if (IS_SYMOP(IC_LEFT(ic)) &&
1972       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1973        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1974     return;
1975
1976   /* save the registers in use at this time but skip the
1977      ones for the result */
1978   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1979                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1980
1981   ic->regsSaved = 1;
1982   if (options.useXstack)
1983     {
1984       int count = bitVectnBitsOn (rsave);
1985
1986       if (count == 1)
1987         {
1988           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1989           if (reg->type == REG_BIT)
1990             {
1991               emitcode ("mov", "a,%s", reg->base);
1992             }
1993           else
1994             {
1995               emitcode ("mov", "a,%s", reg->name);
1996             }
1997           emitcode ("mov", "r0,%s", spname);
1998           emitcode ("inc", "%s", spname);// allocate before use
1999           emitcode ("movx", "@r0,a");
2000           if (bitVectBitValue (rsave, R0_IDX))
2001             emitcode ("mov", "r0,a");
2002         }
2003       else if (count != 0)
2004         {
2005           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2006           int nBits = bitVectnBitsOn (rsavebits);
2007
2008           if (nBits != 0)
2009             {
2010               count = count - nBits + 1;
2011               /* remove all but the first bits as they are pushed all at once */
2012               rsave = bitVectCplAnd (rsave, rsavebits);
2013               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2014             }
2015
2016           if (bitVectBitValue (rsave, R0_IDX))
2017             {
2018               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2019             }
2020           emitcode ("mov", "r0,%s", spname);
2021           MOVA ("r0");
2022           emitcode ("add", "a,#%d", count);
2023           emitcode ("mov", "%s,a", spname);
2024           for (i = 0; i < mcs51_nRegs; i++)
2025             {
2026               if (bitVectBitValue (rsave, i))
2027                 {
2028                   regs * reg = mcs51_regWithIdx (i);
2029                   if (i == R0_IDX)
2030                     {
2031                       emitcode ("pop", "acc");
2032                       emitcode ("push", "acc");
2033                     }
2034                   else if (reg->type == REG_BIT)
2035                     {
2036                       emitcode ("mov", "a,%s", reg->base);
2037                     }
2038                   else
2039                     {
2040                       emitcode ("mov", "a,%s", reg->name);
2041                     }
2042                   emitcode ("movx", "@r0,a");
2043                   if (--count)
2044                     {
2045                       emitcode ("inc", "r0");
2046                     }
2047                 }
2048             }
2049           if (bitVectBitValue (rsave, R0_IDX))
2050             {
2051               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2052             }
2053         }
2054     }
2055   else
2056     {
2057       bool bits_pushed = FALSE;
2058     for (i = 0; i < mcs51_nRegs; i++)
2059       {
2060         if (bitVectBitValue (rsave, i))
2061             {
2062               bits_pushed = pushReg (i, bits_pushed);
2063             }
2064         }
2065       }
2066 }
2067
2068 /*-----------------------------------------------------------------*/
2069 /* unsaveRegisters - pop the pushed registers                      */
2070 /*-----------------------------------------------------------------*/
2071 static void
2072 unsaveRegisters (iCode * ic)
2073 {
2074   int i;
2075   bitVect *rsave;
2076
2077   /* restore the registers in use at this time but skip the
2078      ones for the result */
2079   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2080                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2081
2082   if (options.useXstack)
2083     {
2084       int count = bitVectnBitsOn (rsave);
2085
2086       if (count == 1)
2087         {
2088           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2089           emitcode ("mov", "r0,%s", spname);
2090           emitcode ("dec", "r0");
2091           emitcode ("movx", "a,@r0");
2092           if (reg->type == REG_BIT)
2093             {
2094               emitcode ("mov", "%s,a", reg->base);
2095             }
2096           else
2097             {
2098               emitcode ("mov", "%s,a", reg->name);
2099             }
2100           emitcode ("dec", "%s", spname);
2101         }
2102       else if (count != 0)
2103         {
2104           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2105           int nBits = bitVectnBitsOn (rsavebits);
2106
2107           if (nBits != 0)
2108             {
2109               count = count - nBits + 1;
2110               /* remove all but the first bits as they are popped all at once */
2111               rsave = bitVectCplAnd (rsave, rsavebits);
2112               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2113             }
2114
2115           emitcode ("mov", "r0,%s", spname);
2116           for (i = mcs51_nRegs; i >= 0; i--)
2117             {
2118               if (bitVectBitValue (rsave, i))
2119                 {
2120                   regs * reg = mcs51_regWithIdx (i);
2121                   emitcode ("dec", "r0");
2122                   emitcode ("movx", "a,@r0");
2123                   if (i == R0_IDX)
2124                     {
2125                       emitcode ("push", "acc");
2126                     }
2127                   else if (reg->type == REG_BIT)
2128                     {
2129                       emitcode ("mov", "%s,a", reg->base);
2130                     }
2131                   else
2132                     {
2133                       emitcode ("mov", "%s,a", reg->name);
2134                     }
2135                 }
2136             }
2137           emitcode ("mov", "%s,r0", spname);
2138           if (bitVectBitValue (rsave, R0_IDX))
2139             {
2140               emitcode ("pop", "ar0");
2141             }
2142         }
2143     }
2144   else
2145     {
2146       bool bits_popped = FALSE;
2147     for (i = mcs51_nRegs; i >= 0; i--)
2148       {
2149         if (bitVectBitValue (rsave, i))
2150             {
2151               bits_popped = popReg (i, bits_popped);
2152             }
2153         }
2154       }
2155 }
2156
2157
2158 /*-----------------------------------------------------------------*/
2159 /* pushSide -                */
2160 /*-----------------------------------------------------------------*/
2161 static void
2162 pushSide (operand * oper, int size)
2163 {
2164   int offset = 0;
2165   while (size--)
2166     {
2167       char *l = aopGet (oper, offset++, FALSE, TRUE);
2168       if (AOP_TYPE (oper) != AOP_REG &&
2169           AOP_TYPE (oper) != AOP_DIR &&
2170           strcmp (l, "a"))
2171         {
2172           MOVA (l);
2173           emitcode ("push", "acc");
2174         }
2175       else
2176         {
2177           emitcode ("push", "%s", l);
2178         }
2179     }
2180 }
2181
2182 /*-----------------------------------------------------------------*/
2183 /* assignResultValue - also indicates if acc is in use afterwards  */
2184 /*-----------------------------------------------------------------*/
2185 static bool
2186 assignResultValue (operand * oper, operand * func)
2187 {
2188   int offset = 0;
2189   int size = AOP_SIZE (oper);
2190   bool accuse = FALSE;
2191
2192   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2193     {
2194       outBitC (oper);
2195       return FALSE;
2196     }
2197
2198   while (size--)
2199     {
2200       accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2201       offset++;
2202     }
2203   return accuse;
2204 }
2205
2206
2207 /*-----------------------------------------------------------------*/
2208 /* genXpush - pushes onto the external stack                       */
2209 /*-----------------------------------------------------------------*/
2210 static void
2211 genXpush (iCode * ic)
2212 {
2213   asmop *aop = newAsmop (0);
2214   regs *r;
2215   int size, offset = 0;
2216
2217   D(emitcode (";     genXpush",""));
2218
2219   aopOp (IC_LEFT (ic), ic, FALSE);
2220   r = getFreePtr (ic, &aop, FALSE);
2221
2222   size = AOP_SIZE (IC_LEFT (ic));
2223
2224   if (size == 1)
2225     {
2226       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2227       emitcode ("mov", "%s,%s", r->name, spname);
2228       emitcode ("inc", "%s", spname); // allocate space first
2229       emitcode ("movx", "@%s,a", r->name);
2230     }
2231   else
2232     {
2233       // allocate space first
2234       emitcode ("mov", "%s,%s", r->name, spname);
2235       MOVA (r->name);
2236       emitcode ("add", "a,#%d", size);
2237       emitcode ("mov", "%s,a", spname);
2238
2239       while (size--)
2240         {
2241           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2242           emitcode ("movx", "@%s,a", r->name);
2243           emitcode ("inc", "%s", r->name);
2244         }
2245     }
2246
2247   freeAsmop (NULL, aop, ic, TRUE);
2248   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2249 }
2250
2251 /*-----------------------------------------------------------------*/
2252 /* genIpush - generate code for pushing this gets a little complex */
2253 /*-----------------------------------------------------------------*/
2254 static void
2255 genIpush (iCode * ic)
2256 {
2257   int size, offset = 0;
2258   char *l;
2259   char *prev = "";
2260
2261   D(emitcode (";     genIpush",""));
2262
2263   /* if this is not a parm push : ie. it is spill push
2264      and spill push is always done on the local stack */
2265   if (!ic->parmPush)
2266     {
2267
2268       /* and the item is spilt then do nothing */
2269       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2270         return;
2271
2272       aopOp (IC_LEFT (ic), ic, FALSE);
2273       size = AOP_SIZE (IC_LEFT (ic));
2274       /* push it on the stack */
2275       while (size--)
2276         {
2277           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2278           if (*l == '#')
2279             {
2280               MOVA (l);
2281               l = "acc";
2282             }
2283           emitcode ("push", "%s", l);
2284         }
2285       return;
2286     }
2287
2288   /* this is a parameter push: in this case we call
2289      the routine to find the call and save those
2290      registers that need to be saved */
2291   saveRegisters (ic);
2292
2293   /* if use external stack then call the external
2294      stack pushing routine */
2295   if (options.useXstack)
2296     {
2297       genXpush (ic);
2298       return;
2299     }
2300
2301   /* then do the push */
2302   aopOp (IC_LEFT (ic), ic, FALSE);
2303
2304   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2305   size = AOP_SIZE (IC_LEFT (ic));
2306
2307   while (size--)
2308     {
2309       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2310       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2311           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2312           strcmp (l, "a"))
2313         {
2314           if (strcmp (l, prev) || *l == '@')
2315           MOVA (l);
2316           emitcode ("push", "acc");
2317         }
2318       else
2319         {
2320           emitcode ("push", "%s", l);
2321         }
2322       prev = l;
2323     }
2324
2325   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2326 }
2327
2328 /*-----------------------------------------------------------------*/
2329 /* genIpop - recover the registers: can happen only for spilling   */
2330 /*-----------------------------------------------------------------*/
2331 static void
2332 genIpop (iCode * ic)
2333 {
2334   int size, offset;
2335
2336   D(emitcode (";     genIpop",""));
2337
2338   /* if the temp was not pushed then */
2339   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2340     return;
2341
2342   aopOp (IC_LEFT (ic), ic, FALSE);
2343   size = AOP_SIZE (IC_LEFT (ic));
2344   offset = (size - 1);
2345   while (size--)
2346     emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2347                                    FALSE, TRUE));
2348
2349   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2350 }
2351
2352 /*-----------------------------------------------------------------*/
2353 /* saveRBank - saves an entire register bank on the stack          */
2354 /*-----------------------------------------------------------------*/
2355 static void
2356 saveRBank (int bank, iCode * ic, bool pushPsw)
2357 {
2358   int i;
2359   int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2360   asmop *aop = NULL;
2361   regs *r = NULL;
2362
2363   if (options.useXstack)
2364     {
2365       if (!ic)
2366       {
2367           /* Assume r0 is available for use. */
2368           r = mcs51_regWithIdx (R0_IDX);;
2369       }
2370       else
2371       {
2372           aop = newAsmop (0);
2373           r = getFreePtr (ic, &aop, FALSE);
2374       }
2375       // allocate space first
2376       emitcode ("mov", "%s,%s", r->name, spname);
2377       MOVA (r->name);
2378       emitcode ("add", "a,#%d", count);
2379       emitcode ("mov", "%s,a", spname);
2380     }
2381
2382   for (i = 0; i < mcs51_nRegs; i++)
2383     {
2384       if (options.useXstack)
2385         {
2386           emitcode ("mov", "a,(%s+%d)",
2387                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2388           emitcode ("movx", "@%s,a", r->name);
2389           if (--count)
2390             emitcode ("inc", "%s", r->name);
2391         }
2392       else
2393         emitcode ("push", "(%s+%d)",
2394                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2395     }
2396
2397   if (pushPsw)
2398     {
2399       if (options.useXstack)
2400         {
2401           emitcode ("mov", "a,psw");
2402           emitcode ("movx", "@%s,a", r->name);
2403
2404         }
2405       else
2406         {
2407           emitcode ("push", "psw");
2408         }
2409
2410       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2411     }
2412
2413   if (aop)
2414     {
2415       freeAsmop (NULL, aop, ic, TRUE);
2416     }
2417
2418   if (ic)
2419   {
2420     ic->bankSaved = 1;
2421   }
2422 }
2423
2424 /*-----------------------------------------------------------------*/
2425 /* unsaveRBank - restores the register bank from stack             */
2426 /*-----------------------------------------------------------------*/
2427 static void
2428 unsaveRBank (int bank, iCode * ic, bool popPsw)
2429 {
2430   int i;
2431   asmop *aop = NULL;
2432   regs *r = NULL;
2433
2434   if (options.useXstack)
2435     {
2436       if (!ic)
2437         {
2438           /* Assume r0 is available for use. */
2439           r = mcs51_regWithIdx (R0_IDX);;
2440         }
2441       else
2442         {
2443           aop = newAsmop (0);
2444           r = getFreePtr (ic, &aop, FALSE);
2445         }
2446       emitcode ("mov", "%s,%s", r->name, spname);
2447     }
2448
2449   if (popPsw)
2450     {
2451       if (options.useXstack)
2452         {
2453           emitcode ("dec", "%s", r->name);
2454           emitcode ("movx", "a,@%s", r->name);
2455           emitcode ("mov", "psw,a");
2456         }
2457       else
2458         {
2459           emitcode ("pop", "psw");
2460         }
2461     }
2462
2463   for (i = (mcs51_nRegs - 1); i >= 0; i--)
2464     {
2465       if (options.useXstack)
2466         {
2467           emitcode ("dec", "%s", r->name);
2468           emitcode ("movx", "a,@%s", r->name);
2469           emitcode ("mov", "(%s+%d),a",
2470                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2471         }
2472       else
2473         {
2474           emitcode ("pop", "(%s+%d)",
2475                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2476         }
2477     }
2478
2479   if (options.useXstack)
2480     {
2481       emitcode ("mov", "%s,%s", spname, r->name);
2482     }
2483
2484   if (aop)
2485     {
2486       freeAsmop (NULL, aop, ic, TRUE);
2487     }
2488 }
2489
2490 /*-----------------------------------------------------------------*/
2491 /* genSend - gen code for SEND                                     */
2492 /*-----------------------------------------------------------------*/
2493 static void genSend(set *sendSet)
2494 {
2495     iCode *sic;
2496   int bit_count = 0;
2497
2498   /* first we do all bit parameters */
2499     for (sic = setFirstItem (sendSet); sic;
2500        sic = setNextItem (sendSet))
2501     {
2502       aopOp (IC_LEFT (sic), sic, FALSE);
2503
2504       if (sic->argreg > 12)
2505         {
2506           int bit = sic->argreg-13;
2507
2508           /* if left is a literal then
2509              we know what the value is */
2510           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2511             {
2512               if (((int) operandLitValue (IC_LEFT (sic))))
2513                   emitcode ("setb", "b[%d]", bit);
2514               else
2515                   emitcode ("clr", "b[%d]", bit);
2516             }
2517           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2518             {
2519               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2520                 if (strcmp (l, "c"))
2521                     emitcode ("mov", "c,%s", l);
2522                 emitcode ("mov", "b[%d],c", bit);
2523             }
2524           else
2525             {
2526               /* we need to or */
2527               toBoolean (IC_LEFT (sic));
2528               /* set C, if a >= 1 */
2529               emitcode ("add", "a,#0xff");
2530               emitcode ("mov", "b[%d],c", bit);
2531             }
2532           bit_count++;
2533         }
2534       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2535     }
2536
2537   if (bit_count)
2538     {
2539       saveRegisters (setFirstItem (sendSet));
2540       emitcode ("mov", "bits,b");
2541     }
2542
2543   /* then we do all other parameters */
2544   for (sic = setFirstItem (sendSet); sic;
2545        sic = setNextItem (sendSet))
2546     {
2547           int size, offset = 0;
2548           aopOp (IC_LEFT (sic), sic, FALSE);
2549           size = AOP_SIZE (IC_LEFT (sic));
2550
2551       if (sic->argreg == 1)
2552         {
2553           while (size--)
2554             {
2555               char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2556                   if (strcmp (l, fReturn[offset]))
2557                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2558                   offset++;
2559               }
2560         }
2561       else if (sic->argreg <= 12)
2562         {
2563           while (size--)
2564             {
2565               emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2566                         aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2567               offset++;
2568               }
2569           }
2570           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2571     }
2572 }
2573
2574 /*-----------------------------------------------------------------*/
2575 /* genCall - generates a call statement                            */
2576 /*-----------------------------------------------------------------*/
2577 static void
2578 genCall (iCode * ic)
2579 {
2580   sym_link *dtype;
2581 //  bool restoreBank = FALSE;
2582   bool swapBanks = FALSE;
2583   bool accuse = FALSE;
2584   bool accPushed = FALSE;
2585   bool resultInF0 = FALSE;
2586
2587   D(emitcode(";     genCall",""));
2588
2589   dtype = operandType (IC_LEFT (ic));
2590   /* if send set is not empty then assign */
2591   if (_G.sendSet)
2592     {
2593         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2594             genSend(reverseSet(_G.sendSet));
2595         } else {
2596             genSend(_G.sendSet);
2597         }
2598
2599       _G.sendSet = NULL;
2600     }
2601
2602   /* if we are calling a not _naked function that is not using
2603      the same register bank then we need to save the
2604      destination registers on the stack */
2605   dtype = operandType (IC_LEFT (ic));
2606   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2607       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2608        !IFFUNC_ISISR (dtype))
2609   {
2610       swapBanks = TRUE;
2611   }
2612
2613   /* if caller saves & we have not saved then */
2614   if (!ic->regsSaved)
2615       saveRegisters (ic);
2616
2617   if (swapBanks)
2618   {
2619         emitcode ("mov", "psw,#0x%02x",
2620            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2621   }
2622
2623   /* make the call */
2624   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2625     {
2626       if (IFFUNC_CALLEESAVES(dtype))
2627         {
2628           werror (E_BANKED_WITH_CALLEESAVES);
2629         }
2630       else
2631         {
2632           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2633                      OP_SYMBOL (IC_LEFT (ic))->rname :
2634                      OP_SYMBOL (IC_LEFT (ic))->name);
2635
2636           emitcode ("mov", "r0,#%s", l);
2637           emitcode ("mov", "r1,#(%s >> 8)", l);
2638           emitcode ("mov", "r2,#(%s >> 16)", l);
2639           emitcode ("lcall", "__sdcc_banked_call");
2640         }
2641     }
2642   else
2643     {
2644       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2645                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2646                                 OP_SYMBOL (IC_LEFT (ic))->name));
2647     }
2648
2649   if (swapBanks)
2650   {
2651       /* if result is in carry */
2652       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
2653         {
2654           emitcode ("anl", "psw,#0xE7");
2655           if (FUNC_REGBANK(currFunc->type))
2656             emitcode ("orl", "psw,#0x%02x",
2657                 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2658         }
2659       else
2660         {
2661            emitcode ("mov", "psw,#0x%02x",
2662                ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2663         }
2664     }
2665
2666   /* if we need assign a result value */
2667   if ((IS_ITEMP (IC_RESULT (ic)) &&
2668        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2669        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2670         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2671         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2672       IS_TRUE_SYMOP (IC_RESULT (ic)))
2673     {
2674
2675       _G.accInUse++;
2676       aopOp (IC_RESULT (ic), ic, FALSE);
2677       _G.accInUse--;
2678
2679       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2680
2681       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2682     }
2683
2684   /* adjust the stack for parameters if required */
2685   if (ic->parmBytes)
2686     {
2687       int i;
2688       if (ic->parmBytes > 3)
2689         {
2690           if (accuse)
2691             {
2692               emitcode ("push", "acc");
2693               accPushed = TRUE;
2694             }
2695           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2696               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2697             {
2698               emitcode ("mov", "F0,c");
2699               resultInF0 = TRUE;
2700             }
2701
2702           emitcode ("mov", "a,%s", spname);
2703           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2704           emitcode ("mov", "%s,a", spname);
2705
2706           /* unsaveRegisters from xstack needs acc, but */
2707           /* unsaveRegisters from stack needs this popped */
2708           if (accPushed && !options.useXstack)
2709             {
2710               emitcode ("pop", "acc");
2711               accPushed = FALSE;
2712             }
2713         }
2714       else
2715         for (i = 0; i < ic->parmBytes; i++)
2716           emitcode ("dec", "%s", spname);
2717     }
2718
2719   /* if we had saved some registers then unsave them */
2720   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2721     {
2722       if (accuse && !accPushed && options.useXstack)
2723         {
2724           /* xstack needs acc, but doesn't touch normal stack */
2725           emitcode ("push", "acc");
2726           accPushed = TRUE;
2727         }
2728       unsaveRegisters (ic);
2729     }
2730
2731 //  /* if register bank was saved then pop them */
2732 //  if (restoreBank)
2733 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2734
2735   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2736     {
2737       if (resultInF0)
2738           emitcode ("mov", "c,F0");
2739
2740       aopOp (IC_RESULT (ic), ic, FALSE);
2741       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2742       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2743     }
2744
2745   if (accPushed)
2746     emitcode ("pop", "acc");
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* -10l - generates a call by pointer statement                */
2751 /*-----------------------------------------------------------------*/
2752 static void
2753 genPcall (iCode * ic)
2754 {
2755   sym_link *dtype;
2756   sym_link *etype;
2757   symbol *rlbl = newiTempLabel (NULL);
2758 //  bool restoreBank=FALSE;
2759   bool swapBanks = FALSE;
2760
2761   D(emitcode(";     genPCall",""));
2762
2763   /* if caller saves & we have not saved then */
2764   if (!ic->regsSaved)
2765     saveRegisters (ic);
2766
2767   /* if we are calling a not _naked function that is not using
2768      the same register bank then we need to save the
2769      destination registers on the stack */
2770   dtype = operandType (IC_LEFT (ic))->next;
2771   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2772       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2773       !IFFUNC_ISISR (dtype))
2774   {
2775 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2776 //    restoreBank=TRUE;
2777       swapBanks = TRUE;
2778       // need caution message to user here
2779   }
2780
2781   etype = getSpec(dtype);
2782   if (IS_LITERAL(etype))
2783     {
2784       /* if send set is not empty then assign */
2785       if (_G.sendSet)
2786         {
2787           genSend(reverseSet(_G.sendSet));
2788           _G.sendSet = NULL;
2789         }
2790
2791       if (swapBanks)
2792         {
2793           emitcode ("mov", "psw,#0x%02x",
2794            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2795         }
2796
2797       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2798         {
2799           if (IFFUNC_CALLEESAVES(dtype))
2800             {
2801               werror (E_BANKED_WITH_CALLEESAVES);
2802             }
2803           else
2804             {
2805               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2806
2807               emitcode ("mov", "r0,#%s", l);
2808               emitcode ("mov", "r1,#(%s >> 8)", l);
2809               emitcode ("mov", "r2,#(%s >> 16)", l);
2810               emitcode ("lcall", "__sdcc_banked_call");
2811             }
2812         }
2813       else
2814         {
2815           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2816         }
2817     }
2818   else
2819     {
2820       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2821         {
2822           if (IFFUNC_CALLEESAVES(dtype))
2823             {
2824               werror (E_BANKED_WITH_CALLEESAVES);
2825             }
2826           else
2827             {
2828               aopOp (IC_LEFT (ic), ic, FALSE);
2829
2830               if (!swapBanks)
2831                 {
2832                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2833                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2834                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2835                 }
2836               else
2837                 {
2838                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2839                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2840                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2841                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2842                 }
2843
2844               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2845
2846               /* if send set is not empty then assign */
2847               if (_G.sendSet)
2848                 {
2849                   genSend(reverseSet(_G.sendSet));
2850                   _G.sendSet = NULL;
2851                 }
2852
2853               if (swapBanks)
2854                 {
2855                   emitcode ("mov", "psw,#0x%02x",
2856                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2857                 }
2858
2859               /* make the call */
2860               emitcode ("lcall", "__sdcc_banked_call");
2861             }
2862         }
2863       else
2864         {
2865           /* push the return address on to the stack */
2866           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2867           emitcode ("push", "acc");
2868           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2869           emitcode ("push", "acc");
2870
2871           /* now push the calling address */
2872           aopOp (IC_LEFT (ic), ic, FALSE);
2873
2874           pushSide (IC_LEFT (ic), FPTRSIZE);
2875
2876           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2877
2878           /* if send set is not empty the assign */
2879           if (_G.sendSet)
2880             {
2881               genSend(reverseSet(_G.sendSet));
2882               _G.sendSet = NULL;
2883             }
2884
2885           if (swapBanks)
2886             {
2887               emitcode ("mov", "psw,#0x%02x",
2888                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2889             }
2890
2891           /* make the call */
2892           emitcode ("ret", "");
2893           emitcode ("", "%05d$:", (rlbl->key + 100));
2894         }
2895     }
2896   if (swapBanks)
2897   {
2898        emitcode ("mov", "psw,#0x%02x",
2899           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2900   }
2901
2902   /* if we need assign a result value */
2903   if ((IS_ITEMP (IC_RESULT (ic)) &&
2904        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2905         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2906       IS_TRUE_SYMOP (IC_RESULT (ic)))
2907     {
2908
2909       _G.accInUse++;
2910       aopOp (IC_RESULT (ic), ic, FALSE);
2911       _G.accInUse--;
2912
2913       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2914
2915       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2916     }
2917
2918   /* adjust the stack for parameters if
2919      required */
2920   if (ic->parmBytes)
2921     {
2922       int i;
2923       if (ic->parmBytes > 3)
2924         {
2925           emitcode ("mov", "a,%s", spname);
2926           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2927           emitcode ("mov", "%s,a", spname);
2928         }
2929       else
2930         for (i = 0; i < ic->parmBytes; i++)
2931           emitcode ("dec", "%s", spname);
2932
2933     }
2934
2935 //  /* if register bank was saved then unsave them */
2936 //  if (restoreBank)
2937 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2938
2939   /* if we hade saved some registers then
2940      unsave them */
2941   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2942     unsaveRegisters (ic);
2943 }
2944
2945 /*-----------------------------------------------------------------*/
2946 /* resultRemat - result  is rematerializable                       */
2947 /*-----------------------------------------------------------------*/
2948 static int
2949 resultRemat (iCode * ic)
2950 {
2951   if (SKIP_IC (ic) || ic->op == IFX)
2952     return 0;
2953
2954   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2955     {
2956       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2957       if (sym->remat && !POINTER_SET (ic))
2958         return 1;
2959     }
2960
2961   return 0;
2962 }
2963
2964 #if defined(__BORLANDC__) || defined(_MSC_VER)
2965 #define STRCASECMP stricmp
2966 #else
2967 #define STRCASECMP strcasecmp
2968 #endif
2969
2970 /*-----------------------------------------------------------------*/
2971 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2972 /*-----------------------------------------------------------------*/
2973 static int
2974 regsCmp(void *p1, void *p2)
2975 {
2976   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2977 }
2978
2979 static bool
2980 inExcludeList (char *s)
2981 {
2982   const char *p = setFirstItem(options.excludeRegsSet);
2983
2984   if (p == NULL || STRCASECMP(p, "none") == 0)
2985     return FALSE;
2986
2987
2988   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2989 }
2990
2991 /*-----------------------------------------------------------------*/
2992 /* genFunction - generated code for function entry                 */
2993 /*-----------------------------------------------------------------*/
2994 static void
2995 genFunction (iCode * ic)
2996 {
2997   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
2998   sym_link *ftype;
2999   bool     switchedPSW = FALSE;
3000   int      calleesaves_saved_register = -1;
3001   int      stackAdjust = sym->stack;
3002   int      accIsFree = sym->recvSize < 4;
3003   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3004   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3005
3006   _G.nRegsSaved = 0;
3007   /* create the function header */
3008   emitcode (";", "-----------------------------------------");
3009   emitcode (";", " function %s", sym->name);
3010   emitcode (";", "-----------------------------------------");
3011
3012   emitcode ("", "%s:", sym->rname);
3013   ftype = operandType (IC_LEFT (ic));
3014   _G.currentFunc = sym;
3015
3016   if (IFFUNC_ISNAKED(ftype))
3017   {
3018       emitcode(";", "naked function: no prologue.");
3019       return;
3020   }
3021
3022   /* here we need to generate the equates for the
3023      register bank if required */
3024   if (FUNC_REGBANK (ftype) != rbank)
3025     {
3026       int i;
3027
3028       rbank = FUNC_REGBANK (ftype);
3029       for (i = 0; i < mcs51_nRegs; i++)
3030         {
3031           if (regs8051[i].type != REG_BIT)
3032             {
3033               if (strcmp (regs8051[i].base, "0") == 0)
3034                 emitcode ("", "%s = 0x%02x",
3035                           regs8051[i].dname,
3036                           8 * rbank + regs8051[i].offset);
3037               else
3038                 emitcode ("", "%s = %s + 0x%02x",
3039                           regs8051[i].dname,
3040                           regs8051[i].base,
3041                           8 * rbank + regs8051[i].offset);
3042             }
3043         }
3044     }
3045
3046   /* if this is an interrupt service routine then
3047      save acc, b, dpl, dph  */
3048   if (IFFUNC_ISISR (sym->type))
3049     {
3050
3051       if (!inExcludeList ("acc"))
3052         emitcode ("push", "acc");
3053       if (!inExcludeList ("b"))
3054         emitcode ("push", "b");
3055       if (!inExcludeList ("dpl"))
3056         emitcode ("push", "dpl");
3057       if (!inExcludeList ("dph"))
3058         emitcode ("push", "dph");
3059       /* if this isr has no bank i.e. is going to
3060          run with bank 0 , then we need to save more
3061          registers :-) */
3062       if (!FUNC_REGBANK (sym->type))
3063         {
3064
3065           /* if this function does not call any other
3066              function then we can be economical and
3067              save only those registers that are used */
3068           if (!IFFUNC_HASFCALL(sym->type))
3069             {
3070               int i;
3071
3072               /* if any registers used */
3073               if (sym->regsUsed)
3074                 {
3075                   bool bits_pushed = FALSE;
3076                   /* save the registers used */
3077                   for (i = 0; i < sym->regsUsed->size; i++)
3078                     {
3079                       if (bitVectBitValue (sym->regsUsed, i))
3080                         bits_pushed = pushReg (i, bits_pushed);
3081                     }
3082                 }
3083             }
3084           else
3085             {
3086
3087               /* this function has a function call. We cannot
3088                  determines register usage so we will have to push the
3089                  entire bank */
3090                 saveRBank (0, ic, FALSE);
3091                 if (options.parms_in_bank1) {
3092                     int i;
3093                     for (i=0; i < 8 ; i++ ) {
3094                         emitcode ("push","%s",rb1regs[i]);
3095                     }
3096                 }
3097             }
3098         }
3099         else
3100         {
3101             /* This ISR uses a non-zero bank.
3102              *
3103              * We assume that the bank is available for our
3104              * exclusive use.
3105              *
3106              * However, if this ISR calls a function which uses some
3107              * other bank, we must save that bank entirely.
3108              */
3109             unsigned long banksToSave = 0;
3110
3111             if (IFFUNC_HASFCALL(sym->type))
3112             {
3113
3114 #define MAX_REGISTER_BANKS 4
3115
3116                 iCode *i;
3117                 int ix;
3118
3119                 for (i = ic; i; i = i->next)
3120                 {
3121                     if (i->op == ENDFUNCTION)
3122                     {
3123                         /* we got to the end OK. */
3124                         break;
3125                     }
3126
3127                     if (i->op == CALL)
3128                     {
3129                         sym_link *dtype;
3130
3131                         dtype = operandType (IC_LEFT(i));
3132                         if (dtype
3133                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3134                         {
3135                              /* Mark this bank for saving. */
3136                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3137                              {
3138                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3139                              }
3140                              else
3141                              {
3142                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3143                              }
3144
3145                              /* And note that we don't need to do it in
3146                               * genCall.
3147                               */
3148                              i->bankSaved = 1;
3149                         }
3150                     }
3151                     if (i->op == PCALL)
3152                     {
3153                         /* This is a mess; we have no idea what
3154                          * register bank the called function might
3155                          * use.
3156                          *
3157                          * The only thing I can think of to do is
3158                          * throw a warning and hope.
3159                          */
3160                         werror(W_FUNCPTR_IN_USING_ISR);
3161                     }
3162                 }
3163
3164                 if (banksToSave && options.useXstack)
3165                 {
3166                     /* Since we aren't passing it an ic,
3167                      * saveRBank will assume r0 is available to abuse.
3168                      *
3169                      * So switch to our (trashable) bank now, so
3170                      * the caller's R0 isn't trashed.
3171                      */
3172                     emitcode ("push", "psw");
3173                     emitcode ("mov", "psw,#0x%02x",
3174                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3175                     switchedPSW = TRUE;
3176                 }
3177
3178                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3179                 {
3180                      if (banksToSave & (1 << ix))
3181                      {
3182                          saveRBank(ix, NULL, FALSE);
3183                      }
3184                 }
3185             }
3186             // TODO: this needs a closer look
3187             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3188         }
3189
3190       /* Set the register bank to the desired value if nothing else */
3191       /* has done so yet. */
3192       if (!switchedPSW)
3193         {
3194           emitcode ("push", "psw");
3195           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3196         }
3197     }
3198   else
3199     {
3200       /* This is a non-ISR function. The caller has already switched register */
3201       /* banks, if necessary, so just handle the callee-saves option. */
3202
3203       /* if callee-save to be used for this function
3204          then save the registers being used in this function */
3205       if (IFFUNC_CALLEESAVES(sym->type))
3206         {
3207           int i;
3208
3209           /* if any registers used */
3210           if (sym->regsUsed)
3211             {
3212               bool bits_pushed = FALSE;
3213               /* save the registers used */
3214               for (i = 0; i < sym->regsUsed->size; i++)
3215                 {
3216                   if (bitVectBitValue (sym->regsUsed, i))
3217                     {
3218                       /* remember one saved register for later usage */
3219                       if (calleesaves_saved_register < 0)
3220                         calleesaves_saved_register = i;
3221                       bits_pushed = pushReg (i, bits_pushed);
3222                       _G.nRegsSaved++;
3223                     }
3224                 }
3225             }
3226         }
3227     }
3228
3229
3230   if (fReentrant)
3231     {
3232       if (options.useXstack)
3233         {
3234           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3235             {
3236               emitcode ("mov", "r0,%s", spname);
3237               emitcode ("inc", "%s", spname);
3238               emitcode ("xch", "a,_bpx");
3239               emitcode ("movx", "@r0,a");
3240               emitcode ("inc", "r0");
3241               emitcode ("mov", "a,r0");
3242               emitcode ("xch", "a,_bpx");
3243             }
3244           if (sym->stack)
3245             {
3246               emitcode ("push", "_bp");     /* save the callers stack  */
3247               emitcode ("mov", "_bp,sp");
3248             }
3249         }
3250       else
3251         {
3252           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3253             {
3254               /* set up the stack */
3255               emitcode ("push", "_bp");     /* save the callers stack  */
3256               emitcode ("mov", "_bp,sp");
3257             }
3258         }
3259     }
3260
3261   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3262   /* before setting up the stack frame completely. */
3263   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3264     {
3265       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3266
3267       if (rsym->isitmp)
3268         {
3269           if (rsym && rsym->regType == REG_CND)
3270             rsym = NULL;
3271           if (rsym && (rsym->accuse || rsym->ruonly))
3272             rsym = NULL;
3273           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3274             rsym = rsym->usl.spillLoc;
3275         }
3276
3277       /* If the RECEIVE operand immediately spills to the first entry on the */
3278       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3279       /* rather than the usual @r0/r1 machinations. */
3280       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3281         {
3282           int ofs;
3283
3284           _G.current_iCode = ric;
3285           D(emitcode (";     genReceive",""));
3286           for (ofs=0; ofs < sym->recvSize; ofs++)
3287             {
3288               if (!strcmp (fReturn[ofs], "a"))
3289                 emitcode ("push", "acc");
3290               else
3291                 emitcode ("push", fReturn[ofs]);
3292             }
3293           stackAdjust -= sym->recvSize;
3294           if (stackAdjust<0)
3295             {
3296               assert (stackAdjust>=0);
3297               stackAdjust = 0;
3298             }
3299           _G.current_iCode = ic;
3300           ric->generated = 1;
3301           accIsFree = 1;
3302         }
3303       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3304       /* to free up the accumulator. */
3305       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3306         {
3307           int ofs;
3308
3309           _G.current_iCode = ric;
3310           D(emitcode (";     genReceive",""));
3311           for (ofs=0; ofs < sym->recvSize; ofs++)
3312             {
3313               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3314             }
3315           _G.current_iCode = ic;
3316           ric->generated = 1;
3317           accIsFree = 1;
3318         }
3319     }
3320
3321   /* adjust the stack for the function */
3322   if (stackAdjust)
3323     {
3324       int i = stackAdjust;
3325       if (i > 256)
3326         werror (W_STACK_OVERFLOW, sym->name);
3327
3328       if (i > 3 && accIsFree)
3329         {
3330           emitcode ("mov", "a,sp");
3331           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3332           emitcode ("mov", "sp,a");
3333         }
3334       else if (i > 5)
3335         {
3336           /* The accumulator is not free, so we will need another register */
3337           /* to clobber. No need to worry about a possible conflict with */
3338           /* the above early RECEIVE optimizations since they would have */
3339           /* freed the accumulator if they were generated. */
3340
3341           if (IFFUNC_CALLEESAVES(sym->type))
3342             {
3343               /* if it's a callee-saves function we need a saved register */
3344               if (calleesaves_saved_register >= 0)
3345                 {
3346                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3347                   emitcode ("mov", "a,sp");
3348                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3349                   emitcode ("mov", "sp,a");
3350                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3351                 }
3352               else
3353                 /* do it the hard way */
3354                 while (i--)
3355                   emitcode ("inc", "sp");
3356             }
3357           else
3358             {
3359               /* not callee-saves, we can clobber r0 */
3360               emitcode ("mov", "r0,a");
3361               emitcode ("mov", "a,sp");
3362               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3363               emitcode ("mov", "sp,a");
3364               emitcode ("mov", "a,r0");
3365             }
3366         }
3367       else
3368         while (i--)
3369           emitcode ("inc", "sp");
3370     }
3371
3372   if (sym->xstack)
3373     {
3374       char i = ((char) sym->xstack & 0xff);
3375
3376       if (i > 3 && accIsFree)
3377         {
3378           emitcode ("mov", "a,_spx");
3379           emitcode ("add", "a,#0x%02x", i);
3380           emitcode ("mov", "_spx,a");
3381         }
3382       else if (i > 5)
3383         {
3384           emitcode ("push", "acc");
3385           emitcode ("mov", "a,_spx");
3386           emitcode ("add", "a,#0x%02x", i);
3387           emitcode ("mov", "_spx,a");
3388           emitcode ("pop", "acc");
3389         }
3390       else
3391         {
3392           while (i--)
3393             emitcode ("inc", "_spx");
3394         }
3395     }
3396
3397   /* if critical function then turn interrupts off */
3398   if (IFFUNC_ISCRITICAL (ftype))
3399     {
3400       symbol *tlbl = newiTempLabel (NULL);
3401       emitcode ("setb", "c");
3402       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3403       emitcode ("clr", "c");
3404       emitcode ("", "%05d$:", (tlbl->key + 100));
3405       emitcode ("push", "psw"); /* save old ea via c in psw */
3406     }
3407 }
3408
3409 /*-----------------------------------------------------------------*/
3410 /* genEndFunction - generates epilogue for functions               */
3411 /*-----------------------------------------------------------------*/
3412 static void
3413 genEndFunction (iCode * ic)
3414 {
3415   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3416   lineNode *lnp = lineCurr;
3417   bitVect  *regsUsed;
3418   bitVect  *regsUsedPrologue;
3419   bitVect  *regsUnneeded;
3420   int      idx;
3421
3422   _G.currentFunc = NULL;
3423   if (IFFUNC_ISNAKED(sym->type))
3424   {
3425       emitcode(";", "naked function: no epilogue.");
3426       if (options.debug && currFunc)
3427         debugFile->writeEndFunction (currFunc, ic, 0);
3428       return;
3429   }
3430
3431   if (IFFUNC_ISCRITICAL (sym->type))
3432     {
3433       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3434         {
3435           emitcode ("rlc", "a");   /* save c in a */
3436           emitcode ("pop", "psw"); /* restore ea via c in psw */
3437           emitcode ("mov", "ea,c");
3438           emitcode ("rrc", "a");   /* restore c from a */
3439         }
3440       else
3441         {
3442           emitcode ("pop", "psw"); /* restore ea via c in psw */
3443           emitcode ("mov", "ea,c");
3444         }
3445     }
3446
3447   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3448     {
3449       if (options.useXstack)
3450         {
3451           if (sym->stack)
3452             {
3453               emitcode ("mov", "sp,_bp");
3454               emitcode ("pop", "_bp");
3455             }
3456           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3457             {
3458               emitcode ("xch", "a,_bpx");
3459               emitcode ("mov", "r0,a");
3460               emitcode ("dec", "r0");
3461               emitcode ("movx", "a,@r0");
3462               emitcode ("xch", "a,_bpx");
3463               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3464             }
3465         }
3466       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3467         {
3468           emitcode ("mov", "sp,_bp");
3469           emitcode ("pop", "_bp");
3470         }
3471     }
3472
3473   /* restore the register bank  */
3474   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3475   {
3476     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3477      || !options.useXstack)
3478     {
3479         /* Special case of ISR using non-zero bank with useXstack
3480          * is handled below.
3481          */
3482         emitcode ("pop", "psw");
3483     }
3484   }
3485
3486   if (IFFUNC_ISISR (sym->type))
3487     {
3488
3489       /* now we need to restore the registers */
3490       /* if this isr has no bank i.e. is going to
3491          run with bank 0 , then we need to save more
3492          registers :-) */
3493       if (!FUNC_REGBANK (sym->type))
3494         {
3495           /* if this function does not call any other
3496              function then we can be economical and
3497              save only those registers that are used */
3498           if (!IFFUNC_HASFCALL(sym->type))
3499             {
3500               int i;
3501
3502               /* if any registers used */
3503               if (sym->regsUsed)
3504                 {
3505                   bool bits_popped = FALSE;
3506                   /* save the registers used */
3507                   for (i = sym->regsUsed->size; i >= 0; i--)
3508                     {
3509                       if (bitVectBitValue (sym->regsUsed, i))
3510                         bits_popped = popReg (i, bits_popped);
3511                     }
3512                 }
3513             }
3514           else
3515             {
3516               if (options.parms_in_bank1) {
3517                   int i;
3518                   for (i = 7 ; i >= 0 ; i-- ) {
3519                       emitcode ("pop","%s",rb1regs[i]);
3520                   }
3521               }
3522               /* this function has  a function call cannot
3523                  determines register usage so we will have to pop the
3524                  entire bank */
3525               unsaveRBank (0, ic, FALSE);
3526             }
3527         }
3528         else
3529         {
3530             /* This ISR uses a non-zero bank.
3531              *
3532              * Restore any register banks saved by genFunction
3533              * in reverse order.
3534              */
3535             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3536             int ix;
3537
3538             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3539             {
3540                 if (savedBanks & (1 << ix))
3541                 {
3542                     unsaveRBank(ix, NULL, FALSE);
3543                 }
3544             }
3545
3546             if (options.useXstack)
3547             {
3548                 /* Restore bank AFTER calling unsaveRBank,
3549                  * since it can trash r0.
3550                  */
3551                 emitcode ("pop", "psw");
3552             }
3553         }
3554
3555       if (!inExcludeList ("dph"))
3556         emitcode ("pop", "dph");
3557       if (!inExcludeList ("dpl"))
3558         emitcode ("pop", "dpl");
3559       if (!inExcludeList ("b"))
3560         emitcode ("pop", "b");
3561       if (!inExcludeList ("acc"))
3562         emitcode ("pop", "acc");
3563
3564       /* if debug then send end of function */
3565       if (options.debug && currFunc)
3566         {
3567           debugFile->writeEndFunction (currFunc, ic, 1);
3568         }
3569
3570       emitcode ("reti", "");
3571     }
3572   else
3573     {
3574       if (IFFUNC_CALLEESAVES(sym->type))
3575         {
3576           int i;
3577
3578           /* if any registers used */
3579           if (sym->regsUsed)
3580             {
3581               /* save the registers used */
3582               for (i = sym->regsUsed->size; i >= 0; i--)
3583                 {
3584                   if (bitVectBitValue (sym->regsUsed, i) ||
3585                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3586                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3587                 }
3588             }
3589           else if (mcs51_ptrRegReq)
3590             {
3591               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3592               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3593             }
3594
3595         }
3596
3597       /* if debug then send end of function */
3598       if (options.debug && currFunc)
3599         {
3600           debugFile->writeEndFunction (currFunc, ic, 1);
3601         }
3602
3603       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3604         {
3605           emitcode ("ljmp", "__sdcc_banked_ret");
3606         }
3607       else
3608         {
3609           emitcode ("ret", "");
3610         }
3611     }
3612
3613   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3614     return;
3615
3616   /* If this was an interrupt handler using bank 0 that called another */
3617   /* function, then all registers must be saved; nothing to optimized. */
3618   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3619       && !FUNC_REGBANK(sym->type))
3620     return;
3621
3622   /* There are no push/pops to optimize if not callee-saves or ISR */
3623   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3624     return;
3625
3626   /* If there were stack parameters, we cannot optimize without also    */
3627   /* fixing all of the stack offsets; this is too dificult to consider. */
3628   if (FUNC_HASSTACKPARM(sym->type))
3629     return;
3630
3631   /* Compute the registers actually used */
3632   regsUsed = newBitVect (mcs51_nRegs);
3633   regsUsedPrologue = newBitVect (mcs51_nRegs);
3634   while (lnp)
3635     {
3636       if (lnp->ic && lnp->ic->op == FUNCTION)
3637         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3638       else
3639         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3640
3641       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3642           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3643         break;
3644       if (!lnp->prev)
3645         break;
3646       lnp = lnp->prev;
3647     }
3648
3649   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3650       && !bitVectBitValue (regsUsed, CND_IDX))
3651     {
3652       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3653       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3654           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3655         bitVectUnSetBit (regsUsed, CND_IDX);
3656     }
3657   else
3658     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3659
3660   /* If this was an interrupt handler that called another function */
3661   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3662   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3663     {
3664       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3665       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3666       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3667       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3668       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3669     }
3670
3671   /* Remove the unneeded push/pops */
3672   regsUnneeded = newBitVect (mcs51_nRegs);
3673   while (lnp)
3674     {
3675       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3676         {
3677           if (!strncmp(lnp->line, "push", 4))
3678             {
3679               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3680               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3681                 {
3682                   connectLine (lnp->prev, lnp->next);
3683                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3684                 }
3685             }
3686           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3687             {
3688               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3689               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3690                 {
3691                   connectLine (lnp->prev, lnp->next);
3692                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3693                 }
3694             }
3695         }
3696       lnp = lnp->next;
3697     }
3698
3699   for (idx = 0; idx < regsUnneeded->size; idx++)
3700     if (bitVectBitValue (regsUnneeded, idx))
3701       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3702
3703   freeBitVect (regsUnneeded);
3704   freeBitVect (regsUsed);
3705   freeBitVect (regsUsedPrologue);
3706 }
3707
3708 /*-----------------------------------------------------------------*/
3709 /* genRet - generate code for return statement                     */
3710 /*-----------------------------------------------------------------*/
3711 static void
3712 genRet (iCode * ic)
3713 {
3714   int size, offset = 0, pushed = 0;
3715
3716   D(emitcode (";     genRet",""));
3717
3718   /* if we have no return value then
3719      just generate the "ret" */
3720   if (!IC_LEFT (ic))
3721     goto jumpret;
3722
3723   /* we have something to return then
3724      move the return value into place */
3725   aopOp (IC_LEFT (ic), ic, FALSE);
3726   size = AOP_SIZE (IC_LEFT (ic));
3727
3728
3729   if (IS_BIT(_G.currentFunc->etype))
3730     {
3731       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3732       size = 0;
3733     }
3734
3735   while (size--)
3736     {
3737       char *l;
3738       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3739         {
3740           /* #NOCHANGE */
3741           l = aopGet (IC_LEFT (ic), offset++,
3742                       FALSE, TRUE);
3743           emitcode ("push", "%s", l);
3744           pushed++;
3745         }
3746       else
3747         {
3748           l = aopGet (IC_LEFT (ic), offset,
3749                       FALSE, FALSE);
3750           if (strcmp (fReturn[offset], l))
3751             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3752         }
3753     }
3754
3755   while (pushed)
3756     {
3757       pushed--;
3758       if (strcmp (fReturn[pushed], "a"))
3759         emitcode ("pop", fReturn[pushed]);
3760       else
3761         emitcode ("pop", "acc");
3762     }
3763   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3764
3765 jumpret:
3766   /* generate a jump to the return label
3767      if the next is not the return statement */
3768   if (!(ic->next && ic->next->op == LABEL &&
3769         IC_LABEL (ic->next) == returnLabel))
3770
3771     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3772
3773 }
3774
3775 /*-----------------------------------------------------------------*/
3776 /* genLabel - generates a label                                    */
3777 /*-----------------------------------------------------------------*/
3778 static void
3779 genLabel (iCode * ic)
3780 {
3781   /* special case never generate */
3782   if (IC_LABEL (ic) == entryLabel)
3783     return;
3784
3785   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3786 }
3787
3788 /*-----------------------------------------------------------------*/
3789 /* genGoto - generates a ljmp                                      */
3790 /*-----------------------------------------------------------------*/
3791 static void
3792 genGoto (iCode * ic)
3793 {
3794   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3795 }
3796
3797 /*-----------------------------------------------------------------*/
3798 /* findLabelBackwards: walks back through the iCode chain looking  */
3799 /* for the given label. Returns number of iCode instructions     */
3800 /* between that label and given ic.          */
3801 /* Returns zero if label not found.          */
3802 /*-----------------------------------------------------------------*/
3803 static int
3804 findLabelBackwards (iCode * ic, int key)
3805 {
3806   int count = 0;
3807
3808   while (ic->prev)
3809     {
3810       ic = ic->prev;
3811       count++;
3812
3813       /* If we have any pushes or pops, we cannot predict the distance.
3814          I don't like this at all, this should be dealt with in the
3815          back-end */
3816       if (ic->op == IPUSH || ic->op == IPOP) {
3817         return 0;
3818       }
3819
3820       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3821         {
3822           return count;
3823         }
3824     }
3825
3826   return 0;
3827 }
3828
3829 /*-----------------------------------------------------------------*/
3830 /* genPlusIncr :- does addition with increment if possible         */
3831 /*-----------------------------------------------------------------*/
3832 static bool
3833 genPlusIncr (iCode * ic)
3834 {
3835   unsigned int icount;
3836   unsigned int size = getDataSize (IC_RESULT (ic));
3837
3838   /* will try to generate an increment */
3839   /* if the right side is not a literal
3840      we cannot */
3841   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3842     return FALSE;
3843
3844   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3845
3846   D(emitcode (";     genPlusIncr",""));
3847
3848   /* if increment >=16 bits in register or direct space */
3849   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3850       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3851       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3852       (size > 1) &&
3853       (icount == 1))
3854     {
3855       symbol *tlbl;
3856       int emitTlbl;
3857       int labelRange;
3858
3859       /* If the next instruction is a goto and the goto target
3860        * is < 10 instructions previous to this, we can generate
3861        * jumps straight to that target.
3862        */
3863       if (ic->next && ic->next->op == GOTO
3864           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3865           && labelRange <= 10)
3866         {
3867           emitcode (";", "tail increment optimized");
3868           tlbl = IC_LABEL (ic->next);
3869           emitTlbl = 0;
3870         }
3871       else
3872         {
3873           tlbl = newiTempLabel (NULL);
3874           emitTlbl = 1;
3875         }
3876       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3877       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3878           IS_AOP_PREG (IC_RESULT (ic)))
3879         emitcode ("cjne", "%s,#0x00,%05d$",
3880                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3881                   tlbl->key + 100);
3882       else
3883         {
3884           emitcode ("clr", "a");
3885           emitcode ("cjne", "a,%s,%05d$",
3886                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3887                     tlbl->key + 100);
3888         }
3889
3890       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3891       if (size > 2)
3892         {
3893           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3894               IS_AOP_PREG (IC_RESULT (ic)))
3895             emitcode ("cjne", "%s,#0x00,%05d$",
3896                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3897                       tlbl->key + 100);
3898           else
3899             emitcode ("cjne", "a,%s,%05d$",
3900                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3901                       tlbl->key + 100);
3902
3903           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3904         }
3905       if (size > 3)
3906         {
3907           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3908               IS_AOP_PREG (IC_RESULT (ic)))
3909             emitcode ("cjne", "%s,#0x00,%05d$",
3910                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3911                       tlbl->key + 100);
3912           else
3913             {
3914               emitcode ("cjne", "a,%s,%05d$",
3915                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3916                         tlbl->key + 100);
3917             }
3918           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3919         }
3920
3921       if (emitTlbl)
3922         {
3923           emitcode ("", "%05d$:", tlbl->key + 100);
3924         }
3925       return TRUE;
3926     }
3927
3928   /* if result is dptr */
3929   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3930       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3931       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3932       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3933     {
3934       if (aopGetUsesAcc (IC_LEFT (ic), 0))
3935         return FALSE;
3936
3937       if (icount > 9)
3938         return FALSE;
3939
3940       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3941         return FALSE;
3942
3943       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3944       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3945       while (icount--)
3946         emitcode ("inc", "dptr");
3947
3948       return TRUE;
3949     }
3950
3951   /* if the literal value of the right hand side
3952      is greater than 4 then it is not worth it */
3953   if (icount > 4)
3954     return FALSE;
3955
3956   /* if the sizes are greater than 1 then we cannot */
3957   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3958       AOP_SIZE (IC_LEFT (ic)) > 1)
3959     return FALSE;
3960
3961   /* we can if the aops of the left & result match or
3962      if they are in registers and the registers are the
3963      same */
3964   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3965     {
3966
3967       if (icount > 3)
3968         {
3969           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3970           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3971           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3972         }
3973       else
3974         {
3975
3976           while (icount--)
3977             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3978         }
3979
3980       return TRUE;
3981     }
3982
3983   return FALSE;
3984 }
3985
3986 /*-----------------------------------------------------------------*/
3987 /* outBitAcc - output a bit in acc                                 */
3988 /*-----------------------------------------------------------------*/
3989 static void
3990 outBitAcc (operand * result)
3991 {
3992   symbol *tlbl = newiTempLabel (NULL);
3993   /* if the result is a bit */
3994   if (AOP_TYPE (result) == AOP_CRY)
3995     {
3996       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
3997     }
3998   else
3999     {
4000       emitcode ("jz", "%05d$", tlbl->key + 100);
4001       emitcode ("mov", "a,%s", one);
4002       emitcode ("", "%05d$:", tlbl->key + 100);
4003       outAcc (result);
4004     }
4005 }
4006
4007 /*-----------------------------------------------------------------*/
4008 /* genPlusBits - generates code for addition of two bits           */
4009 /*-----------------------------------------------------------------*/
4010 static void
4011 genPlusBits (iCode * ic)
4012 {
4013   D(emitcode (";     genPlusBits",""));
4014
4015   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4016     {
4017       symbol *lbl = newiTempLabel (NULL);
4018       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4019       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4020       emitcode ("cpl", "c");
4021       emitcode ("", "%05d$:", (lbl->key + 100));
4022       outBitC (IC_RESULT (ic));
4023     }
4024   else
4025     {
4026       emitcode ("clr", "a");
4027       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4028       emitcode ("rlc", "a");
4029       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4030       emitcode ("addc", "a,#0x00");
4031       outAcc (IC_RESULT (ic));
4032     }
4033 }
4034
4035 #if 0
4036 /* This is the original version of this code.
4037
4038  * This is being kept around for reference,
4039  * because I am not entirely sure I got it right...
4040  */
4041 static void
4042 adjustArithmeticResult (iCode * ic)
4043 {
4044   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4045       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4046       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4047     aopPut (IC_RESULT (ic),
4048             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4049             2,
4050             isOperandVolatile (IC_RESULT (ic), FALSE));
4051
4052   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4053       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4054       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4055     aopPut (IC_RESULT (ic),
4056             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4057             2,
4058             isOperandVolatile (IC_RESULT (ic), FALSE));
4059
4060   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4061       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4062       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4063       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4064       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4065     {
4066       char buffer[5];
4067       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4068       aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4069     }
4070 }
4071 #else
4072 /* This is the pure and virtuous version of this code.
4073  * I'm pretty certain it's right, but not enough to toss the old
4074  * code just yet...
4075  */
4076 static void
4077 adjustArithmeticResult (iCode * ic)
4078 {
4079   if (opIsGptr (IC_RESULT (ic)) &&
4080       opIsGptr (IC_LEFT (ic)) &&
4081       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4082     {
4083       aopPut (IC_RESULT (ic),
4084               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4085               GPTRSIZE - 1,
4086               isOperandVolatile (IC_RESULT (ic), FALSE));
4087     }
4088
4089   if (opIsGptr (IC_RESULT (ic)) &&
4090       opIsGptr (IC_RIGHT (ic)) &&
4091       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4092     {
4093       aopPut (IC_RESULT (ic),
4094               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4095               GPTRSIZE - 1,
4096               isOperandVolatile (IC_RESULT (ic), FALSE));
4097     }
4098
4099   if (opIsGptr (IC_RESULT (ic)) &&
4100       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4101       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4102       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4103       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4104     {
4105       char buffer[5];
4106       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4107       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4108     }
4109 }
4110 #endif
4111
4112 /*-----------------------------------------------------------------*/
4113 /* genPlus - generates code for addition                           */
4114 /*-----------------------------------------------------------------*/
4115 static void
4116 genPlus (iCode * ic)
4117 {
4118   int size, offset = 0;
4119   int skip_bytes = 0;
4120   char *add = "add";
4121   operand *leftOp, *rightOp;
4122   operand * op;
4123
4124   /* special cases :- */
4125
4126   D(emitcode (";     genPlus",""));
4127
4128   aopOp (IC_LEFT (ic), ic, FALSE);
4129   aopOp (IC_RIGHT (ic), ic, FALSE);
4130   aopOp (IC_RESULT (ic), ic, TRUE);
4131
4132   /* if literal, literal on the right or
4133      if left requires ACC or right is already
4134      in ACC */
4135   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4136       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4137       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4138     {
4139       operand *t = IC_RIGHT (ic);
4140       IC_RIGHT (ic) = IC_LEFT (ic);
4141       IC_LEFT (ic) = t;
4142     }
4143
4144   /* if both left & right are in bit
4145      space */
4146   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4147       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4148     {
4149       genPlusBits (ic);
4150       goto release;
4151     }
4152
4153   /* if left in bit space & right literal */
4154   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4155       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4156     {
4157       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4158       /* if result in bit space */
4159       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4160         {
4161           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4162             emitcode ("cpl", "c");
4163           outBitC (IC_RESULT (ic));
4164         }
4165       else
4166         {
4167           size = getDataSize (IC_RESULT (ic));
4168           while (size--)
4169             {
4170               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4171               emitcode ("addc", "a,#00");
4172               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4173             }
4174         }
4175       goto release;
4176     }
4177
4178   /* if I can do an increment instead
4179      of add then GOOD for ME */
4180   if (genPlusIncr (ic) == TRUE)
4181     goto release;
4182
4183   size = getDataSize (IC_RESULT (ic));
4184   leftOp = IC_LEFT(ic);
4185   rightOp = IC_RIGHT(ic);
4186   op=IC_LEFT(ic);
4187
4188   /* if this is an add for an array access
4189      at a 256 byte boundary */
4190   if ( 2 == size
4191        && AOP_TYPE (op) == AOP_IMMD
4192        && IS_SYMOP (op)
4193        && IS_SPEC (OP_SYM_ETYPE (op))
4194        && SPEC_ABSA (OP_SYM_ETYPE (op))
4195        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4196      )
4197     {
4198       D(emitcode (";     genPlus aligned array",""));
4199       aopPut (IC_RESULT (ic),
4200               aopGet (rightOp, 0, FALSE, FALSE),
4201               0,
4202               isOperandVolatile (IC_RESULT (ic), FALSE));
4203
4204       if( 1 == getDataSize (IC_RIGHT (ic)) )
4205         {
4206           aopPut (IC_RESULT (ic),
4207                   aopGet (leftOp, 1, FALSE, FALSE),
4208                   1,
4209                   isOperandVolatile (IC_RESULT (ic), FALSE));
4210         }
4211       else
4212         {
4213           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4214           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4215           aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4216         }
4217       goto release;
4218     }
4219
4220   /* if the lower bytes of a literal are zero skip the addition */
4221   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4222     {
4223        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4224               (skip_bytes+1 < size))
4225          {
4226            skip_bytes++;
4227          }
4228        if (skip_bytes)
4229          D(emitcode (";     genPlus shortcut",""));
4230     }
4231
4232   while (size--)
4233     {
4234       if( offset >= skip_bytes )
4235         {
4236           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4237             {
4238               bool pushedB;
4239               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4240               pushedB = pushB ();
4241               emitcode("xch", "a,b");
4242               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4243               emitcode (add, "a,b");
4244               popB (pushedB);
4245             }
4246           else if (aopGetUsesAcc (leftOp, offset))
4247             {
4248               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4249               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4250             }
4251           else
4252             {
4253               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4254               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4255             }
4256           aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4257           add = "addc";  /* further adds must propagate carry */
4258         }
4259       else
4260         {
4261           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4262               isOperandVolatile (IC_RESULT (ic), FALSE))
4263             {
4264               /* just move */
4265               aopPut (IC_RESULT (ic),
4266                       aopGet (leftOp, offset, FALSE, FALSE),
4267                       offset,
4268                       isOperandVolatile (IC_RESULT (ic), FALSE));
4269             }
4270         }
4271       offset++;
4272     }
4273
4274   adjustArithmeticResult (ic);
4275
4276 release:
4277   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4278   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4279   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4280 }
4281
4282 /*-----------------------------------------------------------------*/
4283 /* genMinusDec :- does subtraction with deccrement if possible     */
4284 /*-----------------------------------------------------------------*/
4285 static bool
4286 genMinusDec (iCode * ic)
4287 {
4288   unsigned int icount;
4289   unsigned int size = getDataSize (IC_RESULT (ic));
4290
4291   /* will try to generate an increment */
4292   /* if the right side is not a literal
4293      we cannot */
4294   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4295     return FALSE;
4296
4297   /* if the literal value of the right hand side
4298      is greater than 4 then it is not worth it */
4299   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4300     return FALSE;
4301
4302   D(emitcode (";     genMinusDec",""));
4303
4304   /* if decrement >=16 bits in register or direct space */
4305   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4306       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4307       (size > 1) &&
4308       (icount == 1))
4309     {
4310       symbol *tlbl;
4311       int emitTlbl;
4312       int labelRange;
4313
4314       /* If the next instruction is a goto and the goto target
4315        * is <= 10 instructions previous to this, we can generate
4316        * jumps straight to that target.
4317        */
4318       if (ic->next && ic->next->op == GOTO
4319           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4320           && labelRange <= 10)
4321         {
4322           emitcode (";", "tail decrement optimized");
4323           tlbl = IC_LABEL (ic->next);
4324           emitTlbl = 0;
4325         }
4326       else
4327         {
4328           tlbl = newiTempLabel (NULL);
4329           emitTlbl = 1;
4330         }
4331
4332       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4333       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4334           IS_AOP_PREG (IC_RESULT (ic)))
4335         emitcode ("cjne", "%s,#0xff,%05d$"
4336                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4337                   ,tlbl->key + 100);
4338       else
4339         {
4340           emitcode ("mov", "a,#0xff");
4341           emitcode ("cjne", "a,%s,%05d$"
4342                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4343                     ,tlbl->key + 100);
4344         }
4345       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4346       if (size > 2)
4347         {
4348           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4349               IS_AOP_PREG (IC_RESULT (ic)))
4350             emitcode ("cjne", "%s,#0xff,%05d$"
4351                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4352                       ,tlbl->key + 100);
4353           else
4354             {
4355               emitcode ("cjne", "a,%s,%05d$"
4356                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4357                         ,tlbl->key + 100);
4358             }
4359           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4360         }
4361       if (size > 3)
4362         {
4363           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4364               IS_AOP_PREG (IC_RESULT (ic)))
4365             emitcode ("cjne", "%s,#0xff,%05d$"
4366                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4367                       ,tlbl->key + 100);
4368           else
4369             {
4370               emitcode ("cjne", "a,%s,%05d$"
4371                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4372                         ,tlbl->key + 100);
4373             }
4374           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4375         }
4376       if (emitTlbl)
4377         {
4378           emitcode ("", "%05d$:", tlbl->key + 100);
4379         }
4380       return TRUE;
4381     }
4382
4383   /* if the sizes are greater than 1 then we cannot */
4384   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4385       AOP_SIZE (IC_LEFT (ic)) > 1)
4386     return FALSE;
4387
4388   /* we can if the aops of the left & result match or
4389      if they are in registers and the registers are the
4390      same */
4391   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4392     {
4393
4394       while (icount--)
4395         emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4396
4397       return TRUE;
4398     }
4399
4400   return FALSE;
4401 }
4402
4403 /*-----------------------------------------------------------------*/
4404 /* addSign - complete with sign                                    */
4405 /*-----------------------------------------------------------------*/
4406 static void
4407 addSign (operand * result, int offset, int sign)
4408 {
4409   int size = (getDataSize (result) - offset);
4410   if (size > 0)
4411     {
4412       if (sign)
4413         {
4414           emitcode ("rlc", "a");
4415           emitcode ("subb", "a,acc");
4416           while (size--)
4417             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4418         }
4419       else
4420         while (size--)
4421           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4422     }
4423 }
4424
4425 /*-----------------------------------------------------------------*/
4426 /* genMinusBits - generates code for subtraction  of two bits      */
4427 /*-----------------------------------------------------------------*/
4428 static void
4429 genMinusBits (iCode * ic)
4430 {
4431   symbol *lbl = newiTempLabel (NULL);
4432
4433   D(emitcode (";     genMinusBits",""));
4434
4435   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4436     {
4437       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4438       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4439       emitcode ("cpl", "c");
4440       emitcode ("", "%05d$:", (lbl->key + 100));
4441       outBitC (IC_RESULT (ic));
4442     }
4443   else
4444     {
4445       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4446       emitcode ("subb", "a,acc");
4447       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4448       emitcode ("inc", "a");
4449       emitcode ("", "%05d$:", (lbl->key + 100));
4450       aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4451       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4452     }
4453 }
4454
4455 /*-----------------------------------------------------------------*/
4456 /* genMinus - generates code for subtraction                       */
4457 /*-----------------------------------------------------------------*/
4458 static void
4459 genMinus (iCode * ic)
4460 {
4461   int size, offset = 0;
4462
4463   D(emitcode (";     genMinus",""));
4464
4465   aopOp (IC_LEFT (ic), ic, FALSE);
4466   aopOp (IC_RIGHT (ic), ic, FALSE);
4467   aopOp (IC_RESULT (ic), ic, TRUE);
4468
4469   /* special cases :- */
4470   /* if both left & right are in bit space */
4471   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4472       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4473     {
4474       genMinusBits (ic);
4475       goto release;
4476     }
4477
4478   /* if I can do an decrement instead
4479      of subtract then GOOD for ME */
4480   if (genMinusDec (ic) == TRUE)
4481     goto release;
4482
4483   size = getDataSize (IC_RESULT (ic));
4484
4485   /* if literal, add a,#-lit, else normal subb */
4486   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4487     {
4488       unsigned long lit = 0L;
4489       bool useCarry = FALSE;
4490
4491       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4492       lit = -(long) lit;
4493
4494       while (size--)
4495         {
4496           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) {
4497             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4498             if (!offset && !size && lit== (unsigned long) -1) {
4499               emitcode ("dec", "a");
4500             } else if (!useCarry) {
4501           /* first add without previous c */
4502               emitcode ("add", "a,#0x%02x",
4503                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4504               useCarry = TRUE;
4505           } else {
4506             emitcode ("addc", "a,#0x%02x",
4507                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4508           }
4509             aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4510             } else {
4511               /* no need to add zeroes */
4512               offset++;
4513             }
4514         }
4515     }
4516   else
4517     {
4518       operand *leftOp, *rightOp;
4519
4520       leftOp = IC_LEFT(ic);
4521       rightOp = IC_RIGHT(ic);
4522
4523       while (size--)
4524         {
4525           if (aopGetUsesAcc(rightOp, offset)) {
4526             if (aopGetUsesAcc(leftOp, offset)) {
4527               bool pushedB;
4528
4529               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4530               pushedB = pushB ();
4531               emitcode ("mov", "b,a");
4532               if (offset == 0)
4533                 CLRC;
4534               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4535               emitcode ("subb", "a,b");
4536               popB (pushedB);
4537             } else {
4538               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4539               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4540               if (offset == 0) {
4541                 emitcode( "setb", "c");
4542               }
4543               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4544               emitcode("cpl", "a");
4545             }
4546           } else {
4547             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4548             if (offset == 0)
4549               CLRC;
4550             emitcode ("subb", "a,%s",
4551                       aopGet(rightOp, offset, FALSE, TRUE));
4552           }
4553
4554           aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4555         }
4556     }
4557
4558
4559   adjustArithmeticResult (ic);
4560
4561 release:
4562   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4563   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4564   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4565 }
4566
4567
4568 /*-----------------------------------------------------------------*/
4569 /* genMultbits :- multiplication of bits                           */
4570 /*-----------------------------------------------------------------*/
4571 static void
4572 genMultbits (operand * left,
4573              operand * right,
4574              operand * result)
4575 {
4576   D(emitcode (";     genMultbits",""));
4577
4578   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4580   outBitC (result);
4581 }
4582
4583 /*-----------------------------------------------------------------*/
4584 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4585 /*-----------------------------------------------------------------*/
4586 static void
4587 genMultOneByte (operand * left,
4588                 operand * right,
4589                 operand * result)
4590 {
4591   symbol *lbl;
4592   int size = AOP_SIZE (result);
4593   bool runtimeSign, compiletimeSign;
4594   bool lUnsigned, rUnsigned, pushedB;
4595
4596   D(emitcode (";     genMultOneByte",""));
4597
4598   if (size < 1 || size > 2)
4599     {
4600       /* this should never happen */
4601       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4602                AOP_SIZE(result), __FILE__, lineno);
4603       exit (1);
4604     }
4605
4606   /* (if two literals: the value is computed before) */
4607   /* if one literal, literal on the right */
4608   if (AOP_TYPE (left) == AOP_LIT)
4609     {
4610       operand *t = right;
4611       right = left;
4612       left = t;
4613       /* emitcode (";", "swapped left and right"); */
4614     }
4615   /* if no literal, unsigned on the right: shorter code */
4616   if (   AOP_TYPE (right) != AOP_LIT
4617       && SPEC_USIGN (getSpec (operandType (left))))
4618     {
4619       operand *t = right;
4620       right = left;
4621       left = t;
4622     }
4623
4624   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4625   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4626
4627   pushedB = pushB ();
4628
4629   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4630                    no need to take care about the signedness! */
4631       || (lUnsigned && rUnsigned))
4632     {
4633       /* just an unsigned 8 * 8 = 8 multiply
4634          or 8u * 8u = 16u */
4635       /* emitcode (";","unsigned"); */
4636       /* TODO: check for accumulator clash between left & right aops? */
4637
4638       if (AOP_TYPE (right) == AOP_LIT)
4639         {
4640           /* moving to accumulator first helps peepholes */
4641           MOVA (aopGet (left, 0, FALSE, FALSE));
4642           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4643         }
4644       else
4645         {
4646           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4647           MOVA (aopGet (left, 0, FALSE, FALSE));
4648         }
4649
4650       emitcode ("mul", "ab");
4651       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4652       if (size == 2)
4653         aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4654
4655       popB (pushedB);
4656       return;
4657     }
4658
4659   /* we have to do a signed multiply */
4660   /* emitcode (";", "signed"); */
4661
4662   /* now sign adjust for both left & right */
4663
4664   /* let's see what's needed: */
4665   /* apply negative sign during runtime */
4666   runtimeSign = FALSE;
4667   /* negative sign from literals */
4668   compiletimeSign = FALSE;
4669
4670   if (!lUnsigned)
4671     {
4672       if (AOP_TYPE(left) == AOP_LIT)
4673         {
4674           /* signed literal */
4675           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4676           if (val < 0)
4677             compiletimeSign = TRUE;
4678         }
4679       else
4680         /* signed but not literal */
4681         runtimeSign = TRUE;
4682     }
4683
4684   if (!rUnsigned)
4685     {
4686       if (AOP_TYPE(right) == AOP_LIT)
4687         {
4688           /* signed literal */
4689           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4690           if (val < 0)
4691             compiletimeSign ^= TRUE;
4692         }
4693       else
4694         /* signed but not literal */
4695         runtimeSign = TRUE;
4696     }
4697
4698   /* initialize F0, which stores the runtime sign */
4699   if (runtimeSign)
4700     {
4701       if (compiletimeSign)
4702         emitcode ("setb", "F0"); /* set sign flag */
4703       else
4704         emitcode ("clr", "F0"); /* reset sign flag */
4705     }
4706
4707   /* save the signs of the operands */
4708   if (AOP_TYPE(right) == AOP_LIT)
4709     {
4710       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4711
4712       if (!rUnsigned && val < 0)
4713         emitcode ("mov", "b,#0x%02x", -val);
4714       else
4715         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4716     }
4717   else /* ! literal */
4718     {
4719       if (rUnsigned)  /* emitcode (";", "signed"); */
4720
4721         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4722       else
4723         {
4724           MOVA (aopGet (right, 0, FALSE, FALSE));
4725           lbl = newiTempLabel (NULL);
4726           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4727           emitcode ("cpl", "F0"); /* complement sign flag */
4728           emitcode ("cpl", "a");  /* 2's complement */
4729           emitcode ("inc", "a");
4730           emitcode ("", "%05d$:", (lbl->key + 100));
4731           emitcode ("mov", "b,a");
4732         }
4733     }
4734
4735   if (AOP_TYPE(left) == AOP_LIT)
4736     {
4737       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4738
4739       if (!lUnsigned && val < 0)
4740         emitcode ("mov", "a,#0x%02x", -val);
4741       else
4742         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4743     }
4744   else /* ! literal */
4745     {
4746       MOVA (aopGet (left, 0, FALSE, FALSE));
4747
4748       if (!lUnsigned)
4749         {
4750           lbl = newiTempLabel (NULL);
4751           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4752           emitcode ("cpl", "F0"); /* complement sign flag */
4753           emitcode ("cpl", "a"); /* 2's complement */
4754           emitcode ("inc", "a");
4755           emitcode ("", "%05d$:", (lbl->key + 100));
4756         }
4757     }
4758
4759   /* now the multiplication */
4760   emitcode ("mul", "ab");
4761   if (runtimeSign || compiletimeSign)
4762     {
4763       lbl = newiTempLabel (NULL);
4764       if (runtimeSign)
4765         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4766       emitcode ("cpl", "a"); /* lsb 2's complement */
4767       if (size != 2)
4768         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4769       else
4770         {
4771           emitcode ("add", "a,#1"); /* this sets carry flag */
4772           emitcode ("xch", "a,b");
4773           emitcode ("cpl", "a"); /* msb 2's complement */
4774           emitcode ("addc", "a,#0");
4775           emitcode ("xch", "a,b");
4776         }
4777       emitcode ("", "%05d$:", (lbl->key + 100));
4778     }
4779   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4780   if (size == 2)
4781     aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4782
4783   popB (pushedB);
4784 }
4785
4786 /*-----------------------------------------------------------------*/
4787 /* genMult - generates code for multiplication                     */
4788 /*-----------------------------------------------------------------*/
4789 static void
4790 genMult (iCode * ic)
4791 {
4792   operand *left = IC_LEFT (ic);
4793   operand *right = IC_RIGHT (ic);
4794   operand *result = IC_RESULT (ic);
4795
4796   D(emitcode (";     genMult",""));
4797
4798   /* assign the amsops */
4799   aopOp (left, ic, FALSE);
4800   aopOp (right, ic, FALSE);
4801   aopOp (result, ic, TRUE);
4802
4803   /* special cases first */
4804   /* both are bits */
4805   if (AOP_TYPE (left) == AOP_CRY &&
4806       AOP_TYPE (right) == AOP_CRY)
4807     {
4808       genMultbits (left, right, result);
4809       goto release;
4810     }
4811
4812   /* if both are of size == 1 */
4813 #if 0 // one of them can be a sloc shared with the result
4814     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4815 #else
4816   if (getSize(operandType(left)) == 1 &&
4817       getSize(operandType(right)) == 1)
4818 #endif
4819     {
4820       genMultOneByte (left, right, result);
4821       goto release;
4822     }
4823
4824   /* should have been converted to function call */
4825     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4826              getSize(OP_SYMBOL(right)->type));
4827   assert (0);
4828
4829 release:
4830   freeAsmop (result, NULL, ic, TRUE);
4831   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4832   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4833 }
4834
4835 /*-----------------------------------------------------------------*/
4836 /* genDivbits :- division of bits                                  */
4837 /*-----------------------------------------------------------------*/
4838 static void
4839 genDivbits (operand * left,
4840             operand * right,
4841             operand * result)
4842 {
4843   char *l;
4844   bool pushedB;
4845
4846   D(emitcode (";     genDivbits",""));
4847
4848   pushedB = pushB ();
4849
4850   /* the result must be bit */
4851   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4852   l = aopGet (left, 0, FALSE, FALSE);
4853
4854   MOVA (l);
4855
4856   emitcode ("div", "ab");
4857   emitcode ("rrc", "a");
4858
4859   popB (pushedB);
4860
4861   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4862 }
4863
4864 /*-----------------------------------------------------------------*/
4865 /* genDivOneByte : 8 bit division                                  */
4866 /*-----------------------------------------------------------------*/
4867 static void
4868 genDivOneByte (operand * left,
4869                operand * right,
4870                operand * result)
4871 {
4872   bool lUnsigned, rUnsigned, pushedB;
4873   bool runtimeSign, compiletimeSign;
4874   symbol *lbl;
4875   int size, offset;
4876
4877   D(emitcode (";     genDivOneByte",""));
4878
4879   /* Why is it necessary that genDivOneByte() can return an int result?
4880      Have a look at:
4881
4882         volatile unsigned char uc;
4883         volatile signed char sc1, sc2;
4884         volatile int i;
4885
4886         uc  = 255;
4887         sc1 = -1;
4888         i = uc / sc1;
4889
4890      Or:
4891
4892         sc1 = -128;
4893         sc2 = -1;
4894         i = sc1 / sc2;
4895
4896      In all cases a one byte result would overflow, the following cast to int
4897      would return the wrong result.
4898
4899      Two possible solution:
4900         a) cast operands to int, if ((unsigned) / (signed)) or
4901            ((signed) / (signed))
4902         b) return an 16 bit signed int; this is what we're doing here!
4903   */
4904
4905   size = AOP_SIZE (result) - 1;
4906   offset = 1;
4907   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4908   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4909
4910   pushedB = pushB ();
4911
4912   /* signed or unsigned */
4913   if (lUnsigned && rUnsigned)
4914     {
4915       /* unsigned is easy */
4916       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4917       MOVA (aopGet (left, 0, FALSE, FALSE));
4918       emitcode ("div", "ab");
4919       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4920       while (size--)
4921         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4922
4923       popB (pushedB);
4924       return;
4925     }
4926
4927   /* signed is a little bit more difficult */
4928
4929   /* now sign adjust for both left & right */
4930
4931   /* let's see what's needed: */
4932   /* apply negative sign during runtime */
4933   runtimeSign = FALSE;
4934   /* negative sign from literals */
4935   compiletimeSign = FALSE;
4936
4937   if (!lUnsigned)
4938     {
4939       if (AOP_TYPE(left) == AOP_LIT)
4940         {
4941           /* signed literal */
4942           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4943           if (val < 0)
4944             compiletimeSign = TRUE;
4945         }
4946       else
4947         /* signed but not literal */
4948         runtimeSign = TRUE;
4949     }
4950
4951   if (!rUnsigned)
4952     {
4953       if (AOP_TYPE(right) == AOP_LIT)
4954         {
4955           /* signed literal */
4956           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4957           if (val < 0)
4958             compiletimeSign ^= TRUE;
4959         }
4960       else
4961         /* signed but not literal */
4962         runtimeSign = TRUE;
4963     }
4964
4965   /* initialize F0, which stores the runtime sign */
4966   if (runtimeSign)
4967     {
4968       if (compiletimeSign)
4969         emitcode ("setb", "F0"); /* set sign flag */
4970       else
4971         emitcode ("clr", "F0"); /* reset sign flag */
4972     }
4973
4974   /* save the signs of the operands */
4975   if (AOP_TYPE(right) == AOP_LIT)
4976     {
4977       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4978
4979       if (!rUnsigned && val < 0)
4980         emitcode ("mov", "b,#0x%02x", -val);
4981       else
4982         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4983     }
4984   else /* ! literal */
4985     {
4986       if (rUnsigned)
4987         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4988       else
4989         {
4990           MOVA (aopGet (right, 0, FALSE, FALSE));
4991           lbl = newiTempLabel (NULL);
4992           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4993           emitcode ("cpl", "F0"); /* complement sign flag */
4994           emitcode ("cpl", "a");  /* 2's complement */
4995           emitcode ("inc", "a");
4996           emitcode ("", "%05d$:", (lbl->key + 100));
4997           emitcode ("mov", "b,a");
4998         }
4999     }
5000
5001   if (AOP_TYPE(left) == AOP_LIT)
5002     {
5003       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5004
5005       if (!lUnsigned && val < 0)
5006         emitcode ("mov", "a,#0x%02x", -val);
5007       else
5008         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5009     }
5010   else /* ! literal */
5011     {
5012       MOVA (aopGet (left, 0, FALSE, FALSE));
5013
5014       if (!lUnsigned)
5015         {
5016           lbl = newiTempLabel (NULL);
5017           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5018           emitcode ("cpl", "F0"); /* complement sign flag */
5019           emitcode ("cpl", "a");  /* 2's complement */
5020           emitcode ("inc", "a");
5021           emitcode ("", "%05d$:", (lbl->key + 100));
5022         }
5023     }
5024
5025   /* now the division */
5026   emitcode ("div", "ab");
5027
5028   if (runtimeSign || compiletimeSign)
5029     {
5030       lbl = newiTempLabel (NULL);
5031       if (runtimeSign)
5032         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5033       emitcode ("cpl", "a"); /* lsb 2's complement */
5034       emitcode ("inc", "a");
5035       emitcode ("", "%05d$:", (lbl->key + 100));
5036
5037       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5038       if (size > 0)
5039         {
5040           /* msb is 0x00 or 0xff depending on the sign */
5041           if (runtimeSign)
5042             {
5043               emitcode ("mov", "c,F0");
5044               emitcode ("subb", "a,acc");
5045               while (size--)
5046                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5047             }
5048           else /* compiletimeSign */
5049             while (size--)
5050               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5051         }
5052     }
5053   else
5054     {
5055       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5056       while (size--)
5057         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5058     }
5059
5060   popB (pushedB);
5061 }
5062
5063 /*-----------------------------------------------------------------*/
5064 /* genDiv - generates code for division                            */
5065 /*-----------------------------------------------------------------*/
5066 static void
5067 genDiv (iCode * ic)
5068 {
5069   operand *left = IC_LEFT (ic);
5070   operand *right = IC_RIGHT (ic);
5071   operand *result = IC_RESULT (ic);
5072
5073   D(emitcode (";     genDiv",""));
5074
5075   /* assign the amsops */
5076   aopOp (left, ic, FALSE);
5077   aopOp (right, ic, FALSE);
5078   aopOp (result, ic, TRUE);
5079
5080   /* special cases first */
5081   /* both are bits */
5082   if (AOP_TYPE (left) == AOP_CRY &&
5083       AOP_TYPE (right) == AOP_CRY)
5084     {
5085       genDivbits (left, right, result);
5086       goto release;
5087     }
5088
5089   /* if both are of size == 1 */
5090   if (AOP_SIZE (left) == 1 &&
5091       AOP_SIZE (right) == 1)
5092     {
5093       genDivOneByte (left, right, result);
5094       goto release;
5095     }
5096
5097   /* should have been converted to function call */
5098   assert (0);
5099 release:
5100   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5101   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5102   freeAsmop (result, NULL, ic, TRUE);
5103 }
5104
5105 /*-----------------------------------------------------------------*/
5106 /* genModbits :- modulus of bits                                   */
5107 /*-----------------------------------------------------------------*/
5108 static void
5109 genModbits (operand * left,
5110             operand * right,
5111             operand * result)
5112 {
5113   char *l;
5114   bool pushedB;
5115
5116   D(emitcode (";     genModbits",""));
5117
5118   pushedB = pushB ();
5119
5120   /* the result must be bit */
5121   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5122   l = aopGet (left, 0, FALSE, FALSE);
5123
5124   MOVA (l);
5125
5126   emitcode ("div", "ab");
5127   emitcode ("mov", "a,b");
5128   emitcode ("rrc", "a");
5129
5130   popB (pushedB);
5131
5132   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5133 }
5134
5135 /*-----------------------------------------------------------------*/
5136 /* genModOneByte : 8 bit modulus                                   */
5137 /*-----------------------------------------------------------------*/
5138 static void
5139 genModOneByte (operand * left,
5140                operand * right,
5141                operand * result)
5142 {
5143   bool lUnsigned, rUnsigned, pushedB;
5144   bool runtimeSign, compiletimeSign;
5145   symbol *lbl;
5146   int size, offset;
5147
5148   D(emitcode (";     genModOneByte",""));
5149
5150   size = AOP_SIZE (result) - 1;
5151   offset = 1;
5152   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5153   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5154
5155   /* if right is a literal, check it for 2^n */
5156   if (AOP_TYPE(right) == AOP_LIT)
5157     {
5158       unsigned char val = abs((int) operandLitValue(right));
5159       symbol *lbl2 = NULL;
5160
5161       switch (val)
5162         {
5163           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5164           case 2:
5165           case 4:
5166           case 8:
5167           case 16:
5168           case 32:
5169           case 64:
5170           case 128:
5171             if (lUnsigned)
5172               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5173                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5174               /* because iCode should have been changed to genAnd  */
5175               /* see file "SDCCopt.c", function "convertToFcall()" */
5176
5177             MOVA (aopGet (left, 0, FALSE, FALSE));
5178             emitcode ("mov", "c,acc.7");
5179             emitcode ("anl", "a,#0x%02x", val - 1);
5180             lbl = newiTempLabel (NULL);
5181             emitcode ("jz", "%05d$", (lbl->key + 100));
5182             emitcode ("jnc", "%05d$", (lbl->key + 100));
5183             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5184             if (size)
5185               {
5186                 int size2 = size;
5187                 int offs2 = offset;
5188
5189                 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5190                 while (size2--)
5191                   aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5192                 lbl2 = newiTempLabel (NULL);
5193                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5194               }
5195             emitcode ("", "%05d$:", (lbl->key + 100));
5196             aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5197             while (size--)
5198               aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5199             if (lbl2)
5200               {
5201                 emitcode ("", "%05d$:", (lbl2->key + 100));
5202               }
5203             return;
5204
5205           default:
5206             break;
5207         }
5208     }
5209
5210   pushedB = pushB ();
5211
5212   /* signed or unsigned */
5213   if (lUnsigned && rUnsigned)
5214     {
5215       /* unsigned is easy */
5216       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5217       MOVA (aopGet (left, 0, FALSE, FALSE));
5218       emitcode ("div", "ab");
5219       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5220       while (size--)
5221         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5222
5223       popB (pushedB);
5224       return;
5225     }
5226
5227   /* signed is a little bit more difficult */
5228
5229   /* now sign adjust for both left & right */
5230
5231   /* modulus: sign of the right operand has no influence on the result! */
5232   if (AOP_TYPE(right) == AOP_LIT)
5233     {
5234       signed char val = (char) operandLitValue(right);
5235
5236       if (!rUnsigned && val < 0)
5237         emitcode ("mov", "b,#0x%02x", -val);
5238       else
5239         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5240     }
5241   else /* not literal */
5242     {
5243       if (rUnsigned)
5244         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5245       else
5246         {
5247           MOVA (aopGet (right, 0, FALSE, FALSE));
5248           lbl = newiTempLabel (NULL);
5249           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5250           emitcode ("cpl", "a"); /* 2's complement */
5251           emitcode ("inc", "a");
5252           emitcode ("", "%05d$:", (lbl->key + 100));
5253           emitcode ("mov", "b,a");
5254         }
5255     }
5256
5257   /* let's see what's needed: */
5258   /* apply negative sign during runtime */
5259   runtimeSign = FALSE;
5260   /* negative sign from literals */
5261   compiletimeSign = FALSE;
5262
5263   /* sign adjust left side */
5264   if (AOP_TYPE(left) == AOP_LIT)
5265     {
5266       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5267
5268       if (!lUnsigned && val < 0)
5269         {
5270           compiletimeSign = TRUE; /* set sign flag */
5271           emitcode ("mov", "a,#0x%02x", -val);
5272         }
5273       else
5274         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5275     }
5276   else /* ! literal */
5277     {
5278       MOVA (aopGet (left, 0, FALSE, FALSE));
5279
5280       if (!lUnsigned)
5281         {
5282           runtimeSign = TRUE;
5283           emitcode ("clr", "F0"); /* clear sign flag */
5284
5285           lbl = newiTempLabel (NULL);
5286           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5287           emitcode ("setb", "F0"); /* set sign flag */
5288           emitcode ("cpl", "a");   /* 2's complement */
5289           emitcode ("inc", "a");
5290           emitcode ("", "%05d$:", (lbl->key + 100));
5291         }
5292     }
5293
5294   /* now the modulus */
5295   emitcode ("div", "ab");
5296
5297   if (runtimeSign || compiletimeSign)
5298     {
5299       emitcode ("mov", "a,b");
5300       lbl = newiTempLabel (NULL);
5301       if (runtimeSign)
5302         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5303       emitcode ("cpl", "a"); /* 2's complement */
5304       emitcode ("inc", "a");
5305       emitcode ("", "%05d$:", (lbl->key + 100));
5306
5307       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5308       if (size > 0)
5309         {
5310           /* msb is 0x00 or 0xff depending on the sign */
5311           if (runtimeSign)
5312             {
5313               emitcode ("mov", "c,F0");
5314               emitcode ("subb", "a,acc");
5315               while (size--)
5316                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5317             }
5318           else /* compiletimeSign */
5319             while (size--)
5320               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5321         }
5322     }
5323   else
5324     {
5325       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5326       while (size--)
5327         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5328     }
5329
5330   popB (pushedB);
5331 }
5332
5333 /*-----------------------------------------------------------------*/
5334 /* genMod - generates code for division                            */
5335 /*-----------------------------------------------------------------*/
5336 static void
5337 genMod (iCode * ic)
5338 {
5339   operand *left = IC_LEFT (ic);
5340   operand *right = IC_RIGHT (ic);
5341   operand *result = IC_RESULT (ic);
5342
5343   D(emitcode (";     genMod",""));
5344
5345   /* assign the asmops */
5346   aopOp (left, ic, FALSE);
5347   aopOp (right, ic, FALSE);
5348   aopOp (result, ic, TRUE);
5349
5350   /* special cases first */
5351   /* both are bits */
5352   if (AOP_TYPE (left) == AOP_CRY &&
5353       AOP_TYPE (right) == AOP_CRY)
5354     {
5355       genModbits (left, right, result);
5356       goto release;
5357     }
5358
5359   /* if both are of size == 1 */
5360   if (AOP_SIZE (left) == 1 &&
5361       AOP_SIZE (right) == 1)
5362     {
5363       genModOneByte (left, right, result);
5364       goto release;
5365     }
5366
5367   /* should have been converted to function call */
5368   assert (0);
5369
5370 release:
5371   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5372   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5373   freeAsmop (result, NULL, ic, TRUE);
5374 }
5375
5376 /*-----------------------------------------------------------------*/
5377 /* genIfxJump :- will create a jump depending on the ifx           */
5378 /*-----------------------------------------------------------------*/
5379 static void
5380 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5381 {
5382   symbol *jlbl;
5383   symbol *tlbl = newiTempLabel (NULL);
5384   char *inst;
5385
5386   D(emitcode (";     genIfxJump",""));
5387
5388   /* if true label then we jump if condition
5389      supplied is true */
5390   if (IC_TRUE (ic))
5391     {
5392       jlbl = IC_TRUE (ic);
5393       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5394                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5395     }
5396   else
5397     {
5398       /* false label is present */
5399       jlbl = IC_FALSE (ic);
5400       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5401                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5402     }
5403   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5404     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5405   else
5406     emitcode (inst, "%05d$", tlbl->key + 100);
5407   freeForBranchAsmop (result);
5408   freeForBranchAsmop (right);
5409   freeForBranchAsmop (left);
5410   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5411   emitcode ("", "%05d$:", tlbl->key + 100);
5412
5413   /* mark the icode as generated */
5414   ic->generated = 1;
5415 }
5416
5417 /*-----------------------------------------------------------------*/
5418 /* genCmp :- greater or less than comparison                       */
5419 /*-----------------------------------------------------------------*/
5420 static void
5421 genCmp (operand * left, operand * right,
5422         operand * result, iCode * ifx, int sign, iCode *ic)
5423 {
5424   int size, offset = 0;
5425   unsigned long lit = 0L;
5426   bool rightInB;
5427
5428   D(emitcode (";     genCmp",""));
5429
5430   /* if left & right are bit variables */
5431   if (AOP_TYPE (left) == AOP_CRY &&
5432       AOP_TYPE (right) == AOP_CRY)
5433     {
5434       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5435       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5436     }
5437   else
5438     {
5439       /* subtract right from left if at the
5440          end the carry flag is set then we know that
5441          left is greater than right */
5442       size = max (AOP_SIZE (left), AOP_SIZE (right));
5443
5444       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5445       if ((size == 1) && !sign &&
5446           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5447         {
5448           symbol *lbl = newiTempLabel (NULL);
5449           emitcode ("cjne", "%s,%s,%05d$",
5450                     aopGet (left, offset, FALSE, FALSE),
5451                     aopGet (right, offset, FALSE, FALSE),
5452                     lbl->key + 100);
5453           emitcode ("", "%05d$:", lbl->key + 100);
5454         }
5455       else
5456         {
5457           if (AOP_TYPE (right) == AOP_LIT)
5458             {
5459               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5460               /* optimize if(x < 0) or if(x >= 0) */
5461               if (lit == 0L)
5462                 {
5463                   if (!sign)
5464                     {
5465                       CLRC;
5466                     }
5467                   else
5468                     {
5469                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5470                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5471                         {
5472                           genIfxJump (ifx, "acc.7", left, right, result);
5473                           freeAsmop (right, NULL, ic, TRUE);
5474                           freeAsmop (left, NULL, ic, TRUE);
5475
5476                           return;
5477                         }
5478                       else
5479                         emitcode ("rlc", "a");
5480                     }
5481                   goto release;
5482                 }
5483             }
5484           CLRC;
5485           while (size--)
5486             {
5487               bool pushedB = FALSE;
5488               rightInB = aopGetUsesAcc(right, offset);
5489               if (rightInB)
5490                 {
5491                   pushedB = pushB ();
5492                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5493                 }
5494               MOVA (aopGet (left, offset, FALSE, FALSE));
5495               if (sign && size == 0)
5496                 {
5497                   emitcode ("xrl", "a,#0x80");
5498                   if (AOP_TYPE (right) == AOP_LIT)
5499                     {
5500                       unsigned long lit = (unsigned long)
5501                       floatFromVal (AOP (right)->aopu.aop_lit);
5502                       emitcode ("subb", "a,#0x%02x",
5503                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5504                     }
5505                   else
5506                     {
5507                       if (!rightInB)
5508                         {
5509                           pushedB = pushB ();
5510                           rightInB++;
5511                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5512                         }
5513                       emitcode ("xrl", "b,#0x80");
5514                       emitcode ("subb", "a,b");
5515                     }
5516                 }
5517               else
5518                 {
5519                   if (rightInB)
5520                     emitcode ("subb", "a,b");
5521                   else
5522                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5523                 }
5524               if (rightInB)
5525                 popB (pushedB);
5526               offset++;
5527             }
5528         }
5529     }
5530
5531 release:
5532   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5533   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5534   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5535     {
5536       outBitC (result);
5537     }
5538   else
5539     {
5540       /* if the result is used in the next
5541          ifx conditional branch then generate
5542          code a little differently */
5543       if (ifx)
5544         genIfxJump (ifx, "c", NULL, NULL, result);
5545       else
5546         outBitC (result);
5547       /* leave the result in acc */
5548     }
5549 }
5550
5551 /*-----------------------------------------------------------------*/
5552 /* genCmpGt :- greater than comparison                             */
5553 /*-----------------------------------------------------------------*/
5554 static void
5555 genCmpGt (iCode * ic, iCode * ifx)
5556 {
5557   operand *left, *right, *result;
5558   sym_link *letype, *retype;
5559   int sign;
5560
5561   D(emitcode (";     genCmpGt",""));
5562
5563   left = IC_LEFT (ic);
5564   right = IC_RIGHT (ic);
5565   result = IC_RESULT (ic);
5566
5567   letype = getSpec (operandType (left));
5568   retype = getSpec (operandType (right));
5569   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5570            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5571   /* assign the amsops */
5572   aopOp (left, ic, FALSE);
5573   aopOp (right, ic, FALSE);
5574   aopOp (result, ic, TRUE);
5575
5576   genCmp (right, left, result, ifx, sign, ic);
5577
5578   freeAsmop (result, NULL, ic, TRUE);
5579 }
5580
5581 /*-----------------------------------------------------------------*/
5582 /* genCmpLt - less than comparisons                                */
5583 /*-----------------------------------------------------------------*/
5584 static void
5585 genCmpLt (iCode * ic, iCode * ifx)
5586 {
5587   operand *left, *right, *result;
5588   sym_link *letype, *retype;
5589   int sign;
5590
5591   D(emitcode (";     genCmpLt",""));
5592
5593   left = IC_LEFT (ic);
5594   right = IC_RIGHT (ic);
5595   result = IC_RESULT (ic);
5596
5597   letype = getSpec (operandType (left));
5598   retype = getSpec (operandType (right));
5599   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5600            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5601   /* assign the amsops */
5602   aopOp (left, ic, FALSE);
5603   aopOp (right, ic, FALSE);
5604   aopOp (result, ic, TRUE);
5605
5606   genCmp (left, right, result, ifx, sign,ic);
5607
5608   freeAsmop (result, NULL, ic, TRUE);
5609 }
5610
5611 /*-----------------------------------------------------------------*/
5612 /* gencjneshort - compare and jump if not equal                    */
5613 /*-----------------------------------------------------------------*/
5614 static void
5615 gencjneshort (operand * left, operand * right, symbol * lbl)
5616 {
5617   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5618   int offset = 0;
5619   unsigned long lit = 0L;
5620
5621   /* if the left side is a literal or
5622      if the right is in a pointer register and left
5623      is not */
5624   if ((AOP_TYPE (left) == AOP_LIT) ||
5625       (AOP_TYPE (left) == AOP_IMMD) ||
5626       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5627     {
5628       operand *t = right;
5629       right = left;
5630       left = t;
5631     }
5632
5633   if (AOP_TYPE (right) == AOP_LIT)
5634     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5635
5636   /* if the right side is a literal then anything goes */
5637   if (AOP_TYPE (right) == AOP_LIT &&
5638       AOP_TYPE (left) != AOP_DIR  &&
5639       AOP_TYPE (left) != AOP_IMMD)
5640     {
5641       while (size--)
5642         {
5643           emitcode ("cjne", "%s,%s,%05d$",
5644                     aopGet (left, offset, FALSE, FALSE),
5645                     aopGet (right, offset, FALSE, FALSE),
5646                     lbl->key + 100);
5647           offset++;
5648         }
5649     }
5650
5651   /* if the right side is in a register or in direct space or
5652      if the left is a pointer register & right is not */
5653   else if (AOP_TYPE (right) == AOP_REG ||
5654            AOP_TYPE (right) == AOP_DIR ||
5655            AOP_TYPE (right) == AOP_LIT ||
5656            AOP_TYPE (right) == AOP_IMMD ||
5657            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5658            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5659     {
5660       while (size--)
5661         {
5662           MOVA (aopGet (left, offset, FALSE, FALSE));
5663           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5664               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5665             emitcode ("jnz", "%05d$", lbl->key + 100);
5666           else
5667             emitcode ("cjne", "a,%s,%05d$",
5668                       aopGet (right, offset, FALSE, TRUE),
5669                       lbl->key + 100);
5670           offset++;
5671         }
5672     }
5673   else
5674     {
5675       /* right is a pointer reg need both a & b */
5676       while (size--)
5677         {
5678           char *l;
5679           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5680           wassertl(!BINUSE, "B was in use");
5681           l = aopGet (left, offset, FALSE, FALSE);
5682           if (strcmp (l, "b"))
5683             emitcode ("mov", "b,%s", l);
5684           MOVA (aopGet (right, offset, FALSE, FALSE));
5685           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5686           offset++;
5687         }
5688     }
5689 }
5690
5691 /*-----------------------------------------------------------------*/
5692 /* gencjne - compare and jump if not equal                         */
5693 /*-----------------------------------------------------------------*/
5694 static void
5695 gencjne (operand * left, operand * right, symbol * lbl)
5696 {
5697   symbol *tlbl = newiTempLabel (NULL);
5698
5699   gencjneshort (left, right, lbl);
5700
5701   emitcode ("mov", "a,%s", one);
5702   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5703   emitcode ("", "%05d$:", lbl->key + 100);
5704   emitcode ("clr", "a");
5705   emitcode ("", "%05d$:", tlbl->key + 100);
5706 }
5707
5708 /*-----------------------------------------------------------------*/
5709 /* genCmpEq - generates code for equal to                          */
5710 /*-----------------------------------------------------------------*/
5711 static void
5712 genCmpEq (iCode * ic, iCode * ifx)
5713 {
5714   operand *left, *right, *result;
5715
5716   D(emitcode (";     genCmpEq",""));
5717
5718   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5719   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5720   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5721
5722   /* if literal, literal on the right or
5723      if the right is in a pointer register and left
5724      is not */
5725   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5726       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5727     {
5728       operand *t = IC_RIGHT (ic);
5729       IC_RIGHT (ic) = IC_LEFT (ic);
5730       IC_LEFT (ic) = t;
5731     }
5732
5733   if (ifx && !AOP_SIZE (result))
5734     {
5735       symbol *tlbl;
5736       /* if they are both bit variables */
5737       if (AOP_TYPE (left) == AOP_CRY &&
5738           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5739         {
5740           if (AOP_TYPE (right) == AOP_LIT)
5741             {
5742               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5743               if (lit == 0L)
5744                 {
5745                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5746                   emitcode ("cpl", "c");
5747                 }
5748               else if (lit == 1L)
5749                 {
5750                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5751                 }
5752               else
5753                 {
5754                   emitcode ("clr", "c");
5755                 }
5756               /* AOP_TYPE(right) == AOP_CRY */
5757             }
5758           else
5759             {
5760               symbol *lbl = newiTempLabel (NULL);
5761               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5762               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5763               emitcode ("cpl", "c");
5764               emitcode ("", "%05d$:", (lbl->key + 100));
5765             }
5766           /* if true label then we jump if condition
5767              supplied is true */
5768           tlbl = newiTempLabel (NULL);
5769           if (IC_TRUE (ifx))
5770             {
5771               emitcode ("jnc", "%05d$", tlbl->key + 100);
5772               freeForBranchAsmop (result);
5773               freeForBranchAsmop (right);
5774               freeForBranchAsmop (left);
5775               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5776             }
5777           else
5778             {
5779               emitcode ("jc", "%05d$", tlbl->key + 100);
5780               freeForBranchAsmop (result);
5781               freeForBranchAsmop (right);
5782               freeForBranchAsmop (left);
5783               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5784             }
5785           emitcode ("", "%05d$:", tlbl->key + 100);
5786         }
5787       else
5788         {
5789           tlbl = newiTempLabel (NULL);
5790           gencjneshort (left, right, tlbl);
5791           if (IC_TRUE (ifx))
5792             {
5793               freeForBranchAsmop (result);
5794               freeForBranchAsmop (right);
5795               freeForBranchAsmop (left);
5796               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5797               emitcode ("", "%05d$:", tlbl->key + 100);
5798             }
5799           else
5800             {
5801               symbol *lbl = newiTempLabel (NULL);
5802               emitcode ("sjmp", "%05d$", lbl->key + 100);
5803               emitcode ("", "%05d$:", tlbl->key + 100);
5804               freeForBranchAsmop (result);
5805               freeForBranchAsmop (right);
5806               freeForBranchAsmop (left);
5807               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5808               emitcode ("", "%05d$:", lbl->key + 100);
5809             }
5810         }
5811       /* mark the icode as generated */
5812       ifx->generated = 1;
5813       goto release;
5814     }
5815
5816   /* if they are both bit variables */
5817   if (AOP_TYPE (left) == AOP_CRY &&
5818       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5819     {
5820       if (AOP_TYPE (right) == AOP_LIT)
5821         {
5822           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5823           if (lit == 0L)
5824             {
5825               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5826               emitcode ("cpl", "c");
5827             }
5828           else if (lit == 1L)
5829             {
5830               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5831             }
5832           else
5833             {
5834               emitcode ("clr", "c");
5835             }
5836           /* AOP_TYPE(right) == AOP_CRY */
5837         }
5838       else
5839         {
5840           symbol *lbl = newiTempLabel (NULL);
5841           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5842           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5843           emitcode ("cpl", "c");
5844           emitcode ("", "%05d$:", (lbl->key + 100));
5845         }
5846       /* c = 1 if egal */
5847       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5848         {
5849           outBitC (result);
5850           goto release;
5851         }
5852       if (ifx)
5853         {
5854           genIfxJump (ifx, "c", left, right, result);
5855           goto release;
5856         }
5857       /* if the result is used in an arithmetic operation
5858          then put the result in place */
5859       outBitC (result);
5860     }
5861   else
5862     {
5863       gencjne (left, right, newiTempLabel (NULL));
5864       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5865         {
5866           aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5867           goto release;
5868         }
5869       if (ifx)
5870         {
5871           genIfxJump (ifx, "a", left, right, result);
5872           goto release;
5873         }
5874       /* if the result is used in an arithmetic operation
5875          then put the result in place */
5876       if (AOP_TYPE (result) != AOP_CRY)
5877         outAcc (result);
5878       /* leave the result in acc */
5879     }
5880
5881 release:
5882   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5883   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5884   freeAsmop (result, NULL, ic, TRUE);
5885 }
5886
5887 /*-----------------------------------------------------------------*/
5888 /* ifxForOp - returns the icode containing the ifx for operand     */
5889 /*-----------------------------------------------------------------*/
5890 static iCode *
5891 ifxForOp (operand * op, iCode * ic)
5892 {
5893   /* if true symbol then needs to be assigned */
5894   if (IS_TRUE_SYMOP (op))
5895     return NULL;
5896
5897   /* if this has register type condition and
5898      the next instruction is ifx with the same operand
5899      and live to of the operand is upto the ifx only then */
5900   if (ic->next &&
5901       ic->next->op == IFX &&
5902       IC_COND (ic->next)->key == op->key &&
5903       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5904     return ic->next;
5905
5906   return NULL;
5907 }
5908
5909 /*-----------------------------------------------------------------*/
5910 /* hasInc - operand is incremented before any other use            */
5911 /*-----------------------------------------------------------------*/
5912 static iCode *
5913 hasInc (operand *op, iCode *ic,int osize)
5914 {
5915   sym_link *type = operandType(op);
5916   sym_link *retype = getSpec (type);
5917   iCode *lic = ic->next;
5918   int isize ;
5919
5920   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5921   if (!IS_SYMOP(op)) return NULL;
5922
5923   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5924   if (IS_AGGREGATE(type->next)) return NULL;
5925   if (osize != (isize = getSize(type->next))) return NULL;
5926
5927   while (lic) {
5928     /* if operand of the form op = op + <sizeof *op> */
5929     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5930         isOperandEqual(IC_RESULT(lic),op) &&
5931         isOperandLiteral(IC_RIGHT(lic)) &&
5932         operandLitValue(IC_RIGHT(lic)) == isize) {
5933       return lic;
5934     }
5935     /* if the operand used or deffed */
5936     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5937       return NULL;
5938     }
5939     /* if GOTO or IFX */
5940     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5941     lic = lic->next;
5942   }
5943   return NULL;
5944 }
5945
5946 /*-----------------------------------------------------------------*/
5947 /* genAndOp - for && operation                                     */
5948 /*-----------------------------------------------------------------*/
5949 static void
5950 genAndOp (iCode * ic)
5951 {
5952   operand *left, *right, *result;
5953   symbol *tlbl;
5954
5955   D(emitcode (";     genAndOp",""));
5956
5957   /* note here that && operations that are in an
5958      if statement are taken away by backPatchLabels
5959      only those used in arthmetic operations remain */
5960   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5961   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5962   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5963
5964   /* if both are bit variables */
5965   if (AOP_TYPE (left) == AOP_CRY &&
5966       AOP_TYPE (right) == AOP_CRY)
5967     {
5968       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5969       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5970       outBitC (result);
5971     }
5972   else
5973     {
5974       tlbl = newiTempLabel (NULL);
5975       toBoolean (left);
5976       emitcode ("jz", "%05d$", tlbl->key + 100);
5977       toBoolean (right);
5978       emitcode ("", "%05d$:", tlbl->key + 100);
5979       outBitAcc (result);
5980     }
5981
5982   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5983   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5984   freeAsmop (result, NULL, ic, TRUE);
5985 }
5986
5987
5988 /*-----------------------------------------------------------------*/
5989 /* genOrOp - for || operation                                      */
5990 /*-----------------------------------------------------------------*/
5991 static void
5992 genOrOp (iCode * ic)
5993 {
5994   operand *left, *right, *result;
5995   symbol *tlbl;
5996
5997   D(emitcode (";     genOrOp",""));
5998
5999   /* note here that || operations that are in an
6000      if statement are taken away by backPatchLabels
6001      only those used in arthmetic operations remain */
6002   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6003   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6004   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6005
6006   /* if both are bit variables */
6007   if (AOP_TYPE (left) == AOP_CRY &&
6008       AOP_TYPE (right) == AOP_CRY)
6009     {
6010       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6011       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6012       outBitC (result);
6013     }
6014   else
6015     {
6016       tlbl = newiTempLabel (NULL);
6017       toBoolean (left);
6018       emitcode ("jnz", "%05d$", tlbl->key + 100);
6019       toBoolean (right);
6020       emitcode ("", "%05d$:", tlbl->key + 100);
6021       outBitAcc (result);
6022     }
6023
6024   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6025   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6026   freeAsmop (result, NULL, ic, TRUE);
6027 }
6028
6029 /*-----------------------------------------------------------------*/
6030 /* isLiteralBit - test if lit == 2^n                               */
6031 /*-----------------------------------------------------------------*/
6032 static int
6033 isLiteralBit (unsigned long lit)
6034 {
6035   unsigned long pw[32] =
6036   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6037    0x100L, 0x200L, 0x400L, 0x800L,
6038    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6039    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6040    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6041    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6042    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6043   int idx;
6044
6045   for (idx = 0; idx < 32; idx++)
6046     if (lit == pw[idx])
6047       return idx + 1;
6048   return 0;
6049 }
6050
6051 /*-----------------------------------------------------------------*/
6052 /* continueIfTrue -                                                */
6053 /*-----------------------------------------------------------------*/
6054 static void
6055 continueIfTrue (iCode * ic)
6056 {
6057   if (IC_TRUE (ic))
6058     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6059   ic->generated = 1;
6060 }
6061
6062 /*-----------------------------------------------------------------*/
6063 /* jmpIfTrue -                                                     */
6064 /*-----------------------------------------------------------------*/
6065 static void
6066 jumpIfTrue (iCode * ic)
6067 {
6068   if (!IC_TRUE (ic))
6069     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6070   ic->generated = 1;
6071 }
6072
6073 /*-----------------------------------------------------------------*/
6074 /* jmpTrueOrFalse -                                                */
6075 /*-----------------------------------------------------------------*/
6076 static void
6077 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6078 {
6079   // ugly but optimized by peephole
6080   if (IC_TRUE (ic))
6081     {
6082       symbol *nlbl = newiTempLabel (NULL);
6083       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6084       emitcode ("", "%05d$:", tlbl->key + 100);
6085       freeForBranchAsmop (result);
6086       freeForBranchAsmop (right);
6087       freeForBranchAsmop (left);
6088       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6089       emitcode ("", "%05d$:", nlbl->key + 100);
6090     }
6091   else
6092     {
6093       freeForBranchAsmop (result);
6094       freeForBranchAsmop (right);
6095       freeForBranchAsmop (left);
6096       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6097       emitcode ("", "%05d$:", tlbl->key + 100);
6098     }
6099   ic->generated = 1;
6100 }
6101
6102 /*-----------------------------------------------------------------*/
6103 /* genAnd  - code for and                                          */
6104 /*-----------------------------------------------------------------*/
6105 static void
6106 genAnd (iCode * ic, iCode * ifx)
6107 {
6108   operand *left, *right, *result;
6109   int size, offset = 0;
6110   unsigned long lit = 0L;
6111   int bytelit = 0;
6112   char buffer[10];
6113
6114   D(emitcode (";     genAnd",""));
6115
6116   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6117   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6118   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6119
6120 #ifdef DEBUG_TYPE
6121   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6122             AOP_TYPE (result),
6123             AOP_TYPE (left), AOP_TYPE (right));
6124   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6125             AOP_SIZE (result),
6126             AOP_SIZE (left), AOP_SIZE (right));
6127 #endif
6128
6129   /* if left is a literal & right is not then exchange them */
6130   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6131       AOP_NEEDSACC (left))
6132     {
6133       operand *tmp = right;
6134       right = left;
6135       left = tmp;
6136     }
6137
6138   /* if result = right then exchange left and right */
6139   if (sameRegs (AOP (result), AOP (right)))
6140     {
6141       operand *tmp = right;
6142       right = left;
6143       left = tmp;
6144     }
6145
6146   /* if right is bit then exchange them */
6147   if (AOP_TYPE (right) == AOP_CRY &&
6148       AOP_TYPE (left) != AOP_CRY)
6149     {
6150       operand *tmp = right;
6151       right = left;
6152       left = tmp;
6153     }
6154   if (AOP_TYPE (right) == AOP_LIT)
6155     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6156
6157   size = AOP_SIZE (result);
6158
6159   // if(bit & yy)
6160   // result = bit & yy;
6161   if (AOP_TYPE (left) == AOP_CRY)
6162     {
6163       // c = bit & literal;
6164       if (AOP_TYPE (right) == AOP_LIT)
6165         {
6166           if (lit & 1)
6167             {
6168               if (size && sameRegs (AOP (result), AOP (left)))
6169                 // no change
6170                 goto release;
6171               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6172             }
6173           else
6174             {
6175               // bit(result) = 0;
6176               if (size && (AOP_TYPE (result) == AOP_CRY))
6177                 {
6178                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6179                   goto release;
6180                 }
6181               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6182                 {
6183                   jumpIfTrue (ifx);
6184                   goto release;
6185                 }
6186               emitcode ("clr", "c");
6187             }
6188         }
6189       else
6190         {
6191           if (AOP_TYPE (right) == AOP_CRY)
6192             {
6193               // c = bit & bit;
6194               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6195               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6196             }
6197           else
6198             {
6199               // c = bit & val;
6200               MOVA (aopGet (right, 0, FALSE, FALSE));
6201               // c = lsb
6202               emitcode ("rrc", "a");
6203               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6204             }
6205         }
6206       // bit = c
6207       // val = c
6208       if (size)
6209         outBitC (result);
6210       // if(bit & ...)
6211       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6212         genIfxJump (ifx, "c", left, right, result);
6213       goto release;
6214     }
6215
6216   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6217   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6218   if ((AOP_TYPE (right) == AOP_LIT) &&
6219       (AOP_TYPE (result) == AOP_CRY) &&
6220       (AOP_TYPE (left) != AOP_CRY))
6221     {
6222       int posbit = isLiteralBit (lit);
6223       /* left &  2^n */
6224       if (posbit)
6225         {
6226           posbit--;
6227           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6228           // bit = left & 2^n
6229           if (size)
6230             {
6231               switch (posbit & 0x07)
6232                 {
6233                   case 0: emitcode ("rrc", "a");
6234                           break;
6235                   case 7: emitcode ("rlc", "a");
6236                           break;
6237                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6238                           break;
6239                 }
6240             }
6241           // if(left &  2^n)
6242           else
6243             {
6244               if (ifx)
6245                 {
6246                   SNPRINTF (buffer, sizeof(buffer),
6247                             "acc.%d", posbit & 0x07);
6248                   genIfxJump (ifx, buffer, left, right, result);
6249                 }
6250               else
6251                 {// what is this case? just found it in ds390/gen.c
6252                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6253                 }
6254               goto release;
6255             }
6256         }
6257       else
6258         {
6259           symbol *tlbl = newiTempLabel (NULL);
6260           int sizel = AOP_SIZE (left);
6261           if (size)
6262             emitcode ("setb", "c");
6263           while (sizel--)
6264             {
6265               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6266                 {
6267                   MOVA (aopGet (left, offset, FALSE, FALSE));
6268                   // byte ==  2^n ?
6269                   if ((posbit = isLiteralBit (bytelit)) != 0)
6270                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6271                   else
6272                     {
6273                       if (bytelit != 0x0FFL)
6274                         emitcode ("anl", "a,%s",
6275                                   aopGet (right, offset, FALSE, TRUE));
6276                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6277                     }
6278                 }
6279               offset++;
6280             }
6281           // bit = left & literal
6282           if (size)
6283             {
6284               emitcode ("clr", "c");
6285               emitcode ("", "%05d$:", tlbl->key + 100);
6286             }
6287           // if(left & literal)
6288           else
6289             {
6290               if (ifx)
6291                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6292               else
6293                 emitcode ("", "%05d$:", tlbl->key + 100);
6294               goto release;
6295             }
6296         }
6297       outBitC (result);
6298       goto release;
6299     }
6300
6301   /* if left is same as result */
6302   if (sameRegs (AOP (result), AOP (left)))
6303     {
6304       for (; size--; offset++)
6305         {
6306           if (AOP_TYPE (right) == AOP_LIT)
6307             {
6308               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6309               if (bytelit == 0x0FF)
6310                 {
6311                   /* dummy read of volatile operand */
6312                   if (isOperandVolatile (left, FALSE))
6313                     MOVA (aopGet (left, offset, FALSE, FALSE));
6314                   else
6315                     continue;
6316                 }
6317               else if (bytelit == 0)
6318                 {
6319                   aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6320                 }
6321               else if (IS_AOP_PREG (result))
6322                 {
6323                   MOVA (aopGet (left, offset, FALSE, TRUE));
6324                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6325                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6326                 }
6327               else
6328                 emitcode ("anl", "%s,%s",
6329                           aopGet (left, offset, FALSE, TRUE),
6330                           aopGet (right, offset, FALSE, FALSE));
6331             }
6332           else
6333             {
6334               if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6335                 {
6336                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6337                 }
6338               else
6339                 {
6340                   MOVA (aopGet (right, offset, FALSE, FALSE));
6341                   if (IS_AOP_PREG (result))
6342                     {
6343                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6344                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6345                     }
6346                   else
6347                     emitcode ("anl", "%s,a",
6348                               aopGet (left, offset, FALSE, TRUE));
6349                 }
6350             }
6351         }
6352     }
6353   else
6354     {
6355       // left & result in different registers
6356       if (AOP_TYPE (result) == AOP_CRY)
6357         {
6358           // result = bit
6359           // if(size), result in bit
6360           // if(!size && ifx), conditional oper: if(left & right)
6361           symbol *tlbl = newiTempLabel (NULL);
6362           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6363           if (size)
6364             emitcode ("setb", "c");
6365           while (sizer--)
6366             {
6367               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6368                   && AOP_TYPE(left)==AOP_ACC)
6369                 {
6370                   if (offset)
6371                     emitcode("mov", "a,b");
6372                   emitcode ("anl", "a,%s",
6373                             aopGet (right, offset, FALSE, FALSE));
6374                 } else {
6375                   if (AOP_TYPE(left)==AOP_ACC)
6376                     {
6377                       if (!offset)
6378                         {
6379                           bool pushedB = pushB ();
6380                           emitcode("mov", "b,a");
6381                           MOVA (aopGet (right, offset, FALSE, FALSE));
6382                           emitcode("anl", "a,b");
6383                           popB (pushedB);
6384                         }
6385                       else
6386                         {
6387                           MOVA (aopGet (right, offset, FALSE, FALSE));
6388                           emitcode("anl", "a,b");
6389                         }
6390                 } else {
6391                       MOVA (aopGet (right, offset, FALSE, FALSE));
6392                   emitcode ("anl", "a,%s",
6393                                 aopGet (left, offset, FALSE, FALSE));
6394                 }
6395               }
6396               emitcode ("jnz", "%05d$", tlbl->key + 100);
6397               offset++;
6398             }
6399           if (size)
6400             {
6401               CLRC;
6402               emitcode ("", "%05d$:", tlbl->key + 100);
6403               outBitC (result);
6404             }
6405           else if (ifx)
6406             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6407           else
6408             emitcode ("", "%05d$:", tlbl->key + 100);
6409         }
6410       else
6411         {
6412           for (; (size--); offset++)
6413             {
6414               // normal case
6415               // result = left & right
6416               if (AOP_TYPE (right) == AOP_LIT)
6417                 {
6418                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6419                   if (bytelit == 0x0FF)
6420                     {
6421                       aopPut (result,
6422                               aopGet (left, offset, FALSE, FALSE),
6423                               offset,
6424                               isOperandVolatile (result, FALSE));
6425                       continue;
6426                     }
6427                   else if (bytelit == 0)
6428                     {
6429                       /* dummy read of volatile operand */
6430                       if (isOperandVolatile (left, FALSE))
6431                         MOVA (aopGet (left, offset, FALSE, FALSE));
6432                       aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6433                       continue;
6434                     }
6435                   else if (AOP_TYPE (left) == AOP_ACC)
6436                     {
6437                       if (!offset)
6438                         {
6439                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6440                           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6441                           continue;
6442                         }
6443                       else
6444                         {
6445                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6446                           aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6447                           continue;
6448                         }
6449                     }
6450                 }
6451               // faster than result <- left, anl result,right
6452               // and better if result is SFR
6453               if (AOP_TYPE (left) == AOP_ACC)
6454                 {
6455                   if (offset)
6456                     emitcode("mov", "a,b");
6457                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6458                 }
6459               else
6460                 {
6461                   MOVA (aopGet (right, offset, FALSE, FALSE));
6462                   emitcode ("anl", "a,%s",
6463                             aopGet (left, offset, FALSE, FALSE));
6464                 }
6465               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6466             }
6467         }
6468     }
6469
6470 release:
6471   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6472   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6473   freeAsmop (result, NULL, ic, TRUE);
6474 }
6475
6476 /*-----------------------------------------------------------------*/
6477 /* genOr  - code for or                                            */
6478 /*-----------------------------------------------------------------*/
6479 static void
6480 genOr (iCode * ic, iCode * ifx)
6481 {
6482   operand *left, *right, *result;
6483   int size, offset = 0;
6484   unsigned long lit = 0L;
6485   int bytelit = 0;
6486
6487   D(emitcode (";     genOr",""));
6488
6489   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6490   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6491   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6492
6493 #ifdef DEBUG_TYPE
6494   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6495             AOP_TYPE (result),
6496             AOP_TYPE (left), AOP_TYPE (right));
6497   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6498             AOP_SIZE (result),
6499             AOP_SIZE (left), AOP_SIZE (right));
6500 #endif
6501
6502   /* if left is a literal & right is not then exchange them */
6503   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6504       AOP_NEEDSACC (left))
6505     {
6506       operand *tmp = right;
6507       right = left;
6508       left = tmp;
6509     }
6510
6511   /* if result = right then exchange them */
6512   if (sameRegs (AOP (result), AOP (right)))
6513     {
6514       operand *tmp = right;
6515       right = left;
6516       left = tmp;
6517     }
6518
6519   /* if right is bit then exchange them */
6520   if (AOP_TYPE (right) == AOP_CRY &&
6521       AOP_TYPE (left) != AOP_CRY)
6522     {
6523       operand *tmp = right;
6524       right = left;
6525       left = tmp;
6526     }
6527   if (AOP_TYPE (right) == AOP_LIT)
6528     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6529
6530   size = AOP_SIZE (result);
6531
6532   // if(bit | yy)
6533   // xx = bit | yy;
6534   if (AOP_TYPE (left) == AOP_CRY)
6535     {
6536       if (AOP_TYPE (right) == AOP_LIT)
6537         {
6538           // c = bit | literal;
6539           if (lit)
6540             {
6541               // lit != 0 => result = 1
6542               if (AOP_TYPE (result) == AOP_CRY)
6543                 {
6544                   if (size)
6545                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6546                   else if (ifx)
6547                     continueIfTrue (ifx);
6548                   goto release;
6549                 }
6550               emitcode ("setb", "c");
6551             }
6552           else
6553             {
6554               // lit == 0 => result = left
6555               if (size && sameRegs (AOP (result), AOP (left)))
6556                 goto release;
6557               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6558             }
6559         }
6560       else
6561         {
6562           if (AOP_TYPE (right) == AOP_CRY)
6563             {
6564               // c = bit | bit;
6565               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6566               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6567             }
6568           else
6569             {
6570               // c = bit | val;
6571               symbol *tlbl = newiTempLabel (NULL);
6572               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6573                 emitcode ("setb", "c");
6574               emitcode ("jb", "%s,%05d$",
6575                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6576               toBoolean (right);
6577               emitcode ("jnz", "%05d$", tlbl->key + 100);
6578               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6579                 {
6580                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6581                   goto release;
6582                 }
6583               else
6584                 {
6585                   CLRC;
6586                   emitcode ("", "%05d$:", tlbl->key + 100);
6587                 }
6588             }
6589         }
6590       // bit = c
6591       // val = c
6592       if (size)
6593         outBitC (result);
6594       // if(bit | ...)
6595       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6596         genIfxJump (ifx, "c", left, right, result);
6597       goto release;
6598     }
6599
6600   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6601   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6602   if ((AOP_TYPE (right) == AOP_LIT) &&
6603       (AOP_TYPE (result) == AOP_CRY) &&
6604       (AOP_TYPE (left) != AOP_CRY))
6605     {
6606       if (lit)
6607         {
6608           // result = 1
6609           if (size)
6610             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6611           else
6612             continueIfTrue (ifx);
6613           goto release;
6614         }
6615       else
6616         {
6617           // lit = 0, result = boolean(left)
6618           if (size)
6619             emitcode ("setb", "c");
6620           toBoolean (right);
6621           if (size)
6622             {
6623               symbol *tlbl = newiTempLabel (NULL);
6624               emitcode ("jnz", "%05d$", tlbl->key + 100);
6625               CLRC;
6626               emitcode ("", "%05d$:", tlbl->key + 100);
6627             }
6628           else
6629             {
6630               genIfxJump (ifx, "a", left, right, result);
6631               goto release;
6632             }
6633         }
6634       outBitC (result);
6635       goto release;
6636     }
6637
6638   /* if left is same as result */
6639   if (sameRegs (AOP (result), AOP (left)))
6640     {
6641       for (; size--; offset++)
6642         {
6643           if (AOP_TYPE (right) == AOP_LIT)
6644             {
6645               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6646               if (bytelit == 0)
6647                 {
6648                   /* dummy read of volatile operand */
6649                   if (isOperandVolatile (left, FALSE))
6650                     MOVA (aopGet (left, offset, FALSE, FALSE));
6651                   else
6652                     continue;
6653                 }
6654               else if (bytelit == 0x0FF)
6655                 {
6656                   aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6657                 }
6658               else if (IS_AOP_PREG (left))
6659                 {
6660                   MOVA (aopGet (left, offset, FALSE, TRUE));
6661                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6662                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6663                 }
6664               else
6665                 {
6666                   emitcode ("orl", "%s,%s",
6667                             aopGet (left, offset, FALSE, TRUE),
6668                             aopGet (right, offset, FALSE, FALSE));
6669                 }
6670             }
6671           else
6672             {
6673               if (AOP_TYPE (left) == AOP_ACC)
6674                 {
6675                   if (offset)
6676                     emitcode("mov", "a,b");
6677                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6678                 }
6679               else
6680                 {
6681                   MOVA (aopGet (right, offset, FALSE, FALSE));
6682                   if (IS_AOP_PREG (left))
6683                     {
6684                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6685                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6686                     }
6687                   else
6688                     {
6689                       emitcode ("orl", "%s,a",
6690                                 aopGet (left, offset, FALSE, TRUE));
6691                     }
6692                 }
6693             }
6694         }
6695     }
6696   else
6697     {
6698       // left & result in different registers
6699       if (AOP_TYPE (result) == AOP_CRY)
6700         {
6701           // result = bit
6702           // if(size), result in bit
6703           // if(!size && ifx), conditional oper: if(left | right)
6704           symbol *tlbl = newiTempLabel (NULL);
6705           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6706           if (size)
6707             emitcode ("setb", "c");
6708           while (sizer--)
6709             {
6710               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6711                 if (offset)
6712                   emitcode("mov", "a,b");
6713                 emitcode ("orl", "a,%s",
6714                           aopGet (right, offset, FALSE, FALSE));
6715               } else {
6716                 MOVA (aopGet (right, offset, FALSE, FALSE));
6717                 emitcode ("orl", "a,%s",
6718                           aopGet (left, offset, FALSE, FALSE));
6719               }
6720               emitcode ("jnz", "%05d$", tlbl->key + 100);
6721               offset++;
6722             }
6723           if (size)
6724             {
6725               CLRC;
6726               emitcode ("", "%05d$:", tlbl->key + 100);
6727               outBitC (result);
6728             }
6729           else if (ifx)
6730             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6731           else
6732             emitcode ("", "%05d$:", tlbl->key + 100);
6733         }
6734       else
6735         {
6736           for (; (size--); offset++)
6737             {
6738               // normal case
6739               // result = left | right
6740               if (AOP_TYPE (right) == AOP_LIT)
6741                 {
6742                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6743                   if (bytelit == 0)
6744                     {
6745                       aopPut (result,
6746                               aopGet (left, offset, FALSE, FALSE),
6747                               offset,
6748                               isOperandVolatile (result, FALSE));
6749                       continue;
6750                     }
6751                   else if (bytelit == 0x0FF)
6752                     {
6753                       /* dummy read of volatile operand */
6754                       if (isOperandVolatile (left, FALSE))
6755                         MOVA (aopGet (left, offset, FALSE, FALSE));
6756                       aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6757                       continue;
6758                     }
6759                 }
6760               // faster than result <- left, anl result,right
6761               // and better if result is SFR
6762               if (AOP_TYPE (left) == AOP_ACC)
6763                 {
6764                   if (offset)
6765                     emitcode("mov", "a,b");
6766                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6767                 }
6768               else
6769                 {
6770                   MOVA (aopGet (right, offset, FALSE, FALSE));
6771                   emitcode ("orl", "a,%s",
6772                             aopGet (left, offset, FALSE, FALSE));
6773                 }
6774               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6775             }
6776         }
6777     }
6778
6779 release:
6780   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6781   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6782   freeAsmop (result, NULL, ic, TRUE);
6783 }
6784
6785 /*-----------------------------------------------------------------*/
6786 /* genXor - code for xclusive or                                   */
6787 /*-----------------------------------------------------------------*/
6788 static void
6789 genXor (iCode * ic, iCode * ifx)
6790 {
6791   operand *left, *right, *result;
6792   int size, offset = 0;
6793   unsigned long lit = 0L;
6794   int bytelit = 0;
6795
6796   D(emitcode (";     genXor",""));
6797
6798   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6799   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6800   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6801
6802 #ifdef DEBUG_TYPE
6803   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6804             AOP_TYPE (result),
6805             AOP_TYPE (left), AOP_TYPE (right));
6806   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6807             AOP_SIZE (result),
6808             AOP_SIZE (left), AOP_SIZE (right));
6809 #endif
6810
6811   /* if left is a literal & right is not ||
6812      if left needs acc & right does not */
6813   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6814       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6815     {
6816       operand *tmp = right;
6817       right = left;
6818       left = tmp;
6819     }
6820
6821   /* if result = right then exchange them */
6822   if (sameRegs (AOP (result), AOP (right)))
6823     {
6824       operand *tmp = right;
6825       right = left;
6826       left = tmp;
6827     }
6828
6829   /* if right is bit then exchange them */
6830   if (AOP_TYPE (right) == AOP_CRY &&
6831       AOP_TYPE (left) != AOP_CRY)
6832     {
6833       operand *tmp = right;
6834       right = left;
6835       left = tmp;
6836     }
6837   if (AOP_TYPE (right) == AOP_LIT)
6838     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6839
6840   size = AOP_SIZE (result);
6841
6842   // if(bit ^ yy)
6843   // xx = bit ^ yy;
6844   if (AOP_TYPE (left) == AOP_CRY)
6845     {
6846       if (AOP_TYPE (right) == AOP_LIT)
6847         {
6848           // c = bit & literal;
6849           if (lit >> 1)
6850             {
6851               // lit>>1  != 0 => result = 1
6852               if (AOP_TYPE (result) == AOP_CRY)
6853                 {
6854                   if (size)
6855                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6856                   else if (ifx)
6857                     continueIfTrue (ifx);
6858                   goto release;
6859                 }
6860               emitcode ("setb", "c");
6861             }
6862           else
6863             {
6864               // lit == (0 or 1)
6865               if (lit == 0)
6866                 {
6867                   // lit == 0, result = left
6868                   if (size && sameRegs (AOP (result), AOP (left)))
6869                     goto release;
6870                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6871                 }
6872               else
6873                 {
6874                   // lit == 1, result = not(left)
6875                   if (size && sameRegs (AOP (result), AOP (left)))
6876                     {
6877                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6878                       goto release;
6879                     }
6880                   else
6881                     {
6882                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6883                       emitcode ("cpl", "c");
6884                     }
6885                 }
6886             }
6887
6888         }
6889       else
6890         {
6891           // right != literal
6892           symbol *tlbl = newiTempLabel (NULL);
6893           if (AOP_TYPE (right) == AOP_CRY)
6894             {
6895               // c = bit ^ bit;
6896               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6897             }
6898           else
6899             {
6900               int sizer = AOP_SIZE (right);
6901               // c = bit ^ val
6902               // if val>>1 != 0, result = 1
6903               emitcode ("setb", "c");
6904               while (sizer)
6905                 {
6906                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6907                   if (sizer == 1)
6908                     // test the msb of the lsb
6909                     emitcode ("anl", "a,#0xfe");
6910                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6911                   sizer--;
6912                 }
6913               // val = (0,1)
6914               emitcode ("rrc", "a");
6915             }
6916           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6917           emitcode ("cpl", "c");
6918           emitcode ("", "%05d$:", (tlbl->key + 100));
6919         }
6920       // bit = c
6921       // val = c
6922       if (size)
6923         outBitC (result);
6924       // if(bit | ...)
6925       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6926         genIfxJump (ifx, "c", left, right, result);
6927       goto release;
6928     }
6929
6930   /* if left is same as result */
6931   if (sameRegs (AOP (result), AOP (left)))
6932     {
6933       for (; size--; offset++)
6934         {
6935           if (AOP_TYPE (right) == AOP_LIT)
6936             {
6937               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6938               if (bytelit == 0)
6939                 {
6940                   /* dummy read of volatile operand */
6941                   if (isOperandVolatile (left, FALSE))
6942                     MOVA (aopGet (left, offset, FALSE, FALSE));
6943                   else
6944                     continue;
6945                 }
6946               else if (IS_AOP_PREG (left))
6947                 {
6948                   MOVA (aopGet (left, offset, FALSE, TRUE));
6949                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6950                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6951                 }
6952               else
6953                 {
6954                   emitcode ("xrl", "%s,%s",
6955                             aopGet (left, offset, FALSE, TRUE),
6956                             aopGet (right, offset, FALSE, FALSE));
6957                 }
6958             }
6959           else
6960             {
6961               if (AOP_TYPE (left) == AOP_ACC)
6962                 {
6963                   if (offset)
6964                     emitcode("mov", "a,b");
6965                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6966                 }
6967               else
6968                 {
6969                   MOVA (aopGet (right, offset, FALSE, FALSE));
6970                   if (IS_AOP_PREG (left))
6971                     {
6972                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6973                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6974                     }
6975                   else
6976                     emitcode ("xrl", "%s,a",
6977                               aopGet (left, offset, FALSE, TRUE));
6978                 }
6979             }
6980         }
6981     }
6982   else
6983     {
6984       // left & result in different registers
6985       if (AOP_TYPE (result) == AOP_CRY)
6986         {
6987           // result = bit
6988           // if(size), result in bit
6989           // if(!size && ifx), conditional oper: if(left ^ right)
6990           symbol *tlbl = newiTempLabel (NULL);
6991           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6992           if (size)
6993             emitcode ("setb", "c");
6994           while (sizer--)
6995             {
6996               if ((AOP_TYPE (right) == AOP_LIT) &&
6997                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6998                 {
6999                   MOVA (aopGet (left, offset, FALSE, FALSE));
7000                 }
7001               else
7002                 {
7003                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7004                     if (offset)
7005                       emitcode("mov", "a,b");
7006                     emitcode ("xrl", "a,%s",
7007                               aopGet (right, offset, FALSE, FALSE));
7008                   } else {
7009                     MOVA (aopGet (right, offset, FALSE, FALSE));
7010                     emitcode ("xrl", "a,%s",
7011                               aopGet (left, offset, FALSE, FALSE));
7012                   }
7013                 }
7014               emitcode ("jnz", "%05d$", tlbl->key + 100);
7015               offset++;
7016             }
7017           if (size)
7018             {
7019               CLRC;
7020               emitcode ("", "%05d$:", tlbl->key + 100);
7021               outBitC (result);
7022             }
7023           else if (ifx)
7024             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7025         }
7026       else
7027         {
7028           for (; (size--); offset++)
7029             {
7030               // normal case
7031               // result = left & right
7032               if (AOP_TYPE (right) == AOP_LIT)
7033                 {
7034                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7035                   if (bytelit == 0)
7036                     {
7037                       aopPut (result,
7038                               aopGet (left, offset, FALSE, FALSE),
7039                               offset,
7040                               isOperandVolatile (result, FALSE));
7041                       continue;
7042                     }
7043                 }
7044               // faster than result <- left, anl result,right
7045               // and better if result is SFR
7046               if (AOP_TYPE (left) == AOP_ACC)
7047                 {
7048                   if (offset)
7049                     emitcode("mov", "a,b");
7050                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7051                 }
7052               else
7053                 {
7054                   MOVA (aopGet (right, offset, FALSE, FALSE));
7055                   emitcode ("xrl", "a,%s",
7056                             aopGet (left, offset, FALSE, TRUE));
7057                 }
7058               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7059             }
7060         }
7061     }
7062
7063 release:
7064   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7065   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7066   freeAsmop (result, NULL, ic, TRUE);
7067 }
7068
7069 /*-----------------------------------------------------------------*/
7070 /* genInline - write the inline code out                           */
7071 /*-----------------------------------------------------------------*/
7072 static void
7073 genInline (iCode * ic)
7074 {
7075   char *buffer, *bp, *bp1;
7076
7077   D(emitcode (";     genInline",""));
7078
7079   _G.inLine += (!options.asmpeep);
7080
7081   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7082   strcpy (buffer, IC_INLINE (ic));
7083
7084   /* emit each line as a code */
7085   while (*bp)
7086     {
7087       if (*bp == '\n')
7088         {
7089           *bp++ = '\0';
7090           emitcode (bp1, "");
7091           bp1 = bp;
7092         }
7093       else
7094         {
7095           /* Add \n for labels, not dirs such as c:\mydir */
7096           if ( (*bp == ':') && (isspace(bp[1])) )
7097             {
7098               bp++;
7099               *bp = '\0';
7100               bp++;
7101               emitcode (bp1, "");
7102               bp1 = bp;
7103             }
7104           else
7105             bp++;
7106         }
7107     }
7108   if (bp1 != bp)
7109     emitcode (bp1, "");
7110   /*     emitcode("",buffer); */
7111   _G.inLine -= (!options.asmpeep);
7112 }
7113
7114 /*-----------------------------------------------------------------*/
7115 /* genRRC - rotate right with carry                                */
7116 /*-----------------------------------------------------------------*/
7117 static void
7118 genRRC (iCode * ic)
7119 {
7120   operand *left, *result;
7121   int size, offset = 0;
7122   char *l;
7123
7124   D(emitcode (";     genRRC",""));
7125
7126   /* rotate right with carry */
7127   left = IC_LEFT (ic);
7128   result = IC_RESULT (ic);
7129   aopOp (left, ic, FALSE);
7130   aopOp (result, ic, FALSE);
7131
7132   /* move it to the result */
7133   size = AOP_SIZE (result);
7134   offset = size - 1;
7135   if (size == 1) { /* special case for 1 byte */
7136       l = aopGet (left, offset, FALSE, FALSE);
7137       MOVA (l);
7138       emitcode ("rr", "a");
7139       goto release;
7140   }
7141   /* no need to clear carry, bit7 will be written later */
7142   while (size--)
7143     {
7144       l = aopGet (left, offset, FALSE, FALSE);
7145       MOVA (l);
7146       emitcode ("rrc", "a");
7147       if (AOP_SIZE (result) > 1)
7148         aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7149     }
7150   /* now we need to put the carry into the
7151      highest order byte of the result */
7152   if (AOP_SIZE (result) > 1)
7153     {
7154       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7155       MOVA (l);
7156     }
7157   emitcode ("mov", "acc.7,c");
7158  release:
7159   aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7160   freeAsmop (left, NULL, ic, TRUE);
7161   freeAsmop (result, NULL, ic, TRUE);
7162 }
7163
7164 /*-----------------------------------------------------------------*/
7165 /* genRLC - generate code for rotate left with carry               */
7166 /*-----------------------------------------------------------------*/
7167 static void
7168 genRLC (iCode * ic)
7169 {
7170   operand *left, *result;
7171   int size, offset = 0;
7172   char *l;
7173
7174   D(emitcode (";     genRLC",""));
7175
7176   /* rotate right with carry */
7177   left = IC_LEFT (ic);
7178   result = IC_RESULT (ic);
7179   aopOp (left, ic, FALSE);
7180   aopOp (result, ic, FALSE);
7181
7182   /* move it to the result */
7183   size = AOP_SIZE (result);
7184   offset = 0;
7185   if (size--)
7186     {
7187       l = aopGet (left, offset, FALSE, FALSE);
7188       MOVA (l);
7189       if (size == 0) { /* special case for 1 byte */
7190               emitcode("rl","a");
7191               goto release;
7192       }
7193       emitcode("rlc","a"); /* bit0 will be written later */
7194       if (AOP_SIZE (result) > 1)
7195         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7196       while (size--)
7197         {
7198           l = aopGet (left, offset, FALSE, FALSE);
7199           MOVA (l);
7200           emitcode ("rlc", "a");
7201           if (AOP_SIZE (result) > 1)
7202             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7203         }
7204     }
7205   /* now we need to put the carry into the
7206      highest order byte of the result */
7207   if (AOP_SIZE (result) > 1)
7208     {
7209       l = aopGet (result, 0, FALSE, FALSE);
7210       MOVA (l);
7211     }
7212   emitcode ("mov", "acc.0,c");
7213  release:
7214   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7215   freeAsmop (left, NULL, ic, TRUE);
7216   freeAsmop (result, NULL, ic, TRUE);
7217 }
7218
7219 /*-----------------------------------------------------------------*/
7220 /* genGetHbit - generates code get highest order bit               */
7221 /*-----------------------------------------------------------------*/
7222 static void
7223 genGetHbit (iCode * ic)
7224 {
7225   operand *left, *result;
7226
7227   D(emitcode (";     genGetHbit",""));
7228
7229   left = IC_LEFT (ic);
7230   result = IC_RESULT (ic);
7231   aopOp (left, ic, FALSE);
7232   aopOp (result, ic, FALSE);
7233
7234   /* get the highest order byte into a */
7235   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7236   if (AOP_TYPE (result) == AOP_CRY)
7237     {
7238       emitcode ("rlc", "a");
7239       outBitC (result);
7240     }
7241   else
7242     {
7243       emitcode ("rl", "a");
7244       emitcode ("anl", "a,#0x01");
7245       outAcc (result);
7246     }
7247
7248
7249   freeAsmop (left, NULL, ic, TRUE);
7250   freeAsmop (result, NULL, ic, TRUE);
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* genSwap - generates code to swap nibbles or bytes               */
7255 /*-----------------------------------------------------------------*/
7256 static void
7257 genSwap (iCode * ic)
7258 {
7259   operand *left, *result;
7260
7261   D(emitcode (";     genSwap",""));
7262
7263   left = IC_LEFT (ic);
7264   result = IC_RESULT (ic);
7265   aopOp (left, ic, FALSE);
7266   aopOp (result, ic, FALSE);
7267
7268   switch (AOP_SIZE (left))
7269     {
7270     case 1: /* swap nibbles in byte */
7271       MOVA (aopGet (left, 0, FALSE, FALSE));
7272       emitcode ("swap", "a");
7273       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7274       break;
7275     case 2: /* swap bytes in word */
7276       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7277         {
7278           MOVA (aopGet (left, 0, FALSE, FALSE));
7279           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7280                   0, isOperandVolatile (result, FALSE));
7281           aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7282         }
7283       else if (operandsEqu (left, result))
7284         {
7285           char * reg = "a";
7286           bool pushedB = FALSE, leftInB = FALSE;
7287
7288           MOVA (aopGet (left, 0, FALSE, FALSE));
7289           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7290             {
7291               pushedB = pushB ();
7292               emitcode ("mov", "b,a");
7293               reg = "b";
7294               leftInB = TRUE;
7295             }
7296           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7297                   0, isOperandVolatile (result, FALSE));
7298           aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7299
7300           if (leftInB)
7301             popB (pushedB);
7302         }
7303       else
7304         {
7305           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7306                   0, isOperandVolatile (result, FALSE));
7307           aopPut (result, aopGet (left, 0, FALSE, FALSE),
7308                   1, isOperandVolatile (result, FALSE));
7309         }
7310       break;
7311     default:
7312       wassertl(FALSE, "unsupported SWAP operand size");
7313     }
7314
7315   freeAsmop (left, NULL, ic, TRUE);
7316   freeAsmop (result, NULL, ic, TRUE);
7317 }
7318
7319
7320 /*-----------------------------------------------------------------*/
7321 /* AccRol - rotate left accumulator by known count                 */
7322 /*-----------------------------------------------------------------*/
7323 static void
7324 AccRol (int shCount)
7325 {
7326   shCount &= 0x0007;            // shCount : 0..7
7327
7328   switch (shCount)
7329     {
7330     case 0:
7331       break;
7332     case 1:
7333       emitcode ("rl", "a");
7334       break;
7335     case 2:
7336       emitcode ("rl", "a");
7337       emitcode ("rl", "a");
7338       break;
7339     case 3:
7340       emitcode ("swap", "a");
7341       emitcode ("rr", "a");
7342       break;
7343     case 4:
7344       emitcode ("swap", "a");
7345       break;
7346     case 5:
7347       emitcode ("swap", "a");
7348       emitcode ("rl", "a");
7349       break;
7350     case 6:
7351       emitcode ("rr", "a");
7352       emitcode ("rr", "a");
7353       break;
7354     case 7:
7355       emitcode ("rr", "a");
7356       break;
7357     }
7358 }
7359
7360 /*-----------------------------------------------------------------*/
7361 /* AccLsh - left shift accumulator by known count                  */
7362 /*-----------------------------------------------------------------*/
7363 static void
7364 AccLsh (int shCount)
7365 {
7366   if (shCount != 0)
7367     {
7368       if (shCount == 1)
7369         emitcode ("add", "a,acc");
7370       else if (shCount == 2)
7371         {
7372           emitcode ("add", "a,acc");
7373           emitcode ("add", "a,acc");
7374         }
7375       else
7376         {
7377           /* rotate left accumulator */
7378           AccRol (shCount);
7379           /* and kill the lower order bits */
7380           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7381         }
7382     }
7383 }
7384
7385 /*-----------------------------------------------------------------*/
7386 /* AccRsh - right shift accumulator by known count                 */
7387 /*-----------------------------------------------------------------*/
7388 static void
7389 AccRsh (int shCount)
7390 {
7391   if (shCount != 0)
7392     {
7393       if (shCount == 1)
7394         {
7395           CLRC;
7396           emitcode ("rrc", "a");
7397         }
7398       else
7399         {
7400           /* rotate right accumulator */
7401           AccRol (8 - shCount);
7402           /* and kill the higher order bits */
7403           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7404         }
7405     }
7406 }
7407
7408 /*-----------------------------------------------------------------*/
7409 /* AccSRsh - signed right shift accumulator by known count                 */
7410 /*-----------------------------------------------------------------*/
7411 static void
7412 AccSRsh (int shCount)
7413 {
7414   symbol *tlbl;
7415   if (shCount != 0)
7416     {
7417       if (shCount == 1)
7418         {
7419           emitcode ("mov", "c,acc.7");
7420           emitcode ("rrc", "a");
7421         }
7422       else if (shCount == 2)
7423         {
7424           emitcode ("mov", "c,acc.7");
7425           emitcode ("rrc", "a");
7426           emitcode ("mov", "c,acc.7");
7427           emitcode ("rrc", "a");
7428         }
7429       else
7430         {
7431           tlbl = newiTempLabel (NULL);
7432           /* rotate right accumulator */
7433           AccRol (8 - shCount);
7434           /* and kill the higher order bits */
7435           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7436           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7437           emitcode ("orl", "a,#0x%02x",
7438                     (unsigned char) ~SRMask[shCount]);
7439           emitcode ("", "%05d$:", tlbl->key + 100);
7440         }
7441     }
7442 }
7443
7444 /*-----------------------------------------------------------------*/
7445 /* shiftR1Left2Result - shift right one byte from left to result   */
7446 /*-----------------------------------------------------------------*/
7447 static void
7448 shiftR1Left2Result (operand * left, int offl,
7449                     operand * result, int offr,
7450                     int shCount, int sign)
7451 {
7452   MOVA (aopGet (left, offl, FALSE, FALSE));
7453   /* shift right accumulator */
7454   if (sign)
7455     AccSRsh (shCount);
7456   else
7457     AccRsh (shCount);
7458   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7459 }
7460
7461 /*-----------------------------------------------------------------*/
7462 /* shiftL1Left2Result - shift left one byte from left to result    */
7463 /*-----------------------------------------------------------------*/
7464 static void
7465 shiftL1Left2Result (operand * left, int offl,
7466                     operand * result, int offr, int shCount)
7467 {
7468   char *l;
7469   l = aopGet (left, offl, FALSE, FALSE);
7470   MOVA (l);
7471   /* shift left accumulator */
7472   AccLsh (shCount);
7473   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7474 }
7475
7476 /*-----------------------------------------------------------------*/
7477 /* movLeft2Result - move byte from left to result                  */
7478 /*-----------------------------------------------------------------*/
7479 static void
7480 movLeft2Result (operand * left, int offl,
7481                 operand * result, int offr, int sign)
7482 {
7483   char *l;
7484   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7485     {
7486       l = aopGet (left, offl, FALSE, FALSE);
7487
7488       if (*l == '@' && (IS_AOP_PREG (result)))
7489         {
7490           emitcode ("mov", "a,%s", l);
7491           aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7492         }
7493       else
7494         {
7495           if (!sign)
7496             aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7497           else
7498             {
7499               /* MSB sign in acc.7 ! */
7500               if (getDataSize (left) == offl + 1)
7501                 {
7502                   emitcode ("mov", "a,%s", l);
7503                   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7504                 }
7505             }
7506         }
7507     }
7508 }
7509
7510 /*-----------------------------------------------------------------*/
7511 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7512 /*-----------------------------------------------------------------*/
7513 static void
7514 AccAXRrl1 (char *x)
7515 {
7516   emitcode ("rrc", "a");
7517   emitcode ("xch", "a,%s", x);
7518   emitcode ("rrc", "a");
7519   emitcode ("xch", "a,%s", x);
7520 }
7521
7522 /*-----------------------------------------------------------------*/
7523 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7524 /*-----------------------------------------------------------------*/
7525 static void
7526 AccAXLrl1 (char *x)
7527 {
7528   emitcode ("xch", "a,%s", x);
7529   emitcode ("rlc", "a");
7530   emitcode ("xch", "a,%s", x);
7531   emitcode ("rlc", "a");
7532 }
7533
7534 /*-----------------------------------------------------------------*/
7535 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7536 /*-----------------------------------------------------------------*/
7537 static void
7538 AccAXLsh1 (char *x)
7539 {
7540   emitcode ("xch", "a,%s", x);
7541   emitcode ("add", "a,acc");
7542   emitcode ("xch", "a,%s", x);
7543   emitcode ("rlc", "a");
7544 }
7545
7546 /*-----------------------------------------------------------------*/
7547 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7548 /*-----------------------------------------------------------------*/
7549 static void
7550 AccAXLsh (char *x, int shCount)
7551 {
7552   switch (shCount)
7553     {
7554     case 0:
7555       break;
7556     case 1:
7557       AccAXLsh1 (x);
7558       break;
7559     case 2:
7560       AccAXLsh1 (x);
7561       AccAXLsh1 (x);
7562       break;
7563     case 3:
7564     case 4:
7565     case 5:                     // AAAAABBB:CCCCCDDD
7566
7567       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7568
7569       emitcode ("anl", "a,#0x%02x",
7570                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7571
7572       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7573
7574       AccRol (shCount);         // DDDCCCCC:BBB00000
7575
7576       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7577
7578       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7579
7580       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7581
7582       emitcode ("anl", "a,#0x%02x",
7583                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7584
7585       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7586
7587       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7588
7589       break;
7590     case 6:                     // AAAAAABB:CCCCCCDD
7591       emitcode ("anl", "a,#0x%02x",
7592                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7593       emitcode ("mov", "c,acc.0");      // c = B
7594       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7595 #if 0 // REMOVE ME
7596       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7597       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7598 #else
7599       emitcode("rrc","a");
7600       emitcode("xch","a,%s", x);
7601       emitcode("rrc","a");
7602       emitcode("mov","c,acc.0"); //<< get correct bit
7603       emitcode("xch","a,%s", x);
7604
7605       emitcode("rrc","a");
7606       emitcode("xch","a,%s", x);
7607       emitcode("rrc","a");
7608       emitcode("xch","a,%s", x);
7609 #endif
7610       break;
7611     case 7:                     // a:x <<= 7
7612
7613       emitcode ("anl", "a,#0x%02x",
7614                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7615
7616       emitcode ("mov", "c,acc.0");      // c = B
7617
7618       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7619
7620       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7621
7622       break;
7623     default:
7624       break;
7625     }
7626 }
7627
7628 /*-----------------------------------------------------------------*/
7629 /* AccAXRsh - right shift a:x known count (0..7)                   */
7630 /*-----------------------------------------------------------------*/
7631 static void
7632 AccAXRsh (char *x, int shCount)
7633 {
7634   switch (shCount)
7635     {
7636     case 0:
7637       break;
7638     case 1:
7639       CLRC;
7640       AccAXRrl1 (x);            // 0->a:x
7641
7642       break;
7643     case 2:
7644       CLRC;
7645       AccAXRrl1 (x);            // 0->a:x
7646
7647       CLRC;
7648       AccAXRrl1 (x);            // 0->a:x
7649
7650       break;
7651     case 3:
7652     case 4:
7653     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7654
7655       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7656
7657       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7658
7659       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7660
7661       emitcode ("anl", "a,#0x%02x",
7662                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7663
7664       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7665
7666       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7667
7668       emitcode ("anl", "a,#0x%02x",
7669                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7670
7671       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7672
7673       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7674
7675       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7676
7677       break;
7678     case 6:                     // AABBBBBB:CCDDDDDD
7679
7680       emitcode ("mov", "c,acc.7");
7681       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7682
7683       emitcode ("mov", "c,acc.7");
7684       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7685
7686       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7687
7688       emitcode ("anl", "a,#0x%02x",
7689                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7690
7691       break;
7692     case 7:                     // ABBBBBBB:CDDDDDDD
7693
7694       emitcode ("mov", "c,acc.7");      // c = A
7695
7696       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7697
7698       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7699
7700       emitcode ("anl", "a,#0x%02x",
7701                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7702
7703       break;
7704     default:
7705       break;
7706     }
7707 }
7708
7709 /*-----------------------------------------------------------------*/
7710 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7711 /*-----------------------------------------------------------------*/
7712 static void
7713 AccAXRshS (char *x, int shCount)
7714 {
7715   symbol *tlbl;
7716   switch (shCount)
7717     {
7718     case 0:
7719       break;
7720     case 1:
7721       emitcode ("mov", "c,acc.7");
7722       AccAXRrl1 (x);            // s->a:x
7723
7724       break;
7725     case 2:
7726       emitcode ("mov", "c,acc.7");
7727       AccAXRrl1 (x);            // s->a:x
7728
7729       emitcode ("mov", "c,acc.7");
7730       AccAXRrl1 (x);            // s->a:x
7731
7732       break;
7733     case 3:
7734     case 4:
7735     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7736
7737       tlbl = newiTempLabel (NULL);
7738       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7739
7740       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7741
7742       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7743
7744       emitcode ("anl", "a,#0x%02x",
7745                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7746
7747       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7748
7749       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7750
7751       emitcode ("anl", "a,#0x%02x",
7752                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7753
7754       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7755
7756       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7757
7758       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7759
7760       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7761       emitcode ("orl", "a,#0x%02x",
7762                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7763
7764       emitcode ("", "%05d$:", tlbl->key + 100);
7765       break;                    // SSSSAAAA:BBBCCCCC
7766
7767     case 6:                     // AABBBBBB:CCDDDDDD
7768
7769       tlbl = newiTempLabel (NULL);
7770       emitcode ("mov", "c,acc.7");
7771       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7772
7773       emitcode ("mov", "c,acc.7");
7774       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7775
7776       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7777
7778       emitcode ("anl", "a,#0x%02x",
7779                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7780
7781       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7782       emitcode ("orl", "a,#0x%02x",
7783                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7784
7785       emitcode ("", "%05d$:", tlbl->key + 100);
7786       break;
7787     case 7:                     // ABBBBBBB:CDDDDDDD
7788
7789       tlbl = newiTempLabel (NULL);
7790       emitcode ("mov", "c,acc.7");      // c = A
7791
7792       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7793
7794       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7795
7796       emitcode ("anl", "a,#0x%02x",
7797                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7798
7799       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7800       emitcode ("orl", "a,#0x%02x",
7801                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7802
7803       emitcode ("", "%05d$:", tlbl->key + 100);
7804       break;
7805     default:
7806       break;
7807     }
7808 }
7809
7810 /*-----------------------------------------------------------------*/
7811 /* shiftL2Left2Result - shift left two bytes from left to result   */
7812 /*-----------------------------------------------------------------*/
7813 static void
7814 shiftL2Left2Result (operand * left, int offl,
7815                     operand * result, int offr, int shCount)
7816 {
7817   if (sameRegs (AOP (result), AOP (left)) &&
7818       ((offl + MSB16) == offr))
7819     {
7820       /* don't crash result[offr] */
7821       MOVA (aopGet (left, offl, FALSE, FALSE));
7822       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7823     }
7824   else
7825     {
7826       movLeft2Result (left, offl, result, offr, 0);
7827       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7828     }
7829   /* ax << shCount (x = lsb(result)) */
7830   AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7831   aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7832 }
7833
7834
7835 /*-----------------------------------------------------------------*/
7836 /* shiftR2Left2Result - shift right two bytes from left to result  */
7837 /*-----------------------------------------------------------------*/
7838 static void
7839 shiftR2Left2Result (operand * left, int offl,
7840                     operand * result, int offr,
7841                     int shCount, int sign)
7842 {
7843   if (sameRegs (AOP (result), AOP (left)) &&
7844       ((offl + MSB16) == offr))
7845     {
7846       /* don't crash result[offr] */
7847       MOVA (aopGet (left, offl, FALSE, FALSE));
7848       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7849     }
7850   else
7851     {
7852       movLeft2Result (left, offl, result, offr, 0);
7853       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7854     }
7855   /* a:x >> shCount (x = lsb(result)) */
7856   if (sign)
7857     AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7858   else
7859     AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7860   if (getDataSize (result) > 1)
7861     aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7862 }
7863
7864 /*-----------------------------------------------------------------*/
7865 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7866 /*-----------------------------------------------------------------*/
7867 static void
7868 shiftLLeftOrResult (operand * left, int offl,
7869                     operand * result, int offr, int shCount)
7870 {
7871   MOVA (aopGet (left, offl, FALSE, FALSE));
7872   /* shift left accumulator */
7873   AccLsh (shCount);
7874   /* or with result */
7875   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7876   /* back to result */
7877   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7878 }
7879
7880 /*-----------------------------------------------------------------*/
7881 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7882 /*-----------------------------------------------------------------*/
7883 static void
7884 shiftRLeftOrResult (operand * left, int offl,
7885                     operand * result, int offr, int shCount)
7886 {
7887   MOVA (aopGet (left, offl, FALSE, FALSE));
7888   /* shift right accumulator */
7889   AccRsh (shCount);
7890   /* or with result */
7891   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7892   /* back to result */
7893   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7894 }
7895
7896 /*-----------------------------------------------------------------*/
7897 /* genlshOne - left shift a one byte quantity by known count       */
7898 /*-----------------------------------------------------------------*/
7899 static void
7900 genlshOne (operand * result, operand * left, int shCount)
7901 {
7902   D(emitcode (";     genlshOne",""));
7903
7904   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7905 }
7906
7907 /*-----------------------------------------------------------------*/
7908 /* genlshTwo - left shift two bytes by known amount != 0           */
7909 /*-----------------------------------------------------------------*/
7910 static void
7911 genlshTwo (operand * result, operand * left, int shCount)
7912 {
7913   int size;
7914
7915   D(emitcode (";     genlshTwo",""));
7916
7917   size = getDataSize (result);
7918
7919   /* if shCount >= 8 */
7920   if (shCount >= 8)
7921     {
7922       shCount -= 8;
7923
7924       if (size > 1)
7925         {
7926           if (shCount)
7927             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7928           else
7929             movLeft2Result (left, LSB, result, MSB16, 0);
7930         }
7931       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7932     }
7933
7934   /*  1 <= shCount <= 7 */
7935   else
7936     {
7937       if (size == 1)
7938         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7939       else
7940         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7941     }
7942 }
7943
7944 /*-----------------------------------------------------------------*/
7945 /* shiftLLong - shift left one long from left to result            */
7946 /* offl = LSB or MSB16                                             */
7947 /*-----------------------------------------------------------------*/
7948 static void
7949 shiftLLong (operand * left, operand * result, int offr)
7950 {
7951   char *l;
7952   int size = AOP_SIZE (result);
7953
7954   if (size >= LSB + offr)
7955     {
7956       l = aopGet (left, LSB, FALSE, FALSE);
7957       MOVA (l);
7958       emitcode ("add", "a,acc");
7959       if (sameRegs (AOP (left), AOP (result)) &&
7960           size >= MSB16 + offr && offr != LSB)
7961         emitcode ("xch", "a,%s",
7962                   aopGet (left, LSB + offr, FALSE, FALSE));
7963       else
7964         aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
7965     }
7966
7967   if (size >= MSB16 + offr)
7968     {
7969       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7970         {
7971           l = aopGet (left, MSB16, FALSE, FALSE);
7972           MOVA (l);
7973         }
7974       emitcode ("rlc", "a");
7975       if (sameRegs (AOP (left), AOP (result)) &&
7976           size >= MSB24 + offr && offr != LSB)
7977         emitcode ("xch", "a,%s",
7978                   aopGet (left, MSB16 + offr, FALSE, FALSE));
7979       else
7980         aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7981     }
7982
7983   if (size >= MSB24 + offr)
7984     {
7985       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7986         {
7987           l = aopGet (left, MSB24, FALSE, FALSE);
7988           MOVA (l);
7989         }
7990       emitcode ("rlc", "a");
7991       if (sameRegs (AOP (left), AOP (result)) &&
7992           size >= MSB32 + offr && offr != LSB)
7993         emitcode ("xch", "a,%s",
7994                   aopGet (left, MSB24 + offr, FALSE, FALSE));
7995       else
7996         aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7997     }
7998
7999   if (size > MSB32 + offr)
8000     {
8001       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8002         {
8003           l = aopGet (left, MSB32, FALSE, FALSE);
8004           MOVA (l);
8005         }
8006       emitcode ("rlc", "a");
8007       aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8008     }
8009   if (offr != LSB)
8010     aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8011 }
8012
8013 /*-----------------------------------------------------------------*/
8014 /* genlshFour - shift four byte by a known amount != 0             */
8015 /*-----------------------------------------------------------------*/
8016 static void
8017 genlshFour (operand * result, operand * left, int shCount)
8018 {
8019   int size;
8020
8021   D(emitcode (";     genlshFour",""));
8022
8023   size = AOP_SIZE (result);
8024
8025   /* if shifting more that 3 bytes */
8026   if (shCount >= 24)
8027     {
8028       shCount -= 24;
8029       if (shCount)
8030         /* lowest order of left goes to the highest
8031            order of the destination */
8032         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8033       else
8034         movLeft2Result (left, LSB, result, MSB32, 0);
8035       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8036       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8037       aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8038       return;
8039     }
8040
8041   /* more than two bytes */
8042   else if (shCount >= 16)
8043     {
8044       /* lower order two bytes goes to higher order two bytes */
8045       shCount -= 16;
8046       /* if some more remaining */
8047       if (shCount)
8048         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8049       else
8050         {
8051           movLeft2Result (left, MSB16, result, MSB32, 0);
8052           movLeft2Result (left, LSB, result, MSB24, 0);
8053         }
8054       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8055       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8056       return;
8057     }
8058
8059   /* if more than 1 byte */
8060   else if (shCount >= 8)
8061     {
8062       /* lower order three bytes goes to higher order  three bytes */
8063       shCount -= 8;
8064       if (size == 2)
8065         {
8066           if (shCount)
8067             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8068           else
8069             movLeft2Result (left, LSB, result, MSB16, 0);
8070         }
8071       else
8072         {                       /* size = 4 */
8073           if (shCount == 0)
8074             {
8075               movLeft2Result (left, MSB24, result, MSB32, 0);
8076               movLeft2Result (left, MSB16, result, MSB24, 0);
8077               movLeft2Result (left, LSB, result, MSB16, 0);
8078               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8079             }
8080           else if (shCount == 1)
8081             shiftLLong (left, result, MSB16);
8082           else
8083             {
8084               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8085               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8086               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8087               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8088             }
8089         }
8090     }
8091
8092   /* 1 <= shCount <= 7 */
8093   else if (shCount <= 2)
8094     {
8095       shiftLLong (left, result, LSB);
8096       if (shCount == 2)
8097         shiftLLong (result, result, LSB);
8098     }
8099   /* 3 <= shCount <= 7, optimize */
8100   else
8101     {
8102       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8103       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8104       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8105     }
8106 }
8107
8108 /*-----------------------------------------------------------------*/
8109 /* genLeftShiftLiteral - left shifting by known count              */
8110 /*-----------------------------------------------------------------*/
8111 static void
8112 genLeftShiftLiteral (operand * left,
8113                      operand * right,
8114                      operand * result,
8115                      iCode * ic)
8116 {
8117   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8118   int size;
8119
8120   D(emitcode (";     genLeftShiftLiteral",""));
8121
8122   freeAsmop (right, NULL, ic, TRUE);
8123
8124   aopOp (left, ic, FALSE);
8125   aopOp (result, ic, FALSE);
8126
8127   size = getSize (operandType (result));
8128
8129 #if VIEW_SIZE
8130   emitcode ("; shift left ", "result %d, left %d", size,
8131             AOP_SIZE (left));
8132 #endif
8133
8134   /* I suppose that the left size >= result size */
8135   if (shCount == 0)
8136     {
8137       while (size--)
8138         {
8139           movLeft2Result (left, size, result, size, 0);
8140         }
8141     }
8142
8143   else if (shCount >= (size * 8))
8144     while (size--)
8145       aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8146   else
8147     {
8148       switch (size)
8149         {
8150         case 1:
8151           genlshOne (result, left, shCount);
8152           break;
8153
8154         case 2:
8155           genlshTwo (result, left, shCount);
8156           break;
8157
8158         case 4:
8159           genlshFour (result, left, shCount);
8160           break;
8161         default:
8162           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8163                   "*** ack! mystery literal shift!\n");
8164           break;
8165         }
8166     }
8167   freeAsmop (left, NULL, ic, TRUE);
8168   freeAsmop (result, NULL, ic, TRUE);
8169 }
8170
8171 /*-----------------------------------------------------------------*/
8172 /* genLeftShift - generates code for left shifting                 */
8173 /*-----------------------------------------------------------------*/
8174 static void
8175 genLeftShift (iCode * ic)
8176 {
8177   operand *left, *right, *result;
8178   int size, offset;
8179   char *l;
8180   symbol *tlbl, *tlbl1;
8181   bool pushedB;
8182
8183   D(emitcode (";     genLeftShift",""));
8184
8185   right = IC_RIGHT (ic);
8186   left = IC_LEFT (ic);
8187   result = IC_RESULT (ic);
8188
8189   aopOp (right, ic, FALSE);
8190
8191   /* if the shift count is known then do it
8192      as efficiently as possible */
8193   if (AOP_TYPE (right) == AOP_LIT)
8194     {
8195       genLeftShiftLiteral (left, right, result, ic);
8196       return;
8197     }
8198
8199   /* shift count is unknown then we have to form
8200      a loop get the loop count in B : Note: we take
8201      only the lower order byte since shifting
8202      more that 32 bits make no sense anyway, ( the
8203      largest size of an object can be only 32 bits ) */
8204
8205   pushedB = pushB ();
8206   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8207   emitcode ("inc", "b");
8208   freeAsmop (right, NULL, ic, TRUE);
8209   aopOp (left, ic, FALSE);
8210   aopOp (result, ic, FALSE);
8211
8212   /* now move the left to the result if they are not the same */
8213   if (!sameRegs (AOP (left), AOP (result)) &&
8214       AOP_SIZE (result) > 1)
8215     {
8216
8217       size = AOP_SIZE (result);
8218       offset = 0;
8219       while (size--)
8220         {
8221           l = aopGet (left, offset, FALSE, TRUE);
8222           if (*l == '@' && (IS_AOP_PREG (result)))
8223             {
8224
8225               emitcode ("mov", "a,%s", l);
8226               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8227             }
8228           else
8229             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8230           offset++;
8231         }
8232     }
8233
8234   tlbl = newiTempLabel (NULL);
8235   size = AOP_SIZE (result);
8236   offset = 0;
8237   tlbl1 = newiTempLabel (NULL);
8238
8239   /* if it is only one byte then */
8240   if (size == 1)
8241     {
8242       symbol *tlbl1 = newiTempLabel (NULL);
8243
8244       l = aopGet (left, 0, FALSE, FALSE);
8245       MOVA (l);
8246       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8247       emitcode ("", "%05d$:", tlbl->key + 100);
8248       emitcode ("add", "a,acc");
8249       emitcode ("", "%05d$:", tlbl1->key + 100);
8250       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8251       popB (pushedB);
8252       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8253       goto release;
8254     }
8255
8256   reAdjustPreg (AOP (result));
8257
8258   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8259   emitcode ("", "%05d$:", tlbl->key + 100);
8260   l = aopGet (result, offset, FALSE, FALSE);
8261   MOVA (l);
8262   emitcode ("add", "a,acc");
8263   aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8264   while (--size)
8265     {
8266       l = aopGet (result, offset, FALSE, FALSE);
8267       MOVA (l);
8268       emitcode ("rlc", "a");
8269       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8270     }
8271   reAdjustPreg (AOP (result));
8272
8273   emitcode ("", "%05d$:", tlbl1->key + 100);
8274   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8275   popB (pushedB);
8276 release:
8277   freeAsmop (left, NULL, ic, TRUE);
8278   freeAsmop (result, NULL, ic, TRUE);
8279 }
8280
8281 /*-----------------------------------------------------------------*/
8282 /* genrshOne - right shift a one byte quantity by known count      */
8283 /*-----------------------------------------------------------------*/
8284 static void
8285 genrshOne (operand * result, operand * left,
8286            int shCount, int sign)
8287 {
8288   D(emitcode (";     genrshOne",""));
8289
8290   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8291 }
8292
8293 /*-----------------------------------------------------------------*/
8294 /* genrshTwo - right shift two bytes by known amount != 0          */
8295 /*-----------------------------------------------------------------*/
8296 static void
8297 genrshTwo (operand * result, operand * left,
8298            int shCount, int sign)
8299 {
8300   D(emitcode (";     genrshTwo",""));
8301
8302   /* if shCount >= 8 */
8303   if (shCount >= 8)
8304     {
8305       shCount -= 8;
8306       if (shCount)
8307         shiftR1Left2Result (left, MSB16, result, LSB,
8308                             shCount, sign);
8309       else
8310         movLeft2Result (left, MSB16, result, LSB, sign);
8311       addSign (result, MSB16, sign);
8312     }
8313
8314   /*  1 <= shCount <= 7 */
8315   else
8316     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8317 }
8318
8319 /*-----------------------------------------------------------------*/
8320 /* shiftRLong - shift right one long from left to result           */
8321 /* offl = LSB or MSB16                                             */
8322 /*-----------------------------------------------------------------*/
8323 static void
8324 shiftRLong (operand * left, int offl,
8325             operand * result, int sign)
8326 {
8327   int isSameRegs=sameRegs(AOP(left),AOP(result));
8328
8329   if (isSameRegs && offl>1) {
8330     // we are in big trouble, but this shouldn't happen
8331     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8332   }
8333
8334   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8335
8336   if (offl==MSB16) {
8337     // shift is > 8
8338     if (sign) {
8339       emitcode ("rlc", "a");
8340       emitcode ("subb", "a,acc");
8341       if (isSameRegs)
8342         emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8343       else {
8344         aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8345         MOVA (aopGet (left, MSB32, FALSE, FALSE));
8346       }
8347     } else {
8348       aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8349     }
8350   }
8351
8352   if (!sign) {
8353     emitcode ("clr", "c");
8354   } else {
8355     emitcode ("mov", "c,acc.7");
8356   }
8357
8358   emitcode ("rrc", "a");
8359
8360   if (isSameRegs && offl==MSB16) {
8361     emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8362   } else {
8363     aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8364     MOVA (aopGet (left, MSB24, FALSE, FALSE));
8365   }
8366
8367   emitcode ("rrc", "a");
8368   if (isSameRegs && offl==1) {
8369     emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8370   } else {
8371     aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8372     MOVA (aopGet (left, MSB16, FALSE, FALSE));
8373   }
8374   emitcode ("rrc", "a");
8375   aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8376
8377   if (offl == LSB)
8378     {
8379       MOVA (aopGet (left, LSB, FALSE, FALSE));
8380       emitcode ("rrc", "a");
8381       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8382     }
8383 }
8384
8385 /*-----------------------------------------------------------------*/
8386 /* genrshFour - shift four byte by a known amount != 0             */
8387 /*-----------------------------------------------------------------*/
8388 static void
8389 genrshFour (operand * result, operand * left,
8390             int shCount, int sign)
8391 {
8392   D(emitcode (";     genrshFour",""));
8393
8394   /* if shifting more that 3 bytes */
8395   if (shCount >= 24)
8396     {
8397       shCount -= 24;
8398       if (shCount)
8399         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8400       else
8401         movLeft2Result (left, MSB32, result, LSB, sign);
8402       addSign (result, MSB16, sign);
8403     }
8404   else if (shCount >= 16)
8405     {
8406       shCount -= 16;
8407       if (shCount)
8408         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8409       else
8410         {
8411           movLeft2Result (left, MSB24, result, LSB, 0);
8412           movLeft2Result (left, MSB32, result, MSB16, sign);
8413         }
8414       addSign (result, MSB24, sign);
8415     }
8416   else if (shCount >= 8)
8417     {
8418       shCount -= 8;
8419       if (shCount == 1)
8420         shiftRLong (left, MSB16, result, sign);
8421       else if (shCount == 0)
8422         {
8423           movLeft2Result (left, MSB16, result, LSB, 0);
8424           movLeft2Result (left, MSB24, result, MSB16, 0);
8425           movLeft2Result (left, MSB32, result, MSB24, sign);
8426           addSign (result, MSB32, sign);
8427         }
8428       else
8429         {
8430           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8431           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8432           /* the last shift is signed */
8433           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8434           addSign (result, MSB32, sign);
8435         }
8436     }
8437   else
8438     {                           /* 1 <= shCount <= 7 */
8439       if (shCount <= 2)
8440         {
8441           shiftRLong (left, LSB, result, sign);
8442           if (shCount == 2)
8443             shiftRLong (result, LSB, result, sign);
8444         }
8445       else
8446         {
8447           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8448           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8449           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8450         }
8451     }
8452 }
8453
8454 /*-----------------------------------------------------------------*/
8455 /* genRightShiftLiteral - right shifting by known count            */
8456 /*-----------------------------------------------------------------*/
8457 static void
8458 genRightShiftLiteral (operand * left,
8459                       operand * right,
8460                       operand * result,
8461                       iCode * ic,
8462                       int sign)
8463 {
8464   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8465   int size;
8466
8467   D(emitcode (";     genRightShiftLiteral",""));
8468
8469   freeAsmop (right, NULL, ic, TRUE);
8470
8471   aopOp (left, ic, FALSE);
8472   aopOp (result, ic, FALSE);
8473
8474 #if VIEW_SIZE
8475   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8476             AOP_SIZE (left));
8477 #endif
8478
8479   size = getDataSize (left);
8480   /* test the LEFT size !!! */
8481
8482   /* I suppose that the left size >= result size */
8483   if (shCount == 0)
8484     {
8485       size = getDataSize (result);
8486       while (size--)
8487         movLeft2Result (left, size, result, size, 0);
8488     }
8489
8490   else if (shCount >= (size * 8))
8491     {
8492       if (sign) {
8493         /* get sign in acc.7 */
8494         MOVA (aopGet (left, size - 1, FALSE, FALSE));
8495       }
8496       addSign (result, LSB, sign);
8497     }
8498   else
8499     {
8500       switch (size)
8501         {
8502         case 1:
8503           genrshOne (result, left, shCount, sign);
8504           break;
8505
8506         case 2:
8507           genrshTwo (result, left, shCount, sign);
8508           break;
8509
8510         case 4:
8511           genrshFour (result, left, shCount, sign);
8512           break;
8513         default:
8514           break;
8515         }
8516     }
8517   freeAsmop (left, NULL, ic, TRUE);
8518   freeAsmop (result, NULL, ic, TRUE);
8519 }
8520
8521 /*-----------------------------------------------------------------*/
8522 /* genSignedRightShift - right shift of signed number              */
8523 /*-----------------------------------------------------------------*/
8524 static void
8525 genSignedRightShift (iCode * ic)
8526 {
8527   operand *right, *left, *result;
8528   int size, offset;
8529   char *l;
8530   symbol *tlbl, *tlbl1;
8531   bool pushedB;
8532
8533   D(emitcode (";     genSignedRightShift",""));
8534
8535   /* we do it the hard way put the shift count in b
8536      and loop thru preserving the sign */
8537
8538   right = IC_RIGHT (ic);
8539   left = IC_LEFT (ic);
8540   result = IC_RESULT (ic);
8541
8542   aopOp (right, ic, FALSE);
8543
8544
8545   if (AOP_TYPE (right) == AOP_LIT)
8546     {
8547       genRightShiftLiteral (left, right, result, ic, 1);
8548       return;
8549     }
8550   /* shift count is unknown then we have to form
8551      a loop get the loop count in B : Note: we take
8552      only the lower order byte since shifting
8553      more that 32 bits make no sense anyway, ( the
8554      largest size of an object can be only 32 bits ) */
8555
8556   pushedB = pushB ();
8557   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8558   emitcode ("inc", "b");
8559   freeAsmop (right, NULL, ic, TRUE);
8560   aopOp (left, ic, FALSE);
8561   aopOp (result, ic, FALSE);
8562
8563   /* now move the left to the result if they are not the
8564      same */
8565   if (!sameRegs (AOP (left), AOP (result)) &&
8566       AOP_SIZE (result) > 1)
8567     {
8568
8569       size = AOP_SIZE (result);
8570       offset = 0;
8571       while (size--)
8572         {
8573           l = aopGet (left, offset, FALSE, TRUE);
8574           if (*l == '@' && IS_AOP_PREG (result))
8575             {
8576
8577               emitcode ("mov", "a,%s", l);
8578               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8579             }
8580           else
8581             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8582           offset++;
8583         }
8584     }
8585
8586   /* mov the highest order bit to OVR */
8587   tlbl = newiTempLabel (NULL);
8588   tlbl1 = newiTempLabel (NULL);
8589
8590   size = AOP_SIZE (result);
8591   offset = size - 1;
8592   MOVA (aopGet (left, offset, FALSE, FALSE));
8593   emitcode ("rlc", "a");
8594   emitcode ("mov", "ov,c");
8595   /* if it is only one byte then */
8596   if (size == 1)
8597     {
8598       l = aopGet (left, 0, FALSE, FALSE);
8599       MOVA (l);
8600       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8601       emitcode ("", "%05d$:", tlbl->key + 100);
8602       emitcode ("mov", "c,ov");
8603       emitcode ("rrc", "a");
8604       emitcode ("", "%05d$:", tlbl1->key + 100);
8605       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8606       popB (pushedB);
8607       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8608       goto release;
8609     }
8610
8611   reAdjustPreg (AOP (result));
8612   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8613   emitcode ("", "%05d$:", tlbl->key + 100);
8614   emitcode ("mov", "c,ov");
8615   while (size--)
8616     {
8617       l = aopGet (result, offset, FALSE, FALSE);
8618       MOVA (l);
8619       emitcode ("rrc", "a");
8620       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8621     }
8622   reAdjustPreg (AOP (result));
8623   emitcode ("", "%05d$:", tlbl1->key + 100);
8624   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8625   popB (pushedB);
8626
8627 release:
8628   freeAsmop (left, NULL, ic, TRUE);
8629   freeAsmop (result, NULL, ic, TRUE);
8630 }
8631
8632 /*-----------------------------------------------------------------*/
8633 /* genRightShift - generate code for right shifting                */
8634 /*-----------------------------------------------------------------*/
8635 static void
8636 genRightShift (iCode * ic)
8637 {
8638   operand *right, *left, *result;
8639   sym_link *letype;
8640   int size, offset;
8641   char *l;
8642   symbol *tlbl, *tlbl1;
8643   bool pushedB;
8644
8645   D(emitcode (";     genRightShift",""));
8646
8647   /* if signed then we do it the hard way preserve the
8648      sign bit moving it inwards */
8649   letype = getSpec (operandType (IC_LEFT (ic)));
8650
8651   if (!SPEC_USIGN (letype))
8652     {
8653       genSignedRightShift (ic);
8654       return;
8655     }
8656
8657   /* signed & unsigned types are treated the same : i.e. the
8658      signed is NOT propagated inwards : quoting from the
8659      ANSI - standard : "for E1 >> E2, is equivalent to division
8660      by 2**E2 if unsigned or if it has a non-negative value,
8661      otherwise the result is implementation defined ", MY definition
8662      is that the sign does not get propagated */
8663
8664   right = IC_RIGHT (ic);
8665   left = IC_LEFT (ic);
8666   result = IC_RESULT (ic);
8667
8668   aopOp (right, ic, FALSE);
8669
8670   /* if the shift count is known then do it
8671      as efficiently as possible */
8672   if (AOP_TYPE (right) == AOP_LIT)
8673     {
8674       genRightShiftLiteral (left, right, result, ic, 0);
8675       return;
8676     }
8677
8678   /* shift count is unknown then we have to form
8679      a loop get the loop count in B : Note: we take
8680      only the lower order byte since shifting
8681      more that 32 bits make no sense anyway, ( the
8682      largest size of an object can be only 32 bits ) */
8683
8684   pushedB = pushB ();
8685   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8686   emitcode ("inc", "b");
8687   freeAsmop (right, NULL, ic, TRUE);
8688   aopOp (left, ic, FALSE);
8689   aopOp (result, ic, FALSE);
8690
8691   /* now move the left to the result if they are not the
8692      same */
8693   if (!sameRegs (AOP (left), AOP (result)) &&
8694       AOP_SIZE (result) > 1)
8695     {
8696
8697       size = AOP_SIZE (result);
8698       offset = 0;
8699       while (size--)
8700         {
8701           l = aopGet (left, offset, FALSE, TRUE);
8702           if (*l == '@' && IS_AOP_PREG (result))
8703             {
8704
8705               emitcode ("mov", "a,%s", l);
8706               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8707             }
8708           else
8709             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8710           offset++;
8711         }
8712     }
8713
8714   tlbl = newiTempLabel (NULL);
8715   tlbl1 = newiTempLabel (NULL);
8716   size = AOP_SIZE (result);
8717   offset = size - 1;
8718
8719   /* if it is only one byte then */
8720   if (size == 1)
8721     {
8722       l = aopGet (left, 0, FALSE, FALSE);
8723       MOVA (l);
8724       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8725       emitcode ("", "%05d$:", tlbl->key + 100);
8726       CLRC;
8727       emitcode ("rrc", "a");
8728       emitcode ("", "%05d$:", tlbl1->key + 100);
8729       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8730       popB (pushedB);
8731       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8732       goto release;
8733     }
8734
8735   reAdjustPreg (AOP (result));
8736   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8737   emitcode ("", "%05d$:", tlbl->key + 100);
8738   CLRC;
8739   while (size--)
8740     {
8741       l = aopGet (result, offset, FALSE, FALSE);
8742       MOVA (l);
8743       emitcode ("rrc", "a");
8744       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8745     }
8746   reAdjustPreg (AOP (result));
8747
8748   emitcode ("", "%05d$:", tlbl1->key + 100);
8749   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8750   popB (pushedB);
8751
8752 release:
8753   freeAsmop (left, NULL, ic, TRUE);
8754   freeAsmop (result, NULL, ic, TRUE);
8755 }
8756
8757 /*-----------------------------------------------------------------*/
8758 /* emitPtrByteGet - emits code to get a byte into A through a      */
8759 /*                  pointer register (R0, R1, or DPTR). The        */
8760 /*                  original value of A can be preserved in B.     */
8761 /*-----------------------------------------------------------------*/
8762 static void
8763 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8764 {
8765   switch (p_type)
8766     {
8767     case IPOINTER:
8768     case POINTER:
8769       if (preserveAinB)
8770         emitcode ("mov", "b,a");
8771       emitcode ("mov", "a,@%s", rname);
8772       break;
8773
8774     case PPOINTER:
8775       if (preserveAinB)
8776         emitcode ("mov", "b,a");
8777       emitcode ("movx", "a,@%s", rname);
8778       break;
8779
8780     case FPOINTER:
8781       if (preserveAinB)
8782         emitcode ("mov", "b,a");
8783       emitcode ("movx", "a,@dptr");
8784       break;
8785
8786     case CPOINTER:
8787       if (preserveAinB)
8788         emitcode ("mov", "b,a");
8789       emitcode ("clr", "a");
8790       emitcode ("movc", "a,@a+dptr");
8791       break;
8792
8793     case GPOINTER:
8794       if (preserveAinB)
8795         {
8796           emitcode ("push", "b");
8797           emitcode ("push", "acc");
8798         }
8799       emitcode ("lcall", "__gptrget");
8800       if (preserveAinB)
8801         emitcode ("pop", "b");
8802       break;
8803     }
8804 }
8805
8806 /*-----------------------------------------------------------------*/
8807 /* emitPtrByteSet - emits code to set a byte from src through a    */
8808 /*                  pointer register (R0, R1, or DPTR).            */
8809 /*-----------------------------------------------------------------*/
8810 static void
8811 emitPtrByteSet (char *rname, int p_type, char *src)
8812 {
8813   switch (p_type)
8814     {
8815     case IPOINTER:
8816     case POINTER:
8817       if (*src=='@')
8818         {
8819           MOVA (src);
8820           emitcode ("mov", "@%s,a", rname);
8821         }
8822       else
8823         emitcode ("mov", "@%s,%s", rname, src);
8824       break;
8825
8826     case PPOINTER:
8827       MOVA (src);
8828       emitcode ("movx", "@%s,a", rname);
8829       break;
8830
8831     case FPOINTER:
8832       MOVA (src);
8833       emitcode ("movx", "@dptr,a");
8834       break;
8835
8836     case GPOINTER:
8837       MOVA (src);
8838       emitcode ("lcall", "__gptrput");
8839       break;
8840     }
8841 }
8842
8843 /*-----------------------------------------------------------------*/
8844 /* genUnpackBits - generates code for unpacking bits               */
8845 /*-----------------------------------------------------------------*/
8846 static void
8847 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8848 {
8849   int offset = 0;       /* result byte offset */
8850   int rsize;            /* result size */
8851   int rlen = 0;         /* remaining bitfield length */
8852   sym_link *etype;      /* bitfield type information */
8853   int blen;             /* bitfield length */
8854   int bstr;             /* bitfield starting bit within byte */
8855   char buffer[10];
8856
8857   D(emitcode (";     genUnpackBits",""));
8858
8859   etype = getSpec (operandType (result));
8860   rsize = getSize (operandType (result));
8861   blen = SPEC_BLEN (etype);
8862   bstr = SPEC_BSTR (etype);
8863
8864   if (ifx && blen <= 8)
8865     {
8866       emitPtrByteGet (rname, ptype, FALSE);
8867       if (blen == 1)
8868         {
8869           SNPRINTF (buffer, sizeof(buffer),
8870                     "acc.%d", bstr);
8871           genIfxJump (ifx, buffer, NULL, NULL, NULL);
8872         }
8873       else
8874         {
8875           if (blen < 8)
8876             emitcode ("anl", "a,#0x%02x",
8877                       (((unsigned char) -1) >> (8 - blen)) << bstr);
8878           genIfxJump (ifx, "a", NULL, NULL, NULL);
8879         }
8880       return;
8881     }
8882   wassert (!ifx);
8883
8884   /* If the bitfield length is less than a byte */
8885   if (blen < 8)
8886     {
8887       emitPtrByteGet (rname, ptype, FALSE);
8888       AccRsh (bstr);
8889       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8890       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8891       goto finish;
8892     }
8893
8894   /* Bit field did not fit in a byte. Copy all
8895      but the partial byte at the end.  */
8896   for (rlen=blen;rlen>=8;rlen-=8)
8897     {
8898       emitPtrByteGet (rname, ptype, FALSE);
8899       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8900       if (rlen>8)
8901         emitcode ("inc", "%s", rname);
8902     }
8903
8904   /* Handle the partial byte at the end */
8905   if (rlen)
8906     {
8907       emitPtrByteGet (rname, ptype, FALSE);
8908       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8909       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8910     }
8911
8912 finish:
8913   if (offset < rsize)
8914     {
8915       rsize -= offset;
8916       while (rsize--)
8917         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8918     }
8919 }
8920
8921
8922 /*-----------------------------------------------------------------*/
8923 /* genDataPointerGet - generates code when ptr offset is known     */
8924 /*-----------------------------------------------------------------*/
8925 static void
8926 genDataPointerGet (operand * left,
8927                    operand * result,
8928                    iCode * ic)
8929 {
8930   char *l;
8931   char buffer[256];
8932   int size, offset = 0;
8933
8934   D(emitcode (";     genDataPointerGet",""));
8935
8936   aopOp (result, ic, TRUE);
8937
8938   /* get the string representation of the name */
8939   l = aopGet (left, 0, FALSE, TRUE);
8940   size = AOP_SIZE (result);
8941   while (size--)
8942     {
8943       if (offset)
8944         sprintf (buffer, "(%s + %d)", l + 1, offset);
8945       else
8946         sprintf (buffer, "%s", l + 1);
8947       aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8948     }
8949
8950   freeAsmop (left, NULL, ic, TRUE);
8951   freeAsmop (result, NULL, ic, TRUE);
8952 }
8953
8954 /*-----------------------------------------------------------------*/
8955 /* genNearPointerGet - emitcode for near pointer fetch             */
8956 /*-----------------------------------------------------------------*/
8957 static void
8958 genNearPointerGet (operand * left,
8959                    operand * result,
8960                    iCode * ic,
8961                    iCode * pi,
8962                    iCode * ifx)
8963 {
8964   asmop *aop = NULL;
8965   regs *preg = NULL;
8966   char *rname;
8967   sym_link *rtype, *retype;
8968   sym_link *ltype = operandType (left);
8969   char buffer[80];
8970
8971   D(emitcode (";     genNearPointerGet",""));
8972
8973   rtype = operandType (result);
8974   retype = getSpec (rtype);
8975
8976   aopOp (left, ic, FALSE);
8977
8978   /* if left is rematerialisable and
8979      result is not bitfield variable type and
8980      the left is pointer to data space i.e
8981      lower 128 bytes of space */
8982   if (AOP_TYPE (left) == AOP_IMMD &&
8983       !IS_BITFIELD (retype) &&
8984       DCL_TYPE (ltype) == POINTER)
8985     {
8986       genDataPointerGet (left, result, ic);
8987       return;
8988     }
8989
8990  /* if the value is already in a pointer register
8991      then don't need anything more */
8992   if (!AOP_INPREG (AOP (left)))
8993     {
8994       if (IS_AOP_PREG (left))
8995         {
8996           // Aha, it is a pointer, just in disguise.
8997           rname = aopGet (left, 0, FALSE, FALSE);
8998           if (*rname != '@')
8999             {
9000               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9001                       __FILE__, __LINE__);
9002             }
9003           else
9004             {
9005               // Expected case.
9006               emitcode ("mov", "a%s,%s", rname + 1, rname);
9007               rname++;  // skip the '@'.
9008             }
9009         }
9010       else
9011         {
9012           /* otherwise get a free pointer register */
9013           aop = newAsmop (0);
9014           preg = getFreePtr (ic, &aop, FALSE);
9015           emitcode ("mov", "%s,%s",
9016                     preg->name,
9017                     aopGet (left, 0, FALSE, TRUE));
9018           rname = preg->name;
9019         }
9020     }
9021   else
9022     rname = aopGet (left, 0, FALSE, FALSE);
9023
9024   //aopOp (result, ic, FALSE);
9025   aopOp (result, ic, result?TRUE:FALSE);
9026
9027   /* if bitfield then unpack the bits */
9028   if (IS_BITFIELD (retype))
9029     genUnpackBits (result, rname, POINTER, ifx);
9030   else
9031     {
9032       /* we have can just get the values */
9033       int size = AOP_SIZE (result);
9034       int offset = 0;
9035
9036       while (size--)
9037         {
9038           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9039             {
9040
9041               emitcode ("mov", "a,@%s", rname);
9042               if (!ifx)
9043               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9044             }
9045           else
9046             {
9047               sprintf (buffer, "@%s", rname);
9048               aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9049             }
9050           offset++;
9051           if (size || pi)
9052             emitcode ("inc", "%s", rname);
9053         }
9054     }
9055
9056   /* now some housekeeping stuff */
9057   if (aop)       /* we had to allocate for this iCode */
9058     {
9059       if (pi) { /* post increment present */
9060         aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9061       }
9062       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9063     }
9064   else
9065     {
9066       /* we did not allocate which means left
9067          already in a pointer register, then
9068          if size > 0 && this could be used again
9069          we have to point it back to where it
9070          belongs */
9071       if ((AOP_SIZE (result) > 1 &&
9072            !OP_SYMBOL (left)->remat &&
9073            (OP_SYMBOL (left)->liveTo > ic->seq ||
9074             ic->depth)) &&
9075           !pi)
9076         {
9077           int size = AOP_SIZE (result) - 1;
9078           while (size--)
9079             emitcode ("dec", "%s", rname);
9080         }
9081     }
9082
9083   if (ifx && !ifx->generated)
9084     {
9085       genIfxJump (ifx, "a", left, NULL, result);
9086     }
9087
9088   /* done */
9089   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9090   freeAsmop (left, NULL, ic, TRUE);
9091   if (pi) pi->generated = 1;
9092 }
9093
9094 /*-----------------------------------------------------------------*/
9095 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9096 /*-----------------------------------------------------------------*/
9097 static void
9098 genPagedPointerGet (operand * left,
9099                     operand * result,
9100                     iCode * ic,
9101                     iCode *pi,
9102                     iCode *ifx)
9103 {
9104   asmop *aop = NULL;
9105   regs *preg = NULL;
9106   char *rname;
9107   sym_link *rtype, *retype;
9108
9109   D(emitcode (";     genPagedPointerGet",""));
9110
9111   rtype = operandType (result);
9112   retype = getSpec (rtype);
9113
9114   aopOp (left, ic, FALSE);
9115
9116   /* if the value is already in a pointer register
9117      then don't need anything more */
9118   if (!AOP_INPREG (AOP (left)))
9119     {
9120       /* otherwise get a free pointer register */
9121       aop = newAsmop (0);
9122       preg = getFreePtr (ic, &aop, FALSE);
9123       emitcode ("mov", "%s,%s",
9124                 preg->name,
9125                 aopGet (left, 0, FALSE, TRUE));
9126       rname = preg->name;
9127     }
9128   else
9129     rname = aopGet (left, 0, FALSE, FALSE);
9130
9131   aopOp (result, ic, FALSE);
9132
9133   /* if bitfield then unpack the bits */
9134   if (IS_BITFIELD (retype))
9135     genUnpackBits (result, rname, PPOINTER, ifx);
9136   else
9137     {
9138       /* we have can just get the values */
9139       int size = AOP_SIZE (result);
9140       int offset = 0;
9141
9142       while (size--)
9143         {
9144
9145           emitcode ("movx", "a,@%s", rname);
9146           if (!ifx)
9147           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9148
9149           offset++;
9150
9151           if (size || pi)
9152             emitcode ("inc", "%s", rname);
9153         }
9154     }
9155
9156   /* now some housekeeping stuff */
9157   if (aop) /* we had to allocate for this iCode */
9158     {
9159       if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9160       freeAsmop (NULL, aop, ic, TRUE);
9161     }
9162   else
9163     {
9164       /* we did not allocate which means left
9165          already in a pointer register, then
9166          if size > 0 && this could be used again
9167          we have to point it back to where it
9168          belongs */
9169       if ((AOP_SIZE (result) > 1 &&
9170            !OP_SYMBOL (left)->remat &&
9171            (OP_SYMBOL (left)->liveTo > ic->seq ||
9172             ic->depth)) &&
9173           !pi)
9174         {
9175           int size = AOP_SIZE (result) - 1;
9176           while (size--)
9177             emitcode ("dec", "%s", rname);
9178         }
9179     }
9180
9181   if (ifx && !ifx->generated)
9182     {
9183       genIfxJump (ifx, "a", left, NULL, result);
9184     }
9185
9186   /* done */
9187   freeAsmop (left, NULL, ic, TRUE);
9188   freeAsmop (result, NULL, ic, TRUE);
9189   if (pi) pi->generated = 1;
9190
9191 }
9192
9193 /*--------------------------------------------------------------------*/
9194 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9195 /*--------------------------------------------------------------------*/
9196 static void
9197 loadDptrFromOperand (operand *op, bool loadBToo)
9198 {
9199   if (AOP_TYPE (op) != AOP_STR)
9200     {
9201       /* if this is rematerializable */
9202       if (AOP_TYPE (op) == AOP_IMMD)
9203         {
9204           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9205           if (loadBToo)
9206             {
9207               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9208                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9209               else
9210                 {
9211                   wassertl(FALSE, "need pointerCode");
9212                   emitcode ("", "; mov b,???");
9213                   /* genPointerGet and genPointerSet originally did different
9214                   ** things for this case. Both seem wrong.
9215                   ** from genPointerGet:
9216                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9217                   ** from genPointerSet:
9218                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9219                   */
9220                 }
9221             }
9222         }
9223       else if (AOP_TYPE (op) == AOP_DPTR)
9224         {
9225           if (loadBToo)
9226             {
9227               MOVA (aopGet (op, 0, FALSE, FALSE));
9228               emitcode ("push", "acc");
9229               MOVA (aopGet (op, 1, FALSE, FALSE));
9230               emitcode ("push", "acc");
9231               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9232               emitcode ("pop", "dph");
9233               emitcode ("pop", "dpl");
9234             }
9235           else
9236             {
9237               MOVA (aopGet (op, 0, FALSE, FALSE));
9238               emitcode ("push", "acc");
9239               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9240               emitcode ("pop", "dpl");
9241             }
9242         }
9243       else
9244         {                       /* we need to get it byte by byte */
9245           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9246           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9247           if (loadBToo)
9248             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9249         }
9250     }
9251 }
9252
9253 /*-----------------------------------------------------------------*/
9254 /* genFarPointerGet - gget value from far space                    */
9255 /*-----------------------------------------------------------------*/
9256 static void
9257 genFarPointerGet (operand * left,
9258                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9259 {
9260   int size, offset;
9261   sym_link *retype = getSpec (operandType (result));
9262
9263   D(emitcode (";     genFarPointerGet",""));
9264
9265   aopOp (left, ic, FALSE);
9266   loadDptrFromOperand (left, FALSE);
9267
9268   /* so dptr now contains the address */
9269   aopOp (result, ic, FALSE);
9270
9271   /* if bit then unpack */
9272   if (IS_BITFIELD (retype))
9273     genUnpackBits (result, "dptr", FPOINTER, ifx);
9274   else
9275     {
9276       size = AOP_SIZE (result);
9277       offset = 0;
9278
9279       while (size--)
9280         {
9281           emitcode ("movx", "a,@dptr");
9282           if (!ifx)
9283             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9284           if (size || pi)
9285             emitcode ("inc", "dptr");
9286         }
9287     }
9288
9289   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9290     {
9291     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9292     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9293     pi->generated = 1;
9294   }
9295
9296   if (ifx && !ifx->generated)
9297     {
9298       genIfxJump (ifx, "a", left, NULL, result);
9299     }
9300
9301   freeAsmop (left, NULL, ic, TRUE);
9302   freeAsmop (result, NULL, ic, TRUE);
9303 }
9304
9305 /*-----------------------------------------------------------------*/
9306 /* genCodePointerGet - gget value from code space                  */
9307 /*-----------------------------------------------------------------*/
9308 static void
9309 genCodePointerGet (operand * left,
9310                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9311 {
9312   int size, offset;
9313   sym_link *retype = getSpec (operandType (result));
9314
9315   D(emitcode (";     genCodePointerGet",""));
9316
9317   aopOp (left, ic, FALSE);
9318   loadDptrFromOperand (left, FALSE);
9319
9320   /* so dptr now contains the address */
9321   aopOp (result, ic, FALSE);
9322
9323   /* if bit then unpack */
9324   if (IS_BITFIELD (retype))
9325     genUnpackBits (result, "dptr", CPOINTER, ifx);
9326   else
9327     {
9328       size = AOP_SIZE (result);
9329       offset = 0;
9330
9331       while (size--)
9332         {
9333           if (pi)
9334             {
9335               emitcode ("clr", "a");
9336               emitcode ("movc", "a,@a+dptr");
9337               if (!ifx)
9338               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9339               emitcode ("inc", "dptr");
9340             }
9341           else
9342             {
9343               emitcode ("mov", "a,#0x%02x", offset);
9344               emitcode ("movc", "a,@a+dptr");
9345               if (!ifx)
9346               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9347             }
9348         }
9349     }
9350
9351   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9352     {
9353     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9354     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9355     pi->generated = 1;
9356   }
9357
9358   if (ifx && !ifx->generated)
9359     {
9360       genIfxJump (ifx, "a", left, NULL, result);
9361     }
9362
9363   freeAsmop (left, NULL, ic, TRUE);
9364   freeAsmop (result, NULL, ic, TRUE);
9365 }
9366
9367 /*-----------------------------------------------------------------*/
9368 /* genGenPointerGet - gget value from generic pointer space        */
9369 /*-----------------------------------------------------------------*/
9370 static void
9371 genGenPointerGet (operand * left,
9372                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9373 {
9374   int size, offset;
9375   sym_link *retype = getSpec (operandType (result));
9376
9377   D(emitcode (";     genGenPointerGet",""));
9378
9379   aopOp (left, ic, FALSE);
9380   loadDptrFromOperand (left, TRUE);
9381
9382   /* so dptr know contains the address */
9383   aopOp (result, ic, FALSE);
9384
9385   /* if bit then unpack */
9386   if (IS_BITFIELD (retype))
9387     genUnpackBits (result, "dptr", GPOINTER, ifx);
9388   else
9389     {
9390       size = AOP_SIZE (result);
9391       offset = 0;
9392
9393       while (size--)
9394         {
9395           emitcode ("lcall", "__gptrget");
9396           if (!ifx)
9397           aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9398           if (size || pi)
9399             emitcode ("inc", "dptr");
9400         }
9401     }
9402
9403   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9404     {
9405     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9406     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9407     pi->generated = 1;
9408   }
9409
9410   if (ifx && !ifx->generated)
9411     {
9412       genIfxJump (ifx, "a", left, NULL, result);
9413     }
9414
9415
9416   freeAsmop (left, NULL, ic, TRUE);
9417   freeAsmop (result, NULL, ic, TRUE);
9418 }
9419
9420 /*-----------------------------------------------------------------*/
9421 /* genPointerGet - generate code for pointer get                   */
9422 /*-----------------------------------------------------------------*/
9423 static void
9424 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9425 {
9426   operand *left, *result;
9427   sym_link *type, *etype;
9428   int p_type;
9429
9430   D(emitcode (";     genPointerGet",""));
9431
9432   left = IC_LEFT (ic);
9433   result = IC_RESULT (ic);
9434
9435   if (getSize (operandType (result))>1)
9436     ifx = NULL;
9437
9438   /* depending on the type of pointer we need to
9439      move it to the correct pointer register */
9440   type = operandType (left);
9441   etype = getSpec (type);
9442   /* if left is of type of pointer then it is simple */
9443   if (IS_PTR (type) && !IS_FUNC (type->next))
9444     p_type = DCL_TYPE (type);
9445   else
9446     {
9447       /* we have to go by the storage class */
9448       p_type = PTR_TYPE (SPEC_OCLS (etype));
9449     }
9450
9451   /* special case when cast remat */
9452   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9453       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9454           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9455           type = operandType (left);
9456           p_type = DCL_TYPE (type);
9457   }
9458   /* now that we have the pointer type we assign
9459      the pointer values */
9460   switch (p_type)
9461     {
9462
9463     case POINTER:
9464     case IPOINTER:
9465       genNearPointerGet (left, result, ic, pi, ifx);
9466       break;
9467
9468     case PPOINTER:
9469       genPagedPointerGet (left, result, ic, pi, ifx);
9470       break;
9471
9472     case FPOINTER:
9473       genFarPointerGet (left, result, ic, pi, ifx);
9474       break;
9475
9476     case CPOINTER:
9477       genCodePointerGet (left, result, ic, pi, ifx);
9478       break;
9479
9480     case GPOINTER:
9481       genGenPointerGet (left, result, ic, pi, ifx);
9482       break;
9483     }
9484
9485 }
9486
9487
9488
9489 /*-----------------------------------------------------------------*/
9490 /* genPackBits - generates code for packed bit storage             */
9491 /*-----------------------------------------------------------------*/
9492 static void
9493 genPackBits (sym_link * etype,
9494              operand * right,
9495              char *rname, int p_type)
9496 {
9497   int offset = 0;       /* source byte offset */
9498   int rlen = 0;         /* remaining bitfield length */
9499   int blen;             /* bitfield length */
9500   int bstr;             /* bitfield starting bit within byte */
9501   int litval;           /* source literal value (if AOP_LIT) */
9502   unsigned char mask;   /* bitmask within current byte */
9503
9504   D(emitcode (";     genPackBits",""));
9505
9506   blen = SPEC_BLEN (etype);
9507   bstr = SPEC_BSTR (etype);
9508
9509   /* If the bitfield length is less than a byte */
9510   if (blen < 8)
9511     {
9512       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9513               (unsigned char) (0xFF >> (8 - bstr)));
9514
9515       if (AOP_TYPE (right) == AOP_LIT)
9516         {
9517           /* Case with a bitfield length <8 and literal source
9518           */
9519           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9520           litval <<= bstr;
9521           litval &= (~mask) & 0xff;
9522           emitPtrByteGet (rname, p_type, FALSE);
9523           if ((mask|litval)!=0xff)
9524             emitcode ("anl","a,#0x%02x", mask);
9525           if (litval)
9526             emitcode ("orl","a,#0x%02x", litval);
9527         }
9528       else
9529         {
9530           if ((blen==1) && (p_type!=GPOINTER))
9531             {
9532               /* Case with a bitfield length == 1 and no generic pointer
9533               */
9534               if (AOP_TYPE (right) == AOP_CRY)
9535                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9536               else
9537                 {
9538                   MOVA (aopGet (right, 0, FALSE, FALSE));
9539                   emitcode ("rrc","a");
9540                 }
9541               emitPtrByteGet (rname, p_type, FALSE);
9542               emitcode ("mov","acc.%d,c",bstr);
9543             }
9544           else
9545             {
9546               bool pushedB;
9547               /* Case with a bitfield length < 8 and arbitrary source
9548               */
9549               MOVA (aopGet (right, 0, FALSE, FALSE));
9550               /* shift and mask source value */
9551               AccLsh (bstr);
9552               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9553
9554               pushedB = pushB ();
9555               /* transfer A to B and get next byte */
9556               emitPtrByteGet (rname, p_type, TRUE);
9557
9558               emitcode ("anl", "a,#0x%02x", mask);
9559               emitcode ("orl", "a,b");
9560               if (p_type == GPOINTER)
9561                 emitcode ("pop", "b");
9562
9563               popB (pushedB);
9564            }
9565         }
9566
9567       emitPtrByteSet (rname, p_type, "a");
9568       return;
9569     }
9570
9571   /* Bit length is greater than 7 bits. In this case, copy  */
9572   /* all except the partial byte at the end                 */
9573   for (rlen=blen;rlen>=8;rlen-=8)
9574     {
9575       emitPtrByteSet (rname, p_type,
9576                       aopGet (right, offset++, FALSE, TRUE) );
9577       if (rlen>8)
9578         emitcode ("inc", "%s", rname);
9579     }
9580
9581   /* If there was a partial byte at the end */
9582   if (rlen)
9583     {
9584       mask = (((unsigned char) -1 << rlen) & 0xff);
9585
9586       if (AOP_TYPE (right) == AOP_LIT)
9587         {
9588           /* Case with partial byte and literal source
9589           */
9590           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9591           litval >>= (blen-rlen);
9592           litval &= (~mask) & 0xff;
9593           emitPtrByteGet (rname, p_type, FALSE);
9594           if ((mask|litval)!=0xff)
9595             emitcode ("anl","a,#0x%02x", mask);
9596           if (litval)
9597             emitcode ("orl","a,#0x%02x", litval);
9598         }
9599       else
9600         {
9601           bool pushedB;
9602           /* Case with partial byte and arbitrary source
9603           */
9604           MOVA (aopGet (right, offset++, FALSE, FALSE));
9605           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9606
9607           pushedB = pushB ();
9608           /* transfer A to B and get next byte */
9609           emitPtrByteGet (rname, p_type, TRUE);
9610
9611           emitcode ("anl", "a,#0x%02x", mask);
9612           emitcode ("orl", "a,b");
9613           if (p_type == GPOINTER)
9614             emitcode ("pop", "b");
9615
9616           popB (pushedB);
9617         }
9618       emitPtrByteSet (rname, p_type, "a");
9619     }
9620
9621 }
9622
9623
9624 /*-----------------------------------------------------------------*/
9625 /* genDataPointerSet - remat pointer to data space                 */
9626 /*-----------------------------------------------------------------*/
9627 static void
9628 genDataPointerSet (operand * right,
9629                    operand * result,
9630                    iCode * ic)
9631 {
9632   int size, offset = 0;
9633   char *l, buffer[256];
9634
9635   D(emitcode (";     genDataPointerSet",""));
9636
9637   aopOp (right, ic, FALSE);
9638
9639   l = aopGet (result, 0, FALSE, TRUE);
9640   size = AOP_SIZE (right);
9641   while (size--)
9642     {
9643       if (offset)
9644         sprintf (buffer, "(%s + %d)", l + 1, offset);
9645       else
9646         sprintf (buffer, "%s", l + 1);
9647       emitcode ("mov", "%s,%s", buffer,
9648                 aopGet (right, offset++, FALSE, FALSE));
9649     }
9650
9651   freeAsmop (right, NULL, ic, TRUE);
9652   freeAsmop (result, NULL, ic, TRUE);
9653 }
9654
9655 /*-----------------------------------------------------------------*/
9656 /* genNearPointerSet - emitcode for near pointer put                */
9657 /*-----------------------------------------------------------------*/
9658 static void
9659 genNearPointerSet (operand * right,
9660                    operand * result,
9661                    iCode * ic,
9662                    iCode * pi)
9663 {
9664   asmop *aop = NULL;
9665   regs *preg = NULL;
9666   char *rname, *l;
9667   sym_link *retype, *letype;
9668   sym_link *ptype = operandType (result);
9669
9670   D(emitcode (";     genNearPointerSet",""));
9671
9672   retype = getSpec (operandType (right));
9673   letype = getSpec (ptype);
9674   aopOp (result, ic, FALSE);
9675
9676   /* if the result is rematerializable &
9677      in data space & not a bit variable */
9678   if (AOP_TYPE (result) == AOP_IMMD &&
9679       DCL_TYPE (ptype) == POINTER &&
9680       !IS_BITVAR (retype) &&
9681       !IS_BITVAR (letype))
9682     {
9683       genDataPointerSet (right, result, ic);
9684       return;
9685     }
9686
9687   /* if the value is already in a pointer register
9688      then don't need anything more */
9689   if (!AOP_INPREG (AOP (result)))
9690     {
9691         if (
9692             //AOP_TYPE (result) == AOP_STK
9693             IS_AOP_PREG(result)
9694             )
9695         {
9696             // Aha, it is a pointer, just in disguise.
9697             rname = aopGet (result, 0, FALSE, FALSE);
9698             if (*rname != '@')
9699             {
9700                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9701                         __FILE__, __LINE__);
9702             }
9703             else
9704             {
9705                 // Expected case.
9706                 emitcode ("mov", "a%s,%s", rname + 1, rname);
9707                 rname++;  // skip the '@'.
9708             }
9709         }
9710         else
9711         {
9712             /* otherwise get a free pointer register */
9713             aop = newAsmop (0);
9714             preg = getFreePtr (ic, &aop, FALSE);
9715             emitcode ("mov", "%s,%s",
9716                       preg->name,
9717                       aopGet (result, 0, FALSE, TRUE));
9718             rname = preg->name;
9719         }
9720     }
9721     else
9722     {
9723         rname = aopGet (result, 0, FALSE, FALSE);
9724     }
9725
9726   aopOp (right, ic, FALSE);
9727
9728   /* if bitfield then unpack the bits */
9729   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9730     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9731   else
9732     {
9733       /* we have can just get the values */
9734       int size = AOP_SIZE (right);
9735       int offset = 0;
9736
9737       while (size--)
9738         {
9739           l = aopGet (right, offset, FALSE, TRUE);
9740           if (*l == '@')
9741             {
9742               MOVA (l);
9743               emitcode ("mov", "@%s,a", rname);
9744             }
9745           else
9746             emitcode ("mov", "@%s,%s", rname, l);
9747           if (size || pi)
9748             emitcode ("inc", "%s", rname);
9749           offset++;
9750         }
9751     }
9752
9753   /* now some housekeeping stuff */
9754   if (aop) /* we had to allocate for this iCode */
9755     {
9756       if (pi)
9757         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9758       freeAsmop (NULL, aop, ic, TRUE);
9759     }
9760   else
9761     {
9762       /* we did not allocate which means left
9763          already in a pointer register, then
9764          if size > 0 && this could be used again
9765          we have to point it back to where it
9766          belongs */
9767       if ((AOP_SIZE (right) > 1 &&
9768            !OP_SYMBOL (result)->remat &&
9769            (OP_SYMBOL (result)->liveTo > ic->seq ||
9770             ic->depth)) &&
9771           !pi)
9772         {
9773           int size = AOP_SIZE (right) - 1;
9774           while (size--)
9775             emitcode ("dec", "%s", rname);
9776         }
9777     }
9778
9779   /* done */
9780   if (pi) pi->generated = 1;
9781   freeAsmop (result, NULL, ic, TRUE);
9782   freeAsmop (right, NULL, ic, TRUE);
9783 }
9784
9785 /*-----------------------------------------------------------------*/
9786 /* genPagedPointerSet - emitcode for Paged pointer put             */
9787 /*-----------------------------------------------------------------*/
9788 static void
9789 genPagedPointerSet (operand * right,
9790                     operand * result,
9791                     iCode * ic,
9792                     iCode * pi)
9793 {
9794   asmop *aop = NULL;
9795   regs *preg = NULL;
9796   char *rname, *l;
9797   sym_link *retype, *letype;
9798
9799   D(emitcode (";     genPagedPointerSet",""));
9800
9801   retype = getSpec (operandType (right));
9802   letype = getSpec (operandType (result));
9803
9804   aopOp (result, ic, FALSE);
9805
9806   /* if the value is already in a pointer register
9807      then don't need anything more */
9808   if (!AOP_INPREG (AOP (result)))
9809     {
9810       /* otherwise get a free pointer register */
9811       aop = newAsmop (0);
9812       preg = getFreePtr (ic, &aop, FALSE);
9813       emitcode ("mov", "%s,%s",
9814                 preg->name,
9815                 aopGet (result, 0, FALSE, TRUE));
9816       rname = preg->name;
9817     }
9818   else
9819     rname = aopGet (result, 0, FALSE, FALSE);
9820
9821   aopOp (right, ic, FALSE);
9822
9823   /* if bitfield then unpack the bits */
9824   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9825     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9826   else
9827     {
9828       /* we have can just get the values */
9829       int size = AOP_SIZE (right);
9830       int offset = 0;
9831
9832       while (size--)
9833         {
9834           l = aopGet (right, offset, FALSE, TRUE);
9835
9836           MOVA (l);
9837           emitcode ("movx", "@%s,a", rname);
9838
9839           if (size || pi)
9840             emitcode ("inc", "%s", rname);
9841
9842           offset++;
9843         }
9844     }
9845
9846   /* now some housekeeping stuff */
9847   if (aop) /* we had to allocate for this iCode */
9848     {
9849       if (pi)
9850         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9851       freeAsmop (NULL, aop, ic, TRUE);
9852     }
9853   else
9854     {
9855       /* we did not allocate which means left
9856          already in a pointer register, then
9857          if size > 0 && this could be used again
9858          we have to point it back to where it
9859          belongs */
9860       if (AOP_SIZE (right) > 1 &&
9861           !OP_SYMBOL (result)->remat &&
9862           (OP_SYMBOL (result)->liveTo > ic->seq ||
9863            ic->depth))
9864         {
9865           int size = AOP_SIZE (right) - 1;
9866           while (size--)
9867             emitcode ("dec", "%s", rname);
9868         }
9869     }
9870
9871   /* done */
9872   if (pi) pi->generated = 1;
9873   freeAsmop (result, NULL, ic, TRUE);
9874   freeAsmop (right, NULL, ic, TRUE);
9875
9876
9877 }
9878
9879 /*-----------------------------------------------------------------*/
9880 /* genFarPointerSet - set value from far space                     */
9881 /*-----------------------------------------------------------------*/
9882 static void
9883 genFarPointerSet (operand * right,
9884                   operand * result, iCode * ic, iCode * pi)
9885 {
9886   int size, offset;
9887   sym_link *retype = getSpec (operandType (right));
9888   sym_link *letype = getSpec (operandType (result));
9889
9890   D(emitcode (";     genFarPointerSet",""));
9891
9892   aopOp (result, ic, FALSE);
9893   loadDptrFromOperand (result, FALSE);
9894
9895   /* so dptr know contains the address */
9896   aopOp (right, ic, FALSE);
9897
9898   /* if bit then unpack */
9899   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9900     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9901   else
9902     {
9903       size = AOP_SIZE (right);
9904       offset = 0;
9905
9906       while (size--)
9907         {
9908           char *l = aopGet (right, offset++, FALSE, FALSE);
9909           MOVA (l);
9910           emitcode ("movx", "@dptr,a");
9911           if (size || pi)
9912             emitcode ("inc", "dptr");
9913         }
9914     }
9915   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9916     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9917     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9918     pi->generated=1;
9919   }
9920   freeAsmop (result, NULL, ic, TRUE);
9921   freeAsmop (right, NULL, ic, TRUE);
9922 }
9923
9924 /*-----------------------------------------------------------------*/
9925 /* genGenPointerSet - set value from generic pointer space         */
9926 /*-----------------------------------------------------------------*/
9927 static void
9928 genGenPointerSet (operand * right,
9929                   operand * result, iCode * ic, iCode * pi)
9930 {
9931   int size, offset;
9932   sym_link *retype = getSpec (operandType (right));
9933   sym_link *letype = getSpec (operandType (result));
9934
9935   D(emitcode (";     genGenPointerSet",""));
9936
9937   aopOp (result, ic, FALSE);
9938   loadDptrFromOperand (result, TRUE);
9939
9940   /* so dptr know contains the address */
9941   aopOp (right, ic, FALSE);
9942
9943   /* if bit then unpack */
9944   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9945     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9946   else
9947     {
9948       size = AOP_SIZE (right);
9949       offset = 0;
9950
9951       while (size--)
9952         {
9953           char *l = aopGet (right, offset++, FALSE, FALSE);
9954           MOVA (l);
9955           emitcode ("lcall", "__gptrput");
9956           if (size || pi)
9957             emitcode ("inc", "dptr");
9958         }
9959     }
9960
9961   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9962     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9963     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9964     pi->generated=1;
9965   }
9966   freeAsmop (result, NULL, ic, TRUE);
9967   freeAsmop (right, NULL, ic, TRUE);
9968 }
9969
9970 /*-----------------------------------------------------------------*/
9971 /* genPointerSet - stores the value into a pointer location        */
9972 /*-----------------------------------------------------------------*/
9973 static void
9974 genPointerSet (iCode * ic, iCode *pi)
9975 {
9976   operand *right, *result;
9977   sym_link *type, *etype;
9978   int p_type;
9979
9980   D(emitcode (";     genPointerSet",""));
9981
9982   right = IC_RIGHT (ic);
9983   result = IC_RESULT (ic);
9984
9985   /* depending on the type of pointer we need to
9986      move it to the correct pointer register */
9987   type = operandType (result);
9988   etype = getSpec (type);
9989   /* if left is of type of pointer then it is simple */
9990   if (IS_PTR (type) && !IS_FUNC (type->next))
9991     {
9992       p_type = DCL_TYPE (type);
9993     }
9994   else
9995     {
9996       /* we have to go by the storage class */
9997       p_type = PTR_TYPE (SPEC_OCLS (etype));
9998     }
9999
10000   /* special case when cast remat */
10001   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10002       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10003           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10004           type = operandType (result);
10005           p_type = DCL_TYPE (type);
10006   }
10007   /* now that we have the pointer type we assign
10008      the pointer values */
10009   switch (p_type)
10010     {
10011
10012     case POINTER:
10013     case IPOINTER:
10014       genNearPointerSet (right, result, ic, pi);
10015       break;
10016
10017     case PPOINTER:
10018       genPagedPointerSet (right, result, ic, pi);
10019       break;
10020
10021     case FPOINTER:
10022       genFarPointerSet (right, result, ic, pi);
10023       break;
10024
10025     case GPOINTER:
10026       genGenPointerSet (right, result, ic, pi);
10027       break;
10028
10029     default:
10030       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10031               "genPointerSet: illegal pointer type");
10032     }
10033
10034 }
10035
10036 /*-----------------------------------------------------------------*/
10037 /* genIfx - generate code for Ifx statement                        */
10038 /*-----------------------------------------------------------------*/
10039 static void
10040 genIfx (iCode * ic, iCode * popIc)
10041 {
10042   operand *cond = IC_COND (ic);
10043   int isbit = 0;
10044   char *dup = NULL;
10045
10046   D(emitcode (";     genIfx",""));
10047
10048   aopOp (cond, ic, FALSE);
10049
10050   /* get the value into acc */
10051   if (AOP_TYPE (cond) != AOP_CRY)
10052     toBoolean (cond);
10053   else
10054     {
10055       isbit = 1;
10056       if (AOP(cond)->aopu.aop_dir)
10057         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10058     }
10059   /* the result is now in the accumulator or a directly addressable bit */
10060   freeAsmop (cond, NULL, ic, TRUE);
10061
10062   /* if there was something to be popped then do it */
10063   if (popIc)
10064     genIpop (popIc);
10065
10066   /* if the condition is a bit variable */
10067   if (isbit && dup)
10068     genIfxJump(ic, dup, NULL, NULL, NULL);
10069   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10070     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10071   else if (isbit && !IS_ITEMP (cond))
10072     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10073   else
10074     genIfxJump (ic, "a", NULL, NULL, NULL);
10075
10076   ic->generated = 1;
10077 }
10078
10079 /*-----------------------------------------------------------------*/
10080 /* genAddrOf - generates code for address of                       */
10081 /*-----------------------------------------------------------------*/
10082 static void
10083 genAddrOf (iCode * ic)
10084 {
10085   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10086   int size, offset;
10087
10088   D(emitcode (";     genAddrOf",""));
10089
10090   aopOp (IC_RESULT (ic), ic, FALSE);
10091
10092   /* if the operand is on the stack then we
10093      need to get the stack offset of this
10094      variable */
10095   if (sym->onStack)
10096     {
10097       /* if it has an offset then we need to compute
10098          it */
10099       if (sym->stack)
10100         {
10101           emitcode ("mov", "a,%s", SYM_BP (sym));
10102           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10103                                          ((char) (sym->stack - _G.nRegsSaved)) :
10104                                          ((char) sym->stack)) & 0xff);
10105           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10106         }
10107       else
10108         {
10109           /* we can just move _bp */
10110           aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10111         }
10112       /* fill the result with zero */
10113       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10114
10115       offset = 1;
10116       while (size--)
10117         {
10118           aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10119         }
10120
10121       goto release;
10122     }
10123
10124   /* object not on stack then we need the name */
10125   size = AOP_SIZE (IC_RESULT (ic));
10126   offset = 0;
10127
10128   while (size--)
10129     {
10130       char s[SDCC_NAME_MAX];
10131       if (offset)
10132         sprintf (s, "#(%s >> %d)",
10133                  sym->rname,
10134                  offset * 8);
10135       else
10136         sprintf (s, "#%s", sym->rname);
10137       aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10138     }
10139
10140 release:
10141   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10142
10143 }
10144
10145 /*-----------------------------------------------------------------*/
10146 /* genFarFarAssign - assignment when both are in far space         */
10147 /*-----------------------------------------------------------------*/
10148 static void
10149 genFarFarAssign (operand * result, operand * right, iCode * ic)
10150 {
10151   int size = AOP_SIZE (right);
10152   int offset = 0;
10153   char *l;
10154
10155   D(emitcode (";     genFarFarAssign",""));
10156
10157   /* first push the right side on to the stack */
10158   while (size--)
10159     {
10160       l = aopGet (right, offset++, FALSE, FALSE);
10161       MOVA (l);
10162       emitcode ("push", "acc");
10163     }
10164
10165   freeAsmop (right, NULL, ic, FALSE);
10166   /* now assign DPTR to result */
10167   aopOp (result, ic, FALSE);
10168   size = AOP_SIZE (result);
10169   while (size--)
10170     {
10171       emitcode ("pop", "acc");
10172       aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10173     }
10174   freeAsmop (result, NULL, ic, FALSE);
10175
10176 }
10177
10178 /*-----------------------------------------------------------------*/
10179 /* genAssign - generate code for assignment                        */
10180 /*-----------------------------------------------------------------*/
10181 static void
10182 genAssign (iCode * ic)
10183 {
10184   operand *result, *right;
10185   int size, offset;
10186   unsigned long lit = 0L;
10187
10188   D(emitcode(";     genAssign",""));
10189
10190   result = IC_RESULT (ic);
10191   right = IC_RIGHT (ic);
10192
10193   /* if they are the same */
10194   if (operandsEqu (result, right) &&
10195       !isOperandVolatile (result, FALSE) &&
10196       !isOperandVolatile (right, FALSE))
10197     return;
10198
10199   aopOp (right, ic, FALSE);
10200
10201   /* special case both in far space */
10202   if (AOP_TYPE (right) == AOP_DPTR &&
10203       IS_TRUE_SYMOP (result) &&
10204       isOperandInFarSpace (result))
10205     {
10206
10207       genFarFarAssign (result, right, ic);
10208       return;
10209     }
10210
10211   aopOp (result, ic, TRUE);
10212
10213   /* if they are the same registers */
10214   if (sameRegs (AOP (right), AOP (result)) &&
10215       !isOperandVolatile (result, FALSE) &&
10216       !isOperandVolatile (right, FALSE))
10217     goto release;
10218
10219   /* if the result is a bit */
10220   if (AOP_TYPE (result) == AOP_CRY)
10221     {
10222
10223       /* if the right size is a literal then
10224          we know what the value is */
10225       if (AOP_TYPE (right) == AOP_LIT)
10226         {
10227           if (((int) operandLitValue (right)))
10228             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10229           else
10230             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10231           goto release;
10232         }
10233
10234       /* the right is also a bit variable */
10235       if (AOP_TYPE (right) == AOP_CRY)
10236         {
10237           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10238           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10239           goto release;
10240         }
10241
10242       /* we need to or */
10243       toBoolean (right);
10244       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10245       goto release;
10246     }
10247
10248   /* bit variables done */
10249   /* general case */
10250   size = AOP_SIZE (result);
10251   offset = 0;
10252   if (AOP_TYPE (right) == AOP_LIT)
10253     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10254   if ((size > 1) &&
10255       (AOP_TYPE (result) != AOP_REG) &&
10256       (AOP_TYPE (right) == AOP_LIT) &&
10257       !IS_FLOAT (operandType (right)) &&
10258       (lit < 256L))
10259     {
10260       while ((size) && (lit))
10261         {
10262           aopPut (result,
10263                   aopGet (right, offset, FALSE, FALSE),
10264                   offset,
10265                   isOperandVolatile (result, FALSE));
10266           lit >>= 8;
10267           offset++;
10268           size--;
10269         }
10270       emitcode ("clr", "a");
10271       while (size--)
10272         {
10273           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10274           offset++;
10275         }
10276     }
10277   else
10278     {
10279       while (size--)
10280         {
10281           aopPut (result,
10282                   aopGet (right, offset, FALSE, FALSE),
10283                   offset,
10284                   isOperandVolatile (result, FALSE));
10285           offset++;
10286         }
10287     }
10288
10289 release:
10290   freeAsmop (right, NULL, ic, TRUE);
10291   freeAsmop (result, NULL, ic, TRUE);
10292 }
10293
10294 /*-----------------------------------------------------------------*/
10295 /* genJumpTab - generates code for jump table                      */
10296 /*-----------------------------------------------------------------*/
10297 static void
10298 genJumpTab (iCode * ic)
10299 {
10300   symbol *jtab,*jtablo,*jtabhi;
10301   char *l;
10302   unsigned int count;
10303
10304   D(emitcode (";     genJumpTab",""));
10305
10306   count = elementsInSet( IC_JTLABELS (ic) );
10307
10308   if( count <= 16 )
10309     {
10310       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10311          if the switch argument is in a register.
10312          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10313       /* (MB) What if peephole converts ljmp to sjmp or ret ???
10314          How will multiply by three be updated ???*/
10315       aopOp (IC_JTCOND (ic), ic, FALSE);
10316       /* get the condition into accumulator */
10317       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10318       MOVA (l);
10319       /* multiply by three */
10320       emitcode ("add", "a,acc");
10321       emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10322       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10323
10324       jtab = newiTempLabel (NULL);
10325       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10326       emitcode ("jmp", "@a+dptr");
10327       emitcode ("", "%05d$:", jtab->key + 100);
10328       /* now generate the jump labels */
10329       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10330            jtab = setNextItem (IC_JTLABELS (ic)))
10331         emitcode ("ljmp", "%05d$", jtab->key + 100);
10332     }
10333   else
10334     {
10335       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10336          if the switch argument is in a register.
10337          For n>6 this algorithm may be more compact */
10338       jtablo = newiTempLabel (NULL);
10339       jtabhi = newiTempLabel (NULL);
10340
10341       /* get the condition into accumulator.
10342          Using b as temporary storage, if register push/pop is needed */
10343       aopOp (IC_JTCOND (ic), ic, FALSE);
10344       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10345       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10346           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10347         {
10348           // (MB) what if B is in use???
10349           wassertl(!BINUSE, "B was in use");
10350           emitcode ("mov", "b,%s", l);
10351           l = "b";
10352         }
10353       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10354       MOVA (l);
10355       if( count <= 112 )
10356         {
10357           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10358           emitcode ("movc", "a,@a+pc");
10359           emitcode ("push", "acc");
10360
10361           MOVA (l);
10362           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10363           emitcode ("movc", "a,@a+pc");
10364           emitcode ("push", "acc");
10365         }
10366       else
10367         {
10368           /* this scales up to n<=255, but needs two more bytes
10369              and changes dptr */
10370           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10371           emitcode ("movc", "a,@a+dptr");
10372           emitcode ("push", "acc");
10373
10374           MOVA (l);
10375           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10376           emitcode ("movc", "a,@a+dptr");
10377           emitcode ("push", "acc");
10378         }
10379
10380       emitcode ("ret", "");
10381
10382       /* now generate jump table, LSB */
10383       emitcode ("", "%05d$:", jtablo->key + 100);
10384       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10385            jtab = setNextItem (IC_JTLABELS (ic)))
10386         emitcode (".db", "%05d$", jtab->key + 100);
10387
10388       /* now generate jump table, MSB */
10389       emitcode ("", "%05d$:", jtabhi->key + 100);
10390       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10391            jtab = setNextItem (IC_JTLABELS (ic)))
10392          emitcode (".db", "%05d$>>8", jtab->key + 100);
10393     }
10394 }
10395
10396 /*-----------------------------------------------------------------*/
10397 /* genCast - gen code for casting                                  */
10398 /*-----------------------------------------------------------------*/
10399 static void
10400 genCast (iCode * ic)
10401 {
10402   operand *result = IC_RESULT (ic);
10403   sym_link *ctype = operandType (IC_LEFT (ic));
10404   sym_link *rtype = operandType (IC_RIGHT (ic));
10405   operand *right = IC_RIGHT (ic);
10406   int size, offset;
10407
10408   D(emitcode(";     genCast",""));
10409
10410   /* if they are equivalent then do nothing */
10411   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10412     return;
10413
10414   aopOp (right, ic, FALSE);
10415   aopOp (result, ic, FALSE);
10416
10417   /* if the result is a bit (and not a bitfield) */
10418   // if (AOP_TYPE (result) == AOP_CRY)
10419   if (IS_BITVAR (OP_SYMBOL (result)->type)
10420       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10421     {
10422       /* if the right size is a literal then
10423          we know what the value is */
10424       if (AOP_TYPE (right) == AOP_LIT)
10425         {
10426           if (((int) operandLitValue (right)))
10427             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10428           else
10429             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10430
10431           goto release;
10432         }
10433
10434       /* the right is also a bit variable */
10435       if (AOP_TYPE (right) == AOP_CRY)
10436         {
10437           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10438           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10439           goto release;
10440         }
10441
10442       /* we need to or */
10443       toBoolean (right);
10444       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10445       goto release;
10446     }
10447
10448
10449   /* if they are the same size : or less */
10450   if (AOP_SIZE (result) <= AOP_SIZE (right))
10451     {
10452
10453       /* if they are in the same place */
10454       if (sameRegs (AOP (right), AOP (result)))
10455         goto release;
10456
10457       /* if they in different places then copy */
10458       size = AOP_SIZE (result);
10459       offset = 0;
10460       while (size--)
10461         {
10462           aopPut (result,
10463                   aopGet (right, offset, FALSE, FALSE),
10464                   offset,
10465                   isOperandVolatile (result, FALSE));
10466           offset++;
10467         }
10468       goto release;
10469     }
10470
10471
10472   /* if the result is of type pointer */
10473   if (IS_PTR (ctype))
10474     {
10475
10476       int p_type;
10477       sym_link *type = operandType (right);
10478       sym_link *etype = getSpec (type);
10479
10480       /* pointer to generic pointer */
10481       if (IS_GENPTR (ctype))
10482         {
10483           if (IS_PTR (type))
10484             p_type = DCL_TYPE (type);
10485           else
10486             {
10487               if (SPEC_SCLS(etype)==S_REGISTER) {
10488                 // let's assume it is a generic pointer
10489                 p_type=GPOINTER;
10490               } else {
10491                 /* we have to go by the storage class */
10492                 p_type = PTR_TYPE (SPEC_OCLS (etype));
10493               }
10494             }
10495
10496           /* the first two bytes are known */
10497           size = GPTRSIZE - 1;
10498           offset = 0;
10499           while (size--)
10500             {
10501               aopPut (result,
10502                       aopGet (right, offset, FALSE, FALSE),
10503                       offset,
10504                       isOperandVolatile (result, FALSE));
10505               offset++;
10506             }
10507           /* the last byte depending on type */
10508             {
10509                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10510                 char gpValStr[10];
10511
10512                 if (gpVal == -1)
10513                 {
10514                     // pointerTypeToGPByte will have bitched.
10515                     exit(1);
10516                 }
10517
10518                 sprintf(gpValStr, "#0x%x", gpVal);
10519                 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10520             }
10521           goto release;
10522         }
10523
10524       /* just copy the pointers */
10525       size = AOP_SIZE (result);
10526       offset = 0;
10527       while (size--)
10528         {
10529           aopPut (result,
10530                   aopGet (right, offset, FALSE, FALSE),
10531                   offset,
10532                   isOperandVolatile (result, FALSE));
10533           offset++;
10534         }
10535       goto release;
10536     }
10537
10538   /* so we now know that the size of destination is greater
10539      than the size of the source */
10540   /* we move to result for the size of source */
10541   size = AOP_SIZE (right);
10542   offset = 0;
10543   while (size--)
10544     {
10545       aopPut (result,
10546               aopGet (right, offset, FALSE, FALSE),
10547               offset,
10548               isOperandVolatile (result, FALSE));
10549       offset++;
10550     }
10551
10552   /* now depending on the sign of the source && destination */
10553   size = AOP_SIZE (result) - AOP_SIZE (right);
10554   /* if unsigned or not an integral type */
10555   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10556     {
10557       while (size--)
10558         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10559     }
10560   else
10561     {
10562       /* we need to extend the sign :{ */
10563       char *l = aopGet (right, AOP_SIZE (right) - 1,
10564                         FALSE, FALSE);
10565       MOVA (l);
10566       emitcode ("rlc", "a");
10567       emitcode ("subb", "a,acc");
10568       while (size--)
10569         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10570     }
10571
10572   /* we are done hurray !!!! */
10573
10574 release:
10575   freeAsmop (right, NULL, ic, TRUE);
10576   freeAsmop (result, NULL, ic, TRUE);
10577
10578 }
10579
10580 /*-----------------------------------------------------------------*/
10581 /* genDjnz - generate decrement & jump if not zero instrucion      */
10582 /*-----------------------------------------------------------------*/
10583 static int
10584 genDjnz (iCode * ic, iCode * ifx)
10585 {
10586   symbol *lbl, *lbl1;
10587   if (!ifx)
10588     return 0;
10589
10590   D(emitcode (";     genDjnz",""));
10591
10592   /* if the if condition has a false label
10593      then we cannot save */
10594   if (IC_FALSE (ifx))
10595     return 0;
10596
10597   /* if the minus is not of the form
10598      a = a - 1 */
10599   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10600       !IS_OP_LITERAL (IC_RIGHT (ic)))
10601     return 0;
10602
10603   if (operandLitValue (IC_RIGHT (ic)) != 1)
10604     return 0;
10605
10606   /* if the size of this greater than one then no
10607      saving */
10608   if (getSize (operandType (IC_RESULT (ic))) > 1)
10609     return 0;
10610
10611   /* otherwise we can save BIG */
10612   lbl = newiTempLabel (NULL);
10613   lbl1 = newiTempLabel (NULL);
10614
10615   aopOp (IC_RESULT (ic), ic, FALSE);
10616
10617   if (AOP_NEEDSACC(IC_RESULT(ic)))
10618   {
10619       /* If the result is accessed indirectly via
10620        * the accumulator, we must explicitly write
10621        * it back after the decrement.
10622        */
10623       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10624
10625       if (strcmp(rByte, "a"))
10626       {
10627            /* Something is hopelessly wrong */
10628            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10629                    __FILE__, __LINE__);
10630            /* We can just give up; the generated code will be inefficient,
10631             * but what the hey.
10632             */
10633            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10634            return 0;
10635       }
10636       emitcode ("dec", "%s", rByte);
10637       aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10638       emitcode ("jnz", "%05d$", lbl->key + 100);
10639   }
10640   else if (IS_AOP_PREG (IC_RESULT (ic)))
10641     {
10642       emitcode ("dec", "%s",
10643                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10644       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10645       emitcode ("jnz", "%05d$", lbl->key + 100);
10646     }
10647   else
10648     {
10649       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10650                 lbl->key + 100);
10651     }
10652   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10653   emitcode ("", "%05d$:", lbl->key + 100);
10654   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10655   emitcode ("", "%05d$:", lbl1->key + 100);
10656
10657   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10658   ifx->generated = 1;
10659   return 1;
10660 }
10661
10662 /*-----------------------------------------------------------------*/
10663 /* genReceive - generate code for a receive iCode                  */
10664 /*-----------------------------------------------------------------*/
10665 static void
10666 genReceive (iCode * ic)
10667 {
10668     int size = getSize (operandType (IC_RESULT (ic)));
10669     int offset = 0;
10670
10671   D(emitcode (";     genReceive",""));
10672
10673   if (ic->argreg == 1) { /* first parameter */
10674       if (isOperandInFarSpace (IC_RESULT (ic)) &&
10675           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10676            IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10677
10678           regs *tempRegs[4];
10679           int receivingA = 0;
10680           int roffset = 0;
10681
10682           for (offset = 0; offset<size; offset++)
10683             if (!strcmp (fReturn[offset], "a"))
10684               receivingA = 1;
10685
10686           if (!receivingA)
10687             {
10688               if (size==1 || getTempRegs(tempRegs, size-1, ic))
10689                 {
10690                   for (offset = size-1; offset>0; offset--)
10691                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10692                   emitcode("mov","a,%s", fReturn[0]);
10693                   _G.accInUse++;
10694                   aopOp (IC_RESULT (ic), ic, FALSE);
10695                   _G.accInUse--;
10696                   aopPut (IC_RESULT (ic), "a", offset,
10697                           isOperandVolatile (IC_RESULT (ic), FALSE));
10698                   for (offset = 1; offset<size; offset++)
10699                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10700                             isOperandVolatile (IC_RESULT (ic), FALSE));
10701                   goto release;
10702                 }
10703             }
10704           else
10705             {
10706               if (getTempRegs(tempRegs, size, ic))
10707                 {
10708                   for (offset = 0; offset<size; offset++)
10709                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10710                   aopOp (IC_RESULT (ic), ic, FALSE);
10711                   for (offset = 0; offset<size; offset++)
10712                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10713                             isOperandVolatile (IC_RESULT (ic), FALSE));
10714                   goto release;
10715                 }
10716             }
10717
10718           offset = fReturnSizeMCS51 - size;
10719           while (size--) {
10720               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10721                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10722               offset++;
10723           }
10724           aopOp (IC_RESULT (ic), ic, FALSE);
10725           size = AOP_SIZE (IC_RESULT (ic));
10726           offset = 0;
10727           while (size--) {
10728               emitcode ("pop", "acc");
10729               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10730           }
10731
10732       } else {
10733           _G.accInUse++;
10734           aopOp (IC_RESULT (ic), ic, FALSE);
10735           _G.accInUse--;
10736           assignResultValue (IC_RESULT (ic), NULL);
10737       }
10738   } else { /* second receive onwards */
10739       int rb1off ;
10740       aopOp (IC_RESULT (ic), ic, FALSE);
10741       rb1off = ic->argreg;
10742       while (size--) {
10743           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10744       }
10745   }
10746
10747 release:
10748   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10749 }
10750
10751 /*-----------------------------------------------------------------*/
10752 /* genDummyRead - generate code for dummy read of volatiles        */
10753 /*-----------------------------------------------------------------*/
10754 static void
10755 genDummyRead (iCode * ic)
10756 {
10757   operand *op;
10758   int size, offset;
10759
10760   D(emitcode(";     genDummyRead",""));
10761
10762   op = IC_RIGHT (ic);
10763   if (op && IS_SYMOP (op))
10764     {
10765       aopOp (op, ic, FALSE);
10766
10767       /* if the result is a bit */
10768       if (AOP_TYPE (op) == AOP_CRY)
10769         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10770       else
10771         {
10772           /* bit variables done */
10773           /* general case */
10774           size = AOP_SIZE (op);
10775           offset = 0;
10776           while (size--)
10777           {
10778             MOVA (aopGet (op, offset, FALSE, FALSE));
10779             offset++;
10780           }
10781         }
10782
10783       freeAsmop (op, NULL, ic, TRUE);
10784     }
10785
10786   op = IC_LEFT (ic);
10787   if (op && IS_SYMOP (op))
10788     {
10789       aopOp (op, ic, FALSE);
10790
10791       /* if the result is a bit */
10792       if (AOP_TYPE (op) == AOP_CRY)
10793         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10794       else
10795         {
10796           /* bit variables done */
10797           /* general case */
10798           size = AOP_SIZE (op);
10799           offset = 0;
10800           while (size--)
10801           {
10802             MOVA (aopGet (op, offset, FALSE, FALSE));
10803             offset++;
10804           }
10805         }
10806
10807       freeAsmop (op, NULL, ic, TRUE);
10808     }
10809 }
10810
10811 /*-----------------------------------------------------------------*/
10812 /* genCritical - generate code for start of a critical sequence    */
10813 /*-----------------------------------------------------------------*/
10814 static void
10815 genCritical (iCode *ic)
10816 {
10817   symbol *tlbl = newiTempLabel (NULL);
10818
10819   D(emitcode(";     genCritical",""));
10820
10821   if (IC_RESULT (ic))
10822     {
10823       aopOp (IC_RESULT (ic), ic, TRUE);
10824       aopPut (IC_RESULT (ic), one, 0, 0);
10825       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10826       aopPut (IC_RESULT (ic), zero, 0, 0);
10827       emitcode ("", "%05d$:", (tlbl->key + 100));
10828       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10829     }
10830   else
10831     {
10832       emitcode ("setb", "c");
10833       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10834       emitcode ("clr", "c");
10835       emitcode ("", "%05d$:", (tlbl->key + 100));
10836       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10837     }
10838 }
10839
10840 /*-----------------------------------------------------------------*/
10841 /* genEndCritical - generate code for end of a critical sequence   */
10842 /*-----------------------------------------------------------------*/
10843 static void
10844 genEndCritical (iCode *ic)
10845 {
10846   D(emitcode(";     genEndCritical",""));
10847
10848   if (IC_RIGHT (ic))
10849     {
10850       aopOp (IC_RIGHT (ic), ic, FALSE);
10851       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10852         {
10853           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10854           emitcode ("mov", "ea,c");
10855         }
10856       else
10857         {
10858           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10859             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10860           emitcode ("rrc", "a");
10861           emitcode ("mov", "ea,c");
10862         }
10863       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10864     }
10865   else
10866     {
10867       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10868       emitcode ("mov", "ea,c");
10869     }
10870 }
10871
10872 /*-----------------------------------------------------------------*/
10873 /* gen51Code - generate code for 8051 based controllers            */
10874 /*-----------------------------------------------------------------*/
10875 void
10876 gen51Code (iCode * lic)
10877 {
10878   iCode *ic;
10879   int cln = 0;
10880   /* int cseq = 0; */
10881
10882   _G.currentFunc = NULL;
10883   lineHead = lineCurr = NULL;
10884
10885   /* print the allocation information */
10886   if (allocInfo && currFunc)
10887     printAllocInfo (currFunc, codeOutFile);
10888   /* if debug information required */
10889   if (options.debug && currFunc)
10890     {
10891       debugFile->writeFunction (currFunc, lic);
10892     }
10893   /* stack pointer name */
10894   if (options.useXstack)
10895     spname = "_spx";
10896   else
10897     spname = "sp";
10898
10899
10900   for (ic = lic; ic; ic = ic->next)
10901     {
10902       _G.current_iCode = ic;
10903
10904       if (ic->lineno && cln != ic->lineno)
10905         {
10906           if (options.debug)
10907             {
10908               debugFile->writeCLine (ic);
10909             }
10910           if (!options.noCcodeInAsm) {
10911             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10912                       printCLine(ic->filename, ic->lineno));
10913           }
10914           cln = ic->lineno;
10915         }
10916       #if 0
10917       if (ic->seqPoint && ic->seqPoint != cseq)
10918         {
10919           emitcode ("", "; sequence point %d", ic->seqPoint);
10920           cseq = ic->seqPoint;
10921         }
10922       #endif
10923       if (options.iCodeInAsm) {
10924         char regsInUse[80];
10925         int i;
10926
10927         for (i=0; i<8; i++) {
10928           sprintf (&regsInUse[i],
10929                    "%c", ic->riu & (1<<i) ? i+'0' : '-');
10930         }
10931         regsInUse[i]=0;
10932         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10933       }
10934       /* if the result is marked as
10935          spilt and rematerializable or code for
10936          this has already been generated then
10937          do nothing */
10938       if (resultRemat (ic) || ic->generated)
10939         continue;
10940
10941       /* depending on the operation */
10942       switch (ic->op)
10943         {
10944         case '!':
10945           genNot (ic);
10946           break;
10947
10948         case '~':
10949           genCpl (ic);
10950           break;
10951
10952         case UNARYMINUS:
10953           genUminus (ic);
10954           break;
10955
10956         case IPUSH:
10957           genIpush (ic);
10958           break;
10959
10960         case IPOP:
10961           /* IPOP happens only when trying to restore a
10962              spilt live range, if there is an ifx statement
10963              following this pop then the if statement might
10964              be using some of the registers being popped which
10965              would destory the contents of the register so
10966              we need to check for this condition and handle it */
10967           if (ic->next &&
10968               ic->next->op == IFX &&
10969               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10970             genIfx (ic->next, ic);
10971           else
10972             genIpop (ic);
10973           break;
10974
10975         case CALL:
10976           genCall (ic);
10977           break;
10978
10979         case PCALL:
10980           genPcall (ic);
10981           break;
10982
10983         case FUNCTION:
10984           genFunction (ic);
10985           break;
10986
10987         case ENDFUNCTION:
10988           genEndFunction (ic);
10989           break;
10990
10991         case RETURN:
10992           genRet (ic);
10993           break;
10994
10995         case LABEL:
10996           genLabel (ic);
10997           break;
10998
10999         case GOTO:
11000           genGoto (ic);
11001           break;
11002
11003         case '+':
11004           genPlus (ic);
11005           break;
11006
11007         case '-':
11008           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11009             genMinus (ic);
11010           break;
11011
11012         case '*':
11013           genMult (ic);
11014           break;
11015
11016         case '/':
11017           genDiv (ic);
11018           break;
11019
11020         case '%':
11021           genMod (ic);
11022           break;
11023
11024         case '>':
11025           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11026           break;
11027
11028         case '<':
11029           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11030           break;
11031
11032         case LE_OP:
11033         case GE_OP:
11034         case NE_OP:
11035
11036           /* note these two are xlated by algebraic equivalence
11037              during parsing SDCC.y */
11038           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11039                   "got '>=' or '<=' shouldn't have come here");
11040           break;
11041
11042         case EQ_OP:
11043           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11044           break;
11045
11046         case AND_OP:
11047           genAndOp (ic);
11048           break;
11049
11050         case OR_OP:
11051           genOrOp (ic);
11052           break;
11053
11054         case '^':
11055           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11056           break;
11057
11058         case '|':
11059           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11060           break;
11061
11062         case BITWISEAND:
11063           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11064           break;
11065
11066         case INLINEASM:
11067           genInline (ic);
11068           break;
11069
11070         case RRC:
11071           genRRC (ic);
11072           break;
11073
11074         case RLC:
11075           genRLC (ic);
11076           break;
11077
11078         case GETHBIT:
11079           genGetHbit (ic);
11080           break;
11081
11082         case LEFT_OP:
11083           genLeftShift (ic);
11084           break;
11085
11086         case RIGHT_OP:
11087           genRightShift (ic);
11088           break;
11089
11090         case GET_VALUE_AT_ADDRESS:
11091           genPointerGet (ic,
11092                          hasInc (IC_LEFT (ic), ic,
11093                                  getSize (operandType (IC_RESULT (ic)))),
11094                          ifxForOp (IC_RESULT (ic), ic) );
11095           break;
11096
11097         case '=':
11098           if (POINTER_SET (ic))
11099             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11100           else
11101             genAssign (ic);
11102           break;
11103
11104         case IFX:
11105           genIfx (ic, NULL);
11106           break;
11107
11108         case ADDRESS_OF:
11109           genAddrOf (ic);
11110           break;
11111
11112         case JUMPTABLE:
11113           genJumpTab (ic);
11114           break;
11115
11116         case CAST:
11117           genCast (ic);
11118           break;
11119
11120         case RECEIVE:
11121           genReceive (ic);
11122           break;
11123
11124         case SEND:
11125           addSet (&_G.sendSet, ic);
11126           break;
11127
11128         case DUMMY_READ_VOLATILE:
11129           genDummyRead (ic);
11130           break;
11131
11132         case CRITICAL:
11133           genCritical (ic);
11134           break;
11135
11136         case ENDCRITICAL:
11137           genEndCritical (ic);
11138           break;
11139
11140         case SWAP:
11141           genSwap (ic);
11142           break;
11143
11144         default:
11145           ic = ic;
11146         }
11147     }
11148
11149   _G.current_iCode = NULL;
11150
11151   /* now we are ready to call the
11152      peep hole optimizer */
11153   if (!options.nopeep)
11154     peepHole (&lineHead);
11155
11156   /* now do the actual printing */
11157   printLine (lineHead, codeOutFile);
11158   return;
11159 }