* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[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 ((unsigned char)*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       /* if left==result then cpl bit */
1749       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1750         {
1751           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1752         }
1753       else
1754         {
1755           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1756           emitcode ("cpl", "c");
1757           outBitC (IC_RESULT (ic));
1758         }
1759       goto release;
1760     }
1761
1762   toBoolean (IC_LEFT (ic));
1763
1764   /* set C, if a == 0 */
1765   tlbl = newiTempLabel (NULL);
1766   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1767   emitcode ("", "%05d$:", tlbl->key + 100);
1768   outBitC (IC_RESULT (ic));
1769
1770 release:
1771   /* release the aops */
1772   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1773   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1774 }
1775
1776
1777 /*-----------------------------------------------------------------*/
1778 /* genCpl - generate code for complement                           */
1779 /*-----------------------------------------------------------------*/
1780 static void
1781 genCpl (iCode * ic)
1782 {
1783   int offset = 0;
1784   int size;
1785   symbol *tlbl;
1786   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1787
1788   D(emitcode (";", "genCpl"));
1789
1790   /* assign asmOps to operand & result */
1791   aopOp (IC_LEFT (ic), ic, FALSE);
1792   aopOp (IC_RESULT (ic), ic, TRUE);
1793
1794   /* special case if in bit space */
1795   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1796     {
1797       char *l;
1798
1799       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1800           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1801         {
1802           /* promotion rules are responsible for this strange result:
1803              bit -> int -> ~int -> bit
1804              uchar -> int -> ~int -> bit
1805           */
1806           werror(W_COMPLEMENT);
1807           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1808           goto release;
1809         }
1810
1811       tlbl=newiTempLabel(NULL);
1812       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1813       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1814           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1815           IS_AOP_PREG (IC_LEFT (ic)))
1816         {
1817           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1818         }
1819       else
1820         {
1821           MOVA (l);
1822           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1823         }
1824       emitcode ("", "%05d$:", tlbl->key + 100);
1825       outBitC (IC_RESULT(ic));
1826       goto release;
1827     }
1828
1829   size = AOP_SIZE (IC_RESULT (ic));
1830   while (size--)
1831     {
1832       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1833       MOVA (l);
1834       emitcode ("cpl", "a");
1835       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1836     }
1837
1838
1839 release:
1840   /* release the aops */
1841   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* genUminusFloat - unary minus for floating points                */
1847 /*-----------------------------------------------------------------*/
1848 static void
1849 genUminusFloat (operand * op, operand * result)
1850 {
1851   int size, offset = 0;
1852   char *l;
1853
1854   D(emitcode (";     genUminusFloat",""));
1855
1856   /* for this we just copy and then flip the bit */
1857
1858   size = AOP_SIZE (op) - 1;
1859
1860   while (size--)
1861     {
1862       aopPut (result,
1863               aopGet (op, offset, FALSE, FALSE),
1864               offset,
1865               isOperandVolatile (result, FALSE));
1866       offset++;
1867     }
1868
1869   l = aopGet (op, offset, FALSE, FALSE);
1870
1871   MOVA (l);
1872
1873   emitcode ("cpl", "acc.7");
1874   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1875 }
1876
1877 /*-----------------------------------------------------------------*/
1878 /* genUminus - unary minus code generation                         */
1879 /*-----------------------------------------------------------------*/
1880 static void
1881 genUminus (iCode * ic)
1882 {
1883   int offset, size;
1884   sym_link *optype, *rtype;
1885
1886
1887   D(emitcode (";     genUminus",""));
1888
1889   /* assign asmops */
1890   aopOp (IC_LEFT (ic), ic, FALSE);
1891   aopOp (IC_RESULT (ic), ic, TRUE);
1892
1893   /* if both in bit space then special
1894      case */
1895   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1896       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1897     {
1898
1899       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1900       emitcode ("cpl", "c");
1901       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1902       goto release;
1903     }
1904
1905   optype = operandType (IC_LEFT (ic));
1906   rtype = operandType (IC_RESULT (ic));
1907
1908   /* if float then do float stuff */
1909   if (IS_FLOAT (optype))
1910     {
1911       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1912       goto release;
1913     }
1914
1915   /* otherwise subtract from zero */
1916   size = AOP_SIZE (IC_LEFT (ic));
1917   offset = 0;
1918   //CLRC ;
1919   while (size--)
1920     {
1921       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1922       if (!strcmp (l, "a"))
1923         {
1924           if (offset == 0)
1925             SETC;
1926           emitcode ("cpl", "a");
1927           emitcode ("addc", "a,#0");
1928         }
1929       else
1930         {
1931           if (offset == 0)
1932             CLRC;
1933           emitcode ("clr", "a");
1934           emitcode ("subb", "a,%s", l);
1935         }
1936       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1937     }
1938
1939   /* if any remaining bytes in the result */
1940   /* we just need to propagate the sign   */
1941   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1942     {
1943       emitcode ("rlc", "a");
1944       emitcode ("subb", "a,acc");
1945       while (size--)
1946         aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1947     }
1948
1949 release:
1950   /* release the aops */
1951   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1952   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1953 }
1954
1955 /*-----------------------------------------------------------------*/
1956 /* saveRegisters - will look for a call and save the registers     */
1957 /*-----------------------------------------------------------------*/
1958 static void
1959 saveRegisters (iCode * lic)
1960 {
1961   int i;
1962   iCode *ic;
1963   bitVect *rsave;
1964
1965   /* look for call */
1966   for (ic = lic; ic; ic = ic->next)
1967     if (ic->op == CALL || ic->op == PCALL)
1968       break;
1969
1970   if (!ic)
1971     {
1972       fprintf (stderr, "found parameter push with no function call\n");
1973       return;
1974     }
1975
1976   /* if the registers have been saved already or don't need to be then
1977      do nothing */
1978   if (ic->regsSaved)
1979     return;
1980   if (IS_SYMOP(IC_LEFT(ic)) &&
1981       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1982        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1983     return;
1984
1985   /* save the registers in use at this time but skip the
1986      ones for the result */
1987   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1988                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1989
1990   ic->regsSaved = 1;
1991   if (options.useXstack)
1992     {
1993       int count = bitVectnBitsOn (rsave);
1994
1995       if (count == 1)
1996         {
1997           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1998           if (reg->type == REG_BIT)
1999             {
2000               emitcode ("mov", "a,%s", reg->base);
2001             }
2002           else
2003             {
2004               emitcode ("mov", "a,%s", reg->name);
2005             }
2006           emitcode ("mov", "r0,%s", spname);
2007           emitcode ("inc", "%s", spname);// allocate before use
2008           emitcode ("movx", "@r0,a");
2009           if (bitVectBitValue (rsave, R0_IDX))
2010             emitcode ("mov", "r0,a");
2011         }
2012       else if (count != 0)
2013         {
2014           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2015           int nBits = bitVectnBitsOn (rsavebits);
2016
2017           if (nBits != 0)
2018             {
2019               count = count - nBits + 1;
2020               /* remove all but the first bits as they are pushed all at once */
2021               rsave = bitVectCplAnd (rsave, rsavebits);
2022               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2023             }
2024
2025           if (bitVectBitValue (rsave, R0_IDX))
2026             {
2027               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2028             }
2029           emitcode ("mov", "r0,%s", spname);
2030           MOVA ("r0");
2031           emitcode ("add", "a,#%d", count);
2032           emitcode ("mov", "%s,a", spname);
2033           for (i = 0; i < mcs51_nRegs; i++)
2034             {
2035               if (bitVectBitValue (rsave, i))
2036                 {
2037                   regs * reg = mcs51_regWithIdx (i);
2038                   if (i == R0_IDX)
2039                     {
2040                       emitcode ("pop", "acc");
2041                       emitcode ("push", "acc");
2042                     }
2043                   else if (reg->type == REG_BIT)
2044                     {
2045                       emitcode ("mov", "a,%s", reg->base);
2046                     }
2047                   else
2048                     {
2049                       emitcode ("mov", "a,%s", reg->name);
2050                     }
2051                   emitcode ("movx", "@r0,a");
2052                   if (--count)
2053                     {
2054                       emitcode ("inc", "r0");
2055                     }
2056                 }
2057             }
2058           if (bitVectBitValue (rsave, R0_IDX))
2059             {
2060               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2061             }
2062         }
2063     }
2064   else
2065     {
2066       bool bits_pushed = FALSE;
2067       for (i = 0; i < mcs51_nRegs; i++)
2068         {
2069           if (bitVectBitValue (rsave, i))
2070             {
2071               bits_pushed = pushReg (i, bits_pushed);
2072             }
2073         }
2074     }
2075 }
2076
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRegisters - pop the pushed registers                      */
2079 /*-----------------------------------------------------------------*/
2080 static void
2081 unsaveRegisters (iCode * ic)
2082 {
2083   int i;
2084   bitVect *rsave;
2085
2086   /* restore the registers in use at this time but skip the
2087      ones for the result */
2088   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2089                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2090
2091   if (options.useXstack)
2092     {
2093       int count = bitVectnBitsOn (rsave);
2094
2095       if (count == 1)
2096         {
2097           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2098           emitcode ("mov", "r0,%s", spname);
2099           emitcode ("dec", "r0");
2100           emitcode ("movx", "a,@r0");
2101           if (reg->type == REG_BIT)
2102             {
2103               emitcode ("mov", "%s,a", reg->base);
2104             }
2105           else
2106             {
2107               emitcode ("mov", "%s,a", reg->name);
2108             }
2109           emitcode ("dec", "%s", spname);
2110         }
2111       else if (count != 0)
2112         {
2113           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2114           int nBits = bitVectnBitsOn (rsavebits);
2115
2116           if (nBits != 0)
2117             {
2118               count = count - nBits + 1;
2119               /* remove all but the first bits as they are popped all at once */
2120               rsave = bitVectCplAnd (rsave, rsavebits);
2121               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2122             }
2123
2124           emitcode ("mov", "r0,%s", spname);
2125           for (i = mcs51_nRegs; i >= 0; i--)
2126             {
2127               if (bitVectBitValue (rsave, i))
2128                 {
2129                   regs * reg = mcs51_regWithIdx (i);
2130                   emitcode ("dec", "r0");
2131                   emitcode ("movx", "a,@r0");
2132                   if (i == R0_IDX)
2133                     {
2134                       emitcode ("push", "acc");
2135                     }
2136                   else if (reg->type == REG_BIT)
2137                     {
2138                       emitcode ("mov", "%s,a", reg->base);
2139                     }
2140                   else
2141                     {
2142                       emitcode ("mov", "%s,a", reg->name);
2143                     }
2144                 }
2145             }
2146           emitcode ("mov", "%s,r0", spname);
2147           if (bitVectBitValue (rsave, R0_IDX))
2148             {
2149               emitcode ("pop", "ar0");
2150             }
2151         }
2152     }
2153   else
2154     {
2155       bool bits_popped = FALSE;
2156       for (i = mcs51_nRegs; i >= 0; i--)
2157         {
2158           if (bitVectBitValue (rsave, i))
2159             {
2160               bits_popped = popReg (i, bits_popped);
2161             }
2162         }
2163     }
2164 }
2165
2166
2167 /*-----------------------------------------------------------------*/
2168 /* pushSide -                                                      */
2169 /*-----------------------------------------------------------------*/
2170 static void
2171 pushSide (operand * oper, int size)
2172 {
2173   int offset = 0;
2174   while (size--)
2175     {
2176       char *l = aopGet (oper, offset++, FALSE, TRUE);
2177       if (AOP_TYPE (oper) != AOP_REG &&
2178           AOP_TYPE (oper) != AOP_DIR &&
2179           strcmp (l, "a"))
2180         {
2181           MOVA (l);
2182           emitcode ("push", "acc");
2183         }
2184       else
2185         {
2186           emitcode ("push", "%s", l);
2187         }
2188     }
2189 }
2190
2191 /*-----------------------------------------------------------------*/
2192 /* assignResultValue - also indicates if acc is in use afterwards  */
2193 /*-----------------------------------------------------------------*/
2194 static bool
2195 assignResultValue (operand * oper, operand * func)
2196 {
2197   int offset = 0;
2198   int size = AOP_SIZE (oper);
2199   bool accuse = FALSE;
2200
2201   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2202     {
2203       outBitC (oper);
2204       return FALSE;
2205     }
2206
2207   while (size--)
2208     {
2209       accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2210       offset++;
2211     }
2212   return accuse;
2213 }
2214
2215
2216 /*-----------------------------------------------------------------*/
2217 /* genXpush - pushes onto the external stack                       */
2218 /*-----------------------------------------------------------------*/
2219 static void
2220 genXpush (iCode * ic)
2221 {
2222   asmop *aop = newAsmop (0);
2223   regs *r;
2224   int size, offset = 0;
2225
2226   D(emitcode (";     genXpush",""));
2227
2228   aopOp (IC_LEFT (ic), ic, FALSE);
2229   r = getFreePtr (ic, &aop, FALSE);
2230
2231   size = AOP_SIZE (IC_LEFT (ic));
2232
2233   if (size == 1)
2234     {
2235       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2236       emitcode ("mov", "%s,%s", r->name, spname);
2237       emitcode ("inc", "%s", spname); // allocate space first
2238       emitcode ("movx", "@%s,a", r->name);
2239     }
2240   else
2241     {
2242       // allocate space first
2243       emitcode ("mov", "%s,%s", r->name, spname);
2244       MOVA (r->name);
2245       emitcode ("add", "a,#%d", size);
2246       emitcode ("mov", "%s,a", spname);
2247
2248       while (size--)
2249         {
2250           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2251           emitcode ("movx", "@%s,a", r->name);
2252           emitcode ("inc", "%s", r->name);
2253         }
2254     }
2255
2256   freeAsmop (NULL, aop, ic, TRUE);
2257   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2258 }
2259
2260 /*-----------------------------------------------------------------*/
2261 /* genIpush - generate code for pushing this gets a little complex */
2262 /*-----------------------------------------------------------------*/
2263 static void
2264 genIpush (iCode * ic)
2265 {
2266   int size, offset = 0;
2267   char *l;
2268   char *prev = "";
2269
2270   D(emitcode (";     genIpush",""));
2271
2272   /* if this is not a parm push : ie. it is spill push
2273      and spill push is always done on the local stack */
2274   if (!ic->parmPush)
2275     {
2276
2277       /* and the item is spilt then do nothing */
2278       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2279         return;
2280
2281       aopOp (IC_LEFT (ic), ic, FALSE);
2282       size = AOP_SIZE (IC_LEFT (ic));
2283       /* push it on the stack */
2284       while (size--)
2285         {
2286           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2287           if (*l == '#')
2288             {
2289               MOVA (l);
2290               l = "acc";
2291             }
2292           emitcode ("push", "%s", l);
2293         }
2294       return;
2295     }
2296
2297   /* this is a parameter push: in this case we call
2298      the routine to find the call and save those
2299      registers that need to be saved */
2300   saveRegisters (ic);
2301
2302   /* if use external stack then call the external
2303      stack pushing routine */
2304   if (options.useXstack)
2305     {
2306       genXpush (ic);
2307       return;
2308     }
2309
2310   /* then do the push */
2311   aopOp (IC_LEFT (ic), ic, FALSE);
2312
2313   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2314   size = AOP_SIZE (IC_LEFT (ic));
2315
2316   while (size--)
2317     {
2318       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2319       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2320           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2321           strcmp (l, "a"))
2322         {
2323           if (strcmp (l, prev) || *l == '@')
2324             MOVA (l);
2325           emitcode ("push", "acc");
2326         }
2327       else
2328         {
2329           emitcode ("push", "%s", l);
2330         }
2331       prev = l;
2332     }
2333
2334   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2335 }
2336
2337 /*-----------------------------------------------------------------*/
2338 /* genIpop - recover the registers: can happen only for spilling   */
2339 /*-----------------------------------------------------------------*/
2340 static void
2341 genIpop (iCode * ic)
2342 {
2343   int size, offset;
2344
2345   D(emitcode (";     genIpop",""));
2346
2347   /* if the temp was not pushed then */
2348   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2349     return;
2350
2351   aopOp (IC_LEFT (ic), ic, FALSE);
2352   size = AOP_SIZE (IC_LEFT (ic));
2353   offset = (size - 1);
2354   while (size--)
2355     emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2356                                    FALSE, TRUE));
2357
2358   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2359 }
2360
2361 /*-----------------------------------------------------------------*/
2362 /* saveRBank - saves an entire register bank on the stack          */
2363 /*-----------------------------------------------------------------*/
2364 static void
2365 saveRBank (int bank, iCode * ic, bool pushPsw)
2366 {
2367   int i;
2368   int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2369   asmop *aop = NULL;
2370   regs *r = NULL;
2371
2372   if (options.useXstack)
2373     {
2374       if (!ic)
2375       {
2376           /* Assume r0 is available for use. */
2377           r = mcs51_regWithIdx (R0_IDX);;
2378       }
2379       else
2380       {
2381           aop = newAsmop (0);
2382           r = getFreePtr (ic, &aop, FALSE);
2383       }
2384       // allocate space first
2385       emitcode ("mov", "%s,%s", r->name, spname);
2386       MOVA (r->name);
2387       emitcode ("add", "a,#%d", count);
2388       emitcode ("mov", "%s,a", spname);
2389     }
2390
2391   for (i = 0; i < mcs51_nRegs; i++)
2392     {
2393       if (options.useXstack)
2394         {
2395           emitcode ("mov", "a,(%s+%d)",
2396                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2397           emitcode ("movx", "@%s,a", r->name);
2398           if (--count)
2399             emitcode ("inc", "%s", r->name);
2400         }
2401       else
2402         emitcode ("push", "(%s+%d)",
2403                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2404     }
2405
2406   if (pushPsw)
2407     {
2408       if (options.useXstack)
2409         {
2410           emitcode ("mov", "a,psw");
2411           emitcode ("movx", "@%s,a", r->name);
2412
2413         }
2414       else
2415         {
2416           emitcode ("push", "psw");
2417         }
2418
2419       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2420     }
2421
2422   if (aop)
2423     {
2424       freeAsmop (NULL, aop, ic, TRUE);
2425     }
2426
2427   if (ic)
2428   {
2429     ic->bankSaved = 1;
2430   }
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* unsaveRBank - restores the register bank from stack             */
2435 /*-----------------------------------------------------------------*/
2436 static void
2437 unsaveRBank (int bank, iCode * ic, bool popPsw)
2438 {
2439   int i;
2440   asmop *aop = NULL;
2441   regs *r = NULL;
2442
2443   if (options.useXstack)
2444     {
2445       if (!ic)
2446         {
2447           /* Assume r0 is available for use. */
2448           r = mcs51_regWithIdx (R0_IDX);;
2449         }
2450       else
2451         {
2452           aop = newAsmop (0);
2453           r = getFreePtr (ic, &aop, FALSE);
2454         }
2455       emitcode ("mov", "%s,%s", r->name, spname);
2456     }
2457
2458   if (popPsw)
2459     {
2460       if (options.useXstack)
2461         {
2462           emitcode ("dec", "%s", r->name);
2463           emitcode ("movx", "a,@%s", r->name);
2464           emitcode ("mov", "psw,a");
2465         }
2466       else
2467         {
2468           emitcode ("pop", "psw");
2469         }
2470     }
2471
2472   for (i = (mcs51_nRegs - 1); i >= 0; i--)
2473     {
2474       if (options.useXstack)
2475         {
2476           emitcode ("dec", "%s", r->name);
2477           emitcode ("movx", "a,@%s", r->name);
2478           emitcode ("mov", "(%s+%d),a",
2479                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2480         }
2481       else
2482         {
2483           emitcode ("pop", "(%s+%d)",
2484                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2485         }
2486     }
2487
2488   if (options.useXstack)
2489     {
2490       emitcode ("mov", "%s,%s", spname, r->name);
2491     }
2492
2493   if (aop)
2494     {
2495       freeAsmop (NULL, aop, ic, TRUE);
2496     }
2497 }
2498
2499 /*-----------------------------------------------------------------*/
2500 /* genSend - gen code for SEND                                     */
2501 /*-----------------------------------------------------------------*/
2502 static void genSend(set *sendSet)
2503 {
2504   iCode *sic;
2505   int bit_count = 0;
2506
2507   /* first we do all bit parameters */
2508   for (sic = setFirstItem (sendSet); sic;
2509        sic = setNextItem (sendSet))
2510     {
2511       aopOp (IC_LEFT (sic), sic, FALSE);
2512
2513       if (sic->argreg > 12)
2514         {
2515           int bit = sic->argreg-13;
2516
2517           /* if left is a literal then
2518              we know what the value is */
2519           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2520             {
2521               if (((int) operandLitValue (IC_LEFT (sic))))
2522                   emitcode ("setb", "b[%d]", bit);
2523               else
2524                   emitcode ("clr", "b[%d]", bit);
2525             }
2526           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2527             {
2528               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2529                 if (strcmp (l, "c"))
2530                     emitcode ("mov", "c,%s", l);
2531                 emitcode ("mov", "b[%d],c", bit);
2532             }
2533           else
2534             {
2535               /* we need to or */
2536               toBoolean (IC_LEFT (sic));
2537               /* set C, if a >= 1 */
2538               emitcode ("add", "a,#0xff");
2539               emitcode ("mov", "b[%d],c", bit);
2540             }
2541           bit_count++;
2542           BitBankUsed = 1;
2543         }
2544       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2545     }
2546
2547   if (bit_count)
2548     {
2549       saveRegisters (setFirstItem (sendSet));
2550       emitcode ("mov", "bits,b");
2551     }
2552
2553   /* then we do all other parameters */
2554   for (sic = setFirstItem (sendSet); sic;
2555        sic = setNextItem (sendSet))
2556     {
2557       int size, offset = 0;
2558       aopOp (IC_LEFT (sic), sic, FALSE);
2559       size = AOP_SIZE (IC_LEFT (sic));
2560
2561       if (sic->argreg == 1)
2562         {
2563           while (size--)
2564             {
2565               char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2566               if (strcmp (l, fReturn[offset]))
2567                   emitcode ("mov", "%s,%s", fReturn[offset], l);
2568               offset++;
2569             }
2570         }
2571       else if (sic->argreg <= 12)
2572         {
2573           while (size--)
2574             {
2575               emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2576                         aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2577               offset++;
2578             }
2579         }
2580       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2581     }
2582 }
2583
2584 /*-----------------------------------------------------------------*/
2585 /* selectRegBank - emit code to select the register bank           */
2586 /*-----------------------------------------------------------------*/
2587 static void
2588 selectRegBank (short bank, bool keepFlags)
2589 {
2590   /* if f.e. result is in carry */
2591   if (keepFlags)
2592     {
2593       emitcode ("anl", "psw,#0xE7");
2594       if (bank)
2595         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2596     }
2597   else
2598     {
2599       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2600     }
2601 }
2602
2603 /*-----------------------------------------------------------------*/
2604 /* genCall - generates a call statement                            */
2605 /*-----------------------------------------------------------------*/
2606 static void
2607 genCall (iCode * ic)
2608 {
2609   sym_link *dtype;
2610   sym_link *etype;
2611 //  bool restoreBank = FALSE;
2612   bool swapBanks = FALSE;
2613   bool accuse = FALSE;
2614   bool accPushed = FALSE;
2615   bool resultInF0 = FALSE;
2616
2617   D(emitcode(";     genCall",""));
2618
2619   dtype = operandType (IC_LEFT (ic));
2620   etype = getSpec(dtype);
2621   /* if send set is not empty then assign */
2622   if (_G.sendSet)
2623     {
2624         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2625             genSend(reverseSet(_G.sendSet));
2626         } else {
2627             genSend(_G.sendSet);
2628         }
2629
2630       _G.sendSet = NULL;
2631     }
2632
2633   /* if we are calling a not _naked function that is not using
2634      the same register bank then we need to save the
2635      destination registers on the stack */
2636   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2637       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2638        !IFFUNC_ISISR (dtype))
2639     {
2640       swapBanks = TRUE;
2641     }
2642
2643   /* if caller saves & we have not saved then */
2644   if (!ic->regsSaved)
2645       saveRegisters (ic);
2646
2647   if (swapBanks)
2648     {
2649         emitcode ("mov", "psw,#0x%02x",
2650            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2651     }
2652
2653   /* make the call */
2654   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2655     {
2656       if (IFFUNC_CALLEESAVES(dtype))
2657         {
2658           werror (E_BANKED_WITH_CALLEESAVES);
2659         }
2660       else
2661         {
2662           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2663                      OP_SYMBOL (IC_LEFT (ic))->rname :
2664                      OP_SYMBOL (IC_LEFT (ic))->name);
2665
2666           emitcode ("mov", "r0,#%s", l);
2667           emitcode ("mov", "r1,#(%s >> 8)", l);
2668           emitcode ("mov", "r2,#(%s >> 16)", l);
2669           emitcode ("lcall", "__sdcc_banked_call");
2670         }
2671     }
2672   else
2673     {
2674       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2675                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2676                                 OP_SYMBOL (IC_LEFT (ic))->name));
2677     }
2678
2679   if (swapBanks)
2680     {
2681       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2682     }
2683
2684   /* if we need assign a result value */
2685   if ((IS_ITEMP (IC_RESULT (ic)) &&
2686        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2687        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2688         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2689         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2690       IS_TRUE_SYMOP (IC_RESULT (ic)))
2691     {
2692
2693       _G.accInUse++;
2694       aopOp (IC_RESULT (ic), ic, FALSE);
2695       _G.accInUse--;
2696
2697       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2698
2699       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2700     }
2701
2702   /* adjust the stack for parameters if required */
2703   if (ic->parmBytes)
2704     {
2705       int i;
2706       if (ic->parmBytes > 3)
2707         {
2708           if (accuse)
2709             {
2710               emitcode ("push", "acc");
2711               accPushed = TRUE;
2712             }
2713           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2714               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2715             {
2716               emitcode ("mov", "F0,c");
2717               resultInF0 = TRUE;
2718             }
2719
2720           emitcode ("mov", "a,%s", spname);
2721           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2722           emitcode ("mov", "%s,a", spname);
2723
2724           /* unsaveRegisters from xstack needs acc, but */
2725           /* unsaveRegisters from stack needs this popped */
2726           if (accPushed && !options.useXstack)
2727             {
2728               emitcode ("pop", "acc");
2729               accPushed = FALSE;
2730             }
2731         }
2732       else
2733         for (i = 0; i < ic->parmBytes; i++)
2734           emitcode ("dec", "%s", spname);
2735     }
2736
2737   /* if we had saved some registers then unsave them */
2738   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739     {
2740       if (accuse && !accPushed && options.useXstack)
2741         {
2742           /* xstack needs acc, but doesn't touch normal stack */
2743           emitcode ("push", "acc");
2744           accPushed = TRUE;
2745         }
2746       unsaveRegisters (ic);
2747     }
2748
2749 //  /* if register bank was saved then pop them */
2750 //  if (restoreBank)
2751 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2752
2753   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2754     {
2755       if (resultInF0)
2756           emitcode ("mov", "c,F0");
2757
2758       aopOp (IC_RESULT (ic), ic, FALSE);
2759       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2760       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2761     }
2762
2763   if (accPushed)
2764     emitcode ("pop", "acc");
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* -10l - generates a call by pointer statement                */
2769 /*-----------------------------------------------------------------*/
2770 static void
2771 genPcall (iCode * ic)
2772 {
2773   sym_link *dtype;
2774   sym_link *etype;
2775   symbol *rlbl = newiTempLabel (NULL);
2776 //  bool restoreBank=FALSE;
2777   bool swapBanks = FALSE;
2778   bool resultInF0 = FALSE;
2779
2780   D(emitcode(";     genPCall",""));
2781
2782   dtype = operandType (IC_LEFT (ic))->next;
2783   etype = getSpec(dtype);
2784   /* if caller saves & we have not saved then */
2785   if (!ic->regsSaved)
2786     saveRegisters (ic);
2787
2788   /* if we are calling a not _naked function that is not using
2789      the same register bank then we need to save the
2790      destination registers on the stack */
2791   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2792       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2793       !IFFUNC_ISISR (dtype))
2794     {
2795 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2796 //    restoreBank=TRUE;
2797       swapBanks = TRUE;
2798       // need caution message to user here
2799     }
2800
2801   if (IS_LITERAL(etype))
2802     {
2803       /* if send set is not empty then assign */
2804       if (_G.sendSet)
2805         {
2806           genSend(reverseSet(_G.sendSet));
2807           _G.sendSet = NULL;
2808         }
2809
2810       if (swapBanks)
2811         {
2812           emitcode ("mov", "psw,#0x%02x",
2813            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2814         }
2815
2816       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2817         {
2818           if (IFFUNC_CALLEESAVES(dtype))
2819             {
2820               werror (E_BANKED_WITH_CALLEESAVES);
2821             }
2822           else
2823             {
2824               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2825
2826               emitcode ("mov", "r0,#%s", l);
2827               emitcode ("mov", "r1,#(%s >> 8)", l);
2828               emitcode ("mov", "r2,#(%s >> 16)", l);
2829               emitcode ("lcall", "__sdcc_banked_call");
2830             }
2831         }
2832       else
2833         {
2834           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2835         }
2836     }
2837   else
2838     {
2839       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2840         {
2841           if (IFFUNC_CALLEESAVES(dtype))
2842             {
2843               werror (E_BANKED_WITH_CALLEESAVES);
2844             }
2845           else
2846             {
2847               aopOp (IC_LEFT (ic), ic, FALSE);
2848
2849               if (!swapBanks)
2850                 {
2851                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2852                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2853                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2854                 }
2855               else
2856                 {
2857                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2858                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2859                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2860                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2861                 }
2862
2863               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2864
2865               /* if send set is not empty then assign */
2866               if (_G.sendSet)
2867                 {
2868                   genSend(reverseSet(_G.sendSet));
2869                   _G.sendSet = NULL;
2870                 }
2871
2872               if (swapBanks)
2873                 {
2874                   emitcode ("mov", "psw,#0x%02x",
2875                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2876                 }
2877
2878               /* make the call */
2879               emitcode ("lcall", "__sdcc_banked_call");
2880             }
2881         }
2882       else
2883         {
2884           /* push the return address on to the stack */
2885           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2886           emitcode ("push", "acc");
2887           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2888           emitcode ("push", "acc");
2889
2890           /* now push the calling address */
2891           aopOp (IC_LEFT (ic), ic, FALSE);
2892
2893           pushSide (IC_LEFT (ic), FPTRSIZE);
2894
2895           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2896
2897           /* if send set is not empty the assign */
2898           if (_G.sendSet)
2899             {
2900               genSend(reverseSet(_G.sendSet));
2901               _G.sendSet = NULL;
2902             }
2903
2904           if (swapBanks)
2905             {
2906               emitcode ("mov", "psw,#0x%02x",
2907                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2908             }
2909
2910           /* make the call */
2911           emitcode ("ret", "");
2912           emitcode ("", "%05d$:", (rlbl->key + 100));
2913         }
2914     }
2915   if (swapBanks)
2916     {
2917       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2918     }
2919
2920   /* if we need assign a result value */
2921   if ((IS_ITEMP (IC_RESULT (ic)) &&
2922        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2923        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2924         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2925       IS_TRUE_SYMOP (IC_RESULT (ic)))
2926     {
2927
2928       _G.accInUse++;
2929       aopOp (IC_RESULT (ic), ic, FALSE);
2930       _G.accInUse--;
2931
2932       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2933
2934       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2935     }
2936
2937   /* adjust the stack for parameters if required */
2938   if (ic->parmBytes)
2939     {
2940       int i;
2941       if (ic->parmBytes > 3)
2942         {
2943           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2944               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2945             {
2946               emitcode ("mov", "F0,c");
2947               resultInF0 = TRUE;
2948             }
2949
2950           emitcode ("mov", "a,%s", spname);
2951           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2952           emitcode ("mov", "%s,a", spname);
2953         }
2954       else
2955         for (i = 0; i < ic->parmBytes; i++)
2956           emitcode ("dec", "%s", spname);
2957
2958     }
2959
2960 //  /* if register bank was saved then unsave them */
2961 //  if (restoreBank)
2962 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2963
2964   /* if we had saved some registers then unsave them */
2965   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2966     unsaveRegisters (ic);
2967
2968   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2969     {
2970       if (resultInF0)
2971           emitcode ("mov", "c,F0");
2972
2973       aopOp (IC_RESULT (ic), ic, FALSE);
2974       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2975       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2976     }
2977 }
2978
2979 /*-----------------------------------------------------------------*/
2980 /* resultRemat - result  is rematerializable                       */
2981 /*-----------------------------------------------------------------*/
2982 static int
2983 resultRemat (iCode * ic)
2984 {
2985   if (SKIP_IC (ic) || ic->op == IFX)
2986     return 0;
2987
2988   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2989     {
2990       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2991       if (sym->remat && !POINTER_SET (ic))
2992         return 1;
2993     }
2994
2995   return 0;
2996 }
2997
2998 #if defined(__BORLANDC__) || defined(_MSC_VER)
2999 #define STRCASECMP stricmp
3000 #else
3001 #define STRCASECMP strcasecmp
3002 #endif
3003
3004 /*-----------------------------------------------------------------*/
3005 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3006 /*-----------------------------------------------------------------*/
3007 static int
3008 regsCmp(void *p1, void *p2)
3009 {
3010   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3011 }
3012
3013 static bool
3014 inExcludeList (char *s)
3015 {
3016   const char *p = setFirstItem(options.excludeRegsSet);
3017
3018   if (p == NULL || STRCASECMP(p, "none") == 0)
3019     return FALSE;
3020
3021
3022   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3023 }
3024
3025 /*-----------------------------------------------------------------*/
3026 /* genFunction - generated code for function entry                 */
3027 /*-----------------------------------------------------------------*/
3028 static void
3029 genFunction (iCode * ic)
3030 {
3031   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3032   sym_link *ftype;
3033   bool     switchedPSW = FALSE;
3034   int      calleesaves_saved_register = -1;
3035   int      stackAdjust = sym->stack;
3036   int      accIsFree = sym->recvSize < 4;
3037   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3038   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3039
3040   _G.nRegsSaved = 0;
3041   /* create the function header */
3042   emitcode (";", "-----------------------------------------");
3043   emitcode (";", " function %s", sym->name);
3044   emitcode (";", "-----------------------------------------");
3045
3046   emitcode ("", "%s:", sym->rname);
3047   ftype = operandType (IC_LEFT (ic));
3048   _G.currentFunc = sym;
3049
3050   if (IFFUNC_ISNAKED(ftype))
3051   {
3052       emitcode(";", "naked function: no prologue.");
3053       return;
3054   }
3055
3056   /* here we need to generate the equates for the
3057      register bank if required */
3058   if (FUNC_REGBANK (ftype) != rbank)
3059     {
3060       int i;
3061
3062       rbank = FUNC_REGBANK (ftype);
3063       for (i = 0; i < mcs51_nRegs; i++)
3064         {
3065           if (regs8051[i].type != REG_BIT)
3066             {
3067               if (strcmp (regs8051[i].base, "0") == 0)
3068                 emitcode ("", "%s = 0x%02x",
3069                           regs8051[i].dname,
3070                           8 * rbank + regs8051[i].offset);
3071               else
3072                 emitcode ("", "%s = %s + 0x%02x",
3073                           regs8051[i].dname,
3074                           regs8051[i].base,
3075                           8 * rbank + regs8051[i].offset);
3076             }
3077         }
3078     }
3079
3080   /* if this is an interrupt service routine then
3081      save acc, b, dpl, dph  */
3082   if (IFFUNC_ISISR (sym->type))
3083     {
3084
3085       if (!inExcludeList ("acc"))
3086         emitcode ("push", "acc");
3087       if (!inExcludeList ("b"))
3088         emitcode ("push", "b");
3089       if (!inExcludeList ("dpl"))
3090         emitcode ("push", "dpl");
3091       if (!inExcludeList ("dph"))
3092         emitcode ("push", "dph");
3093       /* if this isr has no bank i.e. is going to
3094          run with bank 0 , then we need to save more
3095          registers :-) */
3096       if (!FUNC_REGBANK (sym->type))
3097         {
3098
3099           /* if this function does not call any other
3100              function then we can be economical and
3101              save only those registers that are used */
3102           if (!IFFUNC_HASFCALL(sym->type))
3103             {
3104               int i;
3105
3106               /* if any registers used */
3107               if (sym->regsUsed)
3108                 {
3109                   bool bits_pushed = FALSE;
3110                   /* save the registers used */
3111                   for (i = 0; i < sym->regsUsed->size; i++)
3112                     {
3113                       if (bitVectBitValue (sym->regsUsed, i))
3114                         bits_pushed = pushReg (i, bits_pushed);
3115                     }
3116                 }
3117             }
3118           else
3119             {
3120
3121               /* this function has a function call. We cannot
3122                  determines register usage so we will have to push the
3123                  entire bank */
3124                 saveRBank (0, ic, FALSE);
3125                 if (options.parms_in_bank1) {
3126                     int i;
3127                     for (i=0; i < 8 ; i++ ) {
3128                         emitcode ("push","%s",rb1regs[i]);
3129                     }
3130                 }
3131             }
3132         }
3133         else
3134         {
3135             /* This ISR uses a non-zero bank.
3136              *
3137              * We assume that the bank is available for our
3138              * exclusive use.
3139              *
3140              * However, if this ISR calls a function which uses some
3141              * other bank, we must save that bank entirely.
3142              */
3143             unsigned long banksToSave = 0;
3144
3145             if (IFFUNC_HASFCALL(sym->type))
3146             {
3147
3148 #define MAX_REGISTER_BANKS 4
3149
3150                 iCode *i;
3151                 int ix;
3152
3153                 for (i = ic; i; i = i->next)
3154                 {
3155                     if (i->op == ENDFUNCTION)
3156                     {
3157                         /* we got to the end OK. */
3158                         break;
3159                     }
3160
3161                     if (i->op == CALL)
3162                     {
3163                         sym_link *dtype;
3164
3165                         dtype = operandType (IC_LEFT(i));
3166                         if (dtype
3167                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3168                         {
3169                              /* Mark this bank for saving. */
3170                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3171                              {
3172                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3173                              }
3174                              else
3175                              {
3176                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3177                              }
3178
3179                              /* And note that we don't need to do it in
3180                               * genCall.
3181                               */
3182                              i->bankSaved = 1;
3183                         }
3184                     }
3185                     if (i->op == PCALL)
3186                     {
3187                         /* This is a mess; we have no idea what
3188                          * register bank the called function might
3189                          * use.
3190                          *
3191                          * The only thing I can think of to do is
3192                          * throw a warning and hope.
3193                          */
3194                         werror(W_FUNCPTR_IN_USING_ISR);
3195                     }
3196                 }
3197
3198                 if (banksToSave && options.useXstack)
3199                 {
3200                     /* Since we aren't passing it an ic,
3201                      * saveRBank will assume r0 is available to abuse.
3202                      *
3203                      * So switch to our (trashable) bank now, so
3204                      * the caller's R0 isn't trashed.
3205                      */
3206                     emitcode ("push", "psw");
3207                     emitcode ("mov", "psw,#0x%02x",
3208                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3209                     switchedPSW = TRUE;
3210                 }
3211
3212                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3213                 {
3214                      if (banksToSave & (1 << ix))
3215                      {
3216                          saveRBank(ix, NULL, FALSE);
3217                      }
3218                 }
3219             }
3220             // TODO: this needs a closer look
3221             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3222         }
3223
3224       /* Set the register bank to the desired value if nothing else */
3225       /* has done so yet. */
3226       if (!switchedPSW)
3227         {
3228           emitcode ("push", "psw");
3229           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3230         }
3231     }
3232   else
3233     {
3234       /* This is a non-ISR function. The caller has already switched register */
3235       /* banks, if necessary, so just handle the callee-saves option. */
3236
3237       /* if callee-save to be used for this function
3238          then save the registers being used in this function */
3239       if (IFFUNC_CALLEESAVES(sym->type))
3240         {
3241           int i;
3242
3243           /* if any registers used */
3244           if (sym->regsUsed)
3245             {
3246               bool bits_pushed = FALSE;
3247               /* save the registers used */
3248               for (i = 0; i < sym->regsUsed->size; i++)
3249                 {
3250                   if (bitVectBitValue (sym->regsUsed, i))
3251                     {
3252                       /* remember one saved register for later usage */
3253                       if (calleesaves_saved_register < 0)
3254                         calleesaves_saved_register = i;
3255                       bits_pushed = pushReg (i, bits_pushed);
3256                       _G.nRegsSaved++;
3257                     }
3258                 }
3259             }
3260         }
3261     }
3262
3263
3264   if (fReentrant)
3265     {
3266       if (options.useXstack)
3267         {
3268           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3269             {
3270               emitcode ("mov", "r0,%s", spname);
3271               emitcode ("inc", "%s", spname);
3272               emitcode ("xch", "a,_bpx");
3273               emitcode ("movx", "@r0,a");
3274               emitcode ("inc", "r0");
3275               emitcode ("mov", "a,r0");
3276               emitcode ("xch", "a,_bpx");
3277             }
3278           if (sym->stack)
3279             {
3280               emitcode ("push", "_bp");     /* save the callers stack  */
3281               emitcode ("mov", "_bp,sp");
3282             }
3283         }
3284       else
3285         {
3286           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3287             {
3288               /* set up the stack */
3289               emitcode ("push", "_bp");     /* save the callers stack  */
3290               emitcode ("mov", "_bp,sp");
3291             }
3292         }
3293     }
3294
3295   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3296   /* before setting up the stack frame completely. */
3297   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3298     {
3299       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3300
3301       if (rsym->isitmp)
3302         {
3303           if (rsym && rsym->regType == REG_CND)
3304             rsym = NULL;
3305           if (rsym && (rsym->accuse || rsym->ruonly))
3306             rsym = NULL;
3307           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3308             rsym = rsym->usl.spillLoc;
3309         }
3310
3311       /* If the RECEIVE operand immediately spills to the first entry on the */
3312       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3313       /* rather than the usual @r0/r1 machinations. */
3314       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3315         {
3316           int ofs;
3317
3318           _G.current_iCode = ric;
3319           D(emitcode (";     genReceive",""));
3320           for (ofs=0; ofs < sym->recvSize; ofs++)
3321             {
3322               if (!strcmp (fReturn[ofs], "a"))
3323                 emitcode ("push", "acc");
3324               else
3325                 emitcode ("push", fReturn[ofs]);
3326             }
3327           stackAdjust -= sym->recvSize;
3328           if (stackAdjust<0)
3329             {
3330               assert (stackAdjust>=0);
3331               stackAdjust = 0;
3332             }
3333           _G.current_iCode = ic;
3334           ric->generated = 1;
3335           accIsFree = 1;
3336         }
3337       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3338       /* to free up the accumulator. */
3339       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3340         {
3341           int ofs;
3342
3343           _G.current_iCode = ric;
3344           D(emitcode (";     genReceive",""));
3345           for (ofs=0; ofs < sym->recvSize; ofs++)
3346             {
3347               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3348             }
3349           _G.current_iCode = ic;
3350           ric->generated = 1;
3351           accIsFree = 1;
3352         }
3353     }
3354
3355   /* adjust the stack for the function */
3356   if (stackAdjust)
3357     {
3358       int i = stackAdjust;
3359       if (i > 256)
3360         werror (W_STACK_OVERFLOW, sym->name);
3361
3362       if (i > 3 && accIsFree)
3363         {
3364           emitcode ("mov", "a,sp");
3365           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3366           emitcode ("mov", "sp,a");
3367         }
3368       else if (i > 5)
3369         {
3370           /* The accumulator is not free, so we will need another register */
3371           /* to clobber. No need to worry about a possible conflict with */
3372           /* the above early RECEIVE optimizations since they would have */
3373           /* freed the accumulator if they were generated. */
3374
3375           if (IFFUNC_CALLEESAVES(sym->type))
3376             {
3377               /* if it's a callee-saves function we need a saved register */
3378               if (calleesaves_saved_register >= 0)
3379                 {
3380                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3381                   emitcode ("mov", "a,sp");
3382                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3383                   emitcode ("mov", "sp,a");
3384                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3385                 }
3386               else
3387                 /* do it the hard way */
3388                 while (i--)
3389                   emitcode ("inc", "sp");
3390             }
3391           else
3392             {
3393               /* not callee-saves, we can clobber r0 */
3394               emitcode ("mov", "r0,a");
3395               emitcode ("mov", "a,sp");
3396               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3397               emitcode ("mov", "sp,a");
3398               emitcode ("mov", "a,r0");
3399             }
3400         }
3401       else
3402         while (i--)
3403           emitcode ("inc", "sp");
3404     }
3405
3406   if (sym->xstack)
3407     {
3408       char i = ((char) sym->xstack & 0xff);
3409
3410       if (i > 3 && accIsFree)
3411         {
3412           emitcode ("mov", "a,_spx");
3413           emitcode ("add", "a,#0x%02x", i);
3414           emitcode ("mov", "_spx,a");
3415         }
3416       else if (i > 5)
3417         {
3418           emitcode ("push", "acc");
3419           emitcode ("mov", "a,_spx");
3420           emitcode ("add", "a,#0x%02x", i);
3421           emitcode ("mov", "_spx,a");
3422           emitcode ("pop", "acc");
3423         }
3424       else
3425         {
3426           while (i--)
3427             emitcode ("inc", "_spx");
3428         }
3429     }
3430
3431   /* if critical function then turn interrupts off */
3432   if (IFFUNC_ISCRITICAL (ftype))
3433     {
3434       symbol *tlbl = newiTempLabel (NULL);
3435       emitcode ("setb", "c");
3436       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3437       emitcode ("clr", "c");
3438       emitcode ("", "%05d$:", (tlbl->key + 100));
3439       emitcode ("push", "psw"); /* save old ea via c in psw */
3440     }
3441 }
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genEndFunction - generates epilogue for functions               */
3445 /*-----------------------------------------------------------------*/
3446 static void
3447 genEndFunction (iCode * ic)
3448 {
3449   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3450   lineNode *lnp = lineCurr;
3451   bitVect  *regsUsed;
3452   bitVect  *regsUsedPrologue;
3453   bitVect  *regsUnneeded;
3454   int      idx;
3455
3456   _G.currentFunc = NULL;
3457   if (IFFUNC_ISNAKED(sym->type))
3458   {
3459       emitcode(";", "naked function: no epilogue.");
3460       if (options.debug && currFunc)
3461         debugFile->writeEndFunction (currFunc, ic, 0);
3462       return;
3463   }
3464
3465   if (IFFUNC_ISCRITICAL (sym->type))
3466     {
3467       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3468         {
3469           emitcode ("rlc", "a");   /* save c in a */
3470           emitcode ("pop", "psw"); /* restore ea via c in psw */
3471           emitcode ("mov", "ea,c");
3472           emitcode ("rrc", "a");   /* restore c from a */
3473         }
3474       else
3475         {
3476           emitcode ("pop", "psw"); /* restore ea via c in psw */
3477           emitcode ("mov", "ea,c");
3478         }
3479     }
3480
3481   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3482     {
3483       if (options.useXstack)
3484         {
3485           if (sym->stack)
3486             {
3487               emitcode ("mov", "sp,_bp");
3488               emitcode ("pop", "_bp");
3489             }
3490           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3491             {
3492               emitcode ("xch", "a,_bpx");
3493               emitcode ("mov", "r0,a");
3494               emitcode ("dec", "r0");
3495               emitcode ("movx", "a,@r0");
3496               emitcode ("xch", "a,_bpx");
3497               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3498             }
3499         }
3500       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3501         {
3502           emitcode ("mov", "sp,_bp");
3503           emitcode ("pop", "_bp");
3504         }
3505     }
3506
3507   /* restore the register bank  */
3508   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3509   {
3510     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3511      || !options.useXstack)
3512     {
3513         /* Special case of ISR using non-zero bank with useXstack
3514          * is handled below.
3515          */
3516         emitcode ("pop", "psw");
3517     }
3518   }
3519
3520   if (IFFUNC_ISISR (sym->type))
3521     {
3522
3523       /* now we need to restore the registers */
3524       /* if this isr has no bank i.e. is going to
3525          run with bank 0 , then we need to save more
3526          registers :-) */
3527       if (!FUNC_REGBANK (sym->type))
3528         {
3529           /* if this function does not call any other
3530              function then we can be economical and
3531              save only those registers that are used */
3532           if (!IFFUNC_HASFCALL(sym->type))
3533             {
3534               int i;
3535
3536               /* if any registers used */
3537               if (sym->regsUsed)
3538                 {
3539                   bool bits_popped = FALSE;
3540                   /* save the registers used */
3541                   for (i = sym->regsUsed->size; i >= 0; i--)
3542                     {
3543                       if (bitVectBitValue (sym->regsUsed, i))
3544                         bits_popped = popReg (i, bits_popped);
3545                     }
3546                 }
3547             }
3548           else
3549             {
3550               if (options.parms_in_bank1) {
3551                   int i;
3552                   for (i = 7 ; i >= 0 ; i-- ) {
3553                       emitcode ("pop","%s",rb1regs[i]);
3554                   }
3555               }
3556               /* this function has  a function call cannot
3557                  determines register usage so we will have to pop the
3558                  entire bank */
3559               unsaveRBank (0, ic, FALSE);
3560             }
3561         }
3562         else
3563         {
3564             /* This ISR uses a non-zero bank.
3565              *
3566              * Restore any register banks saved by genFunction
3567              * in reverse order.
3568              */
3569             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3570             int ix;
3571
3572             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3573             {
3574                 if (savedBanks & (1 << ix))
3575                 {
3576                     unsaveRBank(ix, NULL, FALSE);
3577                 }
3578             }
3579
3580             if (options.useXstack)
3581             {
3582                 /* Restore bank AFTER calling unsaveRBank,
3583                  * since it can trash r0.
3584                  */
3585                 emitcode ("pop", "psw");
3586             }
3587         }
3588
3589       if (!inExcludeList ("dph"))
3590         emitcode ("pop", "dph");
3591       if (!inExcludeList ("dpl"))
3592         emitcode ("pop", "dpl");
3593       if (!inExcludeList ("b"))
3594         emitcode ("pop", "b");
3595       if (!inExcludeList ("acc"))
3596         emitcode ("pop", "acc");
3597
3598       /* if debug then send end of function */
3599       if (options.debug && currFunc)
3600         {
3601           debugFile->writeEndFunction (currFunc, ic, 1);
3602         }
3603
3604       emitcode ("reti", "");
3605     }
3606   else
3607     {
3608       if (IFFUNC_CALLEESAVES(sym->type))
3609         {
3610           int i;
3611
3612           /* if any registers used */
3613           if (sym->regsUsed)
3614             {
3615               /* save the registers used */
3616               for (i = sym->regsUsed->size; i >= 0; i--)
3617                 {
3618                   if (bitVectBitValue (sym->regsUsed, i) ||
3619                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3620                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3621                 }
3622             }
3623           else if (mcs51_ptrRegReq)
3624             {
3625               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3626               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3627             }
3628
3629         }
3630
3631       /* if debug then send end of function */
3632       if (options.debug && currFunc)
3633         {
3634           debugFile->writeEndFunction (currFunc, ic, 1);
3635         }
3636
3637       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3638         {
3639           emitcode ("ljmp", "__sdcc_banked_ret");
3640         }
3641       else
3642         {
3643           emitcode ("ret", "");
3644         }
3645     }
3646
3647   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3648     return;
3649
3650   /* If this was an interrupt handler using bank 0 that called another */
3651   /* function, then all registers must be saved; nothing to optimized. */
3652   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3653       && !FUNC_REGBANK(sym->type))
3654     return;
3655
3656   /* There are no push/pops to optimize if not callee-saves or ISR */
3657   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3658     return;
3659
3660   /* If there were stack parameters, we cannot optimize without also    */
3661   /* fixing all of the stack offsets; this is too dificult to consider. */
3662   if (FUNC_HASSTACKPARM(sym->type))
3663     return;
3664
3665   /* Compute the registers actually used */
3666   regsUsed = newBitVect (mcs51_nRegs);
3667   regsUsedPrologue = newBitVect (mcs51_nRegs);
3668   while (lnp)
3669     {
3670       if (lnp->ic && lnp->ic->op == FUNCTION)
3671         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3672       else
3673         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3674
3675       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3676           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3677         break;
3678       if (!lnp->prev)
3679         break;
3680       lnp = lnp->prev;
3681     }
3682
3683   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3684       && !bitVectBitValue (regsUsed, CND_IDX))
3685     {
3686       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3687       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3688           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3689         bitVectUnSetBit (regsUsed, CND_IDX);
3690     }
3691   else
3692     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3693
3694   /* If this was an interrupt handler that called another function */
3695   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3696   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3697     {
3698       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3699       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3700       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3701       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3702       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3703     }
3704
3705   /* Remove the unneeded push/pops */
3706   regsUnneeded = newBitVect (mcs51_nRegs);
3707   while (lnp)
3708     {
3709       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3710         {
3711           if (!strncmp(lnp->line, "push", 4))
3712             {
3713               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3714               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3715                 {
3716                   connectLine (lnp->prev, lnp->next);
3717                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3718                 }
3719             }
3720           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3721             {
3722               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3723               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3724                 {
3725                   connectLine (lnp->prev, lnp->next);
3726                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3727                 }
3728             }
3729         }
3730       lnp = lnp->next;
3731     }
3732
3733   for (idx = 0; idx < regsUnneeded->size; idx++)
3734     if (bitVectBitValue (regsUnneeded, idx))
3735       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3736
3737   freeBitVect (regsUnneeded);
3738   freeBitVect (regsUsed);
3739   freeBitVect (regsUsedPrologue);
3740 }
3741
3742 /*-----------------------------------------------------------------*/
3743 /* genRet - generate code for return statement                     */
3744 /*-----------------------------------------------------------------*/
3745 static void
3746 genRet (iCode * ic)
3747 {
3748   int size, offset = 0, pushed = 0;
3749
3750   D(emitcode (";     genRet",""));
3751
3752   /* if we have no return value then
3753      just generate the "ret" */
3754   if (!IC_LEFT (ic))
3755     goto jumpret;
3756
3757   /* we have something to return then
3758      move the return value into place */
3759   aopOp (IC_LEFT (ic), ic, FALSE);
3760   size = AOP_SIZE (IC_LEFT (ic));
3761
3762
3763   if (IS_BIT(_G.currentFunc->etype))
3764     {
3765       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3766       size = 0;
3767     }
3768
3769   while (size--)
3770     {
3771       char *l;
3772       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3773         {
3774           /* #NOCHANGE */
3775           l = aopGet (IC_LEFT (ic), offset++,
3776                       FALSE, TRUE);
3777           emitcode ("push", "%s", l);
3778           pushed++;
3779         }
3780       else
3781         {
3782           l = aopGet (IC_LEFT (ic), offset,
3783                       FALSE, FALSE);
3784           if (strcmp (fReturn[offset], l))
3785             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3786         }
3787     }
3788
3789   while (pushed)
3790     {
3791       pushed--;
3792       if (strcmp (fReturn[pushed], "a"))
3793         emitcode ("pop", fReturn[pushed]);
3794       else
3795         emitcode ("pop", "acc");
3796     }
3797   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3798
3799 jumpret:
3800   /* generate a jump to the return label
3801      if the next is not the return statement */
3802   if (!(ic->next && ic->next->op == LABEL &&
3803         IC_LABEL (ic->next) == returnLabel))
3804
3805     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3806
3807 }
3808
3809 /*-----------------------------------------------------------------*/
3810 /* genLabel - generates a label                                    */
3811 /*-----------------------------------------------------------------*/
3812 static void
3813 genLabel (iCode * ic)
3814 {
3815   /* special case never generate */
3816   if (IC_LABEL (ic) == entryLabel)
3817     return;
3818
3819   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3820 }
3821
3822 /*-----------------------------------------------------------------*/
3823 /* genGoto - generates a ljmp                                      */
3824 /*-----------------------------------------------------------------*/
3825 static void
3826 genGoto (iCode * ic)
3827 {
3828   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3829 }
3830
3831 /*-----------------------------------------------------------------*/
3832 /* findLabelBackwards: walks back through the iCode chain looking  */
3833 /* for the given label. Returns number of iCode instructions     */
3834 /* between that label and given ic.          */
3835 /* Returns zero if label not found.          */
3836 /*-----------------------------------------------------------------*/
3837 static int
3838 findLabelBackwards (iCode * ic, int key)
3839 {
3840   int count = 0;
3841
3842   while (ic->prev)
3843     {
3844       ic = ic->prev;
3845       count++;
3846
3847       /* If we have any pushes or pops, we cannot predict the distance.
3848          I don't like this at all, this should be dealt with in the
3849          back-end */
3850       if (ic->op == IPUSH || ic->op == IPOP) {
3851         return 0;
3852       }
3853
3854       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3855         {
3856           return count;
3857         }
3858     }
3859
3860   return 0;
3861 }
3862
3863 /*-----------------------------------------------------------------*/
3864 /* genPlusIncr :- does addition with increment if possible         */
3865 /*-----------------------------------------------------------------*/
3866 static bool
3867 genPlusIncr (iCode * ic)
3868 {
3869   unsigned int icount;
3870   unsigned int size = getDataSize (IC_RESULT (ic));
3871
3872   /* will try to generate an increment */
3873   /* if the right side is not a literal
3874      we cannot */
3875   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3876     return FALSE;
3877
3878   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3879
3880   D(emitcode (";     genPlusIncr",""));
3881
3882   /* if increment >=16 bits in register or direct space */
3883   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3884       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3885       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3886       (size > 1) &&
3887       (icount == 1))
3888     {
3889       symbol *tlbl;
3890       int emitTlbl;
3891       int labelRange;
3892
3893       /* If the next instruction is a goto and the goto target
3894        * is < 10 instructions previous to this, we can generate
3895        * jumps straight to that target.
3896        */
3897       if (ic->next && ic->next->op == GOTO
3898           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3899           && labelRange <= 10)
3900         {
3901           emitcode (";", "tail increment optimized");
3902           tlbl = IC_LABEL (ic->next);
3903           emitTlbl = 0;
3904         }
3905       else
3906         {
3907           tlbl = newiTempLabel (NULL);
3908           emitTlbl = 1;
3909         }
3910       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3911       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3912           IS_AOP_PREG (IC_RESULT (ic)))
3913         emitcode ("cjne", "%s,#0x00,%05d$",
3914                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3915                   tlbl->key + 100);
3916       else
3917         {
3918           emitcode ("clr", "a");
3919           emitcode ("cjne", "a,%s,%05d$",
3920                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3921                     tlbl->key + 100);
3922         }
3923
3924       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3925       if (size > 2)
3926         {
3927           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3928               IS_AOP_PREG (IC_RESULT (ic)))
3929             emitcode ("cjne", "%s,#0x00,%05d$",
3930                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3931                       tlbl->key + 100);
3932           else
3933             emitcode ("cjne", "a,%s,%05d$",
3934                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3935                       tlbl->key + 100);
3936
3937           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3938         }
3939       if (size > 3)
3940         {
3941           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3942               IS_AOP_PREG (IC_RESULT (ic)))
3943             emitcode ("cjne", "%s,#0x00,%05d$",
3944                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3945                       tlbl->key + 100);
3946           else
3947             {
3948               emitcode ("cjne", "a,%s,%05d$",
3949                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3950                         tlbl->key + 100);
3951             }
3952           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3953         }
3954
3955       if (emitTlbl)
3956         {
3957           emitcode ("", "%05d$:", tlbl->key + 100);
3958         }
3959       return TRUE;
3960     }
3961
3962   /* if result is dptr */
3963   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3964       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3965       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3966       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3967     {
3968       if (aopGetUsesAcc (IC_LEFT (ic), 0))
3969         return FALSE;
3970
3971       if (icount > 9)
3972         return FALSE;
3973
3974       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3975         return FALSE;
3976
3977       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3978       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3979       while (icount--)
3980         emitcode ("inc", "dptr");
3981
3982       return TRUE;
3983     }
3984
3985   /* if the literal value of the right hand side
3986      is greater than 4 then it is not worth it */
3987   if (icount > 4)
3988     return FALSE;
3989
3990   /* if the sizes are greater than 1 then we cannot */
3991   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3992       AOP_SIZE (IC_LEFT (ic)) > 1)
3993     return FALSE;
3994
3995   /* we can if the aops of the left & result match or
3996      if they are in registers and the registers are the
3997      same */
3998   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3999     {
4000
4001       if (icount > 3)
4002         {
4003           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4004           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4005           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4006         }
4007       else
4008         {
4009
4010           while (icount--)
4011             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4012         }
4013
4014       return TRUE;
4015     }
4016
4017   return FALSE;
4018 }
4019
4020 /*-----------------------------------------------------------------*/
4021 /* outBitAcc - output a bit in acc                                 */
4022 /*-----------------------------------------------------------------*/
4023 static void
4024 outBitAcc (operand * result)
4025 {
4026   symbol *tlbl = newiTempLabel (NULL);
4027   /* if the result is a bit */
4028   if (AOP_TYPE (result) == AOP_CRY)
4029     {
4030       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4031     }
4032   else
4033     {
4034       emitcode ("jz", "%05d$", tlbl->key + 100);
4035       emitcode ("mov", "a,%s", one);
4036       emitcode ("", "%05d$:", tlbl->key + 100);
4037       outAcc (result);
4038     }
4039 }
4040
4041 /*-----------------------------------------------------------------*/
4042 /* genPlusBits - generates code for addition of two bits           */
4043 /*-----------------------------------------------------------------*/
4044 static void
4045 genPlusBits (iCode * ic)
4046 {
4047   D(emitcode (";     genPlusBits",""));
4048
4049   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4050     {
4051       symbol *lbl = newiTempLabel (NULL);
4052       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4053       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4054       emitcode ("cpl", "c");
4055       emitcode ("", "%05d$:", (lbl->key + 100));
4056       outBitC (IC_RESULT (ic));
4057     }
4058   else
4059     {
4060       emitcode ("clr", "a");
4061       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4062       emitcode ("rlc", "a");
4063       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4064       emitcode ("addc", "a,#0x00");
4065       outAcc (IC_RESULT (ic));
4066     }
4067 }
4068
4069 #if 0
4070 /* This is the original version of this code.
4071
4072  * This is being kept around for reference,
4073  * because I am not entirely sure I got it right...
4074  */
4075 static void
4076 adjustArithmeticResult (iCode * ic)
4077 {
4078   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4079       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4080       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4081     aopPut (IC_RESULT (ic),
4082             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4083             2,
4084             isOperandVolatile (IC_RESULT (ic), FALSE));
4085
4086   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4087       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4088       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4089     aopPut (IC_RESULT (ic),
4090             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4091             2,
4092             isOperandVolatile (IC_RESULT (ic), FALSE));
4093
4094   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4095       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4096       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4097       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4098       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4099     {
4100       char buffer[5];
4101       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4102       aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4103     }
4104 }
4105 #else
4106 /* This is the pure and virtuous version of this code.
4107  * I'm pretty certain it's right, but not enough to toss the old
4108  * code just yet...
4109  */
4110 static void
4111 adjustArithmeticResult (iCode * ic)
4112 {
4113   if (opIsGptr (IC_RESULT (ic)) &&
4114       opIsGptr (IC_LEFT (ic)) &&
4115       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4116     {
4117       aopPut (IC_RESULT (ic),
4118               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4119               GPTRSIZE - 1,
4120               isOperandVolatile (IC_RESULT (ic), FALSE));
4121     }
4122
4123   if (opIsGptr (IC_RESULT (ic)) &&
4124       opIsGptr (IC_RIGHT (ic)) &&
4125       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4126     {
4127       aopPut (IC_RESULT (ic),
4128               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4129               GPTRSIZE - 1,
4130               isOperandVolatile (IC_RESULT (ic), FALSE));
4131     }
4132
4133   if (opIsGptr (IC_RESULT (ic)) &&
4134       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4135       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4136       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4137       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4138     {
4139       char buffer[5];
4140       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4141       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4142     }
4143 }
4144 #endif
4145
4146 /*-----------------------------------------------------------------*/
4147 /* genPlus - generates code for addition                           */
4148 /*-----------------------------------------------------------------*/
4149 static void
4150 genPlus (iCode * ic)
4151 {
4152   int size, offset = 0;
4153   int skip_bytes = 0;
4154   char *add = "add";
4155   operand *leftOp, *rightOp;
4156   operand * op;
4157
4158   /* special cases :- */
4159
4160   D(emitcode (";     genPlus",""));
4161
4162   aopOp (IC_LEFT (ic), ic, FALSE);
4163   aopOp (IC_RIGHT (ic), ic, FALSE);
4164   aopOp (IC_RESULT (ic), ic, TRUE);
4165
4166   /* if literal, literal on the right or
4167      if left requires ACC or right is already
4168      in ACC */
4169   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4170       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4171       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4172     {
4173       operand *t = IC_RIGHT (ic);
4174       IC_RIGHT (ic) = IC_LEFT (ic);
4175       IC_LEFT (ic) = t;
4176     }
4177
4178   /* if both left & right are in bit
4179      space */
4180   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4181       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4182     {
4183       genPlusBits (ic);
4184       goto release;
4185     }
4186
4187   /* if left in bit space & right literal */
4188   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4189       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4190     {
4191       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4192       /* if result in bit space */
4193       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4194         {
4195           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4196             emitcode ("cpl", "c");
4197           outBitC (IC_RESULT (ic));
4198         }
4199       else
4200         {
4201           size = getDataSize (IC_RESULT (ic));
4202           while (size--)
4203             {
4204               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4205               emitcode ("addc", "a,#00");
4206               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4207             }
4208         }
4209       goto release;
4210     }
4211
4212   /* if I can do an increment instead
4213      of add then GOOD for ME */
4214   if (genPlusIncr (ic) == TRUE)
4215     goto release;
4216
4217   size = getDataSize (IC_RESULT (ic));
4218   leftOp = IC_LEFT(ic);
4219   rightOp = IC_RIGHT(ic);
4220   op=IC_LEFT(ic);
4221
4222   /* if this is an add for an array access
4223      at a 256 byte boundary */
4224   if ( 2 == size
4225        && AOP_TYPE (op) == AOP_IMMD
4226        && IS_SYMOP (op)
4227        && IS_SPEC (OP_SYM_ETYPE (op))
4228        && SPEC_ABSA (OP_SYM_ETYPE (op))
4229        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4230      )
4231     {
4232       D(emitcode (";     genPlus aligned array",""));
4233       aopPut (IC_RESULT (ic),
4234               aopGet (rightOp, 0, FALSE, FALSE),
4235               0,
4236               isOperandVolatile (IC_RESULT (ic), FALSE));
4237
4238       if( 1 == getDataSize (IC_RIGHT (ic)) )
4239         {
4240           aopPut (IC_RESULT (ic),
4241                   aopGet (leftOp, 1, FALSE, FALSE),
4242                   1,
4243                   isOperandVolatile (IC_RESULT (ic), FALSE));
4244         }
4245       else
4246         {
4247           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4248           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4249           aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4250         }
4251       goto release;
4252     }
4253
4254   /* if the lower bytes of a literal are zero skip the addition */
4255   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4256     {
4257        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4258               (skip_bytes+1 < size))
4259          {
4260            skip_bytes++;
4261          }
4262        if (skip_bytes)
4263          D(emitcode (";     genPlus shortcut",""));
4264     }
4265
4266   while (size--)
4267     {
4268       if( offset >= skip_bytes )
4269         {
4270           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4271             {
4272               bool pushedB;
4273               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4274               pushedB = pushB ();
4275               emitcode("xch", "a,b");
4276               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4277               emitcode (add, "a,b");
4278               popB (pushedB);
4279             }
4280           else if (aopGetUsesAcc (leftOp, offset))
4281             {
4282               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4283               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4284             }
4285           else
4286             {
4287               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4288               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4289             }
4290           aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4291           add = "addc";  /* further adds must propagate carry */
4292         }
4293       else
4294         {
4295           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4296               isOperandVolatile (IC_RESULT (ic), FALSE))
4297             {
4298               /* just move */
4299               aopPut (IC_RESULT (ic),
4300                       aopGet (leftOp, offset, FALSE, FALSE),
4301                       offset,
4302                       isOperandVolatile (IC_RESULT (ic), FALSE));
4303             }
4304         }
4305       offset++;
4306     }
4307
4308   adjustArithmeticResult (ic);
4309
4310 release:
4311   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4312   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4313   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4314 }
4315
4316 /*-----------------------------------------------------------------*/
4317 /* genMinusDec :- does subtraction with deccrement if possible     */
4318 /*-----------------------------------------------------------------*/
4319 static bool
4320 genMinusDec (iCode * ic)
4321 {
4322   unsigned int icount;
4323   unsigned int size = getDataSize (IC_RESULT (ic));
4324
4325   /* will try to generate an increment */
4326   /* if the right side is not a literal
4327      we cannot */
4328   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4329     return FALSE;
4330
4331   /* if the literal value of the right hand side
4332      is greater than 4 then it is not worth it */
4333   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4334     return FALSE;
4335
4336   D(emitcode (";     genMinusDec",""));
4337
4338   /* if decrement >=16 bits in register or direct space */
4339   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4340       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4341       (size > 1) &&
4342       (icount == 1))
4343     {
4344       symbol *tlbl;
4345       int emitTlbl;
4346       int labelRange;
4347
4348       /* If the next instruction is a goto and the goto target
4349        * is <= 10 instructions previous to this, we can generate
4350        * jumps straight to that target.
4351        */
4352       if (ic->next && ic->next->op == GOTO
4353           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4354           && labelRange <= 10)
4355         {
4356           emitcode (";", "tail decrement optimized");
4357           tlbl = IC_LABEL (ic->next);
4358           emitTlbl = 0;
4359         }
4360       else
4361         {
4362           tlbl = newiTempLabel (NULL);
4363           emitTlbl = 1;
4364         }
4365
4366       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4367       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4368           IS_AOP_PREG (IC_RESULT (ic)))
4369         emitcode ("cjne", "%s,#0xff,%05d$"
4370                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4371                   ,tlbl->key + 100);
4372       else
4373         {
4374           emitcode ("mov", "a,#0xff");
4375           emitcode ("cjne", "a,%s,%05d$"
4376                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4377                     ,tlbl->key + 100);
4378         }
4379       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4380       if (size > 2)
4381         {
4382           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4383               IS_AOP_PREG (IC_RESULT (ic)))
4384             emitcode ("cjne", "%s,#0xff,%05d$"
4385                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4386                       ,tlbl->key + 100);
4387           else
4388             {
4389               emitcode ("cjne", "a,%s,%05d$"
4390                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4391                         ,tlbl->key + 100);
4392             }
4393           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4394         }
4395       if (size > 3)
4396         {
4397           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4398               IS_AOP_PREG (IC_RESULT (ic)))
4399             emitcode ("cjne", "%s,#0xff,%05d$"
4400                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4401                       ,tlbl->key + 100);
4402           else
4403             {
4404               emitcode ("cjne", "a,%s,%05d$"
4405                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4406                         ,tlbl->key + 100);
4407             }
4408           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4409         }
4410       if (emitTlbl)
4411         {
4412           emitcode ("", "%05d$:", tlbl->key + 100);
4413         }
4414       return TRUE;
4415     }
4416
4417   /* if the sizes are greater than 1 then we cannot */
4418   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4419       AOP_SIZE (IC_LEFT (ic)) > 1)
4420     return FALSE;
4421
4422   /* we can if the aops of the left & result match or
4423      if they are in registers and the registers are the
4424      same */
4425   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4426     {
4427
4428       while (icount--)
4429         emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4430
4431       return TRUE;
4432     }
4433
4434   return FALSE;
4435 }
4436
4437 /*-----------------------------------------------------------------*/
4438 /* addSign - complete with sign                                    */
4439 /*-----------------------------------------------------------------*/
4440 static void
4441 addSign (operand * result, int offset, int sign)
4442 {
4443   int size = (getDataSize (result) - offset);
4444   if (size > 0)
4445     {
4446       if (sign)
4447         {
4448           emitcode ("rlc", "a");
4449           emitcode ("subb", "a,acc");
4450           while (size--)
4451             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4452         }
4453       else
4454         while (size--)
4455           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4456     }
4457 }
4458
4459 /*-----------------------------------------------------------------*/
4460 /* genMinusBits - generates code for subtraction  of two bits      */
4461 /*-----------------------------------------------------------------*/
4462 static void
4463 genMinusBits (iCode * ic)
4464 {
4465   symbol *lbl = newiTempLabel (NULL);
4466
4467   D(emitcode (";     genMinusBits",""));
4468
4469   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4470     {
4471       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4472       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4473       emitcode ("cpl", "c");
4474       emitcode ("", "%05d$:", (lbl->key + 100));
4475       outBitC (IC_RESULT (ic));
4476     }
4477   else
4478     {
4479       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4480       emitcode ("subb", "a,acc");
4481       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4482       emitcode ("inc", "a");
4483       emitcode ("", "%05d$:", (lbl->key + 100));
4484       aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4485       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4486     }
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* genMinus - generates code for subtraction                       */
4491 /*-----------------------------------------------------------------*/
4492 static void
4493 genMinus (iCode * ic)
4494 {
4495   int size, offset = 0;
4496
4497   D(emitcode (";     genMinus",""));
4498
4499   aopOp (IC_LEFT (ic), ic, FALSE);
4500   aopOp (IC_RIGHT (ic), ic, FALSE);
4501   aopOp (IC_RESULT (ic), ic, TRUE);
4502
4503   /* special cases :- */
4504   /* if both left & right are in bit space */
4505   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4506       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4507     {
4508       genMinusBits (ic);
4509       goto release;
4510     }
4511
4512   /* if I can do an decrement instead
4513      of subtract then GOOD for ME */
4514   if (genMinusDec (ic) == TRUE)
4515     goto release;
4516
4517   size = getDataSize (IC_RESULT (ic));
4518
4519   /* if literal, add a,#-lit, else normal subb */
4520   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4521     {
4522       unsigned long lit = 0L;
4523       bool useCarry = FALSE;
4524
4525       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4526       lit = -(long) lit;
4527
4528       while (size--)
4529         {
4530           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL)) {
4531             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4532             if (!offset && !size && lit== (unsigned long) -1) {
4533               emitcode ("dec", "a");
4534             } else if (!useCarry) {
4535               /* first add without previous c */
4536               emitcode ("add", "a,#0x%02x",
4537                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4538               useCarry = TRUE;
4539             } else {
4540               emitcode ("addc", "a,#0x%02x",
4541                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4542             }
4543             aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4544             } else {
4545               /* no need to add zeroes */
4546               offset++;
4547             }
4548         }
4549     }
4550   else
4551     {
4552       operand *leftOp, *rightOp;
4553
4554       leftOp = IC_LEFT(ic);
4555       rightOp = IC_RIGHT(ic);
4556
4557       while (size--)
4558         {
4559           if (aopGetUsesAcc(rightOp, offset)) {
4560             if (aopGetUsesAcc(leftOp, offset)) {
4561               bool pushedB;
4562
4563               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4564               pushedB = pushB ();
4565               emitcode ("mov", "b,a");
4566               if (offset == 0)
4567                 CLRC;
4568               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4569               emitcode ("subb", "a,b");
4570               popB (pushedB);
4571             } else {
4572               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4573               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4574               if (offset == 0) {
4575                 emitcode( "setb", "c");
4576               }
4577               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4578               emitcode("cpl", "a");
4579             }
4580           } else {
4581             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4582             if (offset == 0)
4583               CLRC;
4584             emitcode ("subb", "a,%s",
4585                       aopGet(rightOp, offset, FALSE, TRUE));
4586           }
4587
4588           aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4589         }
4590     }
4591
4592
4593   adjustArithmeticResult (ic);
4594
4595 release:
4596   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4599 }
4600
4601
4602 /*-----------------------------------------------------------------*/
4603 /* genMultbits :- multiplication of bits                           */
4604 /*-----------------------------------------------------------------*/
4605 static void
4606 genMultbits (operand * left,
4607              operand * right,
4608              operand * result)
4609 {
4610   D(emitcode (";     genMultbits",""));
4611
4612   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4613   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4614   outBitC (result);
4615 }
4616
4617 /*-----------------------------------------------------------------*/
4618 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4619 /*-----------------------------------------------------------------*/
4620 static void
4621 genMultOneByte (operand * left,
4622                 operand * right,
4623                 operand * result)
4624 {
4625   symbol *lbl;
4626   int size = AOP_SIZE (result);
4627   bool runtimeSign, compiletimeSign;
4628   bool lUnsigned, rUnsigned, pushedB;
4629
4630   D(emitcode (";     genMultOneByte",""));
4631
4632   if (size < 1 || size > 2)
4633     {
4634       /* this should never happen */
4635       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4636                AOP_SIZE(result), __FILE__, lineno);
4637       exit (1);
4638     }
4639
4640   /* (if two literals: the value is computed before) */
4641   /* if one literal, literal on the right */
4642   if (AOP_TYPE (left) == AOP_LIT)
4643     {
4644       operand *t = right;
4645       right = left;
4646       left = t;
4647       /* emitcode (";", "swapped left and right"); */
4648     }
4649   /* if no literal, unsigned on the right: shorter code */
4650   if (   AOP_TYPE (right) != AOP_LIT
4651       && SPEC_USIGN (getSpec (operandType (left))))
4652     {
4653       operand *t = right;
4654       right = left;
4655       left = t;
4656     }
4657
4658   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4659   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4660
4661   pushedB = pushB ();
4662
4663   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4664                    no need to take care about the signedness! */
4665       || (lUnsigned && rUnsigned))
4666     {
4667       /* just an unsigned 8 * 8 = 8 multiply
4668          or 8u * 8u = 16u */
4669       /* emitcode (";","unsigned"); */
4670       /* TODO: check for accumulator clash between left & right aops? */
4671
4672       if (AOP_TYPE (right) == AOP_LIT)
4673         {
4674           /* moving to accumulator first helps peepholes */
4675           MOVA (aopGet (left, 0, FALSE, FALSE));
4676           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4677         }
4678       else
4679         {
4680           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4681           MOVA (aopGet (left, 0, FALSE, FALSE));
4682         }
4683
4684       emitcode ("mul", "ab");
4685       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4686       if (size == 2)
4687         aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4688
4689       popB (pushedB);
4690       return;
4691     }
4692
4693   /* we have to do a signed multiply */
4694   /* emitcode (";", "signed"); */
4695
4696   /* now sign adjust for both left & right */
4697
4698   /* let's see what's needed: */
4699   /* apply negative sign during runtime */
4700   runtimeSign = FALSE;
4701   /* negative sign from literals */
4702   compiletimeSign = FALSE;
4703
4704   if (!lUnsigned)
4705     {
4706       if (AOP_TYPE(left) == AOP_LIT)
4707         {
4708           /* signed literal */
4709           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4710           if (val < 0)
4711             compiletimeSign = TRUE;
4712         }
4713       else
4714         /* signed but not literal */
4715         runtimeSign = TRUE;
4716     }
4717
4718   if (!rUnsigned)
4719     {
4720       if (AOP_TYPE(right) == AOP_LIT)
4721         {
4722           /* signed literal */
4723           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4724           if (val < 0)
4725             compiletimeSign ^= TRUE;
4726         }
4727       else
4728         /* signed but not literal */
4729         runtimeSign = TRUE;
4730     }
4731
4732   /* initialize F0, which stores the runtime sign */
4733   if (runtimeSign)
4734     {
4735       if (compiletimeSign)
4736         emitcode ("setb", "F0"); /* set sign flag */
4737       else
4738         emitcode ("clr", "F0"); /* reset sign flag */
4739     }
4740
4741   /* save the signs of the operands */
4742   if (AOP_TYPE(right) == AOP_LIT)
4743     {
4744       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4745
4746       if (!rUnsigned && val < 0)
4747         emitcode ("mov", "b,#0x%02x", -val);
4748       else
4749         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4750     }
4751   else /* ! literal */
4752     {
4753       if (rUnsigned)  /* emitcode (";", "signed"); */
4754
4755         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4756       else
4757         {
4758           MOVA (aopGet (right, 0, FALSE, FALSE));
4759           lbl = newiTempLabel (NULL);
4760           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4761           emitcode ("cpl", "F0"); /* complement sign flag */
4762           emitcode ("cpl", "a");  /* 2's complement */
4763           emitcode ("inc", "a");
4764           emitcode ("", "%05d$:", (lbl->key + 100));
4765           emitcode ("mov", "b,a");
4766         }
4767     }
4768
4769   if (AOP_TYPE(left) == AOP_LIT)
4770     {
4771       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4772
4773       if (!lUnsigned && val < 0)
4774         emitcode ("mov", "a,#0x%02x", -val);
4775       else
4776         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4777     }
4778   else /* ! literal */
4779     {
4780       MOVA (aopGet (left, 0, FALSE, FALSE));
4781
4782       if (!lUnsigned)
4783         {
4784           lbl = newiTempLabel (NULL);
4785           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4786           emitcode ("cpl", "F0"); /* complement sign flag */
4787           emitcode ("cpl", "a"); /* 2's complement */
4788           emitcode ("inc", "a");
4789           emitcode ("", "%05d$:", (lbl->key + 100));
4790         }
4791     }
4792
4793   /* now the multiplication */
4794   emitcode ("mul", "ab");
4795   if (runtimeSign || compiletimeSign)
4796     {
4797       lbl = newiTempLabel (NULL);
4798       if (runtimeSign)
4799         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4800       emitcode ("cpl", "a"); /* lsb 2's complement */
4801       if (size != 2)
4802         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4803       else
4804         {
4805           emitcode ("add", "a,#1"); /* this sets carry flag */
4806           emitcode ("xch", "a,b");
4807           emitcode ("cpl", "a"); /* msb 2's complement */
4808           emitcode ("addc", "a,#0");
4809           emitcode ("xch", "a,b");
4810         }
4811       emitcode ("", "%05d$:", (lbl->key + 100));
4812     }
4813   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4814   if (size == 2)
4815     aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4816
4817   popB (pushedB);
4818 }
4819
4820 /*-----------------------------------------------------------------*/
4821 /* genMult - generates code for multiplication                     */
4822 /*-----------------------------------------------------------------*/
4823 static void
4824 genMult (iCode * ic)
4825 {
4826   operand *left = IC_LEFT (ic);
4827   operand *right = IC_RIGHT (ic);
4828   operand *result = IC_RESULT (ic);
4829
4830   D(emitcode (";     genMult",""));
4831
4832   /* assign the amsops */
4833   aopOp (left, ic, FALSE);
4834   aopOp (right, ic, FALSE);
4835   aopOp (result, ic, TRUE);
4836
4837   /* special cases first */
4838   /* both are bits */
4839   if (AOP_TYPE (left) == AOP_CRY &&
4840       AOP_TYPE (right) == AOP_CRY)
4841     {
4842       genMultbits (left, right, result);
4843       goto release;
4844     }
4845
4846   /* if both are of size == 1 */
4847 #if 0 // one of them can be a sloc shared with the result
4848     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4849 #else
4850   if (getSize(operandType(left)) == 1 &&
4851       getSize(operandType(right)) == 1)
4852 #endif
4853     {
4854       genMultOneByte (left, right, result);
4855       goto release;
4856     }
4857
4858   /* should have been converted to function call */
4859     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4860              getSize(OP_SYMBOL(right)->type));
4861   assert (0);
4862
4863 release:
4864   freeAsmop (result, NULL, ic, TRUE);
4865   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4866   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867 }
4868
4869 /*-----------------------------------------------------------------*/
4870 /* genDivbits :- division of bits                                  */
4871 /*-----------------------------------------------------------------*/
4872 static void
4873 genDivbits (operand * left,
4874             operand * right,
4875             operand * result)
4876 {
4877   char *l;
4878   bool pushedB;
4879
4880   D(emitcode (";     genDivbits",""));
4881
4882   pushedB = pushB ();
4883
4884   /* the result must be bit */
4885   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4886   l = aopGet (left, 0, FALSE, FALSE);
4887
4888   MOVA (l);
4889
4890   emitcode ("div", "ab");
4891   emitcode ("rrc", "a");
4892
4893   popB (pushedB);
4894
4895   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4896 }
4897
4898 /*-----------------------------------------------------------------*/
4899 /* genDivOneByte : 8 bit division                                  */
4900 /*-----------------------------------------------------------------*/
4901 static void
4902 genDivOneByte (operand * left,
4903                operand * right,
4904                operand * result)
4905 {
4906   bool lUnsigned, rUnsigned, pushedB;
4907   bool runtimeSign, compiletimeSign;
4908   symbol *lbl;
4909   int size, offset;
4910
4911   D(emitcode (";     genDivOneByte",""));
4912
4913   /* Why is it necessary that genDivOneByte() can return an int result?
4914      Have a look at:
4915
4916         volatile unsigned char uc;
4917         volatile signed char sc1, sc2;
4918         volatile int i;
4919
4920         uc  = 255;
4921         sc1 = -1;
4922         i = uc / sc1;
4923
4924      Or:
4925
4926         sc1 = -128;
4927         sc2 = -1;
4928         i = sc1 / sc2;
4929
4930      In all cases a one byte result would overflow, the following cast to int
4931      would return the wrong result.
4932
4933      Two possible solution:
4934         a) cast operands to int, if ((unsigned) / (signed)) or
4935            ((signed) / (signed))
4936         b) return an 16 bit signed int; this is what we're doing here!
4937   */
4938
4939   size = AOP_SIZE (result) - 1;
4940   offset = 1;
4941   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4942   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4943
4944   pushedB = pushB ();
4945
4946   /* signed or unsigned */
4947   if (lUnsigned && rUnsigned)
4948     {
4949       /* unsigned is easy */
4950       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4951       MOVA (aopGet (left, 0, FALSE, FALSE));
4952       emitcode ("div", "ab");
4953       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4954       while (size--)
4955         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4956
4957       popB (pushedB);
4958       return;
4959     }
4960
4961   /* signed is a little bit more difficult */
4962
4963   /* now sign adjust for both left & right */
4964
4965   /* let's see what's needed: */
4966   /* apply negative sign during runtime */
4967   runtimeSign = FALSE;
4968   /* negative sign from literals */
4969   compiletimeSign = FALSE;
4970
4971   if (!lUnsigned)
4972     {
4973       if (AOP_TYPE(left) == AOP_LIT)
4974         {
4975           /* signed literal */
4976           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4977           if (val < 0)
4978             compiletimeSign = TRUE;
4979         }
4980       else
4981         /* signed but not literal */
4982         runtimeSign = TRUE;
4983     }
4984
4985   if (!rUnsigned)
4986     {
4987       if (AOP_TYPE(right) == AOP_LIT)
4988         {
4989           /* signed literal */
4990           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4991           if (val < 0)
4992             compiletimeSign ^= TRUE;
4993         }
4994       else
4995         /* signed but not literal */
4996         runtimeSign = TRUE;
4997     }
4998
4999   /* initialize F0, which stores the runtime sign */
5000   if (runtimeSign)
5001     {
5002       if (compiletimeSign)
5003         emitcode ("setb", "F0"); /* set sign flag */
5004       else
5005         emitcode ("clr", "F0"); /* reset sign flag */
5006     }
5007
5008   /* save the signs of the operands */
5009   if (AOP_TYPE(right) == AOP_LIT)
5010     {
5011       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5012
5013       if (!rUnsigned && val < 0)
5014         emitcode ("mov", "b,#0x%02x", -val);
5015       else
5016         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5017     }
5018   else /* ! literal */
5019     {
5020       if (rUnsigned)
5021         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5022       else
5023         {
5024           MOVA (aopGet (right, 0, FALSE, FALSE));
5025           lbl = newiTempLabel (NULL);
5026           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5027           emitcode ("cpl", "F0"); /* complement sign flag */
5028           emitcode ("cpl", "a");  /* 2's complement */
5029           emitcode ("inc", "a");
5030           emitcode ("", "%05d$:", (lbl->key + 100));
5031           emitcode ("mov", "b,a");
5032         }
5033     }
5034
5035   if (AOP_TYPE(left) == AOP_LIT)
5036     {
5037       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5038
5039       if (!lUnsigned && val < 0)
5040         emitcode ("mov", "a,#0x%02x", -val);
5041       else
5042         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5043     }
5044   else /* ! literal */
5045     {
5046       MOVA (aopGet (left, 0, FALSE, FALSE));
5047
5048       if (!lUnsigned)
5049         {
5050           lbl = newiTempLabel (NULL);
5051           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5052           emitcode ("cpl", "F0"); /* complement sign flag */
5053           emitcode ("cpl", "a");  /* 2's complement */
5054           emitcode ("inc", "a");
5055           emitcode ("", "%05d$:", (lbl->key + 100));
5056         }
5057     }
5058
5059   /* now the division */
5060   emitcode ("div", "ab");
5061
5062   if (runtimeSign || compiletimeSign)
5063     {
5064       lbl = newiTempLabel (NULL);
5065       if (runtimeSign)
5066         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5067       emitcode ("cpl", "a"); /* lsb 2's complement */
5068       emitcode ("inc", "a");
5069       emitcode ("", "%05d$:", (lbl->key + 100));
5070
5071       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5072       if (size > 0)
5073         {
5074           /* msb is 0x00 or 0xff depending on the sign */
5075           if (runtimeSign)
5076             {
5077               emitcode ("mov", "c,F0");
5078               emitcode ("subb", "a,acc");
5079               while (size--)
5080                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5081             }
5082           else /* compiletimeSign */
5083             while (size--)
5084               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5085         }
5086     }
5087   else
5088     {
5089       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5090       while (size--)
5091         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5092     }
5093
5094   popB (pushedB);
5095 }
5096
5097 /*-----------------------------------------------------------------*/
5098 /* genDiv - generates code for division                            */
5099 /*-----------------------------------------------------------------*/
5100 static void
5101 genDiv (iCode * ic)
5102 {
5103   operand *left = IC_LEFT (ic);
5104   operand *right = IC_RIGHT (ic);
5105   operand *result = IC_RESULT (ic);
5106
5107   D(emitcode (";     genDiv",""));
5108
5109   /* assign the amsops */
5110   aopOp (left, ic, FALSE);
5111   aopOp (right, ic, FALSE);
5112   aopOp (result, ic, TRUE);
5113
5114   /* special cases first */
5115   /* both are bits */
5116   if (AOP_TYPE (left) == AOP_CRY &&
5117       AOP_TYPE (right) == AOP_CRY)
5118     {
5119       genDivbits (left, right, result);
5120       goto release;
5121     }
5122
5123   /* if both are of size == 1 */
5124   if (AOP_SIZE (left) == 1 &&
5125       AOP_SIZE (right) == 1)
5126     {
5127       genDivOneByte (left, right, result);
5128       goto release;
5129     }
5130
5131   /* should have been converted to function call */
5132   assert (0);
5133 release:
5134   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136   freeAsmop (result, NULL, ic, TRUE);
5137 }
5138
5139 /*-----------------------------------------------------------------*/
5140 /* genModbits :- modulus of bits                                   */
5141 /*-----------------------------------------------------------------*/
5142 static void
5143 genModbits (operand * left,
5144             operand * right,
5145             operand * result)
5146 {
5147   char *l;
5148   bool pushedB;
5149
5150   D(emitcode (";     genModbits",""));
5151
5152   pushedB = pushB ();
5153
5154   /* the result must be bit */
5155   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5156   l = aopGet (left, 0, FALSE, FALSE);
5157
5158   MOVA (l);
5159
5160   emitcode ("div", "ab");
5161   emitcode ("mov", "a,b");
5162   emitcode ("rrc", "a");
5163
5164   popB (pushedB);
5165
5166   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5167 }
5168
5169 /*-----------------------------------------------------------------*/
5170 /* genModOneByte : 8 bit modulus                                   */
5171 /*-----------------------------------------------------------------*/
5172 static void
5173 genModOneByte (operand * left,
5174                operand * right,
5175                operand * result)
5176 {
5177   bool lUnsigned, rUnsigned, pushedB;
5178   bool runtimeSign, compiletimeSign;
5179   symbol *lbl;
5180   int size, offset;
5181
5182   D(emitcode (";     genModOneByte",""));
5183
5184   size = AOP_SIZE (result) - 1;
5185   offset = 1;
5186   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5187   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5188
5189   /* if right is a literal, check it for 2^n */
5190   if (AOP_TYPE(right) == AOP_LIT)
5191     {
5192       unsigned char val = abs((int) operandLitValue(right));
5193       symbol *lbl2 = NULL;
5194
5195       switch (val)
5196         {
5197           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5198           case 2:
5199           case 4:
5200           case 8:
5201           case 16:
5202           case 32:
5203           case 64:
5204           case 128:
5205             if (lUnsigned)
5206               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5207                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5208               /* because iCode should have been changed to genAnd  */
5209               /* see file "SDCCopt.c", function "convertToFcall()" */
5210
5211             MOVA (aopGet (left, 0, FALSE, FALSE));
5212             emitcode ("mov", "c,acc.7");
5213             emitcode ("anl", "a,#0x%02x", val - 1);
5214             lbl = newiTempLabel (NULL);
5215             emitcode ("jz", "%05d$", (lbl->key + 100));
5216             emitcode ("jnc", "%05d$", (lbl->key + 100));
5217             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5218             if (size)
5219               {
5220                 int size2 = size;
5221                 int offs2 = offset;
5222
5223                 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5224                 while (size2--)
5225                   aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5226                 lbl2 = newiTempLabel (NULL);
5227                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5228               }
5229             emitcode ("", "%05d$:", (lbl->key + 100));
5230             aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5231             while (size--)
5232               aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5233             if (lbl2)
5234               {
5235                 emitcode ("", "%05d$:", (lbl2->key + 100));
5236               }
5237             return;
5238
5239           default:
5240             break;
5241         }
5242     }
5243
5244   pushedB = pushB ();
5245
5246   /* signed or unsigned */
5247   if (lUnsigned && rUnsigned)
5248     {
5249       /* unsigned is easy */
5250       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5251       MOVA (aopGet (left, 0, FALSE, FALSE));
5252       emitcode ("div", "ab");
5253       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5254       while (size--)
5255         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5256
5257       popB (pushedB);
5258       return;
5259     }
5260
5261   /* signed is a little bit more difficult */
5262
5263   /* now sign adjust for both left & right */
5264
5265   /* modulus: sign of the right operand has no influence on the result! */
5266   if (AOP_TYPE(right) == AOP_LIT)
5267     {
5268       signed char val = (char) operandLitValue(right);
5269
5270       if (!rUnsigned && val < 0)
5271         emitcode ("mov", "b,#0x%02x", -val);
5272       else
5273         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5274     }
5275   else /* not literal */
5276     {
5277       if (rUnsigned)
5278         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5279       else
5280         {
5281           MOVA (aopGet (right, 0, FALSE, FALSE));
5282           lbl = newiTempLabel (NULL);
5283           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5284           emitcode ("cpl", "a"); /* 2's complement */
5285           emitcode ("inc", "a");
5286           emitcode ("", "%05d$:", (lbl->key + 100));
5287           emitcode ("mov", "b,a");
5288         }
5289     }
5290
5291   /* let's see what's needed: */
5292   /* apply negative sign during runtime */
5293   runtimeSign = FALSE;
5294   /* negative sign from literals */
5295   compiletimeSign = FALSE;
5296
5297   /* sign adjust left side */
5298   if (AOP_TYPE(left) == AOP_LIT)
5299     {
5300       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5301
5302       if (!lUnsigned && val < 0)
5303         {
5304           compiletimeSign = TRUE; /* set sign flag */
5305           emitcode ("mov", "a,#0x%02x", -val);
5306         }
5307       else
5308         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5309     }
5310   else /* ! literal */
5311     {
5312       MOVA (aopGet (left, 0, FALSE, FALSE));
5313
5314       if (!lUnsigned)
5315         {
5316           runtimeSign = TRUE;
5317           emitcode ("clr", "F0"); /* clear sign flag */
5318
5319           lbl = newiTempLabel (NULL);
5320           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5321           emitcode ("setb", "F0"); /* set sign flag */
5322           emitcode ("cpl", "a");   /* 2's complement */
5323           emitcode ("inc", "a");
5324           emitcode ("", "%05d$:", (lbl->key + 100));
5325         }
5326     }
5327
5328   /* now the modulus */
5329   emitcode ("div", "ab");
5330
5331   if (runtimeSign || compiletimeSign)
5332     {
5333       emitcode ("mov", "a,b");
5334       lbl = newiTempLabel (NULL);
5335       if (runtimeSign)
5336         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5337       emitcode ("cpl", "a"); /* 2's complement */
5338       emitcode ("inc", "a");
5339       emitcode ("", "%05d$:", (lbl->key + 100));
5340
5341       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5342       if (size > 0)
5343         {
5344           /* msb is 0x00 or 0xff depending on the sign */
5345           if (runtimeSign)
5346             {
5347               emitcode ("mov", "c,F0");
5348               emitcode ("subb", "a,acc");
5349               while (size--)
5350                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5351             }
5352           else /* compiletimeSign */
5353             while (size--)
5354               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5355         }
5356     }
5357   else
5358     {
5359       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5360       while (size--)
5361         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5362     }
5363
5364   popB (pushedB);
5365 }
5366
5367 /*-----------------------------------------------------------------*/
5368 /* genMod - generates code for division                            */
5369 /*-----------------------------------------------------------------*/
5370 static void
5371 genMod (iCode * ic)
5372 {
5373   operand *left = IC_LEFT (ic);
5374   operand *right = IC_RIGHT (ic);
5375   operand *result = IC_RESULT (ic);
5376
5377   D(emitcode (";     genMod",""));
5378
5379   /* assign the asmops */
5380   aopOp (left, ic, FALSE);
5381   aopOp (right, ic, FALSE);
5382   aopOp (result, ic, TRUE);
5383
5384   /* special cases first */
5385   /* both are bits */
5386   if (AOP_TYPE (left) == AOP_CRY &&
5387       AOP_TYPE (right) == AOP_CRY)
5388     {
5389       genModbits (left, right, result);
5390       goto release;
5391     }
5392
5393   /* if both are of size == 1 */
5394   if (AOP_SIZE (left) == 1 &&
5395       AOP_SIZE (right) == 1)
5396     {
5397       genModOneByte (left, right, result);
5398       goto release;
5399     }
5400
5401   /* should have been converted to function call */
5402   assert (0);
5403
5404 release:
5405   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5406   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5407   freeAsmop (result, NULL, ic, TRUE);
5408 }
5409
5410 /*-----------------------------------------------------------------*/
5411 /* genIfxJump :- will create a jump depending on the ifx           */
5412 /*-----------------------------------------------------------------*/
5413 static void
5414 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5415 {
5416   symbol *jlbl;
5417   symbol *tlbl = newiTempLabel (NULL);
5418   char *inst;
5419
5420   D(emitcode (";     genIfxJump",""));
5421
5422   /* if true label then we jump if condition
5423      supplied is true */
5424   if (IC_TRUE (ic))
5425     {
5426       jlbl = IC_TRUE (ic);
5427       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5428                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5429     }
5430   else
5431     {
5432       /* false label is present */
5433       jlbl = IC_FALSE (ic);
5434       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5435                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5436     }
5437   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5438     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5439   else
5440     emitcode (inst, "%05d$", tlbl->key + 100);
5441   freeForBranchAsmop (result);
5442   freeForBranchAsmop (right);
5443   freeForBranchAsmop (left);
5444   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5445   emitcode ("", "%05d$:", tlbl->key + 100);
5446
5447   /* mark the icode as generated */
5448   ic->generated = 1;
5449 }
5450
5451 /*-----------------------------------------------------------------*/
5452 /* genCmp :- greater or less than comparison                       */
5453 /*-----------------------------------------------------------------*/
5454 static void
5455 genCmp (operand * left, operand * right,
5456         operand * result, iCode * ifx, int sign, iCode *ic)
5457 {
5458   int size, offset = 0;
5459   unsigned long lit = 0L;
5460   bool rightInB;
5461
5462   D(emitcode (";     genCmp",""));
5463
5464   /* if left & right are bit variables */
5465   if (AOP_TYPE (left) == AOP_CRY &&
5466       AOP_TYPE (right) == AOP_CRY)
5467     {
5468       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5469       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5470     }
5471   else
5472     {
5473       /* subtract right from left if at the
5474          end the carry flag is set then we know that
5475          left is greater than right */
5476       size = max (AOP_SIZE (left), AOP_SIZE (right));
5477
5478       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5479       if ((size == 1) && !sign &&
5480           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5481         {
5482           symbol *lbl = newiTempLabel (NULL);
5483           emitcode ("cjne", "%s,%s,%05d$",
5484                     aopGet (left, offset, FALSE, FALSE),
5485                     aopGet (right, offset, FALSE, FALSE),
5486                     lbl->key + 100);
5487           emitcode ("", "%05d$:", lbl->key + 100);
5488         }
5489       else
5490         {
5491           if (AOP_TYPE (right) == AOP_LIT)
5492             {
5493               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5494               /* optimize if(x < 0) or if(x >= 0) */
5495               if (lit == 0L)
5496                 {
5497                   if (!sign)
5498                     {
5499                       CLRC;
5500                     }
5501                   else
5502                     {
5503                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5504                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5505                         {
5506                           genIfxJump (ifx, "acc.7", left, right, result);
5507                           freeAsmop (right, NULL, ic, TRUE);
5508                           freeAsmop (left, NULL, ic, TRUE);
5509
5510                           return;
5511                         }
5512                       else
5513                         emitcode ("rlc", "a");
5514                     }
5515                   goto release;
5516                 }
5517             }
5518           CLRC;
5519           while (size--)
5520             {
5521               bool pushedB = FALSE;
5522               rightInB = aopGetUsesAcc(right, offset);
5523               if (rightInB)
5524                 {
5525                   pushedB = pushB ();
5526                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5527                 }
5528               MOVA (aopGet (left, offset, FALSE, FALSE));
5529               if (sign && size == 0)
5530                 {
5531                   emitcode ("xrl", "a,#0x80");
5532                   if (AOP_TYPE (right) == AOP_LIT)
5533                     {
5534                       unsigned long lit = (unsigned long)
5535                       floatFromVal (AOP (right)->aopu.aop_lit);
5536                       emitcode ("subb", "a,#0x%02x",
5537                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5538                     }
5539                   else
5540                     {
5541                       if (!rightInB)
5542                         {
5543                           pushedB = pushB ();
5544                           rightInB++;
5545                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5546                         }
5547                       emitcode ("xrl", "b,#0x80");
5548                       emitcode ("subb", "a,b");
5549                     }
5550                 }
5551               else
5552                 {
5553                   if (rightInB)
5554                     emitcode ("subb", "a,b");
5555                   else
5556                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5557                 }
5558               if (rightInB)
5559                 popB (pushedB);
5560               offset++;
5561             }
5562         }
5563     }
5564
5565 release:
5566   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5569     {
5570       outBitC (result);
5571     }
5572   else
5573     {
5574       /* if the result is used in the next
5575          ifx conditional branch then generate
5576          code a little differently */
5577       if (ifx)
5578         genIfxJump (ifx, "c", NULL, NULL, result);
5579       else
5580         outBitC (result);
5581       /* leave the result in acc */
5582     }
5583 }
5584
5585 /*-----------------------------------------------------------------*/
5586 /* genCmpGt :- greater than comparison                             */
5587 /*-----------------------------------------------------------------*/
5588 static void
5589 genCmpGt (iCode * ic, iCode * ifx)
5590 {
5591   operand *left, *right, *result;
5592   sym_link *letype, *retype;
5593   int sign;
5594
5595   D(emitcode (";     genCmpGt",""));
5596
5597   left = IC_LEFT (ic);
5598   right = IC_RIGHT (ic);
5599   result = IC_RESULT (ic);
5600
5601   letype = getSpec (operandType (left));
5602   retype = getSpec (operandType (right));
5603   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5604            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5605   /* assign the amsops */
5606   aopOp (left, ic, FALSE);
5607   aopOp (right, ic, FALSE);
5608   aopOp (result, ic, TRUE);
5609
5610   genCmp (right, left, result, ifx, sign, ic);
5611
5612   freeAsmop (result, NULL, ic, TRUE);
5613 }
5614
5615 /*-----------------------------------------------------------------*/
5616 /* genCmpLt - less than comparisons                                */
5617 /*-----------------------------------------------------------------*/
5618 static void
5619 genCmpLt (iCode * ic, iCode * ifx)
5620 {
5621   operand *left, *right, *result;
5622   sym_link *letype, *retype;
5623   int sign;
5624
5625   D(emitcode (";     genCmpLt",""));
5626
5627   left = IC_LEFT (ic);
5628   right = IC_RIGHT (ic);
5629   result = IC_RESULT (ic);
5630
5631   letype = getSpec (operandType (left));
5632   retype = getSpec (operandType (right));
5633   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5634            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5635   /* assign the amsops */
5636   aopOp (left, ic, FALSE);
5637   aopOp (right, ic, FALSE);
5638   aopOp (result, ic, TRUE);
5639
5640   genCmp (left, right, result, ifx, sign, ic);
5641
5642   freeAsmop (result, NULL, ic, TRUE);
5643 }
5644
5645 /*-----------------------------------------------------------------*/
5646 /* gencjneshort - compare and jump if not equal                    */
5647 /*-----------------------------------------------------------------*/
5648 static void
5649 gencjneshort (operand * left, operand * right, symbol * lbl)
5650 {
5651   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5652   int offset = 0;
5653   unsigned long lit = 0L;
5654
5655   /* if the left side is a literal or
5656      if the right is in a pointer register and left
5657      is not */
5658   if ((AOP_TYPE (left) == AOP_LIT) ||
5659       (AOP_TYPE (left) == AOP_IMMD) ||
5660       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5661     {
5662       operand *t = right;
5663       right = left;
5664       left = t;
5665     }
5666
5667   if (AOP_TYPE (right) == AOP_LIT)
5668     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5669
5670   /* if the right side is a literal then anything goes */
5671   if (AOP_TYPE (right) == AOP_LIT &&
5672       AOP_TYPE (left) != AOP_DIR  &&
5673       AOP_TYPE (left) != AOP_IMMD)
5674     {
5675       while (size--)
5676         {
5677           emitcode ("cjne", "%s,%s,%05d$",
5678                     aopGet (left, offset, FALSE, FALSE),
5679                     aopGet (right, offset, FALSE, FALSE),
5680                     lbl->key + 100);
5681           offset++;
5682         }
5683     }
5684
5685   /* if the right side is in a register or in direct space or
5686      if the left is a pointer register & right is not */
5687   else if (AOP_TYPE (right) == AOP_REG ||
5688            AOP_TYPE (right) == AOP_DIR ||
5689            AOP_TYPE (right) == AOP_LIT ||
5690            AOP_TYPE (right) == AOP_IMMD ||
5691            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5692            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5693     {
5694       while (size--)
5695         {
5696           MOVA (aopGet (left, offset, FALSE, FALSE));
5697           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5698               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5699             emitcode ("jnz", "%05d$", lbl->key + 100);
5700           else
5701             emitcode ("cjne", "a,%s,%05d$",
5702                       aopGet (right, offset, FALSE, TRUE),
5703                       lbl->key + 100);
5704           offset++;
5705         }
5706     }
5707   else
5708     {
5709       /* right is a pointer reg need both a & b */
5710       while (size--)
5711         {
5712           char *l;
5713           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5714           wassertl(!BINUSE, "B was in use");
5715           l = aopGet (left, offset, FALSE, FALSE);
5716           if (strcmp (l, "b"))
5717             emitcode ("mov", "b,%s", l);
5718           MOVA (aopGet (right, offset, FALSE, FALSE));
5719           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5720           offset++;
5721         }
5722     }
5723 }
5724
5725 /*-----------------------------------------------------------------*/
5726 /* gencjne - compare and jump if not equal                         */
5727 /*-----------------------------------------------------------------*/
5728 static void
5729 gencjne (operand * left, operand * right, symbol * lbl)
5730 {
5731   symbol *tlbl = newiTempLabel (NULL);
5732
5733   gencjneshort (left, right, lbl);
5734
5735   emitcode ("mov", "a,%s", one);
5736   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5737   emitcode ("", "%05d$:", lbl->key + 100);
5738   emitcode ("clr", "a");
5739   emitcode ("", "%05d$:", tlbl->key + 100);
5740 }
5741
5742 /*-----------------------------------------------------------------*/
5743 /* genCmpEq - generates code for equal to                          */
5744 /*-----------------------------------------------------------------*/
5745 static void
5746 genCmpEq (iCode * ic, iCode * ifx)
5747 {
5748   operand *left, *right, *result;
5749
5750   D(emitcode (";     genCmpEq",""));
5751
5752   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5753   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5754   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5755
5756   /* if literal, literal on the right or
5757      if the right is in a pointer register and left
5758      is not */
5759   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5760       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5761     {
5762       operand *t = IC_RIGHT (ic);
5763       IC_RIGHT (ic) = IC_LEFT (ic);
5764       IC_LEFT (ic) = t;
5765     }
5766
5767   if (ifx && !AOP_SIZE (result))
5768     {
5769       symbol *tlbl;
5770       /* if they are both bit variables */
5771       if (AOP_TYPE (left) == AOP_CRY &&
5772           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5773         {
5774           if (AOP_TYPE (right) == AOP_LIT)
5775             {
5776               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5777               if (lit == 0L)
5778                 {
5779                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5780                   emitcode ("cpl", "c");
5781                 }
5782               else if (lit == 1L)
5783                 {
5784                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5785                 }
5786               else
5787                 {
5788                   emitcode ("clr", "c");
5789                 }
5790               /* AOP_TYPE(right) == AOP_CRY */
5791             }
5792           else
5793             {
5794               symbol *lbl = newiTempLabel (NULL);
5795               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5796               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5797               emitcode ("cpl", "c");
5798               emitcode ("", "%05d$:", (lbl->key + 100));
5799             }
5800           /* if true label then we jump if condition
5801              supplied is true */
5802           tlbl = newiTempLabel (NULL);
5803           if (IC_TRUE (ifx))
5804             {
5805               emitcode ("jnc", "%05d$", tlbl->key + 100);
5806               freeForBranchAsmop (result);
5807               freeForBranchAsmop (right);
5808               freeForBranchAsmop (left);
5809               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5810             }
5811           else
5812             {
5813               emitcode ("jc", "%05d$", tlbl->key + 100);
5814               freeForBranchAsmop (result);
5815               freeForBranchAsmop (right);
5816               freeForBranchAsmop (left);
5817               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5818             }
5819           emitcode ("", "%05d$:", tlbl->key + 100);
5820         }
5821       else
5822         {
5823           tlbl = newiTempLabel (NULL);
5824           gencjneshort (left, right, tlbl);
5825           if (IC_TRUE (ifx))
5826             {
5827               freeForBranchAsmop (result);
5828               freeForBranchAsmop (right);
5829               freeForBranchAsmop (left);
5830               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5831               emitcode ("", "%05d$:", tlbl->key + 100);
5832             }
5833           else
5834             {
5835               symbol *lbl = newiTempLabel (NULL);
5836               emitcode ("sjmp", "%05d$", lbl->key + 100);
5837               emitcode ("", "%05d$:", tlbl->key + 100);
5838               freeForBranchAsmop (result);
5839               freeForBranchAsmop (right);
5840               freeForBranchAsmop (left);
5841               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5842               emitcode ("", "%05d$:", lbl->key + 100);
5843             }
5844         }
5845       /* mark the icode as generated */
5846       ifx->generated = 1;
5847       goto release;
5848     }
5849
5850   /* if they are both bit variables */
5851   if (AOP_TYPE (left) == AOP_CRY &&
5852       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5853     {
5854       if (AOP_TYPE (right) == AOP_LIT)
5855         {
5856           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5857           if (lit == 0L)
5858             {
5859               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5860               emitcode ("cpl", "c");
5861             }
5862           else if (lit == 1L)
5863             {
5864               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5865             }
5866           else
5867             {
5868               emitcode ("clr", "c");
5869             }
5870           /* AOP_TYPE(right) == AOP_CRY */
5871         }
5872       else
5873         {
5874           symbol *lbl = newiTempLabel (NULL);
5875           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5876           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5877           emitcode ("cpl", "c");
5878           emitcode ("", "%05d$:", (lbl->key + 100));
5879         }
5880       /* c = 1 if egal */
5881       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5882         {
5883           outBitC (result);
5884           goto release;
5885         }
5886       if (ifx)
5887         {
5888           genIfxJump (ifx, "c", left, right, result);
5889           goto release;
5890         }
5891       /* if the result is used in an arithmetic operation
5892          then put the result in place */
5893       outBitC (result);
5894     }
5895   else
5896     {
5897       gencjne (left, right, newiTempLabel (NULL));
5898       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5899         {
5900           aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5901           goto release;
5902         }
5903       if (ifx)
5904         {
5905           genIfxJump (ifx, "a", left, right, result);
5906           goto release;
5907         }
5908       /* if the result is used in an arithmetic operation
5909          then put the result in place */
5910       if (AOP_TYPE (result) != AOP_CRY)
5911         outAcc (result);
5912       /* leave the result in acc */
5913     }
5914
5915 release:
5916   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5917   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5918   freeAsmop (result, NULL, ic, TRUE);
5919 }
5920
5921 /*-----------------------------------------------------------------*/
5922 /* ifxForOp - returns the icode containing the ifx for operand     */
5923 /*-----------------------------------------------------------------*/
5924 static iCode *
5925 ifxForOp (operand * op, iCode * ic)
5926 {
5927   /* if true symbol then needs to be assigned */
5928   if (IS_TRUE_SYMOP (op))
5929     return NULL;
5930
5931   /* if this has register type condition and
5932      the next instruction is ifx with the same operand
5933      and live to of the operand is upto the ifx only then */
5934   if (ic->next &&
5935       ic->next->op == IFX &&
5936       IC_COND (ic->next)->key == op->key &&
5937       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5938     return ic->next;
5939
5940   return NULL;
5941 }
5942
5943 /*-----------------------------------------------------------------*/
5944 /* hasInc - operand is incremented before any other use            */
5945 /*-----------------------------------------------------------------*/
5946 static iCode *
5947 hasInc (operand *op, iCode *ic,int osize)
5948 {
5949   sym_link *type = operandType(op);
5950   sym_link *retype = getSpec (type);
5951   iCode *lic = ic->next;
5952   int isize ;
5953
5954   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5955   if (!IS_SYMOP(op)) return NULL;
5956
5957   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5958   if (IS_AGGREGATE(type->next)) return NULL;
5959   if (osize != (isize = getSize(type->next))) return NULL;
5960
5961   while (lic) {
5962     /* if operand of the form op = op + <sizeof *op> */
5963     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5964         isOperandEqual(IC_RESULT(lic),op) &&
5965         isOperandLiteral(IC_RIGHT(lic)) &&
5966         operandLitValue(IC_RIGHT(lic)) == isize) {
5967       return lic;
5968     }
5969     /* if the operand used or deffed */
5970     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5971       return NULL;
5972     }
5973     /* if GOTO or IFX */
5974     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5975     lic = lic->next;
5976   }
5977   return NULL;
5978 }
5979
5980 /*-----------------------------------------------------------------*/
5981 /* genAndOp - for && operation                                     */
5982 /*-----------------------------------------------------------------*/
5983 static void
5984 genAndOp (iCode * ic)
5985 {
5986   operand *left, *right, *result;
5987   symbol *tlbl;
5988
5989   D(emitcode (";     genAndOp",""));
5990
5991   /* note here that && operations that are in an
5992      if statement are taken away by backPatchLabels
5993      only those used in arthmetic operations remain */
5994   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5995   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5996   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5997
5998   /* if both are bit variables */
5999   if (AOP_TYPE (left) == AOP_CRY &&
6000       AOP_TYPE (right) == AOP_CRY)
6001     {
6002       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6003       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6004       outBitC (result);
6005     }
6006   else
6007     {
6008       tlbl = newiTempLabel (NULL);
6009       toBoolean (left);
6010       emitcode ("jz", "%05d$", tlbl->key + 100);
6011       toBoolean (right);
6012       emitcode ("", "%05d$:", tlbl->key + 100);
6013       outBitAcc (result);
6014     }
6015
6016   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6018   freeAsmop (result, NULL, ic, TRUE);
6019 }
6020
6021
6022 /*-----------------------------------------------------------------*/
6023 /* genOrOp - for || operation                                      */
6024 /*-----------------------------------------------------------------*/
6025 static void
6026 genOrOp (iCode * ic)
6027 {
6028   operand *left, *right, *result;
6029   symbol *tlbl;
6030
6031   D(emitcode (";     genOrOp",""));
6032
6033   /* note here that || operations that are in an
6034      if statement are taken away by backPatchLabels
6035      only those used in arthmetic operations remain */
6036   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6037   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6038   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6039
6040   /* if both are bit variables */
6041   if (AOP_TYPE (left) == AOP_CRY &&
6042       AOP_TYPE (right) == AOP_CRY)
6043     {
6044       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6045       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6046       outBitC (result);
6047     }
6048   else
6049     {
6050       tlbl = newiTempLabel (NULL);
6051       toBoolean (left);
6052       emitcode ("jnz", "%05d$", tlbl->key + 100);
6053       toBoolean (right);
6054       emitcode ("", "%05d$:", tlbl->key + 100);
6055       outBitAcc (result);
6056     }
6057
6058   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6059   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6060   freeAsmop (result, NULL, ic, TRUE);
6061 }
6062
6063 /*-----------------------------------------------------------------*/
6064 /* isLiteralBit - test if lit == 2^n                               */
6065 /*-----------------------------------------------------------------*/
6066 static int
6067 isLiteralBit (unsigned long lit)
6068 {
6069   unsigned long pw[32] =
6070   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6071    0x100L, 0x200L, 0x400L, 0x800L,
6072    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6073    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6074    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6075    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6076    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6077   int idx;
6078
6079   for (idx = 0; idx < 32; idx++)
6080     if (lit == pw[idx])
6081       return idx + 1;
6082   return 0;
6083 }
6084
6085 /*-----------------------------------------------------------------*/
6086 /* continueIfTrue -                                                */
6087 /*-----------------------------------------------------------------*/
6088 static void
6089 continueIfTrue (iCode * ic)
6090 {
6091   if (IC_TRUE (ic))
6092     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6093   ic->generated = 1;
6094 }
6095
6096 /*-----------------------------------------------------------------*/
6097 /* jmpIfTrue -                                                     */
6098 /*-----------------------------------------------------------------*/
6099 static void
6100 jumpIfTrue (iCode * ic)
6101 {
6102   if (!IC_TRUE (ic))
6103     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6104   ic->generated = 1;
6105 }
6106
6107 /*-----------------------------------------------------------------*/
6108 /* jmpTrueOrFalse -                                                */
6109 /*-----------------------------------------------------------------*/
6110 static void
6111 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6112 {
6113   // ugly but optimized by peephole
6114   if (IC_TRUE (ic))
6115     {
6116       symbol *nlbl = newiTempLabel (NULL);
6117       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6118       emitcode ("", "%05d$:", tlbl->key + 100);
6119       freeForBranchAsmop (result);
6120       freeForBranchAsmop (right);
6121       freeForBranchAsmop (left);
6122       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6123       emitcode ("", "%05d$:", nlbl->key + 100);
6124     }
6125   else
6126     {
6127       freeForBranchAsmop (result);
6128       freeForBranchAsmop (right);
6129       freeForBranchAsmop (left);
6130       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6131       emitcode ("", "%05d$:", tlbl->key + 100);
6132     }
6133   ic->generated = 1;
6134 }
6135
6136 /*-----------------------------------------------------------------*/
6137 /* genAnd  - code for and                                          */
6138 /*-----------------------------------------------------------------*/
6139 static void
6140 genAnd (iCode * ic, iCode * ifx)
6141 {
6142   operand *left, *right, *result;
6143   int size, offset = 0;
6144   unsigned long lit = 0L;
6145   int bytelit = 0;
6146   char buffer[10];
6147
6148   D(emitcode (";     genAnd",""));
6149
6150   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6151   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6152   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6153
6154 #ifdef DEBUG_TYPE
6155   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6156             AOP_TYPE (result),
6157             AOP_TYPE (left), AOP_TYPE (right));
6158   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6159             AOP_SIZE (result),
6160             AOP_SIZE (left), AOP_SIZE (right));
6161 #endif
6162
6163   /* if left is a literal & right is not then exchange them */
6164   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6165       AOP_NEEDSACC (left))
6166     {
6167       operand *tmp = right;
6168       right = left;
6169       left = tmp;
6170     }
6171
6172   /* if result = right then exchange left and right */
6173   if (sameRegs (AOP (result), AOP (right)))
6174     {
6175       operand *tmp = right;
6176       right = left;
6177       left = tmp;
6178     }
6179
6180   /* if right is bit then exchange them */
6181   if (AOP_TYPE (right) == AOP_CRY &&
6182       AOP_TYPE (left) != AOP_CRY)
6183     {
6184       operand *tmp = right;
6185       right = left;
6186       left = tmp;
6187     }
6188   if (AOP_TYPE (right) == AOP_LIT)
6189     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6190
6191   size = AOP_SIZE (result);
6192
6193   // if(bit & yy)
6194   // result = bit & yy;
6195   if (AOP_TYPE (left) == AOP_CRY)
6196     {
6197       // c = bit & literal;
6198       if (AOP_TYPE (right) == AOP_LIT)
6199         {
6200           if (lit & 1)
6201             {
6202               if (size && sameRegs (AOP (result), AOP (left)))
6203                 // no change
6204                 goto release;
6205               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6206             }
6207           else
6208             {
6209               // bit(result) = 0;
6210               if (size && (AOP_TYPE (result) == AOP_CRY))
6211                 {
6212                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6213                   goto release;
6214                 }
6215               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6216                 {
6217                   jumpIfTrue (ifx);
6218                   goto release;
6219                 }
6220               emitcode ("clr", "c");
6221             }
6222         }
6223       else
6224         {
6225           if (AOP_TYPE (right) == AOP_CRY)
6226             {
6227               // c = bit & bit;
6228               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6229               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6230             }
6231           else
6232             {
6233               // c = bit & val;
6234               MOVA (aopGet (right, 0, FALSE, FALSE));
6235               // c = lsb
6236               emitcode ("rrc", "a");
6237               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6238             }
6239         }
6240       // bit = c
6241       // val = c
6242       if (size)
6243         outBitC (result);
6244       // if(bit & ...)
6245       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6246         genIfxJump (ifx, "c", left, right, result);
6247       goto release;
6248     }
6249
6250   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6251   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6252   if ((AOP_TYPE (right) == AOP_LIT) &&
6253       (AOP_TYPE (result) == AOP_CRY) &&
6254       (AOP_TYPE (left) != AOP_CRY))
6255     {
6256       int posbit = isLiteralBit (lit);
6257       /* left &  2^n */
6258       if (posbit)
6259         {
6260           posbit--;
6261           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6262           // bit = left & 2^n
6263           if (size)
6264             {
6265               switch (posbit & 0x07)
6266                 {
6267                   case 0: emitcode ("rrc", "a");
6268                           break;
6269                   case 7: emitcode ("rlc", "a");
6270                           break;
6271                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6272                           break;
6273                 }
6274             }
6275           // if(left &  2^n)
6276           else
6277             {
6278               if (ifx)
6279                 {
6280                   SNPRINTF (buffer, sizeof(buffer),
6281                             "acc.%d", posbit & 0x07);
6282                   genIfxJump (ifx, buffer, left, right, result);
6283                 }
6284               else
6285                 {// what is this case? just found it in ds390/gen.c
6286                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6287                 }
6288               goto release;
6289             }
6290         }
6291       else
6292         {
6293           symbol *tlbl = newiTempLabel (NULL);
6294           int sizel = AOP_SIZE (left);
6295           if (size)
6296             emitcode ("setb", "c");
6297           while (sizel--)
6298             {
6299               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6300                 {
6301                   MOVA (aopGet (left, offset, FALSE, FALSE));
6302                   // byte ==  2^n ?
6303                   if ((posbit = isLiteralBit (bytelit)) != 0)
6304                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6305                   else
6306                     {
6307                       if (bytelit != 0x0FFL)
6308                         emitcode ("anl", "a,%s",
6309                                   aopGet (right, offset, FALSE, TRUE));
6310                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6311                     }
6312                 }
6313               offset++;
6314             }
6315           // bit = left & literal
6316           if (size)
6317             {
6318               emitcode ("clr", "c");
6319               emitcode ("", "%05d$:", tlbl->key + 100);
6320             }
6321           // if(left & literal)
6322           else
6323             {
6324               if (ifx)
6325                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6326               else
6327                 emitcode ("", "%05d$:", tlbl->key + 100);
6328               goto release;
6329             }
6330         }
6331       outBitC (result);
6332       goto release;
6333     }
6334
6335   /* if left is same as result */
6336   if (sameRegs (AOP (result), AOP (left)))
6337     {
6338       for (; size--; offset++)
6339         {
6340           if (AOP_TYPE (right) == AOP_LIT)
6341             {
6342               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6343               if (bytelit == 0x0FF)
6344                 {
6345                   /* dummy read of volatile operand */
6346                   if (isOperandVolatile (left, FALSE))
6347                     MOVA (aopGet (left, offset, FALSE, FALSE));
6348                   else
6349                     continue;
6350                 }
6351               else if (bytelit == 0)
6352                 {
6353                   aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6354                 }
6355               else if (IS_AOP_PREG (result))
6356                 {
6357                   MOVA (aopGet (left, offset, FALSE, TRUE));
6358                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6359                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6360                 }
6361               else
6362                 emitcode ("anl", "%s,%s",
6363                           aopGet (left, offset, FALSE, TRUE),
6364                           aopGet (right, offset, FALSE, FALSE));
6365             }
6366           else
6367             {
6368               if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6369                 {
6370                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6371                 }
6372               else
6373                 {
6374                   MOVA (aopGet (right, offset, FALSE, FALSE));
6375                   if (IS_AOP_PREG (result))
6376                     {
6377                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6378                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6379                     }
6380                   else
6381                     emitcode ("anl", "%s,a",
6382                               aopGet (left, offset, FALSE, TRUE));
6383                 }
6384             }
6385         }
6386     }
6387   else
6388     {
6389       // left & result in different registers
6390       if (AOP_TYPE (result) == AOP_CRY)
6391         {
6392           // result = bit
6393           // if(size), result in bit
6394           // if(!size && ifx), conditional oper: if(left & right)
6395           symbol *tlbl = newiTempLabel (NULL);
6396           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6397           if (size)
6398             emitcode ("setb", "c");
6399           while (sizer--)
6400             {
6401               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6402                   && AOP_TYPE(left)==AOP_ACC)
6403                 {
6404                   if (offset)
6405                     emitcode("mov", "a,b");
6406                   emitcode ("anl", "a,%s",
6407                             aopGet (right, offset, FALSE, FALSE));
6408                 } else {
6409                   if (AOP_TYPE(left)==AOP_ACC)
6410                     {
6411                       if (!offset)
6412                         {
6413                           bool pushedB = pushB ();
6414                           emitcode("mov", "b,a");
6415                           MOVA (aopGet (right, offset, FALSE, FALSE));
6416                           emitcode("anl", "a,b");
6417                           popB (pushedB);
6418                         }
6419                       else
6420                         {
6421                           MOVA (aopGet (right, offset, FALSE, FALSE));
6422                           emitcode("anl", "a,b");
6423                         }
6424                     } else {
6425                       MOVA (aopGet (right, offset, FALSE, FALSE));
6426                       emitcode ("anl", "a,%s",
6427                                 aopGet (left, offset, FALSE, FALSE));
6428                     }
6429                 }
6430               emitcode ("jnz", "%05d$", tlbl->key + 100);
6431               offset++;
6432             }
6433           if (size)
6434             {
6435               CLRC;
6436               emitcode ("", "%05d$:", tlbl->key + 100);
6437               outBitC (result);
6438             }
6439           else if (ifx)
6440             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6441           else
6442             emitcode ("", "%05d$:", tlbl->key + 100);
6443         }
6444       else
6445         {
6446           for (; (size--); offset++)
6447             {
6448               // normal case
6449               // result = left & right
6450               if (AOP_TYPE (right) == AOP_LIT)
6451                 {
6452                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6453                   if (bytelit == 0x0FF)
6454                     {
6455                       aopPut (result,
6456                               aopGet (left, offset, FALSE, FALSE),
6457                               offset,
6458                               isOperandVolatile (result, FALSE));
6459                       continue;
6460                     }
6461                   else if (bytelit == 0)
6462                     {
6463                       /* dummy read of volatile operand */
6464                       if (isOperandVolatile (left, FALSE))
6465                         MOVA (aopGet (left, offset, FALSE, FALSE));
6466                       aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6467                       continue;
6468                     }
6469                   else if (AOP_TYPE (left) == AOP_ACC)
6470                     {
6471                       if (!offset)
6472                         {
6473                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6474                           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6475                           continue;
6476                         }
6477                       else
6478                         {
6479                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6480                           aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6481                           continue;
6482                         }
6483                     }
6484                 }
6485               // faster than result <- left, anl result,right
6486               // and better if result is SFR
6487               if (AOP_TYPE (left) == AOP_ACC)
6488                 {
6489                   if (offset)
6490                     emitcode("mov", "a,b");
6491                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6492                 }
6493               else
6494                 {
6495                   MOVA (aopGet (right, offset, FALSE, FALSE));
6496                   emitcode ("anl", "a,%s",
6497                             aopGet (left, offset, FALSE, FALSE));
6498                 }
6499               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6500             }
6501         }
6502     }
6503
6504 release:
6505   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6506   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6507   freeAsmop (result, NULL, ic, TRUE);
6508 }
6509
6510 /*-----------------------------------------------------------------*/
6511 /* genOr  - code for or                                            */
6512 /*-----------------------------------------------------------------*/
6513 static void
6514 genOr (iCode * ic, iCode * ifx)
6515 {
6516   operand *left, *right, *result;
6517   int size, offset = 0;
6518   unsigned long lit = 0L;
6519   int bytelit = 0;
6520
6521   D(emitcode (";     genOr",""));
6522
6523   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6524   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6525   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6526
6527 #ifdef DEBUG_TYPE
6528   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6529             AOP_TYPE (result),
6530             AOP_TYPE (left), AOP_TYPE (right));
6531   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6532             AOP_SIZE (result),
6533             AOP_SIZE (left), AOP_SIZE (right));
6534 #endif
6535
6536   /* if left is a literal & right is not then exchange them */
6537   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6538       AOP_NEEDSACC (left))
6539     {
6540       operand *tmp = right;
6541       right = left;
6542       left = tmp;
6543     }
6544
6545   /* if result = right then exchange them */
6546   if (sameRegs (AOP (result), AOP (right)))
6547     {
6548       operand *tmp = right;
6549       right = left;
6550       left = tmp;
6551     }
6552
6553   /* if right is bit then exchange them */
6554   if (AOP_TYPE (right) == AOP_CRY &&
6555       AOP_TYPE (left) != AOP_CRY)
6556     {
6557       operand *tmp = right;
6558       right = left;
6559       left = tmp;
6560     }
6561   if (AOP_TYPE (right) == AOP_LIT)
6562     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6563
6564   size = AOP_SIZE (result);
6565
6566   // if(bit | yy)
6567   // xx = bit | yy;
6568   if (AOP_TYPE (left) == AOP_CRY)
6569     {
6570       if (AOP_TYPE (right) == AOP_LIT)
6571         {
6572           // c = bit | literal;
6573           if (lit)
6574             {
6575               // lit != 0 => result = 1
6576               if (AOP_TYPE (result) == AOP_CRY)
6577                 {
6578                   if (size)
6579                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6580                   else if (ifx)
6581                     continueIfTrue (ifx);
6582                   goto release;
6583                 }
6584               emitcode ("setb", "c");
6585             }
6586           else
6587             {
6588               // lit == 0 => result = left
6589               if (size && sameRegs (AOP (result), AOP (left)))
6590                 goto release;
6591               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6592             }
6593         }
6594       else
6595         {
6596           if (AOP_TYPE (right) == AOP_CRY)
6597             {
6598               // c = bit | bit;
6599               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6600               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6601             }
6602           else
6603             {
6604               // c = bit | val;
6605               symbol *tlbl = newiTempLabel (NULL);
6606               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6607                 emitcode ("setb", "c");
6608               emitcode ("jb", "%s,%05d$",
6609                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6610               toBoolean (right);
6611               emitcode ("jnz", "%05d$", tlbl->key + 100);
6612               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6613                 {
6614                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6615                   goto release;
6616                 }
6617               else
6618                 {
6619                   CLRC;
6620                   emitcode ("", "%05d$:", tlbl->key + 100);
6621                 }
6622             }
6623         }
6624       // bit = c
6625       // val = c
6626       if (size)
6627         outBitC (result);
6628       // if(bit | ...)
6629       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6630         genIfxJump (ifx, "c", left, right, result);
6631       goto release;
6632     }
6633
6634   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6635   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6636   if ((AOP_TYPE (right) == AOP_LIT) &&
6637       (AOP_TYPE (result) == AOP_CRY) &&
6638       (AOP_TYPE (left) != AOP_CRY))
6639     {
6640       if (lit)
6641         {
6642           // result = 1
6643           if (size)
6644             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6645           else
6646             continueIfTrue (ifx);
6647           goto release;
6648         }
6649       else
6650         {
6651           // lit = 0, result = boolean(left)
6652           if (size)
6653             emitcode ("setb", "c");
6654           toBoolean (right);
6655           if (size)
6656             {
6657               symbol *tlbl = newiTempLabel (NULL);
6658               emitcode ("jnz", "%05d$", tlbl->key + 100);
6659               CLRC;
6660               emitcode ("", "%05d$:", tlbl->key + 100);
6661             }
6662           else
6663             {
6664               genIfxJump (ifx, "a", left, right, result);
6665               goto release;
6666             }
6667         }
6668       outBitC (result);
6669       goto release;
6670     }
6671
6672   /* if left is same as result */
6673   if (sameRegs (AOP (result), AOP (left)))
6674     {
6675       for (; size--; offset++)
6676         {
6677           if (AOP_TYPE (right) == AOP_LIT)
6678             {
6679               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6680               if (bytelit == 0)
6681                 {
6682                   /* dummy read of volatile operand */
6683                   if (isOperandVolatile (left, FALSE))
6684                     MOVA (aopGet (left, offset, FALSE, FALSE));
6685                   else
6686                     continue;
6687                 }
6688               else if (bytelit == 0x0FF)
6689                 {
6690                   aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6691                 }
6692               else if (IS_AOP_PREG (left))
6693                 {
6694                   MOVA (aopGet (left, offset, FALSE, TRUE));
6695                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6696                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6697                 }
6698               else
6699                 {
6700                   emitcode ("orl", "%s,%s",
6701                             aopGet (left, offset, FALSE, TRUE),
6702                             aopGet (right, offset, FALSE, FALSE));
6703                 }
6704             }
6705           else
6706             {
6707               if (AOP_TYPE (left) == AOP_ACC)
6708                 {
6709                   if (offset)
6710                     emitcode("mov", "a,b");
6711                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6712                 }
6713               else
6714                 {
6715                   MOVA (aopGet (right, offset, FALSE, FALSE));
6716                   if (IS_AOP_PREG (left))
6717                     {
6718                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6719                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6720                     }
6721                   else
6722                     {
6723                       emitcode ("orl", "%s,a",
6724                                 aopGet (left, offset, FALSE, TRUE));
6725                     }
6726                 }
6727             }
6728         }
6729     }
6730   else
6731     {
6732       // left & result in different registers
6733       if (AOP_TYPE (result) == AOP_CRY)
6734         {
6735           // result = bit
6736           // if(size), result in bit
6737           // if(!size && ifx), conditional oper: if(left | right)
6738           symbol *tlbl = newiTempLabel (NULL);
6739           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6740           if (size)
6741             emitcode ("setb", "c");
6742           while (sizer--)
6743             {
6744               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6745                 if (offset)
6746                   emitcode("mov", "a,b");
6747                 emitcode ("orl", "a,%s",
6748                           aopGet (right, offset, FALSE, FALSE));
6749               } else {
6750                 MOVA (aopGet (right, offset, FALSE, FALSE));
6751                 emitcode ("orl", "a,%s",
6752                           aopGet (left, offset, FALSE, FALSE));
6753               }
6754               emitcode ("jnz", "%05d$", tlbl->key + 100);
6755               offset++;
6756             }
6757           if (size)
6758             {
6759               CLRC;
6760               emitcode ("", "%05d$:", tlbl->key + 100);
6761               outBitC (result);
6762             }
6763           else if (ifx)
6764             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6765           else
6766             emitcode ("", "%05d$:", tlbl->key + 100);
6767         }
6768       else
6769         {
6770           for (; (size--); offset++)
6771             {
6772               // normal case
6773               // result = left | right
6774               if (AOP_TYPE (right) == AOP_LIT)
6775                 {
6776                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6777                   if (bytelit == 0)
6778                     {
6779                       aopPut (result,
6780                               aopGet (left, offset, FALSE, FALSE),
6781                               offset,
6782                               isOperandVolatile (result, FALSE));
6783                       continue;
6784                     }
6785                   else if (bytelit == 0x0FF)
6786                     {
6787                       /* dummy read of volatile operand */
6788                       if (isOperandVolatile (left, FALSE))
6789                         MOVA (aopGet (left, offset, FALSE, FALSE));
6790                       aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6791                       continue;
6792                     }
6793                 }
6794               // faster than result <- left, anl result,right
6795               // and better if result is SFR
6796               if (AOP_TYPE (left) == AOP_ACC)
6797                 {
6798                   if (offset)
6799                     emitcode("mov", "a,b");
6800                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6801                 }
6802               else
6803                 {
6804                   MOVA (aopGet (right, offset, FALSE, FALSE));
6805                   emitcode ("orl", "a,%s",
6806                             aopGet (left, offset, FALSE, FALSE));
6807                 }
6808               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6809             }
6810         }
6811     }
6812
6813 release:
6814   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6815   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6816   freeAsmop (result, NULL, ic, TRUE);
6817 }
6818
6819 /*-----------------------------------------------------------------*/
6820 /* genXor - code for xclusive or                                   */
6821 /*-----------------------------------------------------------------*/
6822 static void
6823 genXor (iCode * ic, iCode * ifx)
6824 {
6825   operand *left, *right, *result;
6826   int size, offset = 0;
6827   unsigned long lit = 0L;
6828   int bytelit = 0;
6829
6830   D(emitcode (";     genXor",""));
6831
6832   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6833   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6834   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6835
6836 #ifdef DEBUG_TYPE
6837   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6838             AOP_TYPE (result),
6839             AOP_TYPE (left), AOP_TYPE (right));
6840   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6841             AOP_SIZE (result),
6842             AOP_SIZE (left), AOP_SIZE (right));
6843 #endif
6844
6845   /* if left is a literal & right is not ||
6846      if left needs acc & right does not */
6847   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6848       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6849     {
6850       operand *tmp = right;
6851       right = left;
6852       left = tmp;
6853     }
6854
6855   /* if result = right then exchange them */
6856   if (sameRegs (AOP (result), AOP (right)))
6857     {
6858       operand *tmp = right;
6859       right = left;
6860       left = tmp;
6861     }
6862
6863   /* if right is bit then exchange them */
6864   if (AOP_TYPE (right) == AOP_CRY &&
6865       AOP_TYPE (left) != AOP_CRY)
6866     {
6867       operand *tmp = right;
6868       right = left;
6869       left = tmp;
6870     }
6871   if (AOP_TYPE (right) == AOP_LIT)
6872     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6873
6874   size = AOP_SIZE (result);
6875
6876   // if(bit ^ yy)
6877   // xx = bit ^ yy;
6878   if (AOP_TYPE (left) == AOP_CRY)
6879     {
6880       if (AOP_TYPE (right) == AOP_LIT)
6881         {
6882           // c = bit & literal;
6883           if (lit >> 1)
6884             {
6885               // lit>>1  != 0 => result = 1
6886               if (AOP_TYPE (result) == AOP_CRY)
6887                 {
6888                   if (size)
6889                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6890                   else if (ifx)
6891                     continueIfTrue (ifx);
6892                   goto release;
6893                 }
6894               emitcode ("setb", "c");
6895             }
6896           else
6897             {
6898               // lit == (0 or 1)
6899               if (lit == 0)
6900                 {
6901                   // lit == 0, result = left
6902                   if (size && sameRegs (AOP (result), AOP (left)))
6903                     goto release;
6904                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6905                 }
6906               else
6907                 {
6908                   // lit == 1, result = not(left)
6909                   if (size && sameRegs (AOP (result), AOP (left)))
6910                     {
6911                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6912                       goto release;
6913                     }
6914                   else
6915                     {
6916                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6917                       emitcode ("cpl", "c");
6918                     }
6919                 }
6920             }
6921
6922         }
6923       else
6924         {
6925           // right != literal
6926           symbol *tlbl = newiTempLabel (NULL);
6927           if (AOP_TYPE (right) == AOP_CRY)
6928             {
6929               // c = bit ^ bit;
6930               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6931             }
6932           else
6933             {
6934               int sizer = AOP_SIZE (right);
6935               // c = bit ^ val
6936               // if val>>1 != 0, result = 1
6937               emitcode ("setb", "c");
6938               while (sizer)
6939                 {
6940                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6941                   if (sizer == 1)
6942                     // test the msb of the lsb
6943                     emitcode ("anl", "a,#0xfe");
6944                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6945                   sizer--;
6946                 }
6947               // val = (0,1)
6948               emitcode ("rrc", "a");
6949             }
6950           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6951           emitcode ("cpl", "c");
6952           emitcode ("", "%05d$:", (tlbl->key + 100));
6953         }
6954       // bit = c
6955       // val = c
6956       if (size)
6957         outBitC (result);
6958       // if(bit | ...)
6959       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6960         genIfxJump (ifx, "c", left, right, result);
6961       goto release;
6962     }
6963
6964   /* if left is same as result */
6965   if (sameRegs (AOP (result), AOP (left)))
6966     {
6967       for (; size--; offset++)
6968         {
6969           if (AOP_TYPE (right) == AOP_LIT)
6970             {
6971               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6972               if (bytelit == 0)
6973                 {
6974                   /* dummy read of volatile operand */
6975                   if (isOperandVolatile (left, FALSE))
6976                     MOVA (aopGet (left, offset, FALSE, FALSE));
6977                   else
6978                     continue;
6979                 }
6980               else if (IS_AOP_PREG (left))
6981                 {
6982                   MOVA (aopGet (left, offset, FALSE, TRUE));
6983                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6984                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6985                 }
6986               else
6987                 {
6988                   emitcode ("xrl", "%s,%s",
6989                             aopGet (left, offset, FALSE, TRUE),
6990                             aopGet (right, offset, FALSE, FALSE));
6991                 }
6992             }
6993           else
6994             {
6995               if (AOP_TYPE (left) == AOP_ACC)
6996                 {
6997                   if (offset)
6998                     emitcode("mov", "a,b");
6999                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7000                 }
7001               else
7002                 {
7003                   MOVA (aopGet (right, offset, FALSE, FALSE));
7004                   if (IS_AOP_PREG (left))
7005                     {
7006                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7007                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7008                     }
7009                   else
7010                     emitcode ("xrl", "%s,a",
7011                               aopGet (left, offset, FALSE, TRUE));
7012                 }
7013             }
7014         }
7015     }
7016   else
7017     {
7018       // left & result in different registers
7019       if (AOP_TYPE (result) == AOP_CRY)
7020         {
7021           // result = bit
7022           // if(size), result in bit
7023           // if(!size && ifx), conditional oper: if(left ^ right)
7024           symbol *tlbl = newiTempLabel (NULL);
7025           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7026           if (size)
7027             emitcode ("setb", "c");
7028           while (sizer--)
7029             {
7030               if ((AOP_TYPE (right) == AOP_LIT) &&
7031                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7032                 {
7033                   MOVA (aopGet (left, offset, FALSE, FALSE));
7034                 }
7035               else
7036                 {
7037                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7038                     if (offset)
7039                       emitcode("mov", "a,b");
7040                     emitcode ("xrl", "a,%s",
7041                               aopGet (right, offset, FALSE, FALSE));
7042                   } else {
7043                     MOVA (aopGet (right, offset, FALSE, FALSE));
7044                     emitcode ("xrl", "a,%s",
7045                               aopGet (left, offset, FALSE, FALSE));
7046                   }
7047                 }
7048               emitcode ("jnz", "%05d$", tlbl->key + 100);
7049               offset++;
7050             }
7051           if (size)
7052             {
7053               CLRC;
7054               emitcode ("", "%05d$:", tlbl->key + 100);
7055               outBitC (result);
7056             }
7057           else if (ifx)
7058             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7059         }
7060       else
7061         {
7062           for (; (size--); offset++)
7063             {
7064               // normal case
7065               // result = left & right
7066               if (AOP_TYPE (right) == AOP_LIT)
7067                 {
7068                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7069                   if (bytelit == 0)
7070                     {
7071                       aopPut (result,
7072                               aopGet (left, offset, FALSE, FALSE),
7073                               offset,
7074                               isOperandVolatile (result, FALSE));
7075                       continue;
7076                     }
7077                 }
7078               // faster than result <- left, anl result,right
7079               // and better if result is SFR
7080               if (AOP_TYPE (left) == AOP_ACC)
7081                 {
7082                   if (offset)
7083                     emitcode("mov", "a,b");
7084                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7085                 }
7086               else
7087                 {
7088                   MOVA (aopGet (right, offset, FALSE, FALSE));
7089                   emitcode ("xrl", "a,%s",
7090                             aopGet (left, offset, FALSE, TRUE));
7091                 }
7092               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7093             }
7094         }
7095     }
7096
7097 release:
7098   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7099   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7100   freeAsmop (result, NULL, ic, TRUE);
7101 }
7102
7103 /*-----------------------------------------------------------------*/
7104 /* genInline - write the inline code out                           */
7105 /*-----------------------------------------------------------------*/
7106 static void
7107 genInline (iCode * ic)
7108 {
7109   char *buffer, *bp, *bp1;
7110
7111   D(emitcode (";     genInline",""));
7112
7113   _G.inLine += (!options.asmpeep);
7114
7115   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7116   strcpy (buffer, IC_INLINE (ic));
7117
7118   /* emit each line as a code */
7119   while (*bp)
7120     {
7121       if (*bp == '\n')
7122         {
7123           *bp++ = '\0';
7124           emitcode (bp1, "");
7125           bp1 = bp;
7126         }
7127       else
7128         {
7129           /* Add \n for labels, not dirs such as c:\mydir */
7130           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7131             {
7132               bp++;
7133               *bp = '\0';
7134               bp++;
7135               emitcode (bp1, "");
7136               bp1 = bp;
7137             }
7138           else
7139             bp++;
7140         }
7141     }
7142   if (bp1 != bp)
7143     emitcode (bp1, "");
7144   /*     emitcode("",buffer); */
7145   _G.inLine -= (!options.asmpeep);
7146 }
7147
7148 /*-----------------------------------------------------------------*/
7149 /* genRRC - rotate right with carry                                */
7150 /*-----------------------------------------------------------------*/
7151 static void
7152 genRRC (iCode * ic)
7153 {
7154   operand *left, *result;
7155   int size, offset = 0;
7156   char *l;
7157
7158   D(emitcode (";     genRRC",""));
7159
7160   /* rotate right with carry */
7161   left = IC_LEFT (ic);
7162   result = IC_RESULT (ic);
7163   aopOp (left, ic, FALSE);
7164   aopOp (result, ic, FALSE);
7165
7166   /* move it to the result */
7167   size = AOP_SIZE (result);
7168   offset = size - 1;
7169   if (size == 1) { /* special case for 1 byte */
7170       l = aopGet (left, offset, FALSE, FALSE);
7171       MOVA (l);
7172       emitcode ("rr", "a");
7173       goto release;
7174   }
7175   /* no need to clear carry, bit7 will be written later */
7176   while (size--)
7177     {
7178       l = aopGet (left, offset, FALSE, FALSE);
7179       MOVA (l);
7180       emitcode ("rrc", "a");
7181       if (AOP_SIZE (result) > 1)
7182         aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7183     }
7184   /* now we need to put the carry into the
7185      highest order byte of the result */
7186   if (AOP_SIZE (result) > 1)
7187     {
7188       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7189       MOVA (l);
7190     }
7191   emitcode ("mov", "acc.7,c");
7192  release:
7193   aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7194   freeAsmop (left, NULL, ic, TRUE);
7195   freeAsmop (result, NULL, ic, TRUE);
7196 }
7197
7198 /*-----------------------------------------------------------------*/
7199 /* genRLC - generate code for rotate left with carry               */
7200 /*-----------------------------------------------------------------*/
7201 static void
7202 genRLC (iCode * ic)
7203 {
7204   operand *left, *result;
7205   int size, offset = 0;
7206   char *l;
7207
7208   D(emitcode (";     genRLC",""));
7209
7210   /* rotate right with carry */
7211   left = IC_LEFT (ic);
7212   result = IC_RESULT (ic);
7213   aopOp (left, ic, FALSE);
7214   aopOp (result, ic, FALSE);
7215
7216   /* move it to the result */
7217   size = AOP_SIZE (result);
7218   offset = 0;
7219   if (size--)
7220     {
7221       l = aopGet (left, offset, FALSE, FALSE);
7222       MOVA (l);
7223       if (size == 0) { /* special case for 1 byte */
7224               emitcode("rl","a");
7225               goto release;
7226       }
7227       emitcode("rlc","a"); /* bit0 will be written later */
7228       if (AOP_SIZE (result) > 1)
7229         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7230       while (size--)
7231         {
7232           l = aopGet (left, offset, FALSE, FALSE);
7233           MOVA (l);
7234           emitcode ("rlc", "a");
7235           if (AOP_SIZE (result) > 1)
7236             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7237         }
7238     }
7239   /* now we need to put the carry into the
7240      highest order byte of the result */
7241   if (AOP_SIZE (result) > 1)
7242     {
7243       l = aopGet (result, 0, FALSE, FALSE);
7244       MOVA (l);
7245     }
7246   emitcode ("mov", "acc.0,c");
7247  release:
7248   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7249   freeAsmop (left, NULL, ic, TRUE);
7250   freeAsmop (result, NULL, ic, TRUE);
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* genGetHbit - generates code get highest order bit               */
7255 /*-----------------------------------------------------------------*/
7256 static void
7257 genGetHbit (iCode * ic)
7258 {
7259   operand *left, *result;
7260
7261   D(emitcode (";     genGetHbit",""));
7262
7263   left = IC_LEFT (ic);
7264   result = IC_RESULT (ic);
7265   aopOp (left, ic, FALSE);
7266   aopOp (result, ic, FALSE);
7267
7268   /* get the highest order byte into a */
7269   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7270   if (AOP_TYPE (result) == AOP_CRY)
7271     {
7272       emitcode ("rlc", "a");
7273       outBitC (result);
7274     }
7275   else
7276     {
7277       emitcode ("rl", "a");
7278       emitcode ("anl", "a,#0x01");
7279       outAcc (result);
7280     }
7281
7282
7283   freeAsmop (left, NULL, ic, TRUE);
7284   freeAsmop (result, NULL, ic, TRUE);
7285 }
7286
7287 /*-----------------------------------------------------------------*/
7288 /* genSwap - generates code to swap nibbles or bytes               */
7289 /*-----------------------------------------------------------------*/
7290 static void
7291 genSwap (iCode * ic)
7292 {
7293   operand *left, *result;
7294
7295   D(emitcode (";     genSwap",""));
7296
7297   left = IC_LEFT (ic);
7298   result = IC_RESULT (ic);
7299   aopOp (left, ic, FALSE);
7300   aopOp (result, ic, FALSE);
7301
7302   switch (AOP_SIZE (left))
7303     {
7304     case 1: /* swap nibbles in byte */
7305       MOVA (aopGet (left, 0, FALSE, FALSE));
7306       emitcode ("swap", "a");
7307       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7308       break;
7309     case 2: /* swap bytes in word */
7310       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7311         {
7312           MOVA (aopGet (left, 0, FALSE, FALSE));
7313           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7314                   0, isOperandVolatile (result, FALSE));
7315           aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7316         }
7317       else if (operandsEqu (left, result))
7318         {
7319           char * reg = "a";
7320           bool pushedB = FALSE, leftInB = FALSE;
7321
7322           MOVA (aopGet (left, 0, FALSE, FALSE));
7323           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7324             {
7325               pushedB = pushB ();
7326               emitcode ("mov", "b,a");
7327               reg = "b";
7328               leftInB = TRUE;
7329             }
7330           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7331                   0, isOperandVolatile (result, FALSE));
7332           aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7333
7334           if (leftInB)
7335             popB (pushedB);
7336         }
7337       else
7338         {
7339           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7340                   0, isOperandVolatile (result, FALSE));
7341           aopPut (result, aopGet (left, 0, FALSE, FALSE),
7342                   1, isOperandVolatile (result, FALSE));
7343         }
7344       break;
7345     default:
7346       wassertl(FALSE, "unsupported SWAP operand size");
7347     }
7348
7349   freeAsmop (left, NULL, ic, TRUE);
7350   freeAsmop (result, NULL, ic, TRUE);
7351 }
7352
7353
7354 /*-----------------------------------------------------------------*/
7355 /* AccRol - rotate left accumulator by known count                 */
7356 /*-----------------------------------------------------------------*/
7357 static void
7358 AccRol (int shCount)
7359 {
7360   shCount &= 0x0007;            // shCount : 0..7
7361
7362   switch (shCount)
7363     {
7364     case 0:
7365       break;
7366     case 1:
7367       emitcode ("rl", "a");
7368       break;
7369     case 2:
7370       emitcode ("rl", "a");
7371       emitcode ("rl", "a");
7372       break;
7373     case 3:
7374       emitcode ("swap", "a");
7375       emitcode ("rr", "a");
7376       break;
7377     case 4:
7378       emitcode ("swap", "a");
7379       break;
7380     case 5:
7381       emitcode ("swap", "a");
7382       emitcode ("rl", "a");
7383       break;
7384     case 6:
7385       emitcode ("rr", "a");
7386       emitcode ("rr", "a");
7387       break;
7388     case 7:
7389       emitcode ("rr", "a");
7390       break;
7391     }
7392 }
7393
7394 /*-----------------------------------------------------------------*/
7395 /* AccLsh - left shift accumulator by known count                  */
7396 /*-----------------------------------------------------------------*/
7397 static void
7398 AccLsh (int shCount)
7399 {
7400   if (shCount != 0)
7401     {
7402       if (shCount == 1)
7403         emitcode ("add", "a,acc");
7404       else if (shCount == 2)
7405         {
7406           emitcode ("add", "a,acc");
7407           emitcode ("add", "a,acc");
7408         }
7409       else
7410         {
7411           /* rotate left accumulator */
7412           AccRol (shCount);
7413           /* and kill the lower order bits */
7414           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7415         }
7416     }
7417 }
7418
7419 /*-----------------------------------------------------------------*/
7420 /* AccRsh - right shift accumulator by known count                 */
7421 /*-----------------------------------------------------------------*/
7422 static void
7423 AccRsh (int shCount)
7424 {
7425   if (shCount != 0)
7426     {
7427       if (shCount == 1)
7428         {
7429           CLRC;
7430           emitcode ("rrc", "a");
7431         }
7432       else
7433         {
7434           /* rotate right accumulator */
7435           AccRol (8 - shCount);
7436           /* and kill the higher order bits */
7437           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7438         }
7439     }
7440 }
7441
7442 /*-----------------------------------------------------------------*/
7443 /* AccSRsh - signed right shift accumulator by known count                 */
7444 /*-----------------------------------------------------------------*/
7445 static void
7446 AccSRsh (int shCount)
7447 {
7448   symbol *tlbl;
7449   if (shCount != 0)
7450     {
7451       if (shCount == 1)
7452         {
7453           emitcode ("mov", "c,acc.7");
7454           emitcode ("rrc", "a");
7455         }
7456       else if (shCount == 2)
7457         {
7458           emitcode ("mov", "c,acc.7");
7459           emitcode ("rrc", "a");
7460           emitcode ("mov", "c,acc.7");
7461           emitcode ("rrc", "a");
7462         }
7463       else
7464         {
7465           tlbl = newiTempLabel (NULL);
7466           /* rotate right accumulator */
7467           AccRol (8 - shCount);
7468           /* and kill the higher order bits */
7469           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7470           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7471           emitcode ("orl", "a,#0x%02x",
7472                     (unsigned char) ~SRMask[shCount]);
7473           emitcode ("", "%05d$:", tlbl->key + 100);
7474         }
7475     }
7476 }
7477
7478 /*-----------------------------------------------------------------*/
7479 /* shiftR1Left2Result - shift right one byte from left to result   */
7480 /*-----------------------------------------------------------------*/
7481 static void
7482 shiftR1Left2Result (operand * left, int offl,
7483                     operand * result, int offr,
7484                     int shCount, int sign)
7485 {
7486   MOVA (aopGet (left, offl, FALSE, FALSE));
7487   /* shift right accumulator */
7488   if (sign)
7489     AccSRsh (shCount);
7490   else
7491     AccRsh (shCount);
7492   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7493 }
7494
7495 /*-----------------------------------------------------------------*/
7496 /* shiftL1Left2Result - shift left one byte from left to result    */
7497 /*-----------------------------------------------------------------*/
7498 static void
7499 shiftL1Left2Result (operand * left, int offl,
7500                     operand * result, int offr, int shCount)
7501 {
7502   char *l;
7503   l = aopGet (left, offl, FALSE, FALSE);
7504   MOVA (l);
7505   /* shift left accumulator */
7506   AccLsh (shCount);
7507   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7508 }
7509
7510 /*-----------------------------------------------------------------*/
7511 /* movLeft2Result - move byte from left to result                  */
7512 /*-----------------------------------------------------------------*/
7513 static void
7514 movLeft2Result (operand * left, int offl,
7515                 operand * result, int offr, int sign)
7516 {
7517   char *l;
7518   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7519     {
7520       l = aopGet (left, offl, FALSE, FALSE);
7521
7522       if (*l == '@' && (IS_AOP_PREG (result)))
7523         {
7524           emitcode ("mov", "a,%s", l);
7525           aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7526         }
7527       else
7528         {
7529           if (!sign)
7530             aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7531           else
7532             {
7533               /* MSB sign in acc.7 ! */
7534               if (getDataSize (left) == offl + 1)
7535                 {
7536                   emitcode ("mov", "a,%s", l);
7537                   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7538                 }
7539             }
7540         }
7541     }
7542 }
7543
7544 /*-----------------------------------------------------------------*/
7545 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7546 /*-----------------------------------------------------------------*/
7547 static void
7548 AccAXRrl1 (char *x)
7549 {
7550   emitcode ("rrc", "a");
7551   emitcode ("xch", "a,%s", x);
7552   emitcode ("rrc", "a");
7553   emitcode ("xch", "a,%s", x);
7554 }
7555
7556 /*-----------------------------------------------------------------*/
7557 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7558 /*-----------------------------------------------------------------*/
7559 static void
7560 AccAXLrl1 (char *x)
7561 {
7562   emitcode ("xch", "a,%s", x);
7563   emitcode ("rlc", "a");
7564   emitcode ("xch", "a,%s", x);
7565   emitcode ("rlc", "a");
7566 }
7567
7568 /*-----------------------------------------------------------------*/
7569 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7570 /*-----------------------------------------------------------------*/
7571 static void
7572 AccAXLsh1 (char *x)
7573 {
7574   emitcode ("xch", "a,%s", x);
7575   emitcode ("add", "a,acc");
7576   emitcode ("xch", "a,%s", x);
7577   emitcode ("rlc", "a");
7578 }
7579
7580 /*-----------------------------------------------------------------*/
7581 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7582 /*-----------------------------------------------------------------*/
7583 static void
7584 AccAXLsh (char *x, int shCount)
7585 {
7586   switch (shCount)
7587     {
7588     case 0:
7589       break;
7590     case 1:
7591       AccAXLsh1 (x);
7592       break;
7593     case 2:
7594       AccAXLsh1 (x);
7595       AccAXLsh1 (x);
7596       break;
7597     case 3:
7598     case 4:
7599     case 5:                     // AAAAABBB:CCCCCDDD
7600
7601       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7602
7603       emitcode ("anl", "a,#0x%02x",
7604                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7605
7606       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7607
7608       AccRol (shCount);         // DDDCCCCC:BBB00000
7609
7610       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7611
7612       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7613
7614       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7615
7616       emitcode ("anl", "a,#0x%02x",
7617                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7618
7619       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7620
7621       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7622
7623       break;
7624     case 6:                     // AAAAAABB:CCCCCCDD
7625       emitcode ("anl", "a,#0x%02x",
7626                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7627       emitcode ("mov", "c,acc.0");      // c = B
7628       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7629 #if 0 // REMOVE ME
7630       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7631       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7632 #else
7633       emitcode("rrc","a");
7634       emitcode("xch","a,%s", x);
7635       emitcode("rrc","a");
7636       emitcode("mov","c,acc.0"); //<< get correct bit
7637       emitcode("xch","a,%s", x);
7638
7639       emitcode("rrc","a");
7640       emitcode("xch","a,%s", x);
7641       emitcode("rrc","a");
7642       emitcode("xch","a,%s", x);
7643 #endif
7644       break;
7645     case 7:                     // a:x <<= 7
7646
7647       emitcode ("anl", "a,#0x%02x",
7648                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7649
7650       emitcode ("mov", "c,acc.0");      // c = B
7651
7652       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7653
7654       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7655
7656       break;
7657     default:
7658       break;
7659     }
7660 }
7661
7662 /*-----------------------------------------------------------------*/
7663 /* AccAXRsh - right shift a:x known count (0..7)                   */
7664 /*-----------------------------------------------------------------*/
7665 static void
7666 AccAXRsh (char *x, int shCount)
7667 {
7668   switch (shCount)
7669     {
7670     case 0:
7671       break;
7672     case 1:
7673       CLRC;
7674       AccAXRrl1 (x);            // 0->a:x
7675
7676       break;
7677     case 2:
7678       CLRC;
7679       AccAXRrl1 (x);            // 0->a:x
7680
7681       CLRC;
7682       AccAXRrl1 (x);            // 0->a:x
7683
7684       break;
7685     case 3:
7686     case 4:
7687     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7688
7689       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7690
7691       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7692
7693       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7694
7695       emitcode ("anl", "a,#0x%02x",
7696                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7697
7698       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7699
7700       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7701
7702       emitcode ("anl", "a,#0x%02x",
7703                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7704
7705       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7706
7707       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7708
7709       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7710
7711       break;
7712     case 6:                     // AABBBBBB:CCDDDDDD
7713
7714       emitcode ("mov", "c,acc.7");
7715       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7716
7717       emitcode ("mov", "c,acc.7");
7718       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7719
7720       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7721
7722       emitcode ("anl", "a,#0x%02x",
7723                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7724
7725       break;
7726     case 7:                     // ABBBBBBB:CDDDDDDD
7727
7728       emitcode ("mov", "c,acc.7");      // c = A
7729
7730       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7731
7732       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7733
7734       emitcode ("anl", "a,#0x%02x",
7735                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7736
7737       break;
7738     default:
7739       break;
7740     }
7741 }
7742
7743 /*-----------------------------------------------------------------*/
7744 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7745 /*-----------------------------------------------------------------*/
7746 static void
7747 AccAXRshS (char *x, int shCount)
7748 {
7749   symbol *tlbl;
7750   switch (shCount)
7751     {
7752     case 0:
7753       break;
7754     case 1:
7755       emitcode ("mov", "c,acc.7");
7756       AccAXRrl1 (x);            // s->a:x
7757
7758       break;
7759     case 2:
7760       emitcode ("mov", "c,acc.7");
7761       AccAXRrl1 (x);            // s->a:x
7762
7763       emitcode ("mov", "c,acc.7");
7764       AccAXRrl1 (x);            // s->a:x
7765
7766       break;
7767     case 3:
7768     case 4:
7769     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7770
7771       tlbl = newiTempLabel (NULL);
7772       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7773
7774       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7775
7776       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7777
7778       emitcode ("anl", "a,#0x%02x",
7779                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7780
7781       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7782
7783       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7784
7785       emitcode ("anl", "a,#0x%02x",
7786                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7787
7788       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7789
7790       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7791
7792       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7793
7794       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7795       emitcode ("orl", "a,#0x%02x",
7796                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7797
7798       emitcode ("", "%05d$:", tlbl->key + 100);
7799       break;                    // SSSSAAAA:BBBCCCCC
7800
7801     case 6:                     // AABBBBBB:CCDDDDDD
7802
7803       tlbl = newiTempLabel (NULL);
7804       emitcode ("mov", "c,acc.7");
7805       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7806
7807       emitcode ("mov", "c,acc.7");
7808       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7809
7810       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7811
7812       emitcode ("anl", "a,#0x%02x",
7813                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7814
7815       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7816       emitcode ("orl", "a,#0x%02x",
7817                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7818
7819       emitcode ("", "%05d$:", tlbl->key + 100);
7820       break;
7821     case 7:                     // ABBBBBBB:CDDDDDDD
7822
7823       tlbl = newiTempLabel (NULL);
7824       emitcode ("mov", "c,acc.7");      // c = A
7825
7826       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7827
7828       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7829
7830       emitcode ("anl", "a,#0x%02x",
7831                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7832
7833       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7834       emitcode ("orl", "a,#0x%02x",
7835                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7836
7837       emitcode ("", "%05d$:", tlbl->key + 100);
7838       break;
7839     default:
7840       break;
7841     }
7842 }
7843
7844 /*-----------------------------------------------------------------*/
7845 /* shiftL2Left2Result - shift left two bytes from left to result   */
7846 /*-----------------------------------------------------------------*/
7847 static void
7848 shiftL2Left2Result (operand * left, int offl,
7849                     operand * result, int offr, int shCount)
7850 {
7851   if (sameRegs (AOP (result), AOP (left)) &&
7852       ((offl + MSB16) == offr))
7853     {
7854       /* don't crash result[offr] */
7855       MOVA (aopGet (left, offl, FALSE, FALSE));
7856       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7857     }
7858   else
7859     {
7860       movLeft2Result (left, offl, result, offr, 0);
7861       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7862     }
7863   /* ax << shCount (x = lsb(result)) */
7864   AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7865   aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7866 }
7867
7868
7869 /*-----------------------------------------------------------------*/
7870 /* shiftR2Left2Result - shift right two bytes from left to result  */
7871 /*-----------------------------------------------------------------*/
7872 static void
7873 shiftR2Left2Result (operand * left, int offl,
7874                     operand * result, int offr,
7875                     int shCount, int sign)
7876 {
7877   if (sameRegs (AOP (result), AOP (left)) &&
7878       ((offl + MSB16) == offr))
7879     {
7880       /* don't crash result[offr] */
7881       MOVA (aopGet (left, offl, FALSE, FALSE));
7882       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7883     }
7884   else
7885     {
7886       movLeft2Result (left, offl, result, offr, 0);
7887       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7888     }
7889   /* a:x >> shCount (x = lsb(result)) */
7890   if (sign)
7891     AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7892   else
7893     AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7894   if (getDataSize (result) > 1)
7895     aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7896 }
7897
7898 /*-----------------------------------------------------------------*/
7899 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7900 /*-----------------------------------------------------------------*/
7901 static void
7902 shiftLLeftOrResult (operand * left, int offl,
7903                     operand * result, int offr, int shCount)
7904 {
7905   MOVA (aopGet (left, offl, FALSE, FALSE));
7906   /* shift left accumulator */
7907   AccLsh (shCount);
7908   /* or with result */
7909   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7910   /* back to result */
7911   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7912 }
7913
7914 /*-----------------------------------------------------------------*/
7915 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7916 /*-----------------------------------------------------------------*/
7917 static void
7918 shiftRLeftOrResult (operand * left, int offl,
7919                     operand * result, int offr, int shCount)
7920 {
7921   MOVA (aopGet (left, offl, FALSE, FALSE));
7922   /* shift right accumulator */
7923   AccRsh (shCount);
7924   /* or with result */
7925   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7926   /* back to result */
7927   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7928 }
7929
7930 /*-----------------------------------------------------------------*/
7931 /* genlshOne - left shift a one byte quantity by known count       */
7932 /*-----------------------------------------------------------------*/
7933 static void
7934 genlshOne (operand * result, operand * left, int shCount)
7935 {
7936   D(emitcode (";     genlshOne",""));
7937
7938   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7939 }
7940
7941 /*-----------------------------------------------------------------*/
7942 /* genlshTwo - left shift two bytes by known amount != 0           */
7943 /*-----------------------------------------------------------------*/
7944 static void
7945 genlshTwo (operand * result, operand * left, int shCount)
7946 {
7947   int size;
7948
7949   D(emitcode (";     genlshTwo",""));
7950
7951   size = getDataSize (result);
7952
7953   /* if shCount >= 8 */
7954   if (shCount >= 8)
7955     {
7956       shCount -= 8;
7957
7958       if (size > 1)
7959         {
7960           if (shCount)
7961             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7962           else
7963             movLeft2Result (left, LSB, result, MSB16, 0);
7964         }
7965       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7966     }
7967
7968   /*  1 <= shCount <= 7 */
7969   else
7970     {
7971       if (size == 1)
7972         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7973       else
7974         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7975     }
7976 }
7977
7978 /*-----------------------------------------------------------------*/
7979 /* shiftLLong - shift left one long from left to result            */
7980 /* offl = LSB or MSB16                                             */
7981 /*-----------------------------------------------------------------*/
7982 static void
7983 shiftLLong (operand * left, operand * result, int offr)
7984 {
7985   char *l;
7986   int size = AOP_SIZE (result);
7987
7988   if (size >= LSB + offr)
7989     {
7990       l = aopGet (left, LSB, FALSE, FALSE);
7991       MOVA (l);
7992       emitcode ("add", "a,acc");
7993       if (sameRegs (AOP (left), AOP (result)) &&
7994           size >= MSB16 + offr && offr != LSB)
7995         emitcode ("xch", "a,%s",
7996                   aopGet (left, LSB + offr, FALSE, FALSE));
7997       else
7998         aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
7999     }
8000
8001   if (size >= MSB16 + offr)
8002     {
8003       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8004         {
8005           l = aopGet (left, MSB16, FALSE, FALSE);
8006           MOVA (l);
8007         }
8008       emitcode ("rlc", "a");
8009       if (sameRegs (AOP (left), AOP (result)) &&
8010           size >= MSB24 + offr && offr != LSB)
8011         emitcode ("xch", "a,%s",
8012                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8013       else
8014         aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8015     }
8016
8017   if (size >= MSB24 + offr)
8018     {
8019       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8020         {
8021           l = aopGet (left, MSB24, FALSE, FALSE);
8022           MOVA (l);
8023         }
8024       emitcode ("rlc", "a");
8025       if (sameRegs (AOP (left), AOP (result)) &&
8026           size >= MSB32 + offr && offr != LSB)
8027         emitcode ("xch", "a,%s",
8028                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8029       else
8030         aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8031     }
8032
8033   if (size > MSB32 + offr)
8034     {
8035       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8036         {
8037           l = aopGet (left, MSB32, FALSE, FALSE);
8038           MOVA (l);
8039         }
8040       emitcode ("rlc", "a");
8041       aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8042     }
8043   if (offr != LSB)
8044     aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8045 }
8046
8047 /*-----------------------------------------------------------------*/
8048 /* genlshFour - shift four byte by a known amount != 0             */
8049 /*-----------------------------------------------------------------*/
8050 static void
8051 genlshFour (operand * result, operand * left, int shCount)
8052 {
8053   int size;
8054
8055   D(emitcode (";     genlshFour",""));
8056
8057   size = AOP_SIZE (result);
8058
8059   /* if shifting more that 3 bytes */
8060   if (shCount >= 24)
8061     {
8062       shCount -= 24;
8063       if (shCount)
8064         /* lowest order of left goes to the highest
8065            order of the destination */
8066         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8067       else
8068         movLeft2Result (left, LSB, result, MSB32, 0);
8069       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8070       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8071       aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8072       return;
8073     }
8074
8075   /* more than two bytes */
8076   else if (shCount >= 16)
8077     {
8078       /* lower order two bytes goes to higher order two bytes */
8079       shCount -= 16;
8080       /* if some more remaining */
8081       if (shCount)
8082         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8083       else
8084         {
8085           movLeft2Result (left, MSB16, result, MSB32, 0);
8086           movLeft2Result (left, LSB, result, MSB24, 0);
8087         }
8088       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8089       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8090       return;
8091     }
8092
8093   /* if more than 1 byte */
8094   else if (shCount >= 8)
8095     {
8096       /* lower order three bytes goes to higher order  three bytes */
8097       shCount -= 8;
8098       if (size == 2)
8099         {
8100           if (shCount)
8101             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8102           else
8103             movLeft2Result (left, LSB, result, MSB16, 0);
8104         }
8105       else
8106         {                       /* size = 4 */
8107           if (shCount == 0)
8108             {
8109               movLeft2Result (left, MSB24, result, MSB32, 0);
8110               movLeft2Result (left, MSB16, result, MSB24, 0);
8111               movLeft2Result (left, LSB, result, MSB16, 0);
8112               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8113             }
8114           else if (shCount == 1)
8115             shiftLLong (left, result, MSB16);
8116           else
8117             {
8118               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8119               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8120               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8121               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8122             }
8123         }
8124     }
8125
8126   /* 1 <= shCount <= 7 */
8127   else if (shCount <= 2)
8128     {
8129       shiftLLong (left, result, LSB);
8130       if (shCount == 2)
8131         shiftLLong (result, result, LSB);
8132     }
8133   /* 3 <= shCount <= 7, optimize */
8134   else
8135     {
8136       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8137       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8138       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8139     }
8140 }
8141
8142 /*-----------------------------------------------------------------*/
8143 /* genLeftShiftLiteral - left shifting by known count              */
8144 /*-----------------------------------------------------------------*/
8145 static void
8146 genLeftShiftLiteral (operand * left,
8147                      operand * right,
8148                      operand * result,
8149                      iCode * ic)
8150 {
8151   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8152   int size;
8153
8154   D(emitcode (";     genLeftShiftLiteral",""));
8155
8156   freeAsmop (right, NULL, ic, TRUE);
8157
8158   aopOp (left, ic, FALSE);
8159   aopOp (result, ic, FALSE);
8160
8161   size = getSize (operandType (result));
8162
8163 #if VIEW_SIZE
8164   emitcode ("; shift left ", "result %d, left %d", size,
8165             AOP_SIZE (left));
8166 #endif
8167
8168   /* I suppose that the left size >= result size */
8169   if (shCount == 0)
8170     {
8171       while (size--)
8172         {
8173           movLeft2Result (left, size, result, size, 0);
8174         }
8175     }
8176
8177   else if (shCount >= (size * 8))
8178     while (size--)
8179       aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8180   else
8181     {
8182       switch (size)
8183         {
8184         case 1:
8185           genlshOne (result, left, shCount);
8186           break;
8187
8188         case 2:
8189           genlshTwo (result, left, shCount);
8190           break;
8191
8192         case 4:
8193           genlshFour (result, left, shCount);
8194           break;
8195         default:
8196           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8197                   "*** ack! mystery literal shift!\n");
8198           break;
8199         }
8200     }
8201   freeAsmop (left, NULL, ic, TRUE);
8202   freeAsmop (result, NULL, ic, TRUE);
8203 }
8204
8205 /*-----------------------------------------------------------------*/
8206 /* genLeftShift - generates code for left shifting                 */
8207 /*-----------------------------------------------------------------*/
8208 static void
8209 genLeftShift (iCode * ic)
8210 {
8211   operand *left, *right, *result;
8212   int size, offset;
8213   char *l;
8214   symbol *tlbl, *tlbl1;
8215   bool pushedB;
8216
8217   D(emitcode (";     genLeftShift",""));
8218
8219   right = IC_RIGHT (ic);
8220   left = IC_LEFT (ic);
8221   result = IC_RESULT (ic);
8222
8223   aopOp (right, ic, FALSE);
8224
8225   /* if the shift count is known then do it
8226      as efficiently as possible */
8227   if (AOP_TYPE (right) == AOP_LIT)
8228     {
8229       genLeftShiftLiteral (left, right, result, ic);
8230       return;
8231     }
8232
8233   /* shift count is unknown then we have to form
8234      a loop get the loop count in B : Note: we take
8235      only the lower order byte since shifting
8236      more that 32 bits make no sense anyway, ( the
8237      largest size of an object can be only 32 bits ) */
8238
8239   pushedB = pushB ();
8240   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8241   emitcode ("inc", "b");
8242   freeAsmop (right, NULL, ic, TRUE);
8243   aopOp (left, ic, FALSE);
8244   aopOp (result, ic, FALSE);
8245
8246   /* now move the left to the result if they are not the same */
8247   if (!sameRegs (AOP (left), AOP (result)) &&
8248       AOP_SIZE (result) > 1)
8249     {
8250
8251       size = AOP_SIZE (result);
8252       offset = 0;
8253       while (size--)
8254         {
8255           l = aopGet (left, offset, FALSE, TRUE);
8256           if (*l == '@' && (IS_AOP_PREG (result)))
8257             {
8258
8259               emitcode ("mov", "a,%s", l);
8260               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8261             }
8262           else
8263             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8264           offset++;
8265         }
8266     }
8267
8268   tlbl = newiTempLabel (NULL);
8269   size = AOP_SIZE (result);
8270   offset = 0;
8271   tlbl1 = newiTempLabel (NULL);
8272
8273   /* if it is only one byte then */
8274   if (size == 1)
8275     {
8276       symbol *tlbl1 = newiTempLabel (NULL);
8277
8278       l = aopGet (left, 0, FALSE, FALSE);
8279       MOVA (l);
8280       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8281       emitcode ("", "%05d$:", tlbl->key + 100);
8282       emitcode ("add", "a,acc");
8283       emitcode ("", "%05d$:", tlbl1->key + 100);
8284       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8285       popB (pushedB);
8286       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8287       goto release;
8288     }
8289
8290   reAdjustPreg (AOP (result));
8291
8292   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8293   emitcode ("", "%05d$:", tlbl->key + 100);
8294   l = aopGet (result, offset, FALSE, FALSE);
8295   MOVA (l);
8296   emitcode ("add", "a,acc");
8297   aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8298   while (--size)
8299     {
8300       l = aopGet (result, offset, FALSE, FALSE);
8301       MOVA (l);
8302       emitcode ("rlc", "a");
8303       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8304     }
8305   reAdjustPreg (AOP (result));
8306
8307   emitcode ("", "%05d$:", tlbl1->key + 100);
8308   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8309   popB (pushedB);
8310 release:
8311   freeAsmop (left, NULL, ic, TRUE);
8312   freeAsmop (result, NULL, ic, TRUE);
8313 }
8314
8315 /*-----------------------------------------------------------------*/
8316 /* genrshOne - right shift a one byte quantity by known count      */
8317 /*-----------------------------------------------------------------*/
8318 static void
8319 genrshOne (operand * result, operand * left,
8320            int shCount, int sign)
8321 {
8322   D(emitcode (";     genrshOne",""));
8323
8324   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* genrshTwo - right shift two bytes by known amount != 0          */
8329 /*-----------------------------------------------------------------*/
8330 static void
8331 genrshTwo (operand * result, operand * left,
8332            int shCount, int sign)
8333 {
8334   D(emitcode (";     genrshTwo",""));
8335
8336   /* if shCount >= 8 */
8337   if (shCount >= 8)
8338     {
8339       shCount -= 8;
8340       if (shCount)
8341         shiftR1Left2Result (left, MSB16, result, LSB,
8342                             shCount, sign);
8343       else
8344         movLeft2Result (left, MSB16, result, LSB, sign);
8345       addSign (result, MSB16, sign);
8346     }
8347
8348   /*  1 <= shCount <= 7 */
8349   else
8350     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8351 }
8352
8353 /*-----------------------------------------------------------------*/
8354 /* shiftRLong - shift right one long from left to result           */
8355 /* offl = LSB or MSB16                                             */
8356 /*-----------------------------------------------------------------*/
8357 static void
8358 shiftRLong (operand * left, int offl,
8359             operand * result, int sign)
8360 {
8361   int isSameRegs=sameRegs(AOP(left),AOP(result));
8362
8363   if (isSameRegs && offl>1) {
8364     // we are in big trouble, but this shouldn't happen
8365     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8366   }
8367
8368   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8369
8370   if (offl==MSB16) {
8371     // shift is > 8
8372     if (sign) {
8373       emitcode ("rlc", "a");
8374       emitcode ("subb", "a,acc");
8375       if (isSameRegs)
8376         emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8377       else {
8378         aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8379         MOVA (aopGet (left, MSB32, FALSE, FALSE));
8380       }
8381     } else {
8382       aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8383     }
8384   }
8385
8386   if (!sign) {
8387     emitcode ("clr", "c");
8388   } else {
8389     emitcode ("mov", "c,acc.7");
8390   }
8391
8392   emitcode ("rrc", "a");
8393
8394   if (isSameRegs && offl==MSB16) {
8395     emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8396   } else {
8397     aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8398     MOVA (aopGet (left, MSB24, FALSE, FALSE));
8399   }
8400
8401   emitcode ("rrc", "a");
8402   if (isSameRegs && offl==1) {
8403     emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8404   } else {
8405     aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8406     MOVA (aopGet (left, MSB16, FALSE, FALSE));
8407   }
8408   emitcode ("rrc", "a");
8409   aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8410
8411   if (offl == LSB)
8412     {
8413       MOVA (aopGet (left, LSB, FALSE, FALSE));
8414       emitcode ("rrc", "a");
8415       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8416     }
8417 }
8418
8419 /*-----------------------------------------------------------------*/
8420 /* genrshFour - shift four byte by a known amount != 0             */
8421 /*-----------------------------------------------------------------*/
8422 static void
8423 genrshFour (operand * result, operand * left,
8424             int shCount, int sign)
8425 {
8426   D(emitcode (";     genrshFour",""));
8427
8428   /* if shifting more that 3 bytes */
8429   if (shCount >= 24)
8430     {
8431       shCount -= 24;
8432       if (shCount)
8433         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8434       else
8435         movLeft2Result (left, MSB32, result, LSB, sign);
8436       addSign (result, MSB16, sign);
8437     }
8438   else if (shCount >= 16)
8439     {
8440       shCount -= 16;
8441       if (shCount)
8442         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8443       else
8444         {
8445           movLeft2Result (left, MSB24, result, LSB, 0);
8446           movLeft2Result (left, MSB32, result, MSB16, sign);
8447         }
8448       addSign (result, MSB24, sign);
8449     }
8450   else if (shCount >= 8)
8451     {
8452       shCount -= 8;
8453       if (shCount == 1)
8454         shiftRLong (left, MSB16, result, sign);
8455       else if (shCount == 0)
8456         {
8457           movLeft2Result (left, MSB16, result, LSB, 0);
8458           movLeft2Result (left, MSB24, result, MSB16, 0);
8459           movLeft2Result (left, MSB32, result, MSB24, sign);
8460           addSign (result, MSB32, sign);
8461         }
8462       else
8463         {
8464           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8465           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8466           /* the last shift is signed */
8467           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8468           addSign (result, MSB32, sign);
8469         }
8470     }
8471   else
8472     {                           /* 1 <= shCount <= 7 */
8473       if (shCount <= 2)
8474         {
8475           shiftRLong (left, LSB, result, sign);
8476           if (shCount == 2)
8477             shiftRLong (result, LSB, result, sign);
8478         }
8479       else
8480         {
8481           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8482           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8483           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8484         }
8485     }
8486 }
8487
8488 /*-----------------------------------------------------------------*/
8489 /* genRightShiftLiteral - right shifting by known count            */
8490 /*-----------------------------------------------------------------*/
8491 static void
8492 genRightShiftLiteral (operand * left,
8493                       operand * right,
8494                       operand * result,
8495                       iCode * ic,
8496                       int sign)
8497 {
8498   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8499   int size;
8500
8501   D(emitcode (";     genRightShiftLiteral",""));
8502
8503   freeAsmop (right, NULL, ic, TRUE);
8504
8505   aopOp (left, ic, FALSE);
8506   aopOp (result, ic, FALSE);
8507
8508 #if VIEW_SIZE
8509   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8510             AOP_SIZE (left));
8511 #endif
8512
8513   size = getDataSize (left);
8514   /* test the LEFT size !!! */
8515
8516   /* I suppose that the left size >= result size */
8517   if (shCount == 0)
8518     {
8519       size = getDataSize (result);
8520       while (size--)
8521         movLeft2Result (left, size, result, size, 0);
8522     }
8523
8524   else if (shCount >= (size * 8))
8525     {
8526       if (sign) {
8527         /* get sign in acc.7 */
8528         MOVA (aopGet (left, size - 1, FALSE, FALSE));
8529       }
8530       addSign (result, LSB, sign);
8531     }
8532   else
8533     {
8534       switch (size)
8535         {
8536         case 1:
8537           genrshOne (result, left, shCount, sign);
8538           break;
8539
8540         case 2:
8541           genrshTwo (result, left, shCount, sign);
8542           break;
8543
8544         case 4:
8545           genrshFour (result, left, shCount, sign);
8546           break;
8547         default:
8548           break;
8549         }
8550     }
8551   freeAsmop (left, NULL, ic, TRUE);
8552   freeAsmop (result, NULL, ic, TRUE);
8553 }
8554
8555 /*-----------------------------------------------------------------*/
8556 /* genSignedRightShift - right shift of signed number              */
8557 /*-----------------------------------------------------------------*/
8558 static void
8559 genSignedRightShift (iCode * ic)
8560 {
8561   operand *right, *left, *result;
8562   int size, offset;
8563   char *l;
8564   symbol *tlbl, *tlbl1;
8565   bool pushedB;
8566
8567   D(emitcode (";     genSignedRightShift",""));
8568
8569   /* we do it the hard way put the shift count in b
8570      and loop thru preserving the sign */
8571
8572   right = IC_RIGHT (ic);
8573   left = IC_LEFT (ic);
8574   result = IC_RESULT (ic);
8575
8576   aopOp (right, ic, FALSE);
8577
8578
8579   if (AOP_TYPE (right) == AOP_LIT)
8580     {
8581       genRightShiftLiteral (left, right, result, ic, 1);
8582       return;
8583     }
8584   /* shift count is unknown then we have to form
8585      a loop get the loop count in B : Note: we take
8586      only the lower order byte since shifting
8587      more that 32 bits make no sense anyway, ( the
8588      largest size of an object can be only 32 bits ) */
8589
8590   pushedB = pushB ();
8591   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8592   emitcode ("inc", "b");
8593   freeAsmop (right, NULL, ic, TRUE);
8594   aopOp (left, ic, FALSE);
8595   aopOp (result, ic, FALSE);
8596
8597   /* now move the left to the result if they are not the
8598      same */
8599   if (!sameRegs (AOP (left), AOP (result)) &&
8600       AOP_SIZE (result) > 1)
8601     {
8602
8603       size = AOP_SIZE (result);
8604       offset = 0;
8605       while (size--)
8606         {
8607           l = aopGet (left, offset, FALSE, TRUE);
8608           if (*l == '@' && IS_AOP_PREG (result))
8609             {
8610
8611               emitcode ("mov", "a,%s", l);
8612               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8613             }
8614           else
8615             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8616           offset++;
8617         }
8618     }
8619
8620   /* mov the highest order bit to OVR */
8621   tlbl = newiTempLabel (NULL);
8622   tlbl1 = newiTempLabel (NULL);
8623
8624   size = AOP_SIZE (result);
8625   offset = size - 1;
8626   MOVA (aopGet (left, offset, FALSE, FALSE));
8627   emitcode ("rlc", "a");
8628   emitcode ("mov", "ov,c");
8629   /* if it is only one byte then */
8630   if (size == 1)
8631     {
8632       l = aopGet (left, 0, FALSE, FALSE);
8633       MOVA (l);
8634       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8635       emitcode ("", "%05d$:", tlbl->key + 100);
8636       emitcode ("mov", "c,ov");
8637       emitcode ("rrc", "a");
8638       emitcode ("", "%05d$:", tlbl1->key + 100);
8639       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8640       popB (pushedB);
8641       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8642       goto release;
8643     }
8644
8645   reAdjustPreg (AOP (result));
8646   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8647   emitcode ("", "%05d$:", tlbl->key + 100);
8648   emitcode ("mov", "c,ov");
8649   while (size--)
8650     {
8651       l = aopGet (result, offset, FALSE, FALSE);
8652       MOVA (l);
8653       emitcode ("rrc", "a");
8654       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8655     }
8656   reAdjustPreg (AOP (result));
8657   emitcode ("", "%05d$:", tlbl1->key + 100);
8658   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8659   popB (pushedB);
8660
8661 release:
8662   freeAsmop (left, NULL, ic, TRUE);
8663   freeAsmop (result, NULL, ic, TRUE);
8664 }
8665
8666 /*-----------------------------------------------------------------*/
8667 /* genRightShift - generate code for right shifting                */
8668 /*-----------------------------------------------------------------*/
8669 static void
8670 genRightShift (iCode * ic)
8671 {
8672   operand *right, *left, *result;
8673   sym_link *letype;
8674   int size, offset;
8675   char *l;
8676   symbol *tlbl, *tlbl1;
8677   bool pushedB;
8678
8679   D(emitcode (";     genRightShift",""));
8680
8681   /* if signed then we do it the hard way preserve the
8682      sign bit moving it inwards */
8683   letype = getSpec (operandType (IC_LEFT (ic)));
8684
8685   if (!SPEC_USIGN (letype))
8686     {
8687       genSignedRightShift (ic);
8688       return;
8689     }
8690
8691   /* signed & unsigned types are treated the same : i.e. the
8692      signed is NOT propagated inwards : quoting from the
8693      ANSI - standard : "for E1 >> E2, is equivalent to division
8694      by 2**E2 if unsigned or if it has a non-negative value,
8695      otherwise the result is implementation defined ", MY definition
8696      is that the sign does not get propagated */
8697
8698   right = IC_RIGHT (ic);
8699   left = IC_LEFT (ic);
8700   result = IC_RESULT (ic);
8701
8702   aopOp (right, ic, FALSE);
8703
8704   /* if the shift count is known then do it
8705      as efficiently as possible */
8706   if (AOP_TYPE (right) == AOP_LIT)
8707     {
8708       genRightShiftLiteral (left, right, result, ic, 0);
8709       return;
8710     }
8711
8712   /* shift count is unknown then we have to form
8713      a loop get the loop count in B : Note: we take
8714      only the lower order byte since shifting
8715      more that 32 bits make no sense anyway, ( the
8716      largest size of an object can be only 32 bits ) */
8717
8718   pushedB = pushB ();
8719   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8720   emitcode ("inc", "b");
8721   freeAsmop (right, NULL, ic, TRUE);
8722   aopOp (left, ic, FALSE);
8723   aopOp (result, ic, FALSE);
8724
8725   /* now move the left to the result if they are not the
8726      same */
8727   if (!sameRegs (AOP (left), AOP (result)) &&
8728       AOP_SIZE (result) > 1)
8729     {
8730
8731       size = AOP_SIZE (result);
8732       offset = 0;
8733       while (size--)
8734         {
8735           l = aopGet (left, offset, FALSE, TRUE);
8736           if (*l == '@' && IS_AOP_PREG (result))
8737             {
8738
8739               emitcode ("mov", "a,%s", l);
8740               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8741             }
8742           else
8743             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8744           offset++;
8745         }
8746     }
8747
8748   tlbl = newiTempLabel (NULL);
8749   tlbl1 = newiTempLabel (NULL);
8750   size = AOP_SIZE (result);
8751   offset = size - 1;
8752
8753   /* if it is only one byte then */
8754   if (size == 1)
8755     {
8756       l = aopGet (left, 0, FALSE, FALSE);
8757       MOVA (l);
8758       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8759       emitcode ("", "%05d$:", tlbl->key + 100);
8760       CLRC;
8761       emitcode ("rrc", "a");
8762       emitcode ("", "%05d$:", tlbl1->key + 100);
8763       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8764       popB (pushedB);
8765       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8766       goto release;
8767     }
8768
8769   reAdjustPreg (AOP (result));
8770   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8771   emitcode ("", "%05d$:", tlbl->key + 100);
8772   CLRC;
8773   while (size--)
8774     {
8775       l = aopGet (result, offset, FALSE, FALSE);
8776       MOVA (l);
8777       emitcode ("rrc", "a");
8778       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8779     }
8780   reAdjustPreg (AOP (result));
8781
8782   emitcode ("", "%05d$:", tlbl1->key + 100);
8783   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8784   popB (pushedB);
8785
8786 release:
8787   freeAsmop (left, NULL, ic, TRUE);
8788   freeAsmop (result, NULL, ic, TRUE);
8789 }
8790
8791 /*-----------------------------------------------------------------*/
8792 /* emitPtrByteGet - emits code to get a byte into A through a      */
8793 /*                  pointer register (R0, R1, or DPTR). The        */
8794 /*                  original value of A can be preserved in B.     */
8795 /*-----------------------------------------------------------------*/
8796 static void
8797 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8798 {
8799   switch (p_type)
8800     {
8801     case IPOINTER:
8802     case POINTER:
8803       if (preserveAinB)
8804         emitcode ("mov", "b,a");
8805       emitcode ("mov", "a,@%s", rname);
8806       break;
8807
8808     case PPOINTER:
8809       if (preserveAinB)
8810         emitcode ("mov", "b,a");
8811       emitcode ("movx", "a,@%s", rname);
8812       break;
8813
8814     case FPOINTER:
8815       if (preserveAinB)
8816         emitcode ("mov", "b,a");
8817       emitcode ("movx", "a,@dptr");
8818       break;
8819
8820     case CPOINTER:
8821       if (preserveAinB)
8822         emitcode ("mov", "b,a");
8823       emitcode ("clr", "a");
8824       emitcode ("movc", "a,@a+dptr");
8825       break;
8826
8827     case GPOINTER:
8828       if (preserveAinB)
8829         {
8830           emitcode ("push", "b");
8831           emitcode ("push", "acc");
8832         }
8833       emitcode ("lcall", "__gptrget");
8834       if (preserveAinB)
8835         emitcode ("pop", "b");
8836       break;
8837     }
8838 }
8839
8840 /*-----------------------------------------------------------------*/
8841 /* emitPtrByteSet - emits code to set a byte from src through a    */
8842 /*                  pointer register (R0, R1, or DPTR).            */
8843 /*-----------------------------------------------------------------*/
8844 static void
8845 emitPtrByteSet (char *rname, int p_type, char *src)
8846 {
8847   switch (p_type)
8848     {
8849     case IPOINTER:
8850     case POINTER:
8851       if (*src=='@')
8852         {
8853           MOVA (src);
8854           emitcode ("mov", "@%s,a", rname);
8855         }
8856       else
8857         emitcode ("mov", "@%s,%s", rname, src);
8858       break;
8859
8860     case PPOINTER:
8861       MOVA (src);
8862       emitcode ("movx", "@%s,a", rname);
8863       break;
8864
8865     case FPOINTER:
8866       MOVA (src);
8867       emitcode ("movx", "@dptr,a");
8868       break;
8869
8870     case GPOINTER:
8871       MOVA (src);
8872       emitcode ("lcall", "__gptrput");
8873       break;
8874     }
8875 }
8876
8877 /*-----------------------------------------------------------------*/
8878 /* genUnpackBits - generates code for unpacking bits               */
8879 /*-----------------------------------------------------------------*/
8880 static void
8881 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8882 {
8883   int offset = 0;       /* result byte offset */
8884   int rsize;            /* result size */
8885   int rlen = 0;         /* remaining bitfield length */
8886   sym_link *etype;      /* bitfield type information */
8887   int blen;             /* bitfield length */
8888   int bstr;             /* bitfield starting bit within byte */
8889   char buffer[10];
8890
8891   D(emitcode (";     genUnpackBits",""));
8892
8893   etype = getSpec (operandType (result));
8894   rsize = getSize (operandType (result));
8895   blen = SPEC_BLEN (etype);
8896   bstr = SPEC_BSTR (etype);
8897
8898   if (ifx && blen <= 8)
8899     {
8900       emitPtrByteGet (rname, ptype, FALSE);
8901       if (blen == 1)
8902         {
8903           SNPRINTF (buffer, sizeof(buffer),
8904                     "acc.%d", bstr);
8905           genIfxJump (ifx, buffer, NULL, NULL, NULL);
8906         }
8907       else
8908         {
8909           if (blen < 8)
8910             emitcode ("anl", "a,#0x%02x",
8911                       (((unsigned char) -1) >> (8 - blen)) << bstr);
8912           genIfxJump (ifx, "a", NULL, NULL, NULL);
8913         }
8914       return;
8915     }
8916   wassert (!ifx);
8917
8918   /* If the bitfield length is less than a byte */
8919   if (blen < 8)
8920     {
8921       emitPtrByteGet (rname, ptype, FALSE);
8922       AccRsh (bstr);
8923       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8924       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8925       goto finish;
8926     }
8927
8928   /* Bit field did not fit in a byte. Copy all
8929      but the partial byte at the end.  */
8930   for (rlen=blen;rlen>=8;rlen-=8)
8931     {
8932       emitPtrByteGet (rname, ptype, FALSE);
8933       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8934       if (rlen>8)
8935         emitcode ("inc", "%s", rname);
8936     }
8937
8938   /* Handle the partial byte at the end */
8939   if (rlen)
8940     {
8941       emitPtrByteGet (rname, ptype, FALSE);
8942       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8943       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8944     }
8945
8946 finish:
8947   if (offset < rsize)
8948     {
8949       rsize -= offset;
8950       while (rsize--)
8951         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8952     }
8953 }
8954
8955
8956 /*-----------------------------------------------------------------*/
8957 /* genDataPointerGet - generates code when ptr offset is known     */
8958 /*-----------------------------------------------------------------*/
8959 static void
8960 genDataPointerGet (operand * left,
8961                    operand * result,
8962                    iCode * ic)
8963 {
8964   char *l;
8965   char buffer[256];
8966   int size, offset = 0;
8967
8968   D(emitcode (";     genDataPointerGet",""));
8969
8970   aopOp (result, ic, TRUE);
8971
8972   /* get the string representation of the name */
8973   l = aopGet (left, 0, FALSE, TRUE);
8974   size = AOP_SIZE (result);
8975   while (size--)
8976     {
8977       if (offset)
8978         sprintf (buffer, "(%s + %d)", l + 1, offset);
8979       else
8980         sprintf (buffer, "%s", l + 1);
8981       aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8982     }
8983
8984   freeAsmop (left, NULL, ic, TRUE);
8985   freeAsmop (result, NULL, ic, TRUE);
8986 }
8987
8988 /*-----------------------------------------------------------------*/
8989 /* genNearPointerGet - emitcode for near pointer fetch             */
8990 /*-----------------------------------------------------------------*/
8991 static void
8992 genNearPointerGet (operand * left,
8993                    operand * result,
8994                    iCode * ic,
8995                    iCode * pi,
8996                    iCode * ifx)
8997 {
8998   asmop *aop = NULL;
8999   regs *preg = NULL;
9000   char *rname;
9001   sym_link *rtype, *retype;
9002   sym_link *ltype = operandType (left);
9003   char buffer[80];
9004
9005   D(emitcode (";     genNearPointerGet",""));
9006
9007   rtype = operandType (result);
9008   retype = getSpec (rtype);
9009
9010   aopOp (left, ic, FALSE);
9011
9012   /* if left is rematerialisable and
9013      result is not bitfield variable type and
9014      the left is pointer to data space i.e
9015      lower 128 bytes of space */
9016   if (AOP_TYPE (left) == AOP_IMMD &&
9017       !IS_BITFIELD (retype) &&
9018       DCL_TYPE (ltype) == POINTER)
9019     {
9020       genDataPointerGet (left, result, ic);
9021       return;
9022     }
9023
9024  /* if the value is already in a pointer register
9025      then don't need anything more */
9026   if (!AOP_INPREG (AOP (left)))
9027     {
9028       if (IS_AOP_PREG (left))
9029         {
9030           // Aha, it is a pointer, just in disguise.
9031           rname = aopGet (left, 0, FALSE, FALSE);
9032           if (*rname != '@')
9033             {
9034               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9035                       __FILE__, __LINE__);
9036             }
9037           else
9038             {
9039               // Expected case.
9040               emitcode ("mov", "a%s,%s", rname + 1, rname);
9041               rname++;  // skip the '@'.
9042             }
9043         }
9044       else
9045         {
9046           /* otherwise get a free pointer register */
9047           aop = newAsmop (0);
9048           preg = getFreePtr (ic, &aop, FALSE);
9049           emitcode ("mov", "%s,%s",
9050                     preg->name,
9051                     aopGet (left, 0, FALSE, TRUE));
9052           rname = preg->name;
9053         }
9054     }
9055   else
9056     rname = aopGet (left, 0, FALSE, FALSE);
9057
9058   //aopOp (result, ic, FALSE);
9059   aopOp (result, ic, result?TRUE:FALSE);
9060
9061   /* if bitfield then unpack the bits */
9062   if (IS_BITFIELD (retype))
9063     genUnpackBits (result, rname, POINTER, ifx);
9064   else
9065     {
9066       /* we have can just get the values */
9067       int size = AOP_SIZE (result);
9068       int offset = 0;
9069
9070       while (size--)
9071         {
9072           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9073             {
9074
9075               emitcode ("mov", "a,@%s", rname);
9076               if (!ifx)
9077               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9078             }
9079           else
9080             {
9081               sprintf (buffer, "@%s", rname);
9082               aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9083             }
9084           offset++;
9085           if (size || pi)
9086             emitcode ("inc", "%s", rname);
9087         }
9088     }
9089
9090   /* now some housekeeping stuff */
9091   if (aop)       /* we had to allocate for this iCode */
9092     {
9093       if (pi) { /* post increment present */
9094         aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9095       }
9096       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9097     }
9098   else
9099     {
9100       /* we did not allocate which means left
9101          already in a pointer register, then
9102          if size > 0 && this could be used again
9103          we have to point it back to where it
9104          belongs */
9105       if ((AOP_SIZE (result) > 1 &&
9106            !OP_SYMBOL (left)->remat &&
9107            (OP_SYMBOL (left)->liveTo > ic->seq ||
9108             ic->depth)) &&
9109           !pi)
9110         {
9111           int size = AOP_SIZE (result) - 1;
9112           while (size--)
9113             emitcode ("dec", "%s", rname);
9114         }
9115     }
9116
9117   if (ifx && !ifx->generated)
9118     {
9119       genIfxJump (ifx, "a", left, NULL, result);
9120     }
9121
9122   /* done */
9123   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9124   freeAsmop (left, NULL, ic, TRUE);
9125   if (pi) pi->generated = 1;
9126 }
9127
9128 /*-----------------------------------------------------------------*/
9129 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9130 /*-----------------------------------------------------------------*/
9131 static void
9132 genPagedPointerGet (operand * left,
9133                     operand * result,
9134                     iCode * ic,
9135                     iCode *pi,
9136                     iCode *ifx)
9137 {
9138   asmop *aop = NULL;
9139   regs *preg = NULL;
9140   char *rname;
9141   sym_link *rtype, *retype;
9142
9143   D(emitcode (";     genPagedPointerGet",""));
9144
9145   rtype = operandType (result);
9146   retype = getSpec (rtype);
9147
9148   aopOp (left, ic, FALSE);
9149
9150   /* if the value is already in a pointer register
9151      then don't need anything more */
9152   if (!AOP_INPREG (AOP (left)))
9153     {
9154       /* otherwise get a free pointer register */
9155       aop = newAsmop (0);
9156       preg = getFreePtr (ic, &aop, FALSE);
9157       emitcode ("mov", "%s,%s",
9158                 preg->name,
9159                 aopGet (left, 0, FALSE, TRUE));
9160       rname = preg->name;
9161     }
9162   else
9163     rname = aopGet (left, 0, FALSE, FALSE);
9164
9165   aopOp (result, ic, FALSE);
9166
9167   /* if bitfield then unpack the bits */
9168   if (IS_BITFIELD (retype))
9169     genUnpackBits (result, rname, PPOINTER, ifx);
9170   else
9171     {
9172       /* we have can just get the values */
9173       int size = AOP_SIZE (result);
9174       int offset = 0;
9175
9176       while (size--)
9177         {
9178
9179           emitcode ("movx", "a,@%s", rname);
9180           if (!ifx)
9181           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9182
9183           offset++;
9184
9185           if (size || pi)
9186             emitcode ("inc", "%s", rname);
9187         }
9188     }
9189
9190   /* now some housekeeping stuff */
9191   if (aop) /* we had to allocate for this iCode */
9192     {
9193       if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9194       freeAsmop (NULL, aop, ic, TRUE);
9195     }
9196   else
9197     {
9198       /* we did not allocate which means left
9199          already in a pointer register, then
9200          if size > 0 && this could be used again
9201          we have to point it back to where it
9202          belongs */
9203       if ((AOP_SIZE (result) > 1 &&
9204            !OP_SYMBOL (left)->remat &&
9205            (OP_SYMBOL (left)->liveTo > ic->seq ||
9206             ic->depth)) &&
9207           !pi)
9208         {
9209           int size = AOP_SIZE (result) - 1;
9210           while (size--)
9211             emitcode ("dec", "%s", rname);
9212         }
9213     }
9214
9215   if (ifx && !ifx->generated)
9216     {
9217       genIfxJump (ifx, "a", left, NULL, result);
9218     }
9219
9220   /* done */
9221   freeAsmop (left, NULL, ic, TRUE);
9222   freeAsmop (result, NULL, ic, TRUE);
9223   if (pi) pi->generated = 1;
9224
9225 }
9226
9227 /*--------------------------------------------------------------------*/
9228 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9229 /*--------------------------------------------------------------------*/
9230 static void
9231 loadDptrFromOperand (operand *op, bool loadBToo)
9232 {
9233   if (AOP_TYPE (op) != AOP_STR)
9234     {
9235       /* if this is rematerializable */
9236       if (AOP_TYPE (op) == AOP_IMMD)
9237         {
9238           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9239           if (loadBToo)
9240             {
9241               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9242                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9243               else
9244                 {
9245                   wassertl(FALSE, "need pointerCode");
9246                   emitcode ("", "; mov b,???");
9247                   /* genPointerGet and genPointerSet originally did different
9248                   ** things for this case. Both seem wrong.
9249                   ** from genPointerGet:
9250                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9251                   ** from genPointerSet:
9252                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9253                   */
9254                 }
9255             }
9256         }
9257       else if (AOP_TYPE (op) == AOP_DPTR)
9258         {
9259           if (loadBToo)
9260             {
9261               MOVA (aopGet (op, 0, FALSE, FALSE));
9262               emitcode ("push", "acc");
9263               MOVA (aopGet (op, 1, FALSE, FALSE));
9264               emitcode ("push", "acc");
9265               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9266               emitcode ("pop", "dph");
9267               emitcode ("pop", "dpl");
9268             }
9269           else
9270             {
9271               MOVA (aopGet (op, 0, FALSE, FALSE));
9272               emitcode ("push", "acc");
9273               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9274               emitcode ("pop", "dpl");
9275             }
9276         }
9277       else
9278         {                       /* we need to get it byte by byte */
9279           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9280           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9281           if (loadBToo)
9282             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9283         }
9284     }
9285 }
9286
9287 /*-----------------------------------------------------------------*/
9288 /* genFarPointerGet - gget value from far space                    */
9289 /*-----------------------------------------------------------------*/
9290 static void
9291 genFarPointerGet (operand * left,
9292                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9293 {
9294   int size, offset;
9295   sym_link *retype = getSpec (operandType (result));
9296
9297   D(emitcode (";     genFarPointerGet",""));
9298
9299   aopOp (left, ic, FALSE);
9300   loadDptrFromOperand (left, FALSE);
9301
9302   /* so dptr now contains the address */
9303   aopOp (result, ic, FALSE);
9304
9305   /* if bit then unpack */
9306   if (IS_BITFIELD (retype))
9307     genUnpackBits (result, "dptr", FPOINTER, ifx);
9308   else
9309     {
9310       size = AOP_SIZE (result);
9311       offset = 0;
9312
9313       while (size--)
9314         {
9315           emitcode ("movx", "a,@dptr");
9316           if (!ifx)
9317             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9318           if (size || pi)
9319             emitcode ("inc", "dptr");
9320         }
9321     }
9322
9323   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9324     {
9325     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9326     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9327     pi->generated = 1;
9328   }
9329
9330   if (ifx && !ifx->generated)
9331     {
9332       genIfxJump (ifx, "a", left, NULL, result);
9333     }
9334
9335   freeAsmop (left, NULL, ic, TRUE);
9336   freeAsmop (result, NULL, ic, TRUE);
9337 }
9338
9339 /*-----------------------------------------------------------------*/
9340 /* genCodePointerGet - gget value from code space                  */
9341 /*-----------------------------------------------------------------*/
9342 static void
9343 genCodePointerGet (operand * left,
9344                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9345 {
9346   int size, offset;
9347   sym_link *retype = getSpec (operandType (result));
9348
9349   D(emitcode (";     genCodePointerGet",""));
9350
9351   aopOp (left, ic, FALSE);
9352   loadDptrFromOperand (left, FALSE);
9353
9354   /* so dptr now contains the address */
9355   aopOp (result, ic, FALSE);
9356
9357   /* if bit then unpack */
9358   if (IS_BITFIELD (retype))
9359     genUnpackBits (result, "dptr", CPOINTER, ifx);
9360   else
9361     {
9362       size = AOP_SIZE (result);
9363       offset = 0;
9364
9365       while (size--)
9366         {
9367           if (pi)
9368             {
9369               emitcode ("clr", "a");
9370               emitcode ("movc", "a,@a+dptr");
9371               if (!ifx)
9372               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9373               emitcode ("inc", "dptr");
9374             }
9375           else
9376             {
9377               emitcode ("mov", "a,#0x%02x", offset);
9378               emitcode ("movc", "a,@a+dptr");
9379               if (!ifx)
9380               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9381             }
9382         }
9383     }
9384
9385   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9386     {
9387     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9388     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9389     pi->generated = 1;
9390   }
9391
9392   if (ifx && !ifx->generated)
9393     {
9394       genIfxJump (ifx, "a", left, NULL, result);
9395     }
9396
9397   freeAsmop (left, NULL, ic, TRUE);
9398   freeAsmop (result, NULL, ic, TRUE);
9399 }
9400
9401 /*-----------------------------------------------------------------*/
9402 /* genGenPointerGet - gget value from generic pointer space        */
9403 /*-----------------------------------------------------------------*/
9404 static void
9405 genGenPointerGet (operand * left,
9406                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9407 {
9408   int size, offset;
9409   sym_link *retype = getSpec (operandType (result));
9410
9411   D(emitcode (";     genGenPointerGet",""));
9412
9413   aopOp (left, ic, FALSE);
9414   loadDptrFromOperand (left, TRUE);
9415
9416   /* so dptr know contains the address */
9417   aopOp (result, ic, FALSE);
9418
9419   /* if bit then unpack */
9420   if (IS_BITFIELD (retype))
9421     genUnpackBits (result, "dptr", GPOINTER, ifx);
9422   else
9423     {
9424       size = AOP_SIZE (result);
9425       offset = 0;
9426
9427       while (size--)
9428         {
9429           emitcode ("lcall", "__gptrget");
9430           if (!ifx)
9431           aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9432           if (size || pi)
9433             emitcode ("inc", "dptr");
9434         }
9435     }
9436
9437   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9438     {
9439     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9440     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9441     pi->generated = 1;
9442   }
9443
9444   if (ifx && !ifx->generated)
9445     {
9446       genIfxJump (ifx, "a", left, NULL, result);
9447     }
9448
9449
9450   freeAsmop (left, NULL, ic, TRUE);
9451   freeAsmop (result, NULL, ic, TRUE);
9452 }
9453
9454 /*-----------------------------------------------------------------*/
9455 /* genPointerGet - generate code for pointer get                   */
9456 /*-----------------------------------------------------------------*/
9457 static void
9458 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9459 {
9460   operand *left, *result;
9461   sym_link *type, *etype;
9462   int p_type;
9463
9464   D(emitcode (";     genPointerGet",""));
9465
9466   left = IC_LEFT (ic);
9467   result = IC_RESULT (ic);
9468
9469   if (getSize (operandType (result))>1)
9470     ifx = NULL;
9471
9472   /* depending on the type of pointer we need to
9473      move it to the correct pointer register */
9474   type = operandType (left);
9475   etype = getSpec (type);
9476   /* if left is of type of pointer then it is simple */
9477   if (IS_PTR (type) && !IS_FUNC (type->next))
9478     p_type = DCL_TYPE (type);
9479   else
9480     {
9481       /* we have to go by the storage class */
9482       p_type = PTR_TYPE (SPEC_OCLS (etype));
9483     }
9484
9485   /* special case when cast remat */
9486   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9487       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9488           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9489           type = operandType (left);
9490           p_type = DCL_TYPE (type);
9491   }
9492   /* now that we have the pointer type we assign
9493      the pointer values */
9494   switch (p_type)
9495     {
9496
9497     case POINTER:
9498     case IPOINTER:
9499       genNearPointerGet (left, result, ic, pi, ifx);
9500       break;
9501
9502     case PPOINTER:
9503       genPagedPointerGet (left, result, ic, pi, ifx);
9504       break;
9505
9506     case FPOINTER:
9507       genFarPointerGet (left, result, ic, pi, ifx);
9508       break;
9509
9510     case CPOINTER:
9511       genCodePointerGet (left, result, ic, pi, ifx);
9512       break;
9513
9514     case GPOINTER:
9515       genGenPointerGet (left, result, ic, pi, ifx);
9516       break;
9517     }
9518
9519 }
9520
9521
9522
9523 /*-----------------------------------------------------------------*/
9524 /* genPackBits - generates code for packed bit storage             */
9525 /*-----------------------------------------------------------------*/
9526 static void
9527 genPackBits (sym_link * etype,
9528              operand * right,
9529              char *rname, int p_type)
9530 {
9531   int offset = 0;       /* source byte offset */
9532   int rlen = 0;         /* remaining bitfield length */
9533   int blen;             /* bitfield length */
9534   int bstr;             /* bitfield starting bit within byte */
9535   int litval;           /* source literal value (if AOP_LIT) */
9536   unsigned char mask;   /* bitmask within current byte */
9537
9538   D(emitcode (";     genPackBits",""));
9539
9540   blen = SPEC_BLEN (etype);
9541   bstr = SPEC_BSTR (etype);
9542
9543   /* If the bitfield length is less than a byte */
9544   if (blen < 8)
9545     {
9546       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9547               (unsigned char) (0xFF >> (8 - bstr)));
9548
9549       if (AOP_TYPE (right) == AOP_LIT)
9550         {
9551           /* Case with a bitfield length <8 and literal source
9552           */
9553           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9554           litval <<= bstr;
9555           litval &= (~mask) & 0xff;
9556           emitPtrByteGet (rname, p_type, FALSE);
9557           if ((mask|litval)!=0xff)
9558             emitcode ("anl","a,#0x%02x", mask);
9559           if (litval)
9560             emitcode ("orl","a,#0x%02x", litval);
9561         }
9562       else
9563         {
9564           if ((blen==1) && (p_type!=GPOINTER))
9565             {
9566               /* Case with a bitfield length == 1 and no generic pointer
9567               */
9568               if (AOP_TYPE (right) == AOP_CRY)
9569                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9570               else
9571                 {
9572                   MOVA (aopGet (right, 0, FALSE, FALSE));
9573                   emitcode ("rrc","a");
9574                 }
9575               emitPtrByteGet (rname, p_type, FALSE);
9576               emitcode ("mov","acc.%d,c",bstr);
9577             }
9578           else
9579             {
9580               bool pushedB;
9581               /* Case with a bitfield length < 8 and arbitrary source
9582               */
9583               MOVA (aopGet (right, 0, FALSE, FALSE));
9584               /* shift and mask source value */
9585               AccLsh (bstr);
9586               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9587
9588               pushedB = pushB ();
9589               /* transfer A to B and get next byte */
9590               emitPtrByteGet (rname, p_type, TRUE);
9591
9592               emitcode ("anl", "a,#0x%02x", mask);
9593               emitcode ("orl", "a,b");
9594               if (p_type == GPOINTER)
9595                 emitcode ("pop", "b");
9596
9597               popB (pushedB);
9598            }
9599         }
9600
9601       emitPtrByteSet (rname, p_type, "a");
9602       return;
9603     }
9604
9605   /* Bit length is greater than 7 bits. In this case, copy  */
9606   /* all except the partial byte at the end                 */
9607   for (rlen=blen;rlen>=8;rlen-=8)
9608     {
9609       emitPtrByteSet (rname, p_type,
9610                       aopGet (right, offset++, FALSE, TRUE) );
9611       if (rlen>8)
9612         emitcode ("inc", "%s", rname);
9613     }
9614
9615   /* If there was a partial byte at the end */
9616   if (rlen)
9617     {
9618       mask = (((unsigned char) -1 << rlen) & 0xff);
9619
9620       if (AOP_TYPE (right) == AOP_LIT)
9621         {
9622           /* Case with partial byte and literal source
9623           */
9624           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9625           litval >>= (blen-rlen);
9626           litval &= (~mask) & 0xff;
9627           emitPtrByteGet (rname, p_type, FALSE);
9628           if ((mask|litval)!=0xff)
9629             emitcode ("anl","a,#0x%02x", mask);
9630           if (litval)
9631             emitcode ("orl","a,#0x%02x", litval);
9632         }
9633       else
9634         {
9635           bool pushedB;
9636           /* Case with partial byte and arbitrary source
9637           */
9638           MOVA (aopGet (right, offset++, FALSE, FALSE));
9639           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9640
9641           pushedB = pushB ();
9642           /* transfer A to B and get next byte */
9643           emitPtrByteGet (rname, p_type, TRUE);
9644
9645           emitcode ("anl", "a,#0x%02x", mask);
9646           emitcode ("orl", "a,b");
9647           if (p_type == GPOINTER)
9648             emitcode ("pop", "b");
9649
9650           popB (pushedB);
9651         }
9652       emitPtrByteSet (rname, p_type, "a");
9653     }
9654
9655 }
9656
9657
9658 /*-----------------------------------------------------------------*/
9659 /* genDataPointerSet - remat pointer to data space                 */
9660 /*-----------------------------------------------------------------*/
9661 static void
9662 genDataPointerSet (operand * right,
9663                    operand * result,
9664                    iCode * ic)
9665 {
9666   int size, offset = 0;
9667   char *l, buffer[256];
9668
9669   D(emitcode (";     genDataPointerSet",""));
9670
9671   aopOp (right, ic, FALSE);
9672
9673   l = aopGet (result, 0, FALSE, TRUE);
9674   size = AOP_SIZE (right);
9675   while (size--)
9676     {
9677       if (offset)
9678         sprintf (buffer, "(%s + %d)", l + 1, offset);
9679       else
9680         sprintf (buffer, "%s", l + 1);
9681       emitcode ("mov", "%s,%s", buffer,
9682                 aopGet (right, offset++, FALSE, FALSE));
9683     }
9684
9685   freeAsmop (right, NULL, ic, TRUE);
9686   freeAsmop (result, NULL, ic, TRUE);
9687 }
9688
9689 /*-----------------------------------------------------------------*/
9690 /* genNearPointerSet - emitcode for near pointer put                */
9691 /*-----------------------------------------------------------------*/
9692 static void
9693 genNearPointerSet (operand * right,
9694                    operand * result,
9695                    iCode * ic,
9696                    iCode * pi)
9697 {
9698   asmop *aop = NULL;
9699   regs *preg = NULL;
9700   char *rname, *l;
9701   sym_link *retype, *letype;
9702   sym_link *ptype = operandType (result);
9703
9704   D(emitcode (";     genNearPointerSet",""));
9705
9706   retype = getSpec (operandType (right));
9707   letype = getSpec (ptype);
9708   aopOp (result, ic, FALSE);
9709
9710   /* if the result is rematerializable &
9711      in data space & not a bit variable */
9712   if (AOP_TYPE (result) == AOP_IMMD &&
9713       DCL_TYPE (ptype) == POINTER &&
9714       !IS_BITVAR (retype) &&
9715       !IS_BITVAR (letype))
9716     {
9717       genDataPointerSet (right, result, ic);
9718       return;
9719     }
9720
9721   /* if the value is already in a pointer register
9722      then don't need anything more */
9723   if (!AOP_INPREG (AOP (result)))
9724     {
9725         if (
9726             //AOP_TYPE (result) == AOP_STK
9727             IS_AOP_PREG(result)
9728             )
9729         {
9730             // Aha, it is a pointer, just in disguise.
9731             rname = aopGet (result, 0, FALSE, FALSE);
9732             if (*rname != '@')
9733             {
9734                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9735                         __FILE__, __LINE__);
9736             }
9737             else
9738             {
9739                 // Expected case.
9740                 emitcode ("mov", "a%s,%s", rname + 1, rname);
9741                 rname++;  // skip the '@'.
9742             }
9743         }
9744         else
9745         {
9746             /* otherwise get a free pointer register */
9747             aop = newAsmop (0);
9748             preg = getFreePtr (ic, &aop, FALSE);
9749             emitcode ("mov", "%s,%s",
9750                       preg->name,
9751                       aopGet (result, 0, FALSE, TRUE));
9752             rname = preg->name;
9753         }
9754     }
9755     else
9756     {
9757         rname = aopGet (result, 0, FALSE, FALSE);
9758     }
9759
9760   aopOp (right, ic, FALSE);
9761
9762   /* if bitfield then unpack the bits */
9763   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9764     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9765   else
9766     {
9767       /* we have can just get the values */
9768       int size = AOP_SIZE (right);
9769       int offset = 0;
9770
9771       while (size--)
9772         {
9773           l = aopGet (right, offset, FALSE, TRUE);
9774           if (*l == '@')
9775             {
9776               MOVA (l);
9777               emitcode ("mov", "@%s,a", rname);
9778             }
9779           else
9780             emitcode ("mov", "@%s,%s", rname, l);
9781           if (size || pi)
9782             emitcode ("inc", "%s", rname);
9783           offset++;
9784         }
9785     }
9786
9787   /* now some housekeeping stuff */
9788   if (aop) /* we had to allocate for this iCode */
9789     {
9790       if (pi)
9791         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9792       freeAsmop (NULL, aop, ic, TRUE);
9793     }
9794   else
9795     {
9796       /* we did not allocate which means left
9797          already in a pointer register, then
9798          if size > 0 && this could be used again
9799          we have to point it back to where it
9800          belongs */
9801       if ((AOP_SIZE (right) > 1 &&
9802            !OP_SYMBOL (result)->remat &&
9803            (OP_SYMBOL (result)->liveTo > ic->seq ||
9804             ic->depth)) &&
9805           !pi)
9806         {
9807           int size = AOP_SIZE (right) - 1;
9808           while (size--)
9809             emitcode ("dec", "%s", rname);
9810         }
9811     }
9812
9813   /* done */
9814   if (pi) pi->generated = 1;
9815   freeAsmop (result, NULL, ic, TRUE);
9816   freeAsmop (right, NULL, ic, TRUE);
9817 }
9818
9819 /*-----------------------------------------------------------------*/
9820 /* genPagedPointerSet - emitcode for Paged pointer put             */
9821 /*-----------------------------------------------------------------*/
9822 static void
9823 genPagedPointerSet (operand * right,
9824                     operand * result,
9825                     iCode * ic,
9826                     iCode * pi)
9827 {
9828   asmop *aop = NULL;
9829   regs *preg = NULL;
9830   char *rname, *l;
9831   sym_link *retype, *letype;
9832
9833   D(emitcode (";     genPagedPointerSet",""));
9834
9835   retype = getSpec (operandType (right));
9836   letype = getSpec (operandType (result));
9837
9838   aopOp (result, ic, FALSE);
9839
9840   /* if the value is already in a pointer register
9841      then don't need anything more */
9842   if (!AOP_INPREG (AOP (result)))
9843     {
9844       /* otherwise get a free pointer register */
9845       aop = newAsmop (0);
9846       preg = getFreePtr (ic, &aop, FALSE);
9847       emitcode ("mov", "%s,%s",
9848                 preg->name,
9849                 aopGet (result, 0, FALSE, TRUE));
9850       rname = preg->name;
9851     }
9852   else
9853     rname = aopGet (result, 0, FALSE, FALSE);
9854
9855   aopOp (right, ic, FALSE);
9856
9857   /* if bitfield then unpack the bits */
9858   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9859     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9860   else
9861     {
9862       /* we have can just get the values */
9863       int size = AOP_SIZE (right);
9864       int offset = 0;
9865
9866       while (size--)
9867         {
9868           l = aopGet (right, offset, FALSE, TRUE);
9869
9870           MOVA (l);
9871           emitcode ("movx", "@%s,a", rname);
9872
9873           if (size || pi)
9874             emitcode ("inc", "%s", rname);
9875
9876           offset++;
9877         }
9878     }
9879
9880   /* now some housekeeping stuff */
9881   if (aop) /* we had to allocate for this iCode */
9882     {
9883       if (pi)
9884         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9885       freeAsmop (NULL, aop, ic, TRUE);
9886     }
9887   else
9888     {
9889       /* we did not allocate which means left
9890          already in a pointer register, then
9891          if size > 0 && this could be used again
9892          we have to point it back to where it
9893          belongs */
9894       if (AOP_SIZE (right) > 1 &&
9895           !OP_SYMBOL (result)->remat &&
9896           (OP_SYMBOL (result)->liveTo > ic->seq ||
9897            ic->depth))
9898         {
9899           int size = AOP_SIZE (right) - 1;
9900           while (size--)
9901             emitcode ("dec", "%s", rname);
9902         }
9903     }
9904
9905   /* done */
9906   if (pi) pi->generated = 1;
9907   freeAsmop (result, NULL, ic, TRUE);
9908   freeAsmop (right, NULL, ic, TRUE);
9909
9910
9911 }
9912
9913 /*-----------------------------------------------------------------*/
9914 /* genFarPointerSet - set value from far space                     */
9915 /*-----------------------------------------------------------------*/
9916 static void
9917 genFarPointerSet (operand * right,
9918                   operand * result, iCode * ic, iCode * pi)
9919 {
9920   int size, offset;
9921   sym_link *retype = getSpec (operandType (right));
9922   sym_link *letype = getSpec (operandType (result));
9923
9924   D(emitcode (";     genFarPointerSet",""));
9925
9926   aopOp (result, ic, FALSE);
9927   loadDptrFromOperand (result, FALSE);
9928
9929   /* so dptr know contains the address */
9930   aopOp (right, ic, FALSE);
9931
9932   /* if bit then unpack */
9933   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9934     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9935   else
9936     {
9937       size = AOP_SIZE (right);
9938       offset = 0;
9939
9940       while (size--)
9941         {
9942           char *l = aopGet (right, offset++, FALSE, FALSE);
9943           MOVA (l);
9944           emitcode ("movx", "@dptr,a");
9945           if (size || pi)
9946             emitcode ("inc", "dptr");
9947         }
9948     }
9949   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9950     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9951     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9952     pi->generated=1;
9953   }
9954   freeAsmop (result, NULL, ic, TRUE);
9955   freeAsmop (right, NULL, ic, TRUE);
9956 }
9957
9958 /*-----------------------------------------------------------------*/
9959 /* genGenPointerSet - set value from generic pointer space         */
9960 /*-----------------------------------------------------------------*/
9961 static void
9962 genGenPointerSet (operand * right,
9963                   operand * result, iCode * ic, iCode * pi)
9964 {
9965   int size, offset;
9966   sym_link *retype = getSpec (operandType (right));
9967   sym_link *letype = getSpec (operandType (result));
9968
9969   D(emitcode (";     genGenPointerSet",""));
9970
9971   aopOp (result, ic, FALSE);
9972   loadDptrFromOperand (result, TRUE);
9973
9974   /* so dptr know contains the address */
9975   aopOp (right, ic, FALSE);
9976
9977   /* if bit then unpack */
9978   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9979     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9980   else
9981     {
9982       size = AOP_SIZE (right);
9983       offset = 0;
9984
9985       while (size--)
9986         {
9987           char *l = aopGet (right, offset++, FALSE, FALSE);
9988           MOVA (l);
9989           emitcode ("lcall", "__gptrput");
9990           if (size || pi)
9991             emitcode ("inc", "dptr");
9992         }
9993     }
9994
9995   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9996     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9997     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9998     pi->generated=1;
9999   }
10000   freeAsmop (result, NULL, ic, TRUE);
10001   freeAsmop (right, NULL, ic, TRUE);
10002 }
10003
10004 /*-----------------------------------------------------------------*/
10005 /* genPointerSet - stores the value into a pointer location        */
10006 /*-----------------------------------------------------------------*/
10007 static void
10008 genPointerSet (iCode * ic, iCode *pi)
10009 {
10010   operand *right, *result;
10011   sym_link *type, *etype;
10012   int p_type;
10013
10014   D(emitcode (";     genPointerSet",""));
10015
10016   right = IC_RIGHT (ic);
10017   result = IC_RESULT (ic);
10018
10019   /* depending on the type of pointer we need to
10020      move it to the correct pointer register */
10021   type = operandType (result);
10022   etype = getSpec (type);
10023   /* if left is of type of pointer then it is simple */
10024   if (IS_PTR (type) && !IS_FUNC (type->next))
10025     {
10026       p_type = DCL_TYPE (type);
10027     }
10028   else
10029     {
10030       /* we have to go by the storage class */
10031       p_type = PTR_TYPE (SPEC_OCLS (etype));
10032     }
10033
10034   /* special case when cast remat */
10035   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10036       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10037           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10038           type = operandType (result);
10039           p_type = DCL_TYPE (type);
10040   }
10041   /* now that we have the pointer type we assign
10042      the pointer values */
10043   switch (p_type)
10044     {
10045
10046     case POINTER:
10047     case IPOINTER:
10048       genNearPointerSet (right, result, ic, pi);
10049       break;
10050
10051     case PPOINTER:
10052       genPagedPointerSet (right, result, ic, pi);
10053       break;
10054
10055     case FPOINTER:
10056       genFarPointerSet (right, result, ic, pi);
10057       break;
10058
10059     case GPOINTER:
10060       genGenPointerSet (right, result, ic, pi);
10061       break;
10062
10063     default:
10064       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10065               "genPointerSet: illegal pointer type");
10066     }
10067
10068 }
10069
10070 /*-----------------------------------------------------------------*/
10071 /* genIfx - generate code for Ifx statement                        */
10072 /*-----------------------------------------------------------------*/
10073 static void
10074 genIfx (iCode * ic, iCode * popIc)
10075 {
10076   operand *cond = IC_COND (ic);
10077   int isbit = 0;
10078   char *dup = NULL;
10079
10080   D(emitcode (";     genIfx",""));
10081
10082   aopOp (cond, ic, FALSE);
10083
10084   /* get the value into acc */
10085   if (AOP_TYPE (cond) != AOP_CRY)
10086     toBoolean (cond);
10087   else
10088     {
10089       isbit = 1;
10090       if (AOP(cond)->aopu.aop_dir)
10091         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10092     }
10093   /* the result is now in the accumulator or a directly addressable bit */
10094   freeAsmop (cond, NULL, ic, TRUE);
10095
10096   /* if there was something to be popped then do it */
10097   if (popIc)
10098     genIpop (popIc);
10099
10100   /* if the condition is a bit variable */
10101   if (isbit && dup)
10102     genIfxJump(ic, dup, NULL, NULL, NULL);
10103   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10104     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10105   else if (isbit && !IS_ITEMP (cond))
10106     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10107   else
10108     genIfxJump (ic, "a", NULL, NULL, NULL);
10109
10110   ic->generated = 1;
10111 }
10112
10113 /*-----------------------------------------------------------------*/
10114 /* genAddrOf - generates code for address of                       */
10115 /*-----------------------------------------------------------------*/
10116 static void
10117 genAddrOf (iCode * ic)
10118 {
10119   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10120   int size, offset;
10121
10122   D(emitcode (";     genAddrOf",""));
10123
10124   aopOp (IC_RESULT (ic), ic, FALSE);
10125
10126   /* if the operand is on the stack then we
10127      need to get the stack offset of this
10128      variable */
10129   if (sym->onStack)
10130     {
10131       /* if it has an offset then we need to compute
10132          it */
10133       if (sym->stack)
10134         {
10135           emitcode ("mov", "a,%s", SYM_BP (sym));
10136           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10137                                          ((char) (sym->stack - _G.nRegsSaved)) :
10138                                          ((char) sym->stack)) & 0xff);
10139           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10140         }
10141       else
10142         {
10143           /* we can just move _bp */
10144           aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10145         }
10146       /* fill the result with zero */
10147       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10148
10149       offset = 1;
10150       while (size--)
10151         {
10152           aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10153         }
10154
10155       goto release;
10156     }
10157
10158   /* object not on stack then we need the name */
10159   size = AOP_SIZE (IC_RESULT (ic));
10160   offset = 0;
10161
10162   while (size--)
10163     {
10164       char s[SDCC_NAME_MAX];
10165       if (offset)
10166         sprintf (s, "#(%s >> %d)",
10167                  sym->rname,
10168                  offset * 8);
10169       else
10170         sprintf (s, "#%s", sym->rname);
10171       aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10172     }
10173
10174 release:
10175   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10176
10177 }
10178
10179 /*-----------------------------------------------------------------*/
10180 /* genFarFarAssign - assignment when both are in far space         */
10181 /*-----------------------------------------------------------------*/
10182 static void
10183 genFarFarAssign (operand * result, operand * right, iCode * ic)
10184 {
10185   int size = AOP_SIZE (right);
10186   int offset = 0;
10187   char *l;
10188
10189   D(emitcode (";     genFarFarAssign",""));
10190
10191   /* first push the right side on to the stack */
10192   while (size--)
10193     {
10194       l = aopGet (right, offset++, FALSE, FALSE);
10195       MOVA (l);
10196       emitcode ("push", "acc");
10197     }
10198
10199   freeAsmop (right, NULL, ic, FALSE);
10200   /* now assign DPTR to result */
10201   aopOp (result, ic, FALSE);
10202   size = AOP_SIZE (result);
10203   while (size--)
10204     {
10205       emitcode ("pop", "acc");
10206       aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10207     }
10208   freeAsmop (result, NULL, ic, FALSE);
10209
10210 }
10211
10212 /*-----------------------------------------------------------------*/
10213 /* genAssign - generate code for assignment                        */
10214 /*-----------------------------------------------------------------*/
10215 static void
10216 genAssign (iCode * ic)
10217 {
10218   operand *result, *right;
10219   int size, offset;
10220   unsigned long lit = 0L;
10221
10222   D(emitcode(";     genAssign",""));
10223
10224   result = IC_RESULT (ic);
10225   right = IC_RIGHT (ic);
10226
10227   /* if they are the same */
10228   if (operandsEqu (result, right) &&
10229       !isOperandVolatile (result, FALSE) &&
10230       !isOperandVolatile (right, FALSE))
10231     return;
10232
10233   aopOp (right, ic, FALSE);
10234
10235   /* special case both in far space */
10236   if (AOP_TYPE (right) == AOP_DPTR &&
10237       IS_TRUE_SYMOP (result) &&
10238       isOperandInFarSpace (result))
10239     {
10240
10241       genFarFarAssign (result, right, ic);
10242       return;
10243     }
10244
10245   aopOp (result, ic, TRUE);
10246
10247   /* if they are the same registers */
10248   if (sameRegs (AOP (right), AOP (result)) &&
10249       !isOperandVolatile (result, FALSE) &&
10250       !isOperandVolatile (right, FALSE))
10251     goto release;
10252
10253   /* if the result is a bit */
10254   if (AOP_TYPE (result) == AOP_CRY)
10255     {
10256
10257       /* if the right size is a literal then
10258          we know what the value is */
10259       if (AOP_TYPE (right) == AOP_LIT)
10260         {
10261           if (((int) operandLitValue (right)))
10262             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10263           else
10264             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10265           goto release;
10266         }
10267
10268       /* the right is also a bit variable */
10269       if (AOP_TYPE (right) == AOP_CRY)
10270         {
10271           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10272           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10273           goto release;
10274         }
10275
10276       /* we need to or */
10277       toBoolean (right);
10278       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10279       goto release;
10280     }
10281
10282   /* bit variables done */
10283   /* general case */
10284   size = AOP_SIZE (result);
10285   offset = 0;
10286   if (AOP_TYPE (right) == AOP_LIT)
10287     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10288   if ((size > 1) &&
10289       (AOP_TYPE (result) != AOP_REG) &&
10290       (AOP_TYPE (right) == AOP_LIT) &&
10291       !IS_FLOAT (operandType (right)) &&
10292       (lit < 256L))
10293     {
10294       while ((size) && (lit))
10295         {
10296           aopPut (result,
10297                   aopGet (right, offset, FALSE, FALSE),
10298                   offset,
10299                   isOperandVolatile (result, FALSE));
10300           lit >>= 8;
10301           offset++;
10302           size--;
10303         }
10304       emitcode ("clr", "a");
10305       while (size--)
10306         {
10307           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10308           offset++;
10309         }
10310     }
10311   else
10312     {
10313       while (size--)
10314         {
10315           aopPut (result,
10316                   aopGet (right, offset, FALSE, FALSE),
10317                   offset,
10318                   isOperandVolatile (result, FALSE));
10319           offset++;
10320         }
10321     }
10322
10323 release:
10324   freeAsmop (right, NULL, ic, TRUE);
10325   freeAsmop (result, NULL, ic, TRUE);
10326 }
10327
10328 /*-----------------------------------------------------------------*/
10329 /* genJumpTab - generates code for jump table                      */
10330 /*-----------------------------------------------------------------*/
10331 static void
10332 genJumpTab (iCode * ic)
10333 {
10334   symbol *jtab,*jtablo,*jtabhi;
10335   char *l;
10336   unsigned int count;
10337
10338   D(emitcode (";     genJumpTab",""));
10339
10340   count = elementsInSet( IC_JTLABELS (ic) );
10341
10342   if( count <= 16 )
10343     {
10344       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10345          if the switch argument is in a register.
10346          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10347       /* (MB) What if peephole converts ljmp to sjmp or ret ???
10348          How will multiply by three be updated ???*/
10349       aopOp (IC_JTCOND (ic), ic, FALSE);
10350       /* get the condition into accumulator */
10351       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10352       MOVA (l);
10353       /* multiply by three */
10354       emitcode ("add", "a,acc");
10355       emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10356       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10357
10358       jtab = newiTempLabel (NULL);
10359       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10360       emitcode ("jmp", "@a+dptr");
10361       emitcode ("", "%05d$:", jtab->key + 100);
10362       /* now generate the jump labels */
10363       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10364            jtab = setNextItem (IC_JTLABELS (ic)))
10365         emitcode ("ljmp", "%05d$", jtab->key + 100);
10366     }
10367   else
10368     {
10369       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10370          if the switch argument is in a register.
10371          For n>6 this algorithm may be more compact */
10372       jtablo = newiTempLabel (NULL);
10373       jtabhi = newiTempLabel (NULL);
10374
10375       /* get the condition into accumulator.
10376          Using b as temporary storage, if register push/pop is needed */
10377       aopOp (IC_JTCOND (ic), ic, FALSE);
10378       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10379       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10380           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10381         {
10382           // (MB) what if B is in use???
10383           wassertl(!BINUSE, "B was in use");
10384           emitcode ("mov", "b,%s", l);
10385           l = "b";
10386         }
10387       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10388       MOVA (l);
10389       if( count <= 112 )
10390         {
10391           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10392           emitcode ("movc", "a,@a+pc");
10393           emitcode ("push", "acc");
10394
10395           MOVA (l);
10396           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10397           emitcode ("movc", "a,@a+pc");
10398           emitcode ("push", "acc");
10399         }
10400       else
10401         {
10402           /* this scales up to n<=255, but needs two more bytes
10403              and changes dptr */
10404           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10405           emitcode ("movc", "a,@a+dptr");
10406           emitcode ("push", "acc");
10407
10408           MOVA (l);
10409           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10410           emitcode ("movc", "a,@a+dptr");
10411           emitcode ("push", "acc");
10412         }
10413
10414       emitcode ("ret", "");
10415
10416       /* now generate jump table, LSB */
10417       emitcode ("", "%05d$:", jtablo->key + 100);
10418       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10419            jtab = setNextItem (IC_JTLABELS (ic)))
10420         emitcode (".db", "%05d$", jtab->key + 100);
10421
10422       /* now generate jump table, MSB */
10423       emitcode ("", "%05d$:", jtabhi->key + 100);
10424       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10425            jtab = setNextItem (IC_JTLABELS (ic)))
10426          emitcode (".db", "%05d$>>8", jtab->key + 100);
10427     }
10428 }
10429
10430 /*-----------------------------------------------------------------*/
10431 /* genCast - gen code for casting                                  */
10432 /*-----------------------------------------------------------------*/
10433 static void
10434 genCast (iCode * ic)
10435 {
10436   operand *result = IC_RESULT (ic);
10437   sym_link *ctype = operandType (IC_LEFT (ic));
10438   sym_link *rtype = operandType (IC_RIGHT (ic));
10439   operand *right = IC_RIGHT (ic);
10440   int size, offset;
10441
10442   D(emitcode(";     genCast",""));
10443
10444   /* if they are equivalent then do nothing */
10445   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10446     return;
10447
10448   aopOp (right, ic, FALSE);
10449   aopOp (result, ic, FALSE);
10450
10451   /* if the result is a bit (and not a bitfield) */
10452   // if (AOP_TYPE (result) == AOP_CRY)
10453   if (IS_BITVAR (OP_SYMBOL (result)->type)
10454       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10455     {
10456       /* if the right size is a literal then
10457          we know what the value is */
10458       if (AOP_TYPE (right) == AOP_LIT)
10459         {
10460           if (((int) operandLitValue (right)))
10461             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10462           else
10463             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10464
10465           goto release;
10466         }
10467
10468       /* the right is also a bit variable */
10469       if (AOP_TYPE (right) == AOP_CRY)
10470         {
10471           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10472           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10473           goto release;
10474         }
10475
10476       /* we need to or */
10477       toBoolean (right);
10478       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10479       goto release;
10480     }
10481
10482
10483   /* if they are the same size : or less */
10484   if (AOP_SIZE (result) <= AOP_SIZE (right))
10485     {
10486
10487       /* if they are in the same place */
10488       if (sameRegs (AOP (right), AOP (result)))
10489         goto release;
10490
10491       /* if they in different places then copy */
10492       size = AOP_SIZE (result);
10493       offset = 0;
10494       while (size--)
10495         {
10496           aopPut (result,
10497                   aopGet (right, offset, FALSE, FALSE),
10498                   offset,
10499                   isOperandVolatile (result, FALSE));
10500           offset++;
10501         }
10502       goto release;
10503     }
10504
10505
10506   /* if the result is of type pointer */
10507   if (IS_PTR (ctype))
10508     {
10509
10510       int p_type;
10511       sym_link *type = operandType (right);
10512       sym_link *etype = getSpec (type);
10513
10514       /* pointer to generic pointer */
10515       if (IS_GENPTR (ctype))
10516         {
10517           if (IS_PTR (type))
10518             p_type = DCL_TYPE (type);
10519           else
10520             {
10521               if (SPEC_SCLS(etype)==S_REGISTER) {
10522                 // let's assume it is a generic pointer
10523                 p_type=GPOINTER;
10524               } else {
10525                 /* we have to go by the storage class */
10526                 p_type = PTR_TYPE (SPEC_OCLS (etype));
10527               }
10528             }
10529
10530           /* the first two bytes are known */
10531           size = GPTRSIZE - 1;
10532           offset = 0;
10533           while (size--)
10534             {
10535               aopPut (result,
10536                       aopGet (right, offset, FALSE, FALSE),
10537                       offset,
10538                       isOperandVolatile (result, FALSE));
10539               offset++;
10540             }
10541           /* the last byte depending on type */
10542             {
10543                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10544                 char gpValStr[10];
10545
10546                 if (gpVal == -1)
10547                 {
10548                     // pointerTypeToGPByte will have bitched.
10549                     exit(1);
10550                 }
10551
10552                 sprintf(gpValStr, "#0x%x", gpVal);
10553                 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10554             }
10555           goto release;
10556         }
10557
10558       /* just copy the pointers */
10559       size = AOP_SIZE (result);
10560       offset = 0;
10561       while (size--)
10562         {
10563           aopPut (result,
10564                   aopGet (right, offset, FALSE, FALSE),
10565                   offset,
10566                   isOperandVolatile (result, FALSE));
10567           offset++;
10568         }
10569       goto release;
10570     }
10571
10572   /* so we now know that the size of destination is greater
10573      than the size of the source */
10574   /* we move to result for the size of source */
10575   size = AOP_SIZE (right);
10576   offset = 0;
10577   while (size--)
10578     {
10579       aopPut (result,
10580               aopGet (right, offset, FALSE, FALSE),
10581               offset,
10582               isOperandVolatile (result, FALSE));
10583       offset++;
10584     }
10585
10586   /* now depending on the sign of the source && destination */
10587   size = AOP_SIZE (result) - AOP_SIZE (right);
10588   /* if unsigned or not an integral type */
10589   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10590     {
10591       while (size--)
10592         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10593     }
10594   else
10595     {
10596       /* we need to extend the sign :{ */
10597       char *l = aopGet (right, AOP_SIZE (right) - 1,
10598                         FALSE, FALSE);
10599       MOVA (l);
10600       emitcode ("rlc", "a");
10601       emitcode ("subb", "a,acc");
10602       while (size--)
10603         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10604     }
10605
10606   /* we are done hurray !!!! */
10607
10608 release:
10609   freeAsmop (right, NULL, ic, TRUE);
10610   freeAsmop (result, NULL, ic, TRUE);
10611
10612 }
10613
10614 /*-----------------------------------------------------------------*/
10615 /* genDjnz - generate decrement & jump if not zero instrucion      */
10616 /*-----------------------------------------------------------------*/
10617 static int
10618 genDjnz (iCode * ic, iCode * ifx)
10619 {
10620   symbol *lbl, *lbl1;
10621   if (!ifx)
10622     return 0;
10623
10624   D(emitcode (";     genDjnz",""));
10625
10626   /* if the if condition has a false label
10627      then we cannot save */
10628   if (IC_FALSE (ifx))
10629     return 0;
10630
10631   /* if the minus is not of the form
10632      a = a - 1 */
10633   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10634       !IS_OP_LITERAL (IC_RIGHT (ic)))
10635     return 0;
10636
10637   if (operandLitValue (IC_RIGHT (ic)) != 1)
10638     return 0;
10639
10640   /* if the size of this greater than one then no
10641      saving */
10642   if (getSize (operandType (IC_RESULT (ic))) > 1)
10643     return 0;
10644
10645   /* otherwise we can save BIG */
10646   lbl = newiTempLabel (NULL);
10647   lbl1 = newiTempLabel (NULL);
10648
10649   aopOp (IC_RESULT (ic), ic, FALSE);
10650
10651   if (AOP_NEEDSACC(IC_RESULT(ic)))
10652   {
10653       /* If the result is accessed indirectly via
10654        * the accumulator, we must explicitly write
10655        * it back after the decrement.
10656        */
10657       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10658
10659       if (strcmp(rByte, "a"))
10660       {
10661            /* Something is hopelessly wrong */
10662            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10663                    __FILE__, __LINE__);
10664            /* We can just give up; the generated code will be inefficient,
10665             * but what the hey.
10666             */
10667            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10668            return 0;
10669       }
10670       emitcode ("dec", "%s", rByte);
10671       aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10672       emitcode ("jnz", "%05d$", lbl->key + 100);
10673   }
10674   else if (IS_AOP_PREG (IC_RESULT (ic)))
10675     {
10676       emitcode ("dec", "%s",
10677                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10678       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10679       emitcode ("jnz", "%05d$", lbl->key + 100);
10680     }
10681   else
10682     {
10683       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10684                 lbl->key + 100);
10685     }
10686   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10687   emitcode ("", "%05d$:", lbl->key + 100);
10688   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10689   emitcode ("", "%05d$:", lbl1->key + 100);
10690
10691   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10692   ifx->generated = 1;
10693   return 1;
10694 }
10695
10696 /*-----------------------------------------------------------------*/
10697 /* genReceive - generate code for a receive iCode                  */
10698 /*-----------------------------------------------------------------*/
10699 static void
10700 genReceive (iCode * ic)
10701 {
10702   int size = getSize (operandType (IC_RESULT (ic)));
10703   int offset = 0;
10704
10705   D(emitcode (";     genReceive",""));
10706
10707   if (ic->argreg == 1)
10708     { /* first parameter */
10709       if (isOperandInFarSpace (IC_RESULT (ic)) &&
10710           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10711            IS_TRUE_SYMOP (IC_RESULT (ic))))
10712         {
10713           regs *tempRegs[4];
10714           int receivingA = 0;
10715           int roffset = 0;
10716
10717           for (offset = 0; offset<size; offset++)
10718             if (!strcmp (fReturn[offset], "a"))
10719               receivingA = 1;
10720
10721           if (!receivingA)
10722             {
10723               if (size==1 || getTempRegs(tempRegs, size-1, ic))
10724                 {
10725                   for (offset = size-1; offset>0; offset--)
10726                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10727                   emitcode("mov","a,%s", fReturn[0]);
10728                   _G.accInUse++;
10729                   aopOp (IC_RESULT (ic), ic, FALSE);
10730                   _G.accInUse--;
10731                   aopPut (IC_RESULT (ic), "a", offset,
10732                           isOperandVolatile (IC_RESULT (ic), FALSE));
10733                   for (offset = 1; offset<size; offset++)
10734                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10735                             isOperandVolatile (IC_RESULT (ic), FALSE));
10736                   goto release;
10737                 }
10738             }
10739           else
10740             {
10741               if (getTempRegs(tempRegs, size, ic))
10742                 {
10743                   for (offset = 0; offset<size; offset++)
10744                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10745                   aopOp (IC_RESULT (ic), ic, FALSE);
10746                   for (offset = 0; offset<size; offset++)
10747                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10748                             isOperandVolatile (IC_RESULT (ic), FALSE));
10749                   goto release;
10750                 }
10751             }
10752
10753           offset = fReturnSizeMCS51 - size;
10754           while (size--)
10755             {
10756               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10757                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10758               offset++;
10759             }
10760           aopOp (IC_RESULT (ic), ic, FALSE);
10761           size = AOP_SIZE (IC_RESULT (ic));
10762           offset = 0;
10763           while (size--)
10764             {
10765               emitcode ("pop", "acc");
10766               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10767             }
10768         }
10769       else
10770         {
10771           _G.accInUse++;
10772           aopOp (IC_RESULT (ic), ic, FALSE);
10773           _G.accInUse--;
10774           assignResultValue (IC_RESULT (ic), NULL);
10775         }
10776     }
10777   else if (ic->argreg > 12)
10778     { /* bit parameters */
10779       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
10780         {
10781           aopOp (IC_RESULT (ic), ic, FALSE);
10782           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
10783           outBitC(IC_RESULT (ic));
10784         }
10785     }
10786   else
10787     { /* other parameters */
10788       int rb1off ;
10789       aopOp (IC_RESULT (ic), ic, FALSE);
10790       rb1off = ic->argreg;
10791       while (size--)
10792         {
10793           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10794         }
10795     }
10796
10797 release:
10798   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10799 }
10800
10801 /*-----------------------------------------------------------------*/
10802 /* genDummyRead - generate code for dummy read of volatiles        */
10803 /*-----------------------------------------------------------------*/
10804 static void
10805 genDummyRead (iCode * ic)
10806 {
10807   operand *op;
10808   int size, offset;
10809
10810   D(emitcode(";     genDummyRead",""));
10811
10812   op = IC_RIGHT (ic);
10813   if (op && IS_SYMOP (op))
10814     {
10815       aopOp (op, ic, FALSE);
10816
10817       /* if the result is a bit */
10818       if (AOP_TYPE (op) == AOP_CRY)
10819         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10820       else
10821         {
10822           /* bit variables done */
10823           /* general case */
10824           size = AOP_SIZE (op);
10825           offset = 0;
10826           while (size--)
10827           {
10828             MOVA (aopGet (op, offset, FALSE, FALSE));
10829             offset++;
10830           }
10831         }
10832
10833       freeAsmop (op, NULL, ic, TRUE);
10834     }
10835
10836   op = IC_LEFT (ic);
10837   if (op && IS_SYMOP (op))
10838     {
10839       aopOp (op, ic, FALSE);
10840
10841       /* if the result is a bit */
10842       if (AOP_TYPE (op) == AOP_CRY)
10843         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10844       else
10845         {
10846           /* bit variables done */
10847           /* general case */
10848           size = AOP_SIZE (op);
10849           offset = 0;
10850           while (size--)
10851           {
10852             MOVA (aopGet (op, offset, FALSE, FALSE));
10853             offset++;
10854           }
10855         }
10856
10857       freeAsmop (op, NULL, ic, TRUE);
10858     }
10859 }
10860
10861 /*-----------------------------------------------------------------*/
10862 /* genCritical - generate code for start of a critical sequence    */
10863 /*-----------------------------------------------------------------*/
10864 static void
10865 genCritical (iCode *ic)
10866 {
10867   symbol *tlbl = newiTempLabel (NULL);
10868
10869   D(emitcode(";     genCritical",""));
10870
10871   if (IC_RESULT (ic))
10872     {
10873       aopOp (IC_RESULT (ic), ic, TRUE);
10874       aopPut (IC_RESULT (ic), one, 0, 0);
10875       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10876       aopPut (IC_RESULT (ic), zero, 0, 0);
10877       emitcode ("", "%05d$:", (tlbl->key + 100));
10878       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10879     }
10880   else
10881     {
10882       emitcode ("setb", "c");
10883       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10884       emitcode ("clr", "c");
10885       emitcode ("", "%05d$:", (tlbl->key + 100));
10886       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10887     }
10888 }
10889
10890 /*-----------------------------------------------------------------*/
10891 /* genEndCritical - generate code for end of a critical sequence   */
10892 /*-----------------------------------------------------------------*/
10893 static void
10894 genEndCritical (iCode *ic)
10895 {
10896   D(emitcode(";     genEndCritical",""));
10897
10898   if (IC_RIGHT (ic))
10899     {
10900       aopOp (IC_RIGHT (ic), ic, FALSE);
10901       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10902         {
10903           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10904           emitcode ("mov", "ea,c");
10905         }
10906       else
10907         {
10908           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10909             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10910           emitcode ("rrc", "a");
10911           emitcode ("mov", "ea,c");
10912         }
10913       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10914     }
10915   else
10916     {
10917       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10918       emitcode ("mov", "ea,c");
10919     }
10920 }
10921
10922 /*-----------------------------------------------------------------*/
10923 /* gen51Code - generate code for 8051 based controllers            */
10924 /*-----------------------------------------------------------------*/
10925 void
10926 gen51Code (iCode * lic)
10927 {
10928   iCode *ic;
10929   int cln = 0;
10930   /* int cseq = 0; */
10931
10932   _G.currentFunc = NULL;
10933   lineHead = lineCurr = NULL;
10934
10935   /* print the allocation information */
10936   if (allocInfo && currFunc)
10937     printAllocInfo (currFunc, codeOutFile);
10938   /* if debug information required */
10939   if (options.debug && currFunc)
10940     {
10941       debugFile->writeFunction (currFunc, lic);
10942     }
10943   /* stack pointer name */
10944   if (options.useXstack)
10945     spname = "_spx";
10946   else
10947     spname = "sp";
10948
10949
10950   for (ic = lic; ic; ic = ic->next)
10951     {
10952       _G.current_iCode = ic;
10953
10954       if (ic->lineno && cln != ic->lineno)
10955         {
10956           if (options.debug)
10957             {
10958               debugFile->writeCLine (ic);
10959             }
10960           if (!options.noCcodeInAsm) {
10961             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10962                       printCLine(ic->filename, ic->lineno));
10963           }
10964           cln = ic->lineno;
10965         }
10966       #if 0
10967       if (ic->seqPoint && ic->seqPoint != cseq)
10968         {
10969           emitcode ("", "; sequence point %d", ic->seqPoint);
10970           cseq = ic->seqPoint;
10971         }
10972       #endif
10973       if (options.iCodeInAsm) {
10974         char regsInUse[80];
10975         int i;
10976
10977         for (i=0; i<8; i++) {
10978           sprintf (&regsInUse[i],
10979                    "%c", ic->riu & (1<<i) ? i+'0' : '-');
10980         }
10981         regsInUse[i]=0;
10982         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10983       }
10984       /* if the result is marked as
10985          spilt and rematerializable or code for
10986          this has already been generated then
10987          do nothing */
10988       if (resultRemat (ic) || ic->generated)
10989         continue;
10990
10991       /* depending on the operation */
10992       switch (ic->op)
10993         {
10994         case '!':
10995           genNot (ic);
10996           break;
10997
10998         case '~':
10999           genCpl (ic);
11000           break;
11001
11002         case UNARYMINUS:
11003           genUminus (ic);
11004           break;
11005
11006         case IPUSH:
11007           genIpush (ic);
11008           break;
11009
11010         case IPOP:
11011           /* IPOP happens only when trying to restore a
11012              spilt live range, if there is an ifx statement
11013              following this pop then the if statement might
11014              be using some of the registers being popped which
11015              would destory the contents of the register so
11016              we need to check for this condition and handle it */
11017           if (ic->next &&
11018               ic->next->op == IFX &&
11019               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11020             genIfx (ic->next, ic);
11021           else
11022             genIpop (ic);
11023           break;
11024
11025         case CALL:
11026           genCall (ic);
11027           break;
11028
11029         case PCALL:
11030           genPcall (ic);
11031           break;
11032
11033         case FUNCTION:
11034           genFunction (ic);
11035           break;
11036
11037         case ENDFUNCTION:
11038           genEndFunction (ic);
11039           break;
11040
11041         case RETURN:
11042           genRet (ic);
11043           break;
11044
11045         case LABEL:
11046           genLabel (ic);
11047           break;
11048
11049         case GOTO:
11050           genGoto (ic);
11051           break;
11052
11053         case '+':
11054           genPlus (ic);
11055           break;
11056
11057         case '-':
11058           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11059             genMinus (ic);
11060           break;
11061
11062         case '*':
11063           genMult (ic);
11064           break;
11065
11066         case '/':
11067           genDiv (ic);
11068           break;
11069
11070         case '%':
11071           genMod (ic);
11072           break;
11073
11074         case '>':
11075           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11076           break;
11077
11078         case '<':
11079           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11080           break;
11081
11082         case LE_OP:
11083         case GE_OP:
11084         case NE_OP:
11085
11086           /* note these two are xlated by algebraic equivalence
11087              during parsing SDCC.y */
11088           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11089                   "got '>=' or '<=' shouldn't have come here");
11090           break;
11091
11092         case EQ_OP:
11093           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11094           break;
11095
11096         case AND_OP:
11097           genAndOp (ic);
11098           break;
11099
11100         case OR_OP:
11101           genOrOp (ic);
11102           break;
11103
11104         case '^':
11105           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11106           break;
11107
11108         case '|':
11109           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11110           break;
11111
11112         case BITWISEAND:
11113           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11114           break;
11115
11116         case INLINEASM:
11117           genInline (ic);
11118           break;
11119
11120         case RRC:
11121           genRRC (ic);
11122           break;
11123
11124         case RLC:
11125           genRLC (ic);
11126           break;
11127
11128         case GETHBIT:
11129           genGetHbit (ic);
11130           break;
11131
11132         case LEFT_OP:
11133           genLeftShift (ic);
11134           break;
11135
11136         case RIGHT_OP:
11137           genRightShift (ic);
11138           break;
11139
11140         case GET_VALUE_AT_ADDRESS:
11141           genPointerGet (ic,
11142                          hasInc (IC_LEFT (ic), ic,
11143                                  getSize (operandType (IC_RESULT (ic)))),
11144                          ifxForOp (IC_RESULT (ic), ic) );
11145           break;
11146
11147         case '=':
11148           if (POINTER_SET (ic))
11149             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11150           else
11151             genAssign (ic);
11152           break;
11153
11154         case IFX:
11155           genIfx (ic, NULL);
11156           break;
11157
11158         case ADDRESS_OF:
11159           genAddrOf (ic);
11160           break;
11161
11162         case JUMPTABLE:
11163           genJumpTab (ic);
11164           break;
11165
11166         case CAST:
11167           genCast (ic);
11168           break;
11169
11170         case RECEIVE:
11171           genReceive (ic);
11172           break;
11173
11174         case SEND:
11175           addSet (&_G.sendSet, ic);
11176           break;
11177
11178         case DUMMY_READ_VOLATILE:
11179           genDummyRead (ic);
11180           break;
11181
11182         case CRITICAL:
11183           genCritical (ic);
11184           break;
11185
11186         case ENDCRITICAL:
11187           genEndCritical (ic);
11188           break;
11189
11190         case SWAP:
11191           genSwap (ic);
11192           break;
11193
11194         default:
11195           ic = ic;
11196         }
11197     }
11198
11199   _G.current_iCode = NULL;
11200
11201   /* now we are ready to call the
11202      peep hole optimizer */
11203   if (!options.nopeep)
11204     peepHole (&lineHead);
11205
11206   /* now do the actual printing */
11207   printLine (lineHead, codeOutFile);
11208   return;
11209 }