* support/regression/tests/bug1409955.c: new, added
[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 0;
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   aop->allocated = 1;
476   return aop;
477 }
478
479 /*-----------------------------------------------------------------*/
480 /* pointerCode - returns the code for a pointer type               */
481 /*-----------------------------------------------------------------*/
482 static int
483 pointerCode (sym_link * etype)
484 {
485
486   return PTR_TYPE (SPEC_OCLS (etype));
487
488 }
489
490 /*-----------------------------------------------------------------*/
491 /* leftRightUseAcc - returns size of accumulator use by operands   */
492 /*-----------------------------------------------------------------*/
493 static int
494 leftRightUseAcc(iCode *ic)
495 {
496   operand *op;
497   int size;
498   int accuseSize = 0;
499   int accuse = 0;
500
501   if (!ic)
502     {
503       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
504               "null iCode pointer");
505       return 0;
506     }
507
508   if (ic->op == IFX)
509     {
510       op = IC_COND (ic);
511       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
512         {
513           accuse = 1;
514           size = getSize (OP_SYMBOL (op)->type);
515           if (size>accuseSize)
516             accuseSize = size;
517         }
518     }
519   else if (ic->op == JUMPTABLE)
520     {
521       op = IC_JTCOND (ic);
522       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
523         {
524           accuse = 1;
525           size = getSize (OP_SYMBOL (op)->type);
526           if (size>accuseSize)
527             accuseSize = size;
528         }
529     }
530   else
531     {
532       op = IC_LEFT (ic);
533       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
534         {
535           accuse = 1;
536           size = getSize (OP_SYMBOL (op)->type);
537           if (size>accuseSize)
538             accuseSize = size;
539         }
540       op = IC_RIGHT (ic);
541       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
542         {
543           accuse = 1;
544           size = getSize (OP_SYMBOL (op)->type);
545           if (size>accuseSize)
546             accuseSize = size;
547         }
548     }
549
550   if (accuseSize)
551     return accuseSize;
552   else
553     return accuse;
554 }
555
556 /*-----------------------------------------------------------------*/
557 /* aopForSym - for a true symbol                                   */
558 /*-----------------------------------------------------------------*/
559 static asmop *
560 aopForSym (iCode * ic, symbol * sym, bool result)
561 {
562   asmop *aop;
563   memmap *space;
564
565   wassertl (ic != NULL, "Got a null iCode");
566   wassertl (sym != NULL, "Got a null symbol");
567
568   space = SPEC_OCLS (sym->etype);
569
570   /* if already has one */
571   if (sym->aop)
572     {
573           sym->aop->allocated++;
574       return sym->aop;
575     }
576
577   /* assign depending on the storage class */
578   /* if it is on the stack or indirectly addressable */
579   /* space we need to assign either r0 or r1 to it   */
580   if (sym->onStack || sym->iaccess)
581     {
582       sym->aop = aop = newAsmop (0);
583       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
584       aop->size = getSize (sym->type);
585
586       /* now assign the address of the variable to
587          the pointer register */
588       if (aop->type != AOP_STK)
589         {
590
591           if (sym->onStack)
592             {
593               char offset = ((sym->stack < 0) ?
594                          ((char) (sym->stack - _G.nRegsSaved)) :
595                          ((char) sym->stack)) & 0xff;
596
597               if ((offset >= -3) && (offset <= 3))
598                 {
599                   emitcode ("mov", "%s,%s",
600                             aop->aopu.aop_ptr->name, SYM_BP (sym));
601                   while (offset < 0)
602                     {
603                       emitcode ("dec", aop->aopu.aop_ptr->name);
604                       offset++;
605                     }
606                   while (offset > 0)
607                     {
608                       emitcode ("inc", aop->aopu.aop_ptr->name);
609                       offset--;
610                     }
611                 }
612               else
613                 {
614                   if (_G.accInUse || leftRightUseAcc (ic))
615                     emitcode ("push", "acc");
616                   emitcode ("mov", "a,%s", SYM_BP (sym));
617                   emitcode ("add", "a,#0x%02x", offset);
618                   emitcode ("mov", "%s,a",
619                             aop->aopu.aop_ptr->name);
620                   if (_G.accInUse || leftRightUseAcc (ic))
621                     emitcode ("pop", "acc");
622                 }
623             }
624           else
625             emitcode ("mov", "%s,#%s",
626                       aop->aopu.aop_ptr->name,
627                       sym->rname);
628           aop->paged = space->paged;
629         }
630       else
631         aop->aopu.aop_stk = sym->stack;
632       return aop;
633     }
634
635   /* if in bit space */
636   if (IN_BITSPACE (space))
637     {
638       sym->aop = aop = newAsmop (AOP_CRY);
639       aop->aopu.aop_dir = sym->rname;
640       aop->size = getSize (sym->type);
641       return aop;
642     }
643   /* if it is in direct space */
644   if (IN_DIRSPACE (space))
645     {
646       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
647       //printTypeChainRaw(sym->type, NULL);
648       //printf("space = %s\n", space ? space->sname : "NULL");
649       sym->aop = aop = newAsmop (AOP_DIR);
650       aop->aopu.aop_dir = sym->rname;
651       aop->size = getSize (sym->type);
652       return aop;
653     }
654
655   /* special case for a function */
656   if (IS_FUNC (sym->type))
657     {
658       sym->aop = aop = newAsmop (AOP_IMMD);
659       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
660       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
661       aop->size = getSize (sym->type);
662       return aop;
663     }
664
665   /* only remaining is far space */
666   /* in which case DPTR gets the address */
667   sym->aop = aop = newAsmop (AOP_DPTR);
668   emitcode ("mov", "dptr,#%s", sym->rname);
669   aop->size = getSize (sym->type);
670
671   /* if it is in code space */
672   if (IN_CODESPACE (space))
673     aop->code = 1;
674
675   return aop;
676 }
677
678 /*-----------------------------------------------------------------*/
679 /* aopForRemat - rematerialzes an object                           */
680 /*-----------------------------------------------------------------*/
681 static asmop *
682 aopForRemat (symbol * sym)
683 {
684   iCode *ic = sym->rematiCode;
685   asmop *aop = newAsmop (AOP_IMMD);
686   int ptr_type = 0;
687   int val = 0;
688
689   for (;;)
690     {
691       if (ic->op == '+')
692         val += (int) operandLitValue (IC_RIGHT (ic));
693       else if (ic->op == '-')
694         val -= (int) operandLitValue (IC_RIGHT (ic));
695       else if (IS_CAST_ICODE(ic)) {
696               sym_link *from_type = operandType(IC_RIGHT(ic));
697               aop->aopu.aop_immd.from_cast_remat = 1;
698               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
699               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
700               continue;
701       } else break;
702
703       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
704     }
705
706   if (val)
707     sprintf (buffer, "(%s %c 0x%04x)",
708              OP_SYMBOL (IC_LEFT (ic))->rname,
709              val >= 0 ? '+' : '-',
710              abs (val) & 0xffff);
711   else
712     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
713
714   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
715   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
716   /* set immd2 field if required */
717   if (aop->aopu.aop_immd.from_cast_remat) {
718           sprintf(buffer,"#0x%02x",ptr_type);
719           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
720           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
721   }
722
723   return aop;
724 }
725
726 /*-----------------------------------------------------------------*/
727 /* regsInCommon - two operands have some registers in common       */
728 /*-----------------------------------------------------------------*/
729 static bool
730 regsInCommon (operand * op1, operand * op2)
731 {
732   symbol *sym1, *sym2;
733   int i;
734
735   /* if they have registers in common */
736   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
737     return FALSE;
738
739   sym1 = OP_SYMBOL (op1);
740   sym2 = OP_SYMBOL (op2);
741
742   if (sym1->nRegs == 0 || sym2->nRegs == 0)
743     return FALSE;
744
745   for (i = 0; i < sym1->nRegs; i++)
746     {
747       int j;
748       if (!sym1->regs[i])
749         continue;
750
751       for (j = 0; j < sym2->nRegs; j++)
752         {
753           if (!sym2->regs[j])
754             continue;
755
756           if (sym2->regs[j] == sym1->regs[i])
757             return TRUE;
758         }
759     }
760
761   return FALSE;
762 }
763
764 /*-----------------------------------------------------------------*/
765 /* operandsEqu - equivalent                                        */
766 /*-----------------------------------------------------------------*/
767 static bool
768 operandsEqu (operand * op1, operand * op2)
769 {
770   symbol *sym1, *sym2;
771
772   /* if they're not symbols */
773   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
774     return FALSE;
775
776   sym1 = OP_SYMBOL (op1);
777   sym2 = OP_SYMBOL (op2);
778
779   /* if both are itemps & one is spilt
780      and the other is not then false */
781   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
782       sym1->isspilt != sym2->isspilt)
783     return FALSE;
784
785   /* if they are the same */
786   if (sym1 == sym2)
787     return TRUE;
788
789   /* if they have the same rname */
790   if (sym1->rname[0] && sym2->rname[0] &&
791       strcmp (sym1->rname, sym2->rname) == 0 &&
792       !(IS_PARM (op2) && IS_ITEMP (op1)))
793     return TRUE;
794
795   /* if left is a tmp & right is not */
796   if (IS_ITEMP (op1) &&
797       !IS_ITEMP (op2) &&
798       sym1->isspilt &&
799       (sym1->usl.spillLoc == sym2))
800     return TRUE;
801
802   if (IS_ITEMP (op2) &&
803       !IS_ITEMP (op1) &&
804       sym2->isspilt &&
805       sym1->level > 0 &&
806       (sym2->usl.spillLoc == sym1))
807     return TRUE;
808
809   return FALSE;
810 }
811
812 /*-----------------------------------------------------------------*/
813 /* sameRegs - two asmops have the same registers                   */
814 /*-----------------------------------------------------------------*/
815 static bool
816 sameRegs (asmop * aop1, asmop * aop2)
817 {
818   int i;
819
820   if (aop1 == aop2)
821     return TRUE;
822
823   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
824     return FALSE;
825
826   if (aop1->type != aop2->type)
827     return FALSE;
828
829   if (aop1->size != aop2->size)
830     return FALSE;
831
832   for (i = 0; i < aop1->size; i++)
833     if (aop1->aopu.aop_reg[i] !=
834         aop2->aopu.aop_reg[i])
835       return FALSE;
836
837   return TRUE;
838 }
839
840 /*-----------------------------------------------------------------*/
841 /* aopOp - allocates an asmop for an operand  :                    */
842 /*-----------------------------------------------------------------*/
843 static void
844 aopOp (operand * op, iCode * ic, bool result)
845 {
846   asmop *aop;
847   symbol *sym;
848   int i;
849
850   if (!op)
851     return;
852
853   /* if this a literal */
854   if (IS_OP_LITERAL (op))
855     {
856       op->aop = aop = newAsmop (AOP_LIT);
857       aop->aopu.aop_lit = op->operand.valOperand;
858       aop->size = getSize (operandType (op));
859       return;
860     }
861
862   /* if already has a asmop then continue */
863   if (op->aop)
864     {
865           op->aop->allocated++;
866       return;
867     }
868
869   /* if the underlying symbol has a aop */
870   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
871     {
872       op->aop = OP_SYMBOL (op)->aop;
873           op->aop->allocated++;
874       return;
875     }
876
877   /* if this is a true symbol */
878   if (IS_TRUE_SYMOP (op))
879     {
880       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
881       return;
882     }
883
884   /* this is a temporary : this has
885      only five choices :
886      a) register
887      b) spillocation
888      c) rematerialize
889      d) conditional
890      e) can be a return use only */
891
892   sym = OP_SYMBOL (op);
893
894   /* if the type is a conditional */
895   if (sym->regType == REG_CND)
896     {
897       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
898       aop->size = 0;
899       return;
900     }
901
902   /* if it is spilt then two situations
903      a) is rematerialize
904      b) has a spill location */
905   if (sym->isspilt || sym->nRegs == 0)
906     {
907
908       /* rematerialize it NOW */
909       if (sym->remat)
910         {
911           sym->aop = op->aop = aop =
912             aopForRemat (sym);
913           aop->size = getSize (sym->type);
914           return;
915         }
916
917       if (sym->accuse)
918         {
919           int i;
920           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
921           aop->size = getSize (sym->type);
922           for (i = 0; i < 2; i++)
923             aop->aopu.aop_str[i] = accUse[i];
924           return;
925         }
926
927       if (sym->ruonly)
928         {
929           unsigned i;
930
931           aop = op->aop = sym->aop = newAsmop (AOP_STR);
932           aop->size = getSize (sym->type);
933           for (i = 0; i < fReturnSizeMCS51; i++)
934             aop->aopu.aop_str[i] = fReturn[i];
935           return;
936         }
937
938       if (sym->usl.spillLoc)
939         {
940           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
941             {
942               /* force a new aop if sizes differ */
943               sym->usl.spillLoc->aop = NULL;
944             }
945           sym->aop = op->aop = aop =
946                      aopForSym (ic, sym->usl.spillLoc, result);
947           aop->size = getSize (sym->type);
948           return;
949         }
950
951       /* else must be a dummy iTemp */
952       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
953       aop->size = getSize (sym->type);
954       return;
955     }
956
957   /* if the type is a bit register */
958   if (sym->regType == REG_BIT)
959     {
960       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
961       aop->size = sym->nRegs;//1???
962       aop->aopu.aop_reg[0] = sym->regs[0];
963       aop->aopu.aop_dir = sym->regs[0]->name;
964       return;
965     }
966
967   /* must be in a register */
968   sym->aop = op->aop = aop = newAsmop (AOP_REG);
969   aop->size = sym->nRegs;
970   for (i = 0; i < sym->nRegs; i++)
971     aop->aopu.aop_reg[i] = sym->regs[i];
972 }
973
974 /*-----------------------------------------------------------------*/
975 /* freeAsmop - free up the asmop given to an operand               */
976 /*----------------------------------------------------------------*/
977 static void
978 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
979 {
980   asmop *aop;
981
982   if (!op)
983     aop = aaop;
984   else
985     aop = op->aop;
986
987   if (!aop)
988     return;
989
990   aop->allocated--;
991
992   if (aop->allocated)
993     goto dealloc;
994
995   /* depending on the asmop type only three cases need work
996      AOP_R0, AOP_R1 & AOP_STK */
997   switch (aop->type)
998     {
999     case AOP_R0:
1000       if (R0INB)
1001         {
1002           emitcode ("mov", "r0,b");
1003           R0INB--;
1004         }
1005       else if (_G.r0Pushed)
1006         {
1007           if (pop)
1008             {
1009               emitcode ("pop", "ar0");
1010               _G.r0Pushed--;
1011             }
1012         }
1013       bitVectUnSetBit (ic->rUsed, R0_IDX);
1014       break;
1015
1016     case AOP_R1:
1017       if (R1INB)
1018         {
1019           emitcode ("mov", "r1,b");
1020           R1INB--;
1021         }
1022       if (_G.r1Pushed)
1023         {
1024           if (pop)
1025             {
1026               emitcode ("pop", "ar1");
1027               _G.r1Pushed--;
1028             }
1029         }
1030       bitVectUnSetBit (ic->rUsed, R1_IDX);
1031       break;
1032
1033     case AOP_STK:
1034       {
1035         int sz = aop->size;
1036         int stk = aop->aopu.aop_stk + aop->size - 1;
1037         bitVectUnSetBit (ic->rUsed, R0_IDX);
1038         bitVectUnSetBit (ic->rUsed, R1_IDX);
1039
1040         getFreePtr (ic, &aop, FALSE);
1041
1042         if (stk)
1043           {
1044             emitcode ("mov", "a,_bp");
1045             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1046             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1047           }
1048         else
1049           {
1050             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1051           }
1052
1053         while (sz--)
1054           {
1055             emitcode ("pop", "acc");
1056             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1057             if (!sz)
1058               break;
1059             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1060           }
1061         op->aop = aop;
1062         freeAsmop (op, NULL, ic, TRUE);
1063         if (_G.r1Pushed)
1064           {
1065             emitcode ("pop", "ar1");
1066             _G.r1Pushed--;
1067           }
1068
1069         if (_G.r0Pushed)
1070           {
1071             emitcode ("pop", "ar0");
1072             _G.r0Pushed--;
1073           }
1074       }
1075     }
1076
1077 dealloc:
1078   /* all other cases just dealloc */
1079   if (op)
1080     {
1081       op->aop = NULL;
1082       if (IS_SYMOP (op))
1083         {
1084           OP_SYMBOL (op)->aop = NULL;
1085           /* if the symbol has a spill */
1086           if (SPIL_LOC (op))
1087             SPIL_LOC (op)->aop = NULL;
1088         }
1089     }
1090 }
1091
1092 /*------------------------------------------------------------------*/
1093 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1094 /*                      pop r0 or r1 off stack if pushed            */
1095 /*------------------------------------------------------------------*/
1096 static void
1097 freeForBranchAsmop (operand * op)
1098 {
1099   asmop *aop;
1100
1101   if (!op)
1102     return;
1103
1104   aop = op->aop;
1105
1106   if (!aop)
1107     return;
1108
1109   if (!aop->allocated)
1110     return;
1111
1112   switch (aop->type)
1113     {
1114     case AOP_R0:
1115       if (R0INB)
1116         {
1117           emitcode ("mov", "r0,b");
1118         }
1119       else if (_G.r0Pushed)
1120         {
1121           emitcode ("pop", "ar0");
1122         }
1123       break;
1124
1125     case AOP_R1:
1126       if (R1INB)
1127         {
1128           emitcode ("mov", "r1,b");
1129         }
1130       else if (_G.r1Pushed)
1131         {
1132           emitcode ("pop", "ar1");
1133         }
1134       break;
1135
1136     case AOP_STK:
1137       {
1138         int sz = aop->size;
1139         int stk = aop->aopu.aop_stk + aop->size - 1;
1140
1141         emitcode ("mov", "b,r0");
1142         if (stk)
1143           {
1144             emitcode ("mov", "a,_bp");
1145             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1146             emitcode ("mov", "r0,a");
1147           }
1148         else
1149           {
1150             emitcode ("mov", "r0,_bp");
1151           }
1152
1153         while (sz--)
1154           {
1155             emitcode ("pop", "acc");
1156             emitcode ("mov", "@r0,a");
1157             if (!sz)
1158               break;
1159             emitcode ("dec", "r0");
1160           }
1161         emitcode ("mov", "r0,b");
1162       }
1163     }
1164
1165 }
1166
1167 /*-----------------------------------------------------------------*/
1168 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1169 /*                 clobber the accumulator                         */
1170 /*-----------------------------------------------------------------*/
1171 static bool
1172 aopGetUsesAcc (operand * oper, int offset)
1173 {
1174   asmop * aop = AOP (oper);
1175
1176   if (offset > (aop->size - 1))
1177     return FALSE;
1178
1179   switch (aop->type)
1180     {
1181
1182     case AOP_R0:
1183     case AOP_R1:
1184       if (aop->paged)
1185         return TRUE;
1186       return FALSE;
1187     case AOP_DPTR:
1188       return TRUE;
1189     case AOP_IMMD:
1190       return FALSE;
1191     case AOP_DIR:
1192       return FALSE;
1193     case AOP_REG:
1194       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1195       return FALSE;
1196     case AOP_CRY:
1197       return TRUE;
1198     case AOP_ACC:
1199       if (offset)
1200         return FALSE;
1201       return TRUE;
1202     case AOP_LIT:
1203       return FALSE;
1204     case AOP_STR:
1205       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1206         return TRUE;
1207       return FALSE;
1208     case AOP_DUMMY:
1209       return FALSE;
1210     default:
1211       /* Error case --- will have been caught already */
1212       wassert(0);
1213       return FALSE;
1214     }
1215 }
1216
1217 /*-----------------------------------------------------------------*/
1218 /* aopGet - for fetching value of the aop                          */
1219 /*-----------------------------------------------------------------*/
1220 static char *
1221 aopGet (operand * oper, int offset, bool bit16, bool dname)
1222 {
1223   char *s = buffer;
1224   char *rs;
1225   asmop * aop = AOP (oper);
1226
1227   /* offset is greater than
1228      size then zero */
1229   if (offset > (aop->size - 1) &&
1230       aop->type != AOP_LIT)
1231     return zero;
1232
1233   /* depending on type */
1234   switch (aop->type)
1235     {
1236     case AOP_DUMMY:
1237       return zero;
1238
1239     case AOP_R0:
1240     case AOP_R1:
1241       /* if we need to increment it */
1242       while (offset > aop->coff)
1243         {
1244           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1245           aop->coff++;
1246         }
1247
1248       while (offset < aop->coff)
1249         {
1250           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1251           aop->coff--;
1252         }
1253
1254       aop->coff = offset;
1255       if (aop->paged)
1256         {
1257           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1258           return (dname ? "acc" : "a");
1259         }
1260       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1261       rs = Safe_calloc (1, strlen (s) + 1);
1262       strcpy (rs, s);
1263       return rs;
1264
1265     case AOP_DPTR:
1266       if (aop->code && aop->coff==0 && offset>=1) {
1267         emitcode ("mov", "a,#0x%02x", offset);
1268         emitcode ("movc", "a,@a+dptr");
1269         return (dname ? "acc" : "a");
1270       }
1271
1272       while (offset > aop->coff)
1273         {
1274           emitcode ("inc", "dptr");
1275           aop->coff++;
1276         }
1277
1278       while (offset < aop->coff)
1279         {
1280           emitcode ("lcall", "__decdptr");
1281           aop->coff--;
1282         }
1283
1284       aop->coff = offset;
1285       if (aop->code)
1286         {
1287           emitcode ("clr", "a");
1288           emitcode ("movc", "a,@a+dptr");
1289         }
1290       else
1291         {
1292           emitcode ("movx", "a,@dptr");
1293         }
1294       return (dname ? "acc" : "a");
1295
1296
1297     case AOP_IMMD:
1298       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1299               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1300       } else if (bit16)
1301         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1302       else if (offset)
1303         sprintf (s, "#(%s >> %d)",
1304                  aop->aopu.aop_immd.aop_immd1,
1305                  offset * 8);
1306       else
1307         sprintf (s, "#%s",
1308                  aop->aopu.aop_immd.aop_immd1);
1309       rs = Safe_calloc (1, strlen (s) + 1);
1310       strcpy (rs, s);
1311       return rs;
1312
1313     case AOP_DIR:
1314       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1315         sprintf (s, "(%s >> %d)",
1316                  aop->aopu.aop_dir, offset * 8);
1317       else if (offset)
1318         sprintf (s, "(%s + %d)",
1319                  aop->aopu.aop_dir,
1320                  offset);
1321       else
1322         sprintf (s, "%s", aop->aopu.aop_dir);
1323       rs = Safe_calloc (1, strlen (s) + 1);
1324       strcpy (rs, s);
1325       return rs;
1326
1327     case AOP_REG:
1328       if (dname)
1329         return aop->aopu.aop_reg[offset]->dname;
1330       else
1331         return aop->aopu.aop_reg[offset]->name;
1332
1333     case AOP_CRY:
1334       emitcode ("clr", "a");
1335       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1336       emitcode ("rlc", "a");
1337       return (dname ? "acc" : "a");
1338
1339     case AOP_ACC:
1340       if (!offset && dname)
1341         return "acc";
1342       return aop->aopu.aop_str[offset];
1343
1344     case AOP_LIT:
1345       return aopLiteral (aop->aopu.aop_lit, offset);
1346
1347     case AOP_STR:
1348       aop->coff = offset;
1349       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1350           dname)
1351         return "acc";
1352
1353       return aop->aopu.aop_str[offset];
1354
1355     }
1356
1357   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1358           "aopget got unsupported aop->type");
1359   exit (1);
1360 }
1361
1362 /*-----------------------------------------------------------------*/
1363 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1364 /*                 clobber the accumulator                         */
1365 /*-----------------------------------------------------------------*/
1366 static bool
1367 aopPutUsesAcc (operand * oper, const char *s, int offset)
1368 {
1369   asmop * aop = AOP (oper);
1370
1371   if (offset > (aop->size - 1))
1372     return FALSE;
1373
1374   switch (aop->type)
1375     {
1376     case AOP_DUMMY:
1377       return TRUE;
1378     case AOP_DIR:
1379       return FALSE;
1380     case AOP_REG:
1381       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1382       return FALSE;
1383     case AOP_DPTR:
1384       return TRUE;
1385     case AOP_R0:
1386     case AOP_R1:
1387       return ((aop->paged) || (*s == '@'));
1388     case AOP_STK:
1389       return (*s == '@');
1390     case AOP_CRY:
1391       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1392     case AOP_STR:
1393       return FALSE;
1394     case AOP_IMMD:
1395       return FALSE;
1396     case AOP_ACC:
1397       return FALSE;
1398     default:
1399       /* Error case --- will have been caught already */
1400       wassert(0);
1401       return FALSE;
1402     }
1403 }
1404
1405 /*-----------------------------------------------------------------*/
1406 /* aopPut - puts a string for a aop and indicates if acc is in use */
1407 /*-----------------------------------------------------------------*/
1408 static bool
1409 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1410 {
1411   char *d = buffer;
1412   bool accuse = FALSE;
1413   asmop * aop = AOP (result);
1414
1415   if (aop->size && offset > (aop->size - 1))
1416     {
1417       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1418               "aopPut got offset > aop->size");
1419       exit (1);
1420     }
1421
1422   /* will assign value to value */
1423   /* depending on where it is ofcourse */
1424   switch (aop->type)
1425     {
1426     case AOP_DUMMY:
1427       MOVA (s);         /* read s in case it was volatile */
1428       accuse = TRUE;
1429       break;
1430
1431     case AOP_DIR:
1432       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1433         sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1434       else if (offset)
1435         sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1436       else
1437         sprintf (d, "%s", aop->aopu.aop_dir);
1438
1439       if (strcmp (d, s) || bvolatile)
1440           emitcode ("mov", "%s,%s", d, s);
1441       if (!strcmp (d, "acc"))
1442           accuse = TRUE;
1443
1444       break;
1445
1446     case AOP_REG:
1447       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1448           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1449         {
1450           if (*s == '@' ||
1451               strcmp (s, "r0") == 0 ||
1452               strcmp (s, "r1") == 0 ||
1453               strcmp (s, "r2") == 0 ||
1454               strcmp (s, "r3") == 0 ||
1455               strcmp (s, "r4") == 0 ||
1456               strcmp (s, "r5") == 0 ||
1457               strcmp (s, "r6") == 0 ||
1458               strcmp (s, "r7") == 0)
1459             emitcode ("mov", "%s,%s",
1460                       aop->aopu.aop_reg[offset]->dname, s);
1461           else
1462             emitcode ("mov", "%s,%s",
1463                       aop->aopu.aop_reg[offset]->name, s);
1464         }
1465       break;
1466
1467     case AOP_DPTR:
1468       if (aop->code)
1469         {
1470           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1471                   "aopPut writing to code space");
1472           exit (1);
1473         }
1474
1475       while (offset > aop->coff)
1476         {
1477           aop->coff++;
1478           emitcode ("inc", "dptr");
1479         }
1480
1481       while (offset < aop->coff)
1482         {
1483           aop->coff--;
1484           emitcode ("lcall", "__decdptr");
1485         }
1486
1487       aop->coff = offset;
1488
1489       /* if not in accumulator */
1490       MOVA (s);
1491
1492       emitcode ("movx", "@dptr,a");
1493       break;
1494
1495     case AOP_R0:
1496     case AOP_R1:
1497       while (offset > aop->coff)
1498         {
1499           aop->coff++;
1500           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1501         }
1502       while (offset < aop->coff)
1503         {
1504           aop->coff--;
1505           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1506         }
1507       aop->coff = offset;
1508
1509       if (aop->paged)
1510         {
1511           MOVA (s);
1512           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1513         }
1514       else if (*s == '@')
1515         {
1516           MOVA (s);
1517           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1518         }
1519       else if (strcmp (s, "r0") == 0 ||
1520                strcmp (s, "r1") == 0 ||
1521                strcmp (s, "r2") == 0 ||
1522                strcmp (s, "r3") == 0 ||
1523                strcmp (s, "r4") == 0 ||
1524                strcmp (s, "r5") == 0 ||
1525                strcmp (s, "r6") == 0 ||
1526                strcmp (s, "r7") == 0)
1527         {
1528           char buffer[10];
1529           sprintf (buffer, "a%s", s);
1530           emitcode ("mov", "@%s,%s",
1531                     aop->aopu.aop_ptr->name, buffer);
1532         }
1533       else
1534         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1535
1536       break;
1537
1538     case AOP_STK:
1539       if (strcmp (s, "a") == 0)
1540         emitcode ("push", "acc");
1541       else
1542         if (*s=='@') {
1543           MOVA(s);
1544           emitcode ("push", "acc");
1545         } else {
1546           emitcode ("push", s);
1547         }
1548
1549       break;
1550
1551     case AOP_CRY:
1552       /* if not bit variable */
1553       if (!aop->aopu.aop_dir)
1554         {
1555           /* inefficient: move carry into A and use jz/jnz */
1556           emitcode ("clr", "a");
1557           emitcode ("rlc", "a");
1558           accuse = TRUE;
1559         }
1560       else
1561         {
1562           if (s == zero)
1563             emitcode ("clr", "%s", aop->aopu.aop_dir);
1564           else if (s == one)
1565             emitcode ("setb", "%s", aop->aopu.aop_dir);
1566           else if (!strcmp (s, "c"))
1567             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1568           else if (strcmp (s, aop->aopu.aop_dir))
1569             {
1570               MOVA (s);
1571               /* set C, if a >= 1 */
1572               emitcode ("add", "a,#0xff");
1573               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1574             }
1575         }
1576       break;
1577
1578     case AOP_STR:
1579       aop->coff = offset;
1580       if (strcmp (aop->aopu.aop_str[offset], s) ||
1581           bvolatile)
1582         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1583       break;
1584
1585     case AOP_ACC:
1586       accuse = TRUE;
1587       aop->coff = offset;
1588       if (!offset && (strcmp (s, "acc") == 0) &&
1589           !bvolatile)
1590         break;
1591
1592       if (strcmp (aop->aopu.aop_str[offset], s) &&
1593           !bvolatile)
1594         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1595       break;
1596
1597     default:
1598       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1599               "aopPut got unsupported aop->type");
1600       exit (1);
1601     }
1602
1603     return accuse;
1604 }
1605
1606
1607 #if 0
1608 /*-----------------------------------------------------------------*/
1609 /* pointToEnd :- points to the last byte of the operand            */
1610 /*-----------------------------------------------------------------*/
1611 static void
1612 pointToEnd (asmop * aop)
1613 {
1614   int count;
1615   if (!aop)
1616     return;
1617
1618   aop->coff = count = (aop->size - 1);
1619   switch (aop->type)
1620     {
1621     case AOP_R0:
1622     case AOP_R1:
1623       while (count--)
1624         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1625       break;
1626     case AOP_DPTR:
1627       while (count--)
1628         emitcode ("inc", "dptr");
1629       break;
1630     }
1631
1632 }
1633 #endif
1634
1635 /*-----------------------------------------------------------------*/
1636 /* reAdjustPreg - points a register back to where it should        */
1637 /*-----------------------------------------------------------------*/
1638 static void
1639 reAdjustPreg (asmop * aop)
1640 {
1641   if ((aop->coff==0) || aop->size <= 1)
1642     return;
1643
1644   switch (aop->type)
1645     {
1646     case AOP_R0:
1647     case AOP_R1:
1648       while (aop->coff--)
1649         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1650       break;
1651     case AOP_DPTR:
1652       while (aop->coff--)
1653         {
1654           emitcode ("lcall", "__decdptr");
1655         }
1656       break;
1657     }
1658   aop->coff = 0;
1659 }
1660
1661 /*-----------------------------------------------------------------*/
1662 /* opIsGptr: returns non-zero if the passed operand is       */
1663 /* a generic pointer type.             */
1664 /*-----------------------------------------------------------------*/
1665 static int
1666 opIsGptr (operand * op)
1667 {
1668   sym_link *type = operandType (op);
1669
1670   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1671     {
1672       return 1;
1673     }
1674   return 0;
1675 }
1676
1677 /*-----------------------------------------------------------------*/
1678 /* getDataSize - get the operand data size                         */
1679 /*-----------------------------------------------------------------*/
1680 static int
1681 getDataSize (operand * op)
1682 {
1683   int size;
1684   size = AOP_SIZE (op);
1685   if (size == GPTRSIZE)
1686     {
1687       sym_link *type = operandType (op);
1688       if (IS_GENPTR (type))
1689         {
1690           /* generic pointer; arithmetic operations
1691            * should ignore the high byte (pointer type).
1692            */
1693           size--;
1694         }
1695     }
1696   return size;
1697 }
1698
1699 /*-----------------------------------------------------------------*/
1700 /* outAcc - output Acc                                             */
1701 /*-----------------------------------------------------------------*/
1702 static void
1703 outAcc (operand * result)
1704 {
1705   int size, offset;
1706   size = getDataSize (result);
1707   if (size)
1708     {
1709       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1710       size--;
1711       offset = 1;
1712       /* unsigned or positive */
1713       while (size--)
1714         {
1715           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1716         }
1717     }
1718 }
1719
1720 /*-----------------------------------------------------------------*/
1721 /* outBitC - output a bit C                                        */
1722 /*-----------------------------------------------------------------*/
1723 static void
1724 outBitC (operand * result)
1725 {
1726   /* if the result is bit */
1727   if (AOP_TYPE (result) == AOP_CRY)
1728     aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1729   else
1730     {
1731       emitcode ("clr", "a");
1732       emitcode ("rlc", "a");
1733       outAcc (result);
1734     }
1735 }
1736
1737 /*-----------------------------------------------------------------*/
1738 /* toBoolean - emit code for orl a,operator(sizeop)                */
1739 /*-----------------------------------------------------------------*/
1740 static void
1741 toBoolean (operand * oper)
1742 {
1743   int size = AOP_SIZE (oper) - 1;
1744   int offset = 1;
1745   bool AccUsed = FALSE;
1746   bool pushedB;
1747
1748   while (!AccUsed && size--)
1749     {
1750       AccUsed |= aopGetUsesAcc(oper, offset++);
1751     }
1752
1753   size = AOP_SIZE (oper) - 1;
1754   offset = 1;
1755   MOVA (aopGet (oper, 0, FALSE, FALSE));
1756   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1757     {
1758       pushedB = pushB ();
1759       emitcode("mov", "b,a");
1760       while (--size)
1761         {
1762           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1763           emitcode ("orl", "b,a");
1764         }
1765       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1766       emitcode ("orl", "a,b");
1767       popB (pushedB);
1768     }
1769   else
1770     {
1771       while (size--)
1772         {
1773           emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1774         }
1775     }
1776 }
1777
1778
1779 /*-----------------------------------------------------------------*/
1780 /* genNot - generate code for ! operation                          */
1781 /*-----------------------------------------------------------------*/
1782 static void
1783 genNot (iCode * ic)
1784 {
1785   symbol *tlbl;
1786
1787   D(emitcode (";     genNot",""));
1788
1789   /* assign asmOps to operand & result */
1790   aopOp (IC_LEFT (ic), ic, FALSE);
1791   aopOp (IC_RESULT (ic), ic, TRUE);
1792
1793   /* if in bit space then a special case */
1794   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1795     {
1796       /* if left==result then cpl bit */
1797       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1798         {
1799           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1800         }
1801       else
1802         {
1803           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1804           emitcode ("cpl", "c");
1805           outBitC (IC_RESULT (ic));
1806         }
1807       goto release;
1808     }
1809
1810   toBoolean (IC_LEFT (ic));
1811
1812   /* set C, if a == 0 */
1813   tlbl = newiTempLabel (NULL);
1814   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1815   emitcode ("", "%05d$:", tlbl->key + 100);
1816   outBitC (IC_RESULT (ic));
1817
1818 release:
1819   /* release the aops */
1820   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1821   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1822 }
1823
1824
1825 /*-----------------------------------------------------------------*/
1826 /* genCpl - generate code for complement                           */
1827 /*-----------------------------------------------------------------*/
1828 static void
1829 genCpl (iCode * ic)
1830 {
1831   int offset = 0;
1832   int size;
1833   symbol *tlbl;
1834   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1835
1836   D(emitcode (";", "genCpl"));
1837
1838   /* assign asmOps to operand & result */
1839   aopOp (IC_LEFT (ic), ic, FALSE);
1840   aopOp (IC_RESULT (ic), ic, TRUE);
1841
1842   /* special case if in bit space */
1843   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1844     {
1845       char *l;
1846
1847       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1848           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1849         {
1850           /* promotion rules are responsible for this strange result:
1851              bit -> int -> ~int -> bit
1852              uchar -> int -> ~int -> bit
1853           */
1854           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1855           goto release;
1856         }
1857
1858       tlbl=newiTempLabel(NULL);
1859       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1860       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1861           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1862           IS_AOP_PREG (IC_LEFT (ic)))
1863         {
1864           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1865         }
1866       else
1867         {
1868           MOVA (l);
1869           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1870         }
1871       emitcode ("", "%05d$:", tlbl->key + 100);
1872       outBitC (IC_RESULT(ic));
1873       goto release;
1874     }
1875
1876   size = AOP_SIZE (IC_RESULT (ic));
1877   while (size--)
1878     {
1879       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1880       MOVA (l);
1881       emitcode ("cpl", "a");
1882       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1883     }
1884
1885
1886 release:
1887   /* release the aops */
1888   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1889   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1890 }
1891
1892 /*-----------------------------------------------------------------*/
1893 /* genUminusFloat - unary minus for floating points                */
1894 /*-----------------------------------------------------------------*/
1895 static void
1896 genUminusFloat (operand * op, operand * result)
1897 {
1898   int size, offset = 0;
1899   char *l;
1900
1901   D(emitcode (";     genUminusFloat",""));
1902
1903   /* for this we just copy and then flip the bit */
1904
1905   size = AOP_SIZE (op) - 1;
1906
1907   while (size--)
1908     {
1909       aopPut (result,
1910               aopGet (op, offset, FALSE, FALSE),
1911               offset,
1912               isOperandVolatile (result, FALSE));
1913       offset++;
1914     }
1915
1916   l = aopGet (op, offset, FALSE, FALSE);
1917
1918   MOVA (l);
1919
1920   emitcode ("cpl", "acc.7");
1921   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1922 }
1923
1924 /*-----------------------------------------------------------------*/
1925 /* genUminus - unary minus code generation                         */
1926 /*-----------------------------------------------------------------*/
1927 static void
1928 genUminus (iCode * ic)
1929 {
1930   int offset, size;
1931   sym_link *optype, *rtype;
1932
1933
1934   D(emitcode (";     genUminus",""));
1935
1936   /* assign asmops */
1937   aopOp (IC_LEFT (ic), ic, FALSE);
1938   aopOp (IC_RESULT (ic), ic, TRUE);
1939
1940   /* if both in bit space then special
1941      case */
1942   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1943       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1944     {
1945
1946       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1947       emitcode ("cpl", "c");
1948       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1949       goto release;
1950     }
1951
1952   optype = operandType (IC_LEFT (ic));
1953   rtype = operandType (IC_RESULT (ic));
1954
1955   /* if float then do float stuff */
1956   if (IS_FLOAT (optype))
1957     {
1958       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1959       goto release;
1960     }
1961
1962   /* otherwise subtract from zero */
1963   size = AOP_SIZE (IC_LEFT (ic));
1964   offset = 0;
1965   //CLRC ;
1966   while (size--)
1967     {
1968       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1969       if (!strcmp (l, "a"))
1970         {
1971           if (offset == 0)
1972             SETC;
1973           emitcode ("cpl", "a");
1974           emitcode ("addc", "a,#0");
1975         }
1976       else
1977         {
1978           if (offset == 0)
1979             CLRC;
1980           emitcode ("clr", "a");
1981           emitcode ("subb", "a,%s", l);
1982         }
1983       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1984     }
1985
1986   /* if any remaining bytes in the result */
1987   /* we just need to propagate the sign   */
1988   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1989     {
1990       emitcode ("rlc", "a");
1991       emitcode ("subb", "a,acc");
1992       while (size--)
1993         aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1994     }
1995
1996 release:
1997   /* release the aops */
1998   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1999   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2000 }
2001
2002 /*-----------------------------------------------------------------*/
2003 /* saveRegisters - will look for a call and save the registers     */
2004 /*-----------------------------------------------------------------*/
2005 static void
2006 saveRegisters (iCode * lic)
2007 {
2008   int i;
2009   iCode *ic;
2010   bitVect *rsave;
2011
2012   /* look for call */
2013   for (ic = lic; ic; ic = ic->next)
2014     if (ic->op == CALL || ic->op == PCALL)
2015       break;
2016
2017   if (!ic)
2018     {
2019       fprintf (stderr, "found parameter push with no function call\n");
2020       return;
2021     }
2022
2023   /* if the registers have been saved already or don't need to be then
2024      do nothing */
2025   if (ic->regsSaved)
2026     return;
2027   if (IS_SYMOP(IC_LEFT(ic)) &&
2028       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2029        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2030     return;
2031
2032   /* save the registers in use at this time but skip the
2033      ones for the result */
2034   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2035                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2036
2037   ic->regsSaved = 1;
2038   if (options.useXstack)
2039     {
2040       int count = bitVectnBitsOn (rsave);
2041
2042       if (count == 1)
2043         {
2044           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2045           if (reg->type == REG_BIT)
2046             {
2047               emitcode ("mov", "a,%s", reg->base);
2048             }
2049           else
2050             {
2051               emitcode ("mov", "a,%s", reg->name);
2052             }
2053           emitcode ("mov", "r0,%s", spname);
2054           emitcode ("inc", "%s", spname);// allocate before use
2055           emitcode ("movx", "@r0,a");
2056           if (bitVectBitValue (rsave, R0_IDX))
2057             emitcode ("mov", "r0,a");
2058         }
2059       else if (count != 0)
2060         {
2061           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2062           int nBits = bitVectnBitsOn (rsavebits);
2063
2064           if (nBits != 0)
2065             {
2066               count = count - nBits + 1;
2067               /* remove all but the first bits as they are pushed all at once */
2068               rsave = bitVectCplAnd (rsave, rsavebits);
2069               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2070             }
2071
2072           if (bitVectBitValue (rsave, R0_IDX))
2073             {
2074               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2075             }
2076           emitcode ("mov", "r0,%s", spname);
2077           MOVA ("r0");
2078           emitcode ("add", "a,#%d", count);
2079           emitcode ("mov", "%s,a", spname);
2080           for (i = 0; i < mcs51_nRegs; i++)
2081             {
2082               if (bitVectBitValue (rsave, i))
2083                 {
2084                   regs * reg = mcs51_regWithIdx (i);
2085                   if (i == R0_IDX)
2086                     {
2087                       emitcode ("pop", "acc");
2088                       emitcode ("push", "acc");
2089                     }
2090                   else if (reg->type == REG_BIT)
2091                     {
2092                       emitcode ("mov", "a,%s", reg->base);
2093                     }
2094                   else
2095                     {
2096                       emitcode ("mov", "a,%s", reg->name);
2097                     }
2098                   emitcode ("movx", "@r0,a");
2099                   if (--count)
2100                     {
2101                       emitcode ("inc", "r0");
2102                     }
2103                 }
2104             }
2105           if (bitVectBitValue (rsave, R0_IDX))
2106             {
2107               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2108             }
2109         }
2110     }
2111   else
2112     {
2113       bool bits_pushed = FALSE;
2114       for (i = 0; i < mcs51_nRegs; i++)
2115         {
2116           if (bitVectBitValue (rsave, i))
2117             {
2118               bits_pushed = pushReg (i, bits_pushed);
2119             }
2120         }
2121     }
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* unsaveRegisters - pop the pushed registers                      */
2126 /*-----------------------------------------------------------------*/
2127 static void
2128 unsaveRegisters (iCode * ic)
2129 {
2130   int i;
2131   bitVect *rsave;
2132
2133   /* restore the registers in use at this time but skip the
2134      ones for the result */
2135   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2136                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2137
2138   if (options.useXstack)
2139     {
2140       int count = bitVectnBitsOn (rsave);
2141
2142       if (count == 1)
2143         {
2144           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2145           emitcode ("mov", "r0,%s", spname);
2146           emitcode ("dec", "r0");
2147           emitcode ("movx", "a,@r0");
2148           if (reg->type == REG_BIT)
2149             {
2150               emitcode ("mov", "%s,a", reg->base);
2151             }
2152           else
2153             {
2154               emitcode ("mov", "%s,a", reg->name);
2155             }
2156           emitcode ("dec", "%s", spname);
2157         }
2158       else if (count != 0)
2159         {
2160           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2161           int nBits = bitVectnBitsOn (rsavebits);
2162
2163           if (nBits != 0)
2164             {
2165               count = count - nBits + 1;
2166               /* remove all but the first bits as they are popped all at once */
2167               rsave = bitVectCplAnd (rsave, rsavebits);
2168               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2169             }
2170
2171           emitcode ("mov", "r0,%s", spname);
2172           for (i = mcs51_nRegs; i >= 0; i--)
2173             {
2174               if (bitVectBitValue (rsave, i))
2175                 {
2176                   regs * reg = mcs51_regWithIdx (i);
2177                   emitcode ("dec", "r0");
2178                   emitcode ("movx", "a,@r0");
2179                   if (i == R0_IDX)
2180                     {
2181                       emitcode ("push", "acc");
2182                     }
2183                   else if (reg->type == REG_BIT)
2184                     {
2185                       emitcode ("mov", "%s,a", reg->base);
2186                     }
2187                   else
2188                     {
2189                       emitcode ("mov", "%s,a", reg->name);
2190                     }
2191                 }
2192             }
2193           emitcode ("mov", "%s,r0", spname);
2194           if (bitVectBitValue (rsave, R0_IDX))
2195             {
2196               emitcode ("pop", "ar0");
2197             }
2198         }
2199     }
2200   else
2201     {
2202       bool bits_popped = FALSE;
2203       for (i = mcs51_nRegs; i >= 0; i--)
2204         {
2205           if (bitVectBitValue (rsave, i))
2206             {
2207               bits_popped = popReg (i, bits_popped);
2208             }
2209         }
2210     }
2211 }
2212
2213
2214 /*-----------------------------------------------------------------*/
2215 /* pushSide -                                                      */
2216 /*-----------------------------------------------------------------*/
2217 static void
2218 pushSide (operand * oper, int size)
2219 {
2220   int offset = 0;
2221   while (size--)
2222     {
2223       char *l = aopGet (oper, offset++, FALSE, TRUE);
2224       if (AOP_TYPE (oper) != AOP_REG &&
2225           AOP_TYPE (oper) != AOP_DIR &&
2226           strcmp (l, "a"))
2227         {
2228           MOVA (l);
2229           emitcode ("push", "acc");
2230         }
2231       else
2232         {
2233           emitcode ("push", "%s", l);
2234         }
2235     }
2236 }
2237
2238 /*-----------------------------------------------------------------*/
2239 /* assignResultValue - also indicates if acc is in use afterwards  */
2240 /*-----------------------------------------------------------------*/
2241 static bool
2242 assignResultValue (operand * oper, operand * func)
2243 {
2244   int offset = 0;
2245   int size = AOP_SIZE (oper);
2246   bool accuse = FALSE;
2247   bool pushedA = FALSE;
2248
2249   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2250     {
2251       outBitC (oper);
2252       return FALSE;
2253     }
2254
2255   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2256     {
2257       emitcode ("push", "acc");
2258       pushedA = TRUE;
2259     }
2260   while (size--)
2261     {
2262       if ((offset == 3) && pushedA)
2263         emitcode ("pop", "acc");
2264       accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2265       offset++;
2266     }
2267   return accuse;
2268 }
2269
2270
2271 /*-----------------------------------------------------------------*/
2272 /* genXpush - pushes onto the external stack                       */
2273 /*-----------------------------------------------------------------*/
2274 static void
2275 genXpush (iCode * ic)
2276 {
2277   asmop *aop = newAsmop (0);
2278   regs *r;
2279   int size, offset = 0;
2280
2281   D(emitcode (";     genXpush",""));
2282
2283   aopOp (IC_LEFT (ic), ic, FALSE);
2284   r = getFreePtr (ic, &aop, FALSE);
2285
2286   size = AOP_SIZE (IC_LEFT (ic));
2287
2288   if (size == 1)
2289     {
2290       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2291       emitcode ("mov", "%s,%s", r->name, spname);
2292       emitcode ("inc", "%s", spname); // allocate space first
2293       emitcode ("movx", "@%s,a", r->name);
2294     }
2295   else
2296     {
2297       // allocate space first
2298       emitcode ("mov", "%s,%s", r->name, spname);
2299       MOVA (r->name);
2300       emitcode ("add", "a,#%d", size);
2301       emitcode ("mov", "%s,a", spname);
2302
2303       while (size--)
2304         {
2305           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2306           emitcode ("movx", "@%s,a", r->name);
2307           emitcode ("inc", "%s", r->name);
2308         }
2309     }
2310
2311   freeAsmop (NULL, aop, ic, TRUE);
2312   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2313 }
2314
2315 /*-----------------------------------------------------------------*/
2316 /* genIpush - generate code for pushing this gets a little complex */
2317 /*-----------------------------------------------------------------*/
2318 static void
2319 genIpush (iCode * ic)
2320 {
2321   int size, offset = 0;
2322   char *l;
2323   char *prev = "";
2324
2325   D(emitcode (";     genIpush",""));
2326
2327   /* if this is not a parm push : ie. it is spill push
2328      and spill push is always done on the local stack */
2329   if (!ic->parmPush)
2330     {
2331
2332       /* and the item is spilt then do nothing */
2333       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2334         return;
2335
2336       aopOp (IC_LEFT (ic), ic, FALSE);
2337       size = AOP_SIZE (IC_LEFT (ic));
2338       /* push it on the stack */
2339       while (size--)
2340         {
2341           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2342           if (*l == '#')
2343             {
2344               MOVA (l);
2345               l = "acc";
2346             }
2347           emitcode ("push", "%s", l);
2348         }
2349       return;
2350     }
2351
2352   /* this is a parameter push: in this case we call
2353      the routine to find the call and save those
2354      registers that need to be saved */
2355   saveRegisters (ic);
2356
2357   /* if use external stack then call the external
2358      stack pushing routine */
2359   if (options.useXstack)
2360     {
2361       genXpush (ic);
2362       return;
2363     }
2364
2365   /* then do the push */
2366   aopOp (IC_LEFT (ic), ic, FALSE);
2367
2368   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2369   size = AOP_SIZE (IC_LEFT (ic));
2370
2371   while (size--)
2372     {
2373       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2374       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2375           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2376           strcmp (l, "a"))
2377         {
2378           if (strcmp (l, prev) || *l == '@')
2379             MOVA (l);
2380           emitcode ("push", "acc");
2381         }
2382       else
2383         {
2384           emitcode ("push", "%s", l);
2385         }
2386       prev = l;
2387     }
2388
2389   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2390 }
2391
2392 /*-----------------------------------------------------------------*/
2393 /* genIpop - recover the registers: can happen only for spilling   */
2394 /*-----------------------------------------------------------------*/
2395 static void
2396 genIpop (iCode * ic)
2397 {
2398   int size, offset;
2399
2400   D(emitcode (";     genIpop",""));
2401
2402   /* if the temp was not pushed then */
2403   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2404     return;
2405
2406   aopOp (IC_LEFT (ic), ic, FALSE);
2407   size = AOP_SIZE (IC_LEFT (ic));
2408   offset = (size - 1);
2409   while (size--)
2410     emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2411                                    FALSE, TRUE));
2412
2413   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2414 }
2415
2416 /*-----------------------------------------------------------------*/
2417 /* saveRBank - saves an entire register bank on the stack          */
2418 /*-----------------------------------------------------------------*/
2419 static void
2420 saveRBank (int bank, iCode * ic, bool pushPsw)
2421 {
2422   int i;
2423   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2424   asmop *aop = NULL;
2425   regs *r = NULL;
2426
2427   if (options.useXstack)
2428     {
2429       if (!ic)
2430       {
2431           /* Assume r0 is available for use. */
2432           r = mcs51_regWithIdx (R0_IDX);;
2433       }
2434       else
2435       {
2436           aop = newAsmop (0);
2437           r = getFreePtr (ic, &aop, FALSE);
2438       }
2439       // allocate space first
2440       emitcode ("mov", "%s,%s", r->name, spname);
2441       MOVA (r->name);
2442       emitcode ("add", "a,#%d", count);
2443       emitcode ("mov", "%s,a", spname);
2444     }
2445
2446   for (i = 0; i < 8; i++)
2447     {
2448       if (options.useXstack)
2449         {
2450           emitcode ("mov", "a,(%s+%d)",
2451                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2452           emitcode ("movx", "@%s,a", r->name);
2453           if (--count)
2454             emitcode ("inc", "%s", r->name);
2455         }
2456       else
2457         emitcode ("push", "(%s+%d)",
2458                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2459     }
2460
2461   if (mcs51_nRegs > 8)
2462     {
2463       if (options.useXstack)
2464         {
2465           emitcode ("mov", "a,bits");
2466           emitcode ("movx", "@%s,a", r->name);
2467           if (--count)
2468             emitcode ("inc", "%s", r->name);
2469         }
2470       else
2471         {
2472           emitcode ("push", "bits");
2473         }
2474       BitBankUsed = 1;
2475     }
2476
2477   if (pushPsw)
2478     {
2479       if (options.useXstack)
2480         {
2481           emitcode ("mov", "a,psw");
2482           emitcode ("movx", "@%s,a", r->name);
2483
2484         }
2485       else
2486         {
2487           emitcode ("push", "psw");
2488         }
2489
2490       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2491     }
2492
2493   if (aop)
2494     {
2495       freeAsmop (NULL, aop, ic, TRUE);
2496     }
2497
2498   if (ic)
2499   {
2500     ic->bankSaved = 1;
2501   }
2502 }
2503
2504 /*-----------------------------------------------------------------*/
2505 /* unsaveRBank - restores the register bank from stack             */
2506 /*-----------------------------------------------------------------*/
2507 static void
2508 unsaveRBank (int bank, iCode * ic, bool popPsw)
2509 {
2510   int i;
2511   asmop *aop = NULL;
2512   regs *r = NULL;
2513
2514   if (options.useXstack)
2515     {
2516       if (!ic)
2517         {
2518           /* Assume r0 is available for use. */
2519           r = mcs51_regWithIdx (R0_IDX);;
2520         }
2521       else
2522         {
2523           aop = newAsmop (0);
2524           r = getFreePtr (ic, &aop, FALSE);
2525         }
2526       emitcode ("mov", "%s,%s", r->name, spname);
2527     }
2528
2529   if (popPsw)
2530     {
2531       if (options.useXstack)
2532         {
2533           emitcode ("dec", "%s", r->name);
2534           emitcode ("movx", "a,@%s", r->name);
2535           emitcode ("mov", "psw,a");
2536         }
2537       else
2538         {
2539           emitcode ("pop", "psw");
2540         }
2541     }
2542
2543   if (mcs51_nRegs > 8)
2544     {
2545       if (options.useXstack)
2546         {
2547           emitcode ("dec", "%s", r->name);
2548           emitcode ("movx", "a,@%s", r->name);
2549           emitcode ("mov", "bits,a");
2550         }
2551       else
2552         {
2553           emitcode ("pop", "bits");
2554         }
2555     }
2556
2557   for (i = 7; i >= 0; i--)
2558     {
2559       if (options.useXstack)
2560         {
2561           emitcode ("dec", "%s", r->name);
2562           emitcode ("movx", "a,@%s", r->name);
2563           emitcode ("mov", "(%s+%d),a",
2564                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2565         }
2566       else
2567         {
2568           emitcode ("pop", "(%s+%d)",
2569                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2570         }
2571     }
2572
2573   if (options.useXstack)
2574     {
2575       emitcode ("mov", "%s,%s", spname, r->name);
2576     }
2577
2578   if (aop)
2579     {
2580       freeAsmop (NULL, aop, ic, TRUE);
2581     }
2582 }
2583
2584 /*-----------------------------------------------------------------*/
2585 /* genSend - gen code for SEND                                     */
2586 /*-----------------------------------------------------------------*/
2587 static void genSend(set *sendSet)
2588 {
2589   iCode *sic;
2590   int bit_count = 0;
2591
2592   /* first we do all bit parameters */
2593   for (sic = setFirstItem (sendSet); sic;
2594        sic = setNextItem (sendSet))
2595     {
2596       aopOp (IC_LEFT (sic), sic, FALSE);
2597
2598       if (sic->argreg > 12)
2599         {
2600           int bit = sic->argreg-13;
2601
2602           /* if left is a literal then
2603              we know what the value is */
2604           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2605             {
2606               if (((int) operandLitValue (IC_LEFT (sic))))
2607                   emitcode ("setb", "b[%d]", bit);
2608               else
2609                   emitcode ("clr", "b[%d]", bit);
2610             }
2611           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2612             {
2613               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2614                 if (strcmp (l, "c"))
2615                     emitcode ("mov", "c,%s", l);
2616                 emitcode ("mov", "b[%d],c", bit);
2617             }
2618           else
2619             {
2620               /* we need to or */
2621               toBoolean (IC_LEFT (sic));
2622               /* set C, if a >= 1 */
2623               emitcode ("add", "a,#0xff");
2624               emitcode ("mov", "b[%d],c", bit);
2625             }
2626           bit_count++;
2627           BitBankUsed = 1;
2628         }
2629       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2630     }
2631
2632   if (bit_count)
2633     {
2634       saveRegisters (setFirstItem (sendSet));
2635       emitcode ("mov", "bits,b");
2636     }
2637
2638   /* then we do all other parameters */
2639   for (sic = setFirstItem (sendSet); sic;
2640        sic = setNextItem (sendSet))
2641     {
2642       int size, offset = 0;
2643       aopOp (IC_LEFT (sic), sic, FALSE);
2644       size = AOP_SIZE (IC_LEFT (sic));
2645
2646       if (sic->argreg == 1)
2647         {
2648           while (size--)
2649             {
2650               char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2651               if (strcmp (l, fReturn[offset]))
2652                   emitcode ("mov", "%s,%s", fReturn[offset], l);
2653               offset++;
2654             }
2655         }
2656       else if (sic->argreg <= 12)
2657         {
2658           while (size--)
2659             {
2660               emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2661                         aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2662               offset++;
2663             }
2664         }
2665       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2666     }
2667 }
2668
2669 /*-----------------------------------------------------------------*/
2670 /* selectRegBank - emit code to select the register bank           */
2671 /*-----------------------------------------------------------------*/
2672 static void
2673 selectRegBank (short bank, bool keepFlags)
2674 {
2675   /* if f.e. result is in carry */
2676   if (keepFlags)
2677     {
2678       emitcode ("anl", "psw,#0xE7");
2679       if (bank)
2680         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2681     }
2682   else
2683     {
2684       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2685     }
2686 }
2687
2688 /*-----------------------------------------------------------------*/
2689 /* genCall - generates a call statement                            */
2690 /*-----------------------------------------------------------------*/
2691 static void
2692 genCall (iCode * ic)
2693 {
2694   sym_link *dtype;
2695   sym_link *etype;
2696 //  bool restoreBank = FALSE;
2697   bool swapBanks = FALSE;
2698   bool accuse = FALSE;
2699   bool accPushed = FALSE;
2700   bool resultInF0 = FALSE;
2701
2702   D(emitcode(";     genCall",""));
2703
2704   dtype = operandType (IC_LEFT (ic));
2705   etype = getSpec(dtype);
2706   /* if send set is not empty then assign */
2707   if (_G.sendSet)
2708     {
2709         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2710             genSend(reverseSet(_G.sendSet));
2711         } else {
2712             genSend(_G.sendSet);
2713         }
2714
2715       _G.sendSet = NULL;
2716     }
2717
2718   /* if we are calling a not _naked function that is not using
2719      the same register bank then we need to save the
2720      destination registers on the stack */
2721   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2722       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2723        !IFFUNC_ISISR (dtype))
2724     {
2725       swapBanks = TRUE;
2726     }
2727
2728   /* if caller saves & we have not saved then */
2729   if (!ic->regsSaved)
2730       saveRegisters (ic);
2731
2732   if (swapBanks)
2733     {
2734         emitcode ("mov", "psw,#0x%02x",
2735            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2736     }
2737
2738   /* make the call */
2739   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2740     {
2741       if (IFFUNC_CALLEESAVES(dtype))
2742         {
2743           werror (E_BANKED_WITH_CALLEESAVES);
2744         }
2745       else
2746         {
2747           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2748                      OP_SYMBOL (IC_LEFT (ic))->rname :
2749                      OP_SYMBOL (IC_LEFT (ic))->name);
2750
2751           emitcode ("mov", "r0,#%s", l);
2752           emitcode ("mov", "r1,#(%s >> 8)", l);
2753           emitcode ("mov", "r2,#(%s >> 16)", l);
2754           emitcode ("lcall", "__sdcc_banked_call");
2755         }
2756     }
2757   else
2758     {
2759       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2760                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2761                                 OP_SYMBOL (IC_LEFT (ic))->name));
2762     }
2763
2764   if (swapBanks)
2765     {
2766       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2767     }
2768
2769   /* if we need assign a result value */
2770   if ((IS_ITEMP (IC_RESULT (ic)) &&
2771        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2772        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2773         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2774         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2775       IS_TRUE_SYMOP (IC_RESULT (ic)))
2776     {
2777
2778       _G.accInUse++;
2779       aopOp (IC_RESULT (ic), ic, FALSE);
2780       _G.accInUse--;
2781
2782       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2783
2784       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2785     }
2786
2787   /* adjust the stack for parameters if required */
2788   if (ic->parmBytes)
2789     {
2790       int i;
2791       if (ic->parmBytes > 3)
2792         {
2793           if (accuse)
2794             {
2795               emitcode ("push", "acc");
2796               accPushed = TRUE;
2797             }
2798           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2799               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2800             {
2801               emitcode ("mov", "F0,c");
2802               resultInF0 = TRUE;
2803             }
2804
2805           emitcode ("mov", "a,%s", spname);
2806           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2807           emitcode ("mov", "%s,a", spname);
2808
2809           /* unsaveRegisters from xstack needs acc, but */
2810           /* unsaveRegisters from stack needs this popped */
2811           if (accPushed && !options.useXstack)
2812             {
2813               emitcode ("pop", "acc");
2814               accPushed = FALSE;
2815             }
2816         }
2817       else
2818         for (i = 0; i < ic->parmBytes; i++)
2819           emitcode ("dec", "%s", spname);
2820     }
2821
2822   /* if we had saved some registers then unsave them */
2823   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2824     {
2825       if (accuse && !accPushed && options.useXstack)
2826         {
2827           /* xstack needs acc, but doesn't touch normal stack */
2828           emitcode ("push", "acc");
2829           accPushed = TRUE;
2830         }
2831       unsaveRegisters (ic);
2832     }
2833
2834 //  /* if register bank was saved then pop them */
2835 //  if (restoreBank)
2836 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2837
2838   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2839     {
2840       if (resultInF0)
2841           emitcode ("mov", "c,F0");
2842
2843       aopOp (IC_RESULT (ic), ic, FALSE);
2844       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2845       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2846     }
2847
2848   if (accPushed)
2849     emitcode ("pop", "acc");
2850 }
2851
2852 /*-----------------------------------------------------------------*/
2853 /* -10l - generates a call by pointer statement                */
2854 /*-----------------------------------------------------------------*/
2855 static void
2856 genPcall (iCode * ic)
2857 {
2858   sym_link *dtype;
2859   sym_link *etype;
2860   symbol *rlbl = newiTempLabel (NULL);
2861 //  bool restoreBank=FALSE;
2862   bool swapBanks = FALSE;
2863   bool resultInF0 = FALSE;
2864
2865   D(emitcode(";     genPCall",""));
2866
2867   dtype = operandType (IC_LEFT (ic))->next;
2868   etype = getSpec(dtype);
2869   /* if caller saves & we have not saved then */
2870   if (!ic->regsSaved)
2871     saveRegisters (ic);
2872
2873   /* if we are calling a not _naked function that is not using
2874      the same register bank then we need to save the
2875      destination registers on the stack */
2876   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2877       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2878       !IFFUNC_ISISR (dtype))
2879     {
2880 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2881 //    restoreBank=TRUE;
2882       swapBanks = TRUE;
2883       // need caution message to user here
2884     }
2885
2886   if (IS_LITERAL(etype))
2887     {
2888       /* if send set is not empty then assign */
2889       if (_G.sendSet)
2890         {
2891           genSend(reverseSet(_G.sendSet));
2892           _G.sendSet = NULL;
2893         }
2894
2895       if (swapBanks)
2896         {
2897           emitcode ("mov", "psw,#0x%02x",
2898            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2899         }
2900
2901       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2902         {
2903           if (IFFUNC_CALLEESAVES(dtype))
2904             {
2905               werror (E_BANKED_WITH_CALLEESAVES);
2906             }
2907           else
2908             {
2909               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2910
2911               emitcode ("mov", "r0,#%s", l);
2912               emitcode ("mov", "r1,#(%s >> 8)", l);
2913               emitcode ("mov", "r2,#(%s >> 16)", l);
2914               emitcode ("lcall", "__sdcc_banked_call");
2915             }
2916         }
2917       else
2918         {
2919           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2920         }
2921     }
2922   else
2923     {
2924       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2925         {
2926           if (IFFUNC_CALLEESAVES(dtype))
2927             {
2928               werror (E_BANKED_WITH_CALLEESAVES);
2929             }
2930           else
2931             {
2932               aopOp (IC_LEFT (ic), ic, FALSE);
2933
2934               if (!swapBanks)
2935                 {
2936                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2937                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2938                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2939                 }
2940               else
2941                 {
2942                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2943                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2944                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2945                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2946                 }
2947
2948               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2949
2950               /* if send set is not empty then assign */
2951               if (_G.sendSet)
2952                 {
2953                   genSend(reverseSet(_G.sendSet));
2954                   _G.sendSet = NULL;
2955                 }
2956
2957               if (swapBanks)
2958                 {
2959                   emitcode ("mov", "psw,#0x%02x",
2960                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2961                 }
2962
2963               /* make the call */
2964               emitcode ("lcall", "__sdcc_banked_call");
2965             }
2966         }
2967       else
2968         {
2969           /* push the return address on to the stack */
2970           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2971           emitcode ("push", "acc");
2972           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2973           emitcode ("push", "acc");
2974
2975           /* now push the calling address */
2976           aopOp (IC_LEFT (ic), ic, FALSE);
2977
2978           pushSide (IC_LEFT (ic), FPTRSIZE);
2979
2980           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2981
2982           /* if send set is not empty the assign */
2983           if (_G.sendSet)
2984             {
2985               genSend(reverseSet(_G.sendSet));
2986               _G.sendSet = NULL;
2987             }
2988
2989           if (swapBanks)
2990             {
2991               emitcode ("mov", "psw,#0x%02x",
2992                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2993             }
2994
2995           /* make the call */
2996           emitcode ("ret", "");
2997           emitcode ("", "%05d$:", (rlbl->key + 100));
2998         }
2999     }
3000   if (swapBanks)
3001     {
3002       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3003     }
3004
3005   /* if we need assign a result value */
3006   if ((IS_ITEMP (IC_RESULT (ic)) &&
3007        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3008        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3009         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3010       IS_TRUE_SYMOP (IC_RESULT (ic)))
3011     {
3012
3013       _G.accInUse++;
3014       aopOp (IC_RESULT (ic), ic, FALSE);
3015       _G.accInUse--;
3016
3017       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3018
3019       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3020     }
3021
3022   /* adjust the stack for parameters if required */
3023   if (ic->parmBytes)
3024     {
3025       int i;
3026       if (ic->parmBytes > 3)
3027         {
3028           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3029               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3030             {
3031               emitcode ("mov", "F0,c");
3032               resultInF0 = TRUE;
3033             }
3034
3035           emitcode ("mov", "a,%s", spname);
3036           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3037           emitcode ("mov", "%s,a", spname);
3038         }
3039       else
3040         for (i = 0; i < ic->parmBytes; i++)
3041           emitcode ("dec", "%s", spname);
3042
3043     }
3044
3045 //  /* if register bank was saved then unsave them */
3046 //  if (restoreBank)
3047 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3048
3049   /* if we had saved some registers then unsave them */
3050   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3051     unsaveRegisters (ic);
3052
3053   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3054     {
3055       if (resultInF0)
3056           emitcode ("mov", "c,F0");
3057
3058       aopOp (IC_RESULT (ic), ic, FALSE);
3059       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3060       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3061     }
3062 }
3063
3064 /*-----------------------------------------------------------------*/
3065 /* resultRemat - result  is rematerializable                       */
3066 /*-----------------------------------------------------------------*/
3067 static int
3068 resultRemat (iCode * ic)
3069 {
3070   if (SKIP_IC (ic) || ic->op == IFX)
3071     return 0;
3072
3073   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3074     {
3075       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3076       if (sym->remat && !POINTER_SET (ic))
3077         return 1;
3078     }
3079
3080   return 0;
3081 }
3082
3083 #if defined(__BORLANDC__) || defined(_MSC_VER)
3084 #define STRCASECMP stricmp
3085 #else
3086 #define STRCASECMP strcasecmp
3087 #endif
3088
3089 /*-----------------------------------------------------------------*/
3090 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3091 /*-----------------------------------------------------------------*/
3092 static int
3093 regsCmp(void *p1, void *p2)
3094 {
3095   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3096 }
3097
3098 static bool
3099 inExcludeList (char *s)
3100 {
3101   const char *p = setFirstItem(options.excludeRegsSet);
3102
3103   if (p == NULL || STRCASECMP(p, "none") == 0)
3104     return FALSE;
3105
3106
3107   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3108 }
3109
3110 /*-----------------------------------------------------------------*/
3111 /* genFunction - generated code for function entry                 */
3112 /*-----------------------------------------------------------------*/
3113 static void
3114 genFunction (iCode * ic)
3115 {
3116   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3117   sym_link *ftype;
3118   bool     switchedPSW = FALSE;
3119   int      calleesaves_saved_register = -1;
3120   int      stackAdjust = sym->stack;
3121   int      accIsFree = sym->recvSize < 4;
3122   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3123   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3124
3125   _G.nRegsSaved = 0;
3126   /* create the function header */
3127   emitcode (";", "-----------------------------------------");
3128   emitcode (";", " function %s", sym->name);
3129   emitcode (";", "-----------------------------------------");
3130
3131   emitcode ("", "%s:", sym->rname);
3132   ftype = operandType (IC_LEFT (ic));
3133   _G.currentFunc = sym;
3134
3135   if (IFFUNC_ISNAKED(ftype))
3136   {
3137       emitcode(";", "naked function: no prologue.");
3138       return;
3139   }
3140
3141   /* here we need to generate the equates for the
3142      register bank if required */
3143   if (FUNC_REGBANK (ftype) != rbank)
3144     {
3145       int i;
3146
3147       rbank = FUNC_REGBANK (ftype);
3148       for (i = 0; i < mcs51_nRegs; i++)
3149         {
3150           if (regs8051[i].type != REG_BIT)
3151             {
3152               if (strcmp (regs8051[i].base, "0") == 0)
3153                 emitcode ("", "%s = 0x%02x",
3154                           regs8051[i].dname,
3155                           8 * rbank + regs8051[i].offset);
3156               else
3157                 emitcode ("", "%s = %s + 0x%02x",
3158                           regs8051[i].dname,
3159                           regs8051[i].base,
3160                           8 * rbank + regs8051[i].offset);
3161             }
3162         }
3163     }
3164
3165   /* if this is an interrupt service routine then
3166      save acc, b, dpl, dph  */
3167   if (IFFUNC_ISISR (sym->type))
3168     {
3169
3170       if (!inExcludeList ("acc"))
3171         emitcode ("push", "acc");
3172       if (!inExcludeList ("b"))
3173         emitcode ("push", "b");
3174       if (!inExcludeList ("dpl"))
3175         emitcode ("push", "dpl");
3176       if (!inExcludeList ("dph"))
3177         emitcode ("push", "dph");
3178       /* if this isr has no bank i.e. is going to
3179          run with bank 0 , then we need to save more
3180          registers :-) */
3181       if (!FUNC_REGBANK (sym->type))
3182         {
3183
3184           /* if this function does not call any other
3185              function then we can be economical and
3186              save only those registers that are used */
3187           if (!IFFUNC_HASFCALL(sym->type))
3188             {
3189               int i;
3190
3191               /* if any registers used */
3192               if (sym->regsUsed)
3193                 {
3194                   bool bits_pushed = FALSE;
3195                   /* save the registers used */
3196                   for (i = 0; i < sym->regsUsed->size; i++)
3197                     {
3198                       if (bitVectBitValue (sym->regsUsed, i))
3199                         bits_pushed = pushReg (i, bits_pushed);
3200                     }
3201                 }
3202             }
3203           else
3204             {
3205
3206               /* this function has a function call. We cannot
3207                  determines register usage so we will have to push the
3208                  entire bank */
3209                 saveRBank (0, ic, FALSE);
3210                 if (options.parms_in_bank1) {
3211                     int i;
3212                     for (i=0; i < 8 ; i++ ) {
3213                         emitcode ("push","%s",rb1regs[i]);
3214                     }
3215                 }
3216             }
3217         }
3218         else
3219         {
3220             /* This ISR uses a non-zero bank.
3221              *
3222              * We assume that the bank is available for our
3223              * exclusive use.
3224              *
3225              * However, if this ISR calls a function which uses some
3226              * other bank, we must save that bank entirely.
3227              */
3228             unsigned long banksToSave = 0;
3229
3230             if (IFFUNC_HASFCALL(sym->type))
3231             {
3232
3233 #define MAX_REGISTER_BANKS 4
3234
3235                 iCode *i;
3236                 int ix;
3237
3238                 for (i = ic; i; i = i->next)
3239                 {
3240                     if (i->op == ENDFUNCTION)
3241                     {
3242                         /* we got to the end OK. */
3243                         break;
3244                     }
3245
3246                     if (i->op == CALL)
3247                     {
3248                         sym_link *dtype;
3249
3250                         dtype = operandType (IC_LEFT(i));
3251                         if (dtype
3252                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3253                         {
3254                              /* Mark this bank for saving. */
3255                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3256                              {
3257                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3258                              }
3259                              else
3260                              {
3261                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3262                              }
3263
3264                              /* And note that we don't need to do it in
3265                               * genCall.
3266                               */
3267                              i->bankSaved = 1;
3268                         }
3269                     }
3270                     if (i->op == PCALL)
3271                     {
3272                         /* This is a mess; we have no idea what
3273                          * register bank the called function might
3274                          * use.
3275                          *
3276                          * The only thing I can think of to do is
3277                          * throw a warning and hope.
3278                          */
3279                         werror(W_FUNCPTR_IN_USING_ISR);
3280                     }
3281                 }
3282
3283                 if (banksToSave && options.useXstack)
3284                 {
3285                     /* Since we aren't passing it an ic,
3286                      * saveRBank will assume r0 is available to abuse.
3287                      *
3288                      * So switch to our (trashable) bank now, so
3289                      * the caller's R0 isn't trashed.
3290                      */
3291                     emitcode ("push", "psw");
3292                     emitcode ("mov", "psw,#0x%02x",
3293                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3294                     switchedPSW = TRUE;
3295                 }
3296
3297                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3298                 {
3299                      if (banksToSave & (1 << ix))
3300                      {
3301                          saveRBank(ix, NULL, FALSE);
3302                      }
3303                 }
3304             }
3305             // TODO: this needs a closer look
3306             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3307         }
3308
3309       /* Set the register bank to the desired value if nothing else */
3310       /* has done so yet. */
3311       if (!switchedPSW)
3312         {
3313           emitcode ("push", "psw");
3314           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3315         }
3316     }
3317   else
3318     {
3319       /* This is a non-ISR function. The caller has already switched register */
3320       /* banks, if necessary, so just handle the callee-saves option. */
3321
3322       /* if callee-save to be used for this function
3323          then save the registers being used in this function */
3324       if (IFFUNC_CALLEESAVES(sym->type))
3325         {
3326           int i;
3327
3328           /* if any registers used */
3329           if (sym->regsUsed)
3330             {
3331               bool bits_pushed = FALSE;
3332               /* save the registers used */
3333               for (i = 0; i < sym->regsUsed->size; i++)
3334                 {
3335                   if (bitVectBitValue (sym->regsUsed, i))
3336                     {
3337                       /* remember one saved register for later usage */
3338                       if (calleesaves_saved_register < 0)
3339                         calleesaves_saved_register = i;
3340                       bits_pushed = pushReg (i, bits_pushed);
3341                       _G.nRegsSaved++;
3342                     }
3343                 }
3344             }
3345         }
3346     }
3347
3348
3349   if (fReentrant)
3350     {
3351       if (options.useXstack)
3352         {
3353           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3354             {
3355               emitcode ("mov", "r0,%s", spname);
3356               emitcode ("inc", "%s", spname);
3357               emitcode ("xch", "a,_bpx");
3358               emitcode ("movx", "@r0,a");
3359               emitcode ("inc", "r0");
3360               emitcode ("mov", "a,r0");
3361               emitcode ("xch", "a,_bpx");
3362             }
3363           if (sym->stack)
3364             {
3365               emitcode ("push", "_bp");     /* save the callers stack  */
3366               emitcode ("mov", "_bp,sp");
3367             }
3368         }
3369       else
3370         {
3371           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3372             {
3373               /* set up the stack */
3374               emitcode ("push", "_bp");     /* save the callers stack  */
3375               emitcode ("mov", "_bp,sp");
3376             }
3377         }
3378     }
3379
3380   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3381   /* before setting up the stack frame completely. */
3382   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3383     {
3384       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3385
3386       if (rsym->isitmp)
3387         {
3388           if (rsym && rsym->regType == REG_CND)
3389             rsym = NULL;
3390           if (rsym && (rsym->accuse || rsym->ruonly))
3391             rsym = NULL;
3392           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3393             rsym = rsym->usl.spillLoc;
3394         }
3395
3396       /* If the RECEIVE operand immediately spills to the first entry on the */
3397       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3398       /* rather than the usual @r0/r1 machinations. */
3399       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3400         {
3401           int ofs;
3402
3403           _G.current_iCode = ric;
3404           D(emitcode (";     genReceive",""));
3405           for (ofs=0; ofs < sym->recvSize; ofs++)
3406             {
3407               if (!strcmp (fReturn[ofs], "a"))
3408                 emitcode ("push", "acc");
3409               else
3410                 emitcode ("push", fReturn[ofs]);
3411             }
3412           stackAdjust -= sym->recvSize;
3413           if (stackAdjust<0)
3414             {
3415               assert (stackAdjust>=0);
3416               stackAdjust = 0;
3417             }
3418           _G.current_iCode = ic;
3419           ric->generated = 1;
3420           accIsFree = 1;
3421         }
3422       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3423       /* to free up the accumulator. */
3424       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3425         {
3426           int ofs;
3427
3428           _G.current_iCode = ric;
3429           D(emitcode (";     genReceive",""));
3430           for (ofs=0; ofs < sym->recvSize; ofs++)
3431             {
3432               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3433             }
3434           _G.current_iCode = ic;
3435           ric->generated = 1;
3436           accIsFree = 1;
3437         }
3438     }
3439
3440   /* adjust the stack for the function */
3441   if (stackAdjust)
3442     {
3443       int i = stackAdjust;
3444       if (i > 256)
3445         werror (W_STACK_OVERFLOW, sym->name);
3446
3447       if (i > 3 && accIsFree)
3448         {
3449           emitcode ("mov", "a,sp");
3450           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3451           emitcode ("mov", "sp,a");
3452         }
3453       else if (i > 5)
3454         {
3455           /* The accumulator is not free, so we will need another register */
3456           /* to clobber. No need to worry about a possible conflict with */
3457           /* the above early RECEIVE optimizations since they would have */
3458           /* freed the accumulator if they were generated. */
3459
3460           if (IFFUNC_CALLEESAVES(sym->type))
3461             {
3462               /* if it's a callee-saves function we need a saved register */
3463               if (calleesaves_saved_register >= 0)
3464                 {
3465                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3466                   emitcode ("mov", "a,sp");
3467                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3468                   emitcode ("mov", "sp,a");
3469                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3470                 }
3471               else
3472                 /* do it the hard way */
3473                 while (i--)
3474                   emitcode ("inc", "sp");
3475             }
3476           else
3477             {
3478               /* not callee-saves, we can clobber r0 */
3479               emitcode ("mov", "r0,a");
3480               emitcode ("mov", "a,sp");
3481               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3482               emitcode ("mov", "sp,a");
3483               emitcode ("mov", "a,r0");
3484             }
3485         }
3486       else
3487         while (i--)
3488           emitcode ("inc", "sp");
3489     }
3490
3491   if (sym->xstack)
3492     {
3493       char i = ((char) sym->xstack & 0xff);
3494
3495       if (i > 3 && accIsFree)
3496         {
3497           emitcode ("mov", "a,_spx");
3498           emitcode ("add", "a,#0x%02x", i);
3499           emitcode ("mov", "_spx,a");
3500         }
3501       else if (i > 5)
3502         {
3503           emitcode ("push", "acc");
3504           emitcode ("mov", "a,_spx");
3505           emitcode ("add", "a,#0x%02x", i);
3506           emitcode ("mov", "_spx,a");
3507           emitcode ("pop", "acc");
3508         }
3509       else
3510         {
3511           while (i--)
3512             emitcode ("inc", "_spx");
3513         }
3514     }
3515
3516   /* if critical function then turn interrupts off */
3517   if (IFFUNC_ISCRITICAL (ftype))
3518     {
3519       symbol *tlbl = newiTempLabel (NULL);
3520       emitcode ("setb", "c");
3521       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3522       emitcode ("clr", "c");
3523       emitcode ("", "%05d$:", (tlbl->key + 100));
3524       emitcode ("push", "psw"); /* save old ea via c in psw */
3525     }
3526 }
3527
3528 /*-----------------------------------------------------------------*/
3529 /* genEndFunction - generates epilogue for functions               */
3530 /*-----------------------------------------------------------------*/
3531 static void
3532 genEndFunction (iCode * ic)
3533 {
3534   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3535   lineNode *lnp = lineCurr;
3536   bitVect  *regsUsed;
3537   bitVect  *regsUsedPrologue;
3538   bitVect  *regsUnneeded;
3539   int      idx;
3540
3541   _G.currentFunc = NULL;
3542   if (IFFUNC_ISNAKED(sym->type))
3543   {
3544       emitcode(";", "naked function: no epilogue.");
3545       if (options.debug && currFunc)
3546         debugFile->writeEndFunction (currFunc, ic, 0);
3547       return;
3548   }
3549
3550   if (IFFUNC_ISCRITICAL (sym->type))
3551     {
3552       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3553         {
3554           emitcode ("rlc", "a");   /* save c in a */
3555           emitcode ("pop", "psw"); /* restore ea via c in psw */
3556           emitcode ("mov", "ea,c");
3557           emitcode ("rrc", "a");   /* restore c from a */
3558         }
3559       else
3560         {
3561           emitcode ("pop", "psw"); /* restore ea via c in psw */
3562           emitcode ("mov", "ea,c");
3563         }
3564     }
3565
3566   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3567     {
3568       if (options.useXstack)
3569         {
3570           if (sym->stack)
3571             {
3572               emitcode ("mov", "sp,_bp");
3573               emitcode ("pop", "_bp");
3574             }
3575           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3576             {
3577               emitcode ("xch", "a,_bpx");
3578               emitcode ("mov", "r0,a");
3579               emitcode ("dec", "r0");
3580               emitcode ("movx", "a,@r0");
3581               emitcode ("xch", "a,_bpx");
3582               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3583             }
3584         }
3585       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3586         {
3587           emitcode ("mov", "sp,_bp");
3588           emitcode ("pop", "_bp");
3589         }
3590     }
3591
3592   /* restore the register bank  */
3593   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3594   {
3595     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3596      || !options.useXstack)
3597     {
3598         /* Special case of ISR using non-zero bank with useXstack
3599          * is handled below.
3600          */
3601         emitcode ("pop", "psw");
3602     }
3603   }
3604
3605   if (IFFUNC_ISISR (sym->type))
3606     {
3607
3608       /* now we need to restore the registers */
3609       /* if this isr has no bank i.e. is going to
3610          run with bank 0 , then we need to save more
3611          registers :-) */
3612       if (!FUNC_REGBANK (sym->type))
3613         {
3614           /* if this function does not call any other
3615              function then we can be economical and
3616              save only those registers that are used */
3617           if (!IFFUNC_HASFCALL(sym->type))
3618             {
3619               int i;
3620
3621               /* if any registers used */
3622               if (sym->regsUsed)
3623                 {
3624                   bool bits_popped = FALSE;
3625                   /* save the registers used */
3626                   for (i = sym->regsUsed->size; i >= 0; i--)
3627                     {
3628                       if (bitVectBitValue (sym->regsUsed, i))
3629                         bits_popped = popReg (i, bits_popped);
3630                     }
3631                 }
3632             }
3633           else
3634             {
3635               if (options.parms_in_bank1) {
3636                   int i;
3637                   for (i = 7 ; i >= 0 ; i-- ) {
3638                       emitcode ("pop","%s",rb1regs[i]);
3639                   }
3640               }
3641               /* this function has  a function call cannot
3642                  determines register usage so we will have to pop the
3643                  entire bank */
3644               unsaveRBank (0, ic, FALSE);
3645             }
3646         }
3647         else
3648         {
3649             /* This ISR uses a non-zero bank.
3650              *
3651              * Restore any register banks saved by genFunction
3652              * in reverse order.
3653              */
3654             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3655             int ix;
3656
3657             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3658             {
3659                 if (savedBanks & (1 << ix))
3660                 {
3661                     unsaveRBank(ix, NULL, FALSE);
3662                 }
3663             }
3664
3665             if (options.useXstack)
3666             {
3667                 /* Restore bank AFTER calling unsaveRBank,
3668                  * since it can trash r0.
3669                  */
3670                 emitcode ("pop", "psw");
3671             }
3672         }
3673
3674       if (!inExcludeList ("dph"))
3675         emitcode ("pop", "dph");
3676       if (!inExcludeList ("dpl"))
3677         emitcode ("pop", "dpl");
3678       if (!inExcludeList ("b"))
3679         emitcode ("pop", "b");
3680       if (!inExcludeList ("acc"))
3681         emitcode ("pop", "acc");
3682
3683       /* if debug then send end of function */
3684       if (options.debug && currFunc)
3685         {
3686           debugFile->writeEndFunction (currFunc, ic, 1);
3687         }
3688
3689       emitcode ("reti", "");
3690     }
3691   else
3692     {
3693       if (IFFUNC_CALLEESAVES(sym->type))
3694         {
3695           int i;
3696
3697           /* if any registers used */
3698           if (sym->regsUsed)
3699             {
3700               /* save the registers used */
3701               for (i = sym->regsUsed->size; i >= 0; i--)
3702                 {
3703                   if (bitVectBitValue (sym->regsUsed, i) ||
3704                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3705                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3706                 }
3707             }
3708           else if (mcs51_ptrRegReq)
3709             {
3710               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3711               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3712             }
3713
3714         }
3715
3716       /* if debug then send end of function */
3717       if (options.debug && currFunc)
3718         {
3719           debugFile->writeEndFunction (currFunc, ic, 1);
3720         }
3721
3722       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3723         {
3724           emitcode ("ljmp", "__sdcc_banked_ret");
3725         }
3726       else
3727         {
3728           emitcode ("ret", "");
3729         }
3730     }
3731
3732   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3733     return;
3734
3735   /* If this was an interrupt handler using bank 0 that called another */
3736   /* function, then all registers must be saved; nothing to optimized. */
3737   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3738       && !FUNC_REGBANK(sym->type))
3739     return;
3740
3741   /* There are no push/pops to optimize if not callee-saves or ISR */
3742   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3743     return;
3744
3745   /* If there were stack parameters, we cannot optimize without also    */
3746   /* fixing all of the stack offsets; this is too dificult to consider. */
3747   if (FUNC_HASSTACKPARM(sym->type))
3748     return;
3749
3750   /* Compute the registers actually used */
3751   regsUsed = newBitVect (mcs51_nRegs);
3752   regsUsedPrologue = newBitVect (mcs51_nRegs);
3753   while (lnp)
3754     {
3755       if (lnp->ic && lnp->ic->op == FUNCTION)
3756         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3757       else
3758         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3759
3760       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3761           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3762         break;
3763       if (!lnp->prev)
3764         break;
3765       lnp = lnp->prev;
3766     }
3767
3768   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3769       && !bitVectBitValue (regsUsed, CND_IDX))
3770     {
3771       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3772       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3773           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3774         bitVectUnSetBit (regsUsed, CND_IDX);
3775     }
3776   else
3777     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3778
3779   /* If this was an interrupt handler that called another function */
3780   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3781   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3782     {
3783       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3784       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3785       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3786       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3787       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3788     }
3789
3790   /* Remove the unneeded push/pops */
3791   regsUnneeded = newBitVect (mcs51_nRegs);
3792   while (lnp)
3793     {
3794       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3795         {
3796           if (!strncmp(lnp->line, "push", 4))
3797             {
3798               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3799               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3800                 {
3801                   connectLine (lnp->prev, lnp->next);
3802                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3803                 }
3804             }
3805           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3806             {
3807               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3808               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3809                 {
3810                   connectLine (lnp->prev, lnp->next);
3811                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3812                 }
3813             }
3814         }
3815       lnp = lnp->next;
3816     }
3817
3818   for (idx = 0; idx < regsUnneeded->size; idx++)
3819     if (bitVectBitValue (regsUnneeded, idx))
3820       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3821
3822   freeBitVect (regsUnneeded);
3823   freeBitVect (regsUsed);
3824   freeBitVect (regsUsedPrologue);
3825 }
3826
3827 /*-----------------------------------------------------------------*/
3828 /* genRet - generate code for return statement                     */
3829 /*-----------------------------------------------------------------*/
3830 static void
3831 genRet (iCode * ic)
3832 {
3833   int size, offset = 0, pushed = 0;
3834
3835   D(emitcode (";     genRet",""));
3836
3837   /* if we have no return value then
3838      just generate the "ret" */
3839   if (!IC_LEFT (ic))
3840     goto jumpret;
3841
3842   /* we have something to return then
3843      move the return value into place */
3844   aopOp (IC_LEFT (ic), ic, FALSE);
3845   size = AOP_SIZE (IC_LEFT (ic));
3846
3847
3848   if (IS_BIT(_G.currentFunc->etype))
3849     {
3850       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3851       size = 0;
3852     }
3853
3854   while (size--)
3855     {
3856       char *l;
3857       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3858         {
3859           /* #NOCHANGE */
3860           l = aopGet (IC_LEFT (ic), offset++,
3861                       FALSE, TRUE);
3862           emitcode ("push", "%s", l);
3863           pushed++;
3864         }
3865       else
3866         {
3867           l = aopGet (IC_LEFT (ic), offset,
3868                       FALSE, FALSE);
3869           if (strcmp (fReturn[offset], l))
3870             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3871         }
3872     }
3873
3874   while (pushed)
3875     {
3876       pushed--;
3877       if (strcmp (fReturn[pushed], "a"))
3878         emitcode ("pop", fReturn[pushed]);
3879       else
3880         emitcode ("pop", "acc");
3881     }
3882   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3883
3884 jumpret:
3885   /* generate a jump to the return label
3886      if the next is not the return statement */
3887   if (!(ic->next && ic->next->op == LABEL &&
3888         IC_LABEL (ic->next) == returnLabel))
3889
3890     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3891
3892 }
3893
3894 /*-----------------------------------------------------------------*/
3895 /* genLabel - generates a label                                    */
3896 /*-----------------------------------------------------------------*/
3897 static void
3898 genLabel (iCode * ic)
3899 {
3900   /* special case never generate */
3901   if (IC_LABEL (ic) == entryLabel)
3902     return;
3903
3904   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3905 }
3906
3907 /*-----------------------------------------------------------------*/
3908 /* genGoto - generates a ljmp                                      */
3909 /*-----------------------------------------------------------------*/
3910 static void
3911 genGoto (iCode * ic)
3912 {
3913   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3914 }
3915
3916 /*-----------------------------------------------------------------*/
3917 /* findLabelBackwards: walks back through the iCode chain looking  */
3918 /* for the given label. Returns number of iCode instructions     */
3919 /* between that label and given ic.          */
3920 /* Returns zero if label not found.          */
3921 /*-----------------------------------------------------------------*/
3922 static int
3923 findLabelBackwards (iCode * ic, int key)
3924 {
3925   int count = 0;
3926
3927   while (ic->prev)
3928     {
3929       ic = ic->prev;
3930       count++;
3931
3932       /* If we have any pushes or pops, we cannot predict the distance.
3933          I don't like this at all, this should be dealt with in the
3934          back-end */
3935       if (ic->op == IPUSH || ic->op == IPOP) {
3936         return 0;
3937       }
3938
3939       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3940         {
3941           return count;
3942         }
3943     }
3944
3945   return 0;
3946 }
3947
3948 /*-----------------------------------------------------------------*/
3949 /* genPlusIncr :- does addition with increment if possible         */
3950 /*-----------------------------------------------------------------*/
3951 static bool
3952 genPlusIncr (iCode * ic)
3953 {
3954   unsigned int icount;
3955   unsigned int size = getDataSize (IC_RESULT (ic));
3956
3957   /* will try to generate an increment */
3958   /* if the right side is not a literal
3959      we cannot */
3960   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3961     return FALSE;
3962
3963   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3964
3965   D(emitcode (";     genPlusIncr",""));
3966
3967   /* if increment >=16 bits in register or direct space */
3968   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3969       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3970       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3971       (size > 1) &&
3972       (icount == 1))
3973     {
3974       symbol *tlbl;
3975       int emitTlbl;
3976       int labelRange;
3977
3978       /* If the next instruction is a goto and the goto target
3979        * is < 10 instructions previous to this, we can generate
3980        * jumps straight to that target.
3981        */
3982       if (ic->next && ic->next->op == GOTO
3983           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3984           && labelRange <= 10)
3985         {
3986           emitcode (";", "tail increment optimized");
3987           tlbl = IC_LABEL (ic->next);
3988           emitTlbl = 0;
3989         }
3990       else
3991         {
3992           tlbl = newiTempLabel (NULL);
3993           emitTlbl = 1;
3994         }
3995       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3996       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3997           IS_AOP_PREG (IC_RESULT (ic)))
3998         emitcode ("cjne", "%s,#0x00,%05d$",
3999                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4000                   tlbl->key + 100);
4001       else
4002         {
4003           emitcode ("clr", "a");
4004           emitcode ("cjne", "a,%s,%05d$",
4005                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4006                     tlbl->key + 100);
4007         }
4008
4009       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4010       if (size > 2)
4011         {
4012           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4013               IS_AOP_PREG (IC_RESULT (ic)))
4014             emitcode ("cjne", "%s,#0x00,%05d$",
4015                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4016                       tlbl->key + 100);
4017           else
4018             emitcode ("cjne", "a,%s,%05d$",
4019                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4020                       tlbl->key + 100);
4021
4022           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4023         }
4024       if (size > 3)
4025         {
4026           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4027               IS_AOP_PREG (IC_RESULT (ic)))
4028             emitcode ("cjne", "%s,#0x00,%05d$",
4029                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4030                       tlbl->key + 100);
4031           else
4032             {
4033               emitcode ("cjne", "a,%s,%05d$",
4034                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4035                         tlbl->key + 100);
4036             }
4037           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4038         }
4039
4040       if (emitTlbl)
4041         {
4042           emitcode ("", "%05d$:", tlbl->key + 100);
4043         }
4044       return TRUE;
4045     }
4046
4047   /* if result is dptr */
4048   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4049       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4050       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4051       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4052     {
4053       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4054         return FALSE;
4055
4056       if (icount > 9)
4057         return FALSE;
4058
4059       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4060         return FALSE;
4061
4062       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4063       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4064       while (icount--)
4065         emitcode ("inc", "dptr");
4066
4067       return TRUE;
4068     }
4069
4070   /* if the literal value of the right hand side
4071      is greater than 4 then it is not worth it */
4072   if (icount > 4)
4073     return FALSE;
4074
4075   /* if the sizes are greater than 1 then we cannot */
4076   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4077       AOP_SIZE (IC_LEFT (ic)) > 1)
4078     return FALSE;
4079
4080   /* we can if the aops of the left & result match or
4081      if they are in registers and the registers are the
4082      same */
4083   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4084     {
4085
4086       if (icount > 3)
4087         {
4088           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4089           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4090           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4091         }
4092       else
4093         {
4094
4095           while (icount--)
4096             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4097         }
4098
4099       return TRUE;
4100     }
4101
4102   return FALSE;
4103 }
4104
4105 /*-----------------------------------------------------------------*/
4106 /* outBitAcc - output a bit in acc                                 */
4107 /*-----------------------------------------------------------------*/
4108 static void
4109 outBitAcc (operand * result)
4110 {
4111   symbol *tlbl = newiTempLabel (NULL);
4112   /* if the result is a bit */
4113   if (AOP_TYPE (result) == AOP_CRY)
4114     {
4115       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4116     }
4117   else
4118     {
4119       emitcode ("jz", "%05d$", tlbl->key + 100);
4120       emitcode ("mov", "a,%s", one);
4121       emitcode ("", "%05d$:", tlbl->key + 100);
4122       outAcc (result);
4123     }
4124 }
4125
4126 /*-----------------------------------------------------------------*/
4127 /* genPlusBits - generates code for addition of two bits           */
4128 /*-----------------------------------------------------------------*/
4129 static void
4130 genPlusBits (iCode * ic)
4131 {
4132   D(emitcode (";     genPlusBits",""));
4133
4134   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4135     {
4136       symbol *lbl = newiTempLabel (NULL);
4137       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4138       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4139       emitcode ("cpl", "c");
4140       emitcode ("", "%05d$:", (lbl->key + 100));
4141       outBitC (IC_RESULT (ic));
4142     }
4143   else
4144     {
4145       emitcode ("clr", "a");
4146       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4147       emitcode ("rlc", "a");
4148       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4149       emitcode ("addc", "a,#0x00");
4150       outAcc (IC_RESULT (ic));
4151     }
4152 }
4153
4154 #if 0
4155 /* This is the original version of this code.
4156
4157  * This is being kept around for reference,
4158  * because I am not entirely sure I got it right...
4159  */
4160 static void
4161 adjustArithmeticResult (iCode * ic)
4162 {
4163   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4164       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4165       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4166     aopPut (IC_RESULT (ic),
4167             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4168             2,
4169             isOperandVolatile (IC_RESULT (ic), FALSE));
4170
4171   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4172       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4173       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4174     aopPut (IC_RESULT (ic),
4175             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4176             2,
4177             isOperandVolatile (IC_RESULT (ic), FALSE));
4178
4179   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4180       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4181       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4182       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4183       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4184     {
4185       char buffer[5];
4186       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4187       aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4188     }
4189 }
4190 #else
4191 /* This is the pure and virtuous version of this code.
4192  * I'm pretty certain it's right, but not enough to toss the old
4193  * code just yet...
4194  */
4195 static void
4196 adjustArithmeticResult (iCode * ic)
4197 {
4198   if (opIsGptr (IC_RESULT (ic)) &&
4199       opIsGptr (IC_LEFT (ic)) &&
4200       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4201     {
4202       aopPut (IC_RESULT (ic),
4203               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4204               GPTRSIZE - 1,
4205               isOperandVolatile (IC_RESULT (ic), FALSE));
4206     }
4207
4208   if (opIsGptr (IC_RESULT (ic)) &&
4209       opIsGptr (IC_RIGHT (ic)) &&
4210       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4211     {
4212       aopPut (IC_RESULT (ic),
4213               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4214               GPTRSIZE - 1,
4215               isOperandVolatile (IC_RESULT (ic), FALSE));
4216     }
4217
4218   if (opIsGptr (IC_RESULT (ic)) &&
4219       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4220       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4221       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4222       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4223     {
4224       char buffer[5];
4225       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4226       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4227     }
4228 }
4229 #endif
4230
4231 /*-----------------------------------------------------------------*/
4232 /* genPlus - generates code for addition                           */
4233 /*-----------------------------------------------------------------*/
4234 static void
4235 genPlus (iCode * ic)
4236 {
4237   int size, offset = 0;
4238   int skip_bytes = 0;
4239   char *add = "add";
4240   bool swappedLR = FALSE;
4241   operand *leftOp, *rightOp;
4242   operand * op;
4243
4244   /* special cases :- */
4245
4246   D(emitcode (";     genPlus",""));
4247
4248   aopOp (IC_LEFT (ic), ic, FALSE);
4249   aopOp (IC_RIGHT (ic), ic, FALSE);
4250   aopOp (IC_RESULT (ic), ic, TRUE);
4251
4252   /* if literal, literal on the right or
4253      if left requires ACC or right is already
4254      in ACC */
4255   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4256       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4257       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4258     {
4259       operand *t = IC_RIGHT (ic);
4260       IC_RIGHT (ic) = IC_LEFT (ic);
4261       IC_LEFT (ic) = t;
4262           swappedLR = TRUE;
4263     }
4264
4265   /* if both left & right are in bit
4266      space */
4267   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4268       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4269     {
4270       genPlusBits (ic);
4271       goto release;
4272     }
4273
4274   /* if left in bit space & right literal */
4275   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4276       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4277     {
4278       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4279       /* if result in bit space */
4280       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4281         {
4282           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4283             emitcode ("cpl", "c");
4284           outBitC (IC_RESULT (ic));
4285         }
4286       else
4287         {
4288           size = getDataSize (IC_RESULT (ic));
4289           while (size--)
4290             {
4291               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4292               emitcode ("addc", "a,#00");
4293               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4294             }
4295         }
4296       goto release;
4297     }
4298
4299   /* if I can do an increment instead
4300      of add then GOOD for ME */
4301   if (genPlusIncr (ic) == TRUE)
4302     goto release;
4303
4304   size = getDataSize (IC_RESULT (ic));
4305   leftOp = IC_LEFT(ic);
4306   rightOp = IC_RIGHT(ic);
4307   op = IC_LEFT(ic);
4308
4309   /* if this is an add for an array access
4310      at a 256 byte boundary */
4311   if ( 2 == size
4312        && AOP_TYPE (op) == AOP_IMMD
4313        && IS_SYMOP (op)
4314        && IS_SPEC (OP_SYM_ETYPE (op))
4315        && SPEC_ABSA (OP_SYM_ETYPE (op))
4316        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4317      )
4318     {
4319       D(emitcode (";     genPlus aligned array",""));
4320       aopPut (IC_RESULT (ic),
4321               aopGet (rightOp, 0, FALSE, FALSE),
4322               0,
4323               isOperandVolatile (IC_RESULT (ic), FALSE));
4324
4325       if( 1 == getDataSize (IC_RIGHT (ic)) )
4326         {
4327           aopPut (IC_RESULT (ic),
4328                   aopGet (leftOp, 1, FALSE, FALSE),
4329                   1,
4330                   isOperandVolatile (IC_RESULT (ic), FALSE));
4331         }
4332       else
4333         {
4334           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4335           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4336           aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4337         }
4338       goto release;
4339     }
4340
4341   /* if the lower bytes of a literal are zero skip the addition */
4342   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4343     {
4344        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4345               (skip_bytes+1 < size))
4346          {
4347            skip_bytes++;
4348          }
4349        if (skip_bytes)
4350          D(emitcode (";     genPlus shortcut",""));
4351     }
4352
4353   while (size--)
4354     {
4355       if( offset >= skip_bytes )
4356         {
4357           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4358             {
4359               bool pushedB;
4360               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4361               pushedB = pushB ();
4362               emitcode("xch", "a,b");
4363               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4364               emitcode (add, "a,b");
4365               popB (pushedB);
4366             }
4367           else if (aopGetUsesAcc (leftOp, offset))
4368             {
4369               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4370               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4371             }
4372           else
4373             {
4374               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4375               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4376             }
4377           aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4378           add = "addc";  /* further adds must propagate carry */
4379         }
4380       else
4381         {
4382           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4383               isOperandVolatile (IC_RESULT (ic), FALSE))
4384             {
4385               /* just move */
4386               aopPut (IC_RESULT (ic),
4387                       aopGet (leftOp, offset, FALSE, FALSE),
4388                       offset,
4389                       isOperandVolatile (IC_RESULT (ic), FALSE));
4390             }
4391         }
4392       offset++;
4393     }
4394
4395   adjustArithmeticResult (ic);
4396
4397 release:
4398   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4399   if (!swappedLR)
4400     {
4401       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4402       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4403     }
4404   else
4405     {
4406       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4407       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4408     }
4409 }
4410
4411 /*-----------------------------------------------------------------*/
4412 /* genMinusDec :- does subtraction with decrement if possible      */
4413 /*-----------------------------------------------------------------*/
4414 static bool
4415 genMinusDec (iCode * ic)
4416 {
4417   unsigned int icount;
4418   unsigned int size = getDataSize (IC_RESULT (ic));
4419
4420   /* will try to generate an increment */
4421   /* if the right side is not a literal
4422      we cannot */
4423   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4424     return FALSE;
4425
4426   /* if the literal value of the right hand side
4427      is greater than 4 then it is not worth it */
4428   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4429     return FALSE;
4430
4431   D(emitcode (";     genMinusDec",""));
4432
4433   /* if decrement >=16 bits in register or direct space */
4434   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4435       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4436       (size > 1) &&
4437       (icount == 1))
4438     {
4439       symbol *tlbl;
4440       int emitTlbl;
4441       int labelRange;
4442
4443       /* If the next instruction is a goto and the goto target
4444        * is <= 10 instructions previous to this, we can generate
4445        * jumps straight to that target.
4446        */
4447       if (ic->next && ic->next->op == GOTO
4448           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4449           && labelRange <= 10)
4450         {
4451           emitcode (";", "tail decrement optimized");
4452           tlbl = IC_LABEL (ic->next);
4453           emitTlbl = 0;
4454         }
4455       else
4456         {
4457           tlbl = newiTempLabel (NULL);
4458           emitTlbl = 1;
4459         }
4460
4461       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4462       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4463           IS_AOP_PREG (IC_RESULT (ic)))
4464         emitcode ("cjne", "%s,#0xff,%05d$"
4465                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4466                   ,tlbl->key + 100);
4467       else
4468         {
4469           emitcode ("mov", "a,#0xff");
4470           emitcode ("cjne", "a,%s,%05d$"
4471                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4472                     ,tlbl->key + 100);
4473         }
4474       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4475       if (size > 2)
4476         {
4477           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4478               IS_AOP_PREG (IC_RESULT (ic)))
4479             emitcode ("cjne", "%s,#0xff,%05d$"
4480                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4481                       ,tlbl->key + 100);
4482           else
4483             {
4484               emitcode ("cjne", "a,%s,%05d$"
4485                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4486                         ,tlbl->key + 100);
4487             }
4488           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4489         }
4490       if (size > 3)
4491         {
4492           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4493               IS_AOP_PREG (IC_RESULT (ic)))
4494             emitcode ("cjne", "%s,#0xff,%05d$"
4495                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4496                       ,tlbl->key + 100);
4497           else
4498             {
4499               emitcode ("cjne", "a,%s,%05d$"
4500                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4501                         ,tlbl->key + 100);
4502             }
4503           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4504         }
4505       if (emitTlbl)
4506         {
4507           emitcode ("", "%05d$:", tlbl->key + 100);
4508         }
4509       return TRUE;
4510     }
4511
4512   /* if the sizes are greater than 1 then we cannot */
4513   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4514       AOP_SIZE (IC_LEFT (ic)) > 1)
4515     return FALSE;
4516
4517   /* we can if the aops of the left & result match or
4518      if they are in registers and the registers are the
4519      same */
4520   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4521     {
4522       char *l;
4523
4524       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4525         {
4526           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4527           l = "a";
4528         }
4529       else
4530         {
4531           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4532         }
4533
4534       while (icount--)
4535         emitcode ("dec", "%s", l);
4536
4537       if (AOP_NEEDSACC (IC_RESULT (ic)))
4538         aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4539
4540       return TRUE;
4541     }
4542
4543   return FALSE;
4544 }
4545
4546 /*-----------------------------------------------------------------*/
4547 /* addSign - complete with sign                                    */
4548 /*-----------------------------------------------------------------*/
4549 static void
4550 addSign (operand * result, int offset, int sign)
4551 {
4552   int size = (getDataSize (result) - offset);
4553   if (size > 0)
4554     {
4555       if (sign)
4556         {
4557           emitcode ("rlc", "a");
4558           emitcode ("subb", "a,acc");
4559           while (size--)
4560             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4561         }
4562       else
4563         while (size--)
4564           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4565     }
4566 }
4567
4568 /*-----------------------------------------------------------------*/
4569 /* genMinusBits - generates code for subtraction  of two bits      */
4570 /*-----------------------------------------------------------------*/
4571 static void
4572 genMinusBits (iCode * ic)
4573 {
4574   symbol *lbl = newiTempLabel (NULL);
4575
4576   D(emitcode (";     genMinusBits",""));
4577
4578   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4579     {
4580       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4581       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4582       emitcode ("cpl", "c");
4583       emitcode ("", "%05d$:", (lbl->key + 100));
4584       outBitC (IC_RESULT (ic));
4585     }
4586   else
4587     {
4588       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4589       emitcode ("subb", "a,acc");
4590       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4591       emitcode ("inc", "a");
4592       emitcode ("", "%05d$:", (lbl->key + 100));
4593       aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4594       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4595     }
4596 }
4597
4598 /*-----------------------------------------------------------------*/
4599 /* genMinus - generates code for subtraction                       */
4600 /*-----------------------------------------------------------------*/
4601 static void
4602 genMinus (iCode * ic)
4603 {
4604   int size, offset = 0;
4605
4606   D(emitcode (";     genMinus",""));
4607
4608   aopOp (IC_LEFT (ic), ic, FALSE);
4609   aopOp (IC_RIGHT (ic), ic, FALSE);
4610   aopOp (IC_RESULT (ic), ic, TRUE);
4611
4612   /* special cases :- */
4613   /* if both left & right are in bit space */
4614   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4615       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4616     {
4617       genMinusBits (ic);
4618       goto release;
4619     }
4620
4621   /* if I can do an decrement instead
4622      of subtract then GOOD for ME */
4623   if (genMinusDec (ic) == TRUE)
4624     goto release;
4625
4626   size = getDataSize (IC_RESULT (ic));
4627
4628   /* if literal, add a,#-lit, else normal subb */
4629   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4630     {
4631       unsigned long lit = 0L;
4632       bool useCarry = FALSE;
4633
4634       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4635       lit = -(long) lit;
4636
4637       while (size--)
4638         {
4639           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4640             {
4641             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4642               if (!offset && !size && lit== (unsigned long) -1)
4643                 {
4644                   emitcode ("dec", "a");
4645                 }
4646               else if (!useCarry)
4647                 {
4648                   /* first add without previous c */
4649                   emitcode ("add", "a,#0x%02x",
4650                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4651                   useCarry = TRUE;
4652                 }
4653               else
4654                 {
4655                   emitcode ("addc", "a,#0x%02x",
4656                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4657                 }
4658               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4659             }
4660           else
4661             {
4662               /* no need to add zeroes */
4663               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4664                 {
4665                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4666                           offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4667                 }
4668               offset++;
4669             }
4670         }
4671     }
4672   else
4673     {
4674       operand *leftOp, *rightOp;
4675
4676       leftOp = IC_LEFT(ic);
4677       rightOp = IC_RIGHT(ic);
4678
4679       while (size--)
4680         {
4681           if (aopGetUsesAcc(rightOp, offset)) {
4682             if (aopGetUsesAcc(leftOp, offset)) {
4683               bool pushedB;
4684
4685               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4686               pushedB = pushB ();
4687               emitcode ("mov", "b,a");
4688               if (offset == 0)
4689                 CLRC;
4690               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4691               emitcode ("subb", "a,b");
4692               popB (pushedB);
4693             } else {
4694               /* reverse subtraction with 2's complement */
4695               if (offset == 0)
4696                 emitcode( "setb", "c");
4697                else
4698                 emitcode( "cpl", "c");
4699               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4700               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4701               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4702               emitcode("cpl", "a");
4703               if (size) /* skip if last byte */
4704                 emitcode( "cpl", "c");
4705             }
4706           } else {
4707             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4708             if (offset == 0)
4709               CLRC;
4710             emitcode ("subb", "a,%s",
4711                       aopGet(rightOp, offset, FALSE, TRUE));
4712           }
4713
4714           aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4715         }
4716     }
4717
4718
4719   adjustArithmeticResult (ic);
4720
4721 release:
4722   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4723   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4724   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4725 }
4726
4727
4728 /*-----------------------------------------------------------------*/
4729 /* genMultbits :- multiplication of bits                           */
4730 /*-----------------------------------------------------------------*/
4731 static void
4732 genMultbits (operand * left,
4733              operand * right,
4734              operand * result)
4735 {
4736   D(emitcode (";     genMultbits",""));
4737
4738   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4739   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4740   outBitC (result);
4741 }
4742
4743 /*-----------------------------------------------------------------*/
4744 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4745 /*-----------------------------------------------------------------*/
4746 static void
4747 genMultOneByte (operand * left,
4748                 operand * right,
4749                 operand * result)
4750 {
4751   symbol *lbl;
4752   int size = AOP_SIZE (result);
4753   bool runtimeSign, compiletimeSign;
4754   bool lUnsigned, rUnsigned, pushedB;
4755
4756   D(emitcode (";     genMultOneByte",""));
4757
4758   if (size < 1 || size > 2)
4759     {
4760       /* this should never happen */
4761       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4762                AOP_SIZE(result), __FILE__, lineno);
4763       exit (1);
4764     }
4765
4766   /* (if two literals: the value is computed before) */
4767   /* if one literal, literal on the right */
4768   if (AOP_TYPE (left) == AOP_LIT)
4769     {
4770       operand *t = right;
4771       right = left;
4772       left = t;
4773       /* emitcode (";", "swapped left and right"); */
4774     }
4775   /* if no literal, unsigned on the right: shorter code */
4776   if (   AOP_TYPE (right) != AOP_LIT
4777       && SPEC_USIGN (getSpec (operandType (left))))
4778     {
4779       operand *t = right;
4780       right = left;
4781       left = t;
4782     }
4783
4784   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4785   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4786
4787   pushedB = pushB ();
4788
4789   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4790                    no need to take care about the signedness! */
4791       || (lUnsigned && rUnsigned))
4792     {
4793       /* just an unsigned 8 * 8 = 8 multiply
4794          or 8u * 8u = 16u */
4795       /* emitcode (";","unsigned"); */
4796       /* TODO: check for accumulator clash between left & right aops? */
4797
4798       if (AOP_TYPE (right) == AOP_LIT)
4799         {
4800           /* moving to accumulator first helps peepholes */
4801           MOVA (aopGet (left, 0, FALSE, FALSE));
4802           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4803         }
4804       else
4805         {
4806           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4807           MOVA (aopGet (left, 0, FALSE, FALSE));
4808         }
4809
4810       emitcode ("mul", "ab");
4811       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4812       if (size == 2)
4813         aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4814
4815       popB (pushedB);
4816       return;
4817     }
4818
4819   /* we have to do a signed multiply */
4820   /* emitcode (";", "signed"); */
4821
4822   /* now sign adjust for both left & right */
4823
4824   /* let's see what's needed: */
4825   /* apply negative sign during runtime */
4826   runtimeSign = FALSE;
4827   /* negative sign from literals */
4828   compiletimeSign = FALSE;
4829
4830   if (!lUnsigned)
4831     {
4832       if (AOP_TYPE(left) == AOP_LIT)
4833         {
4834           /* signed literal */
4835           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4836           if (val < 0)
4837             compiletimeSign = TRUE;
4838         }
4839       else
4840         /* signed but not literal */
4841         runtimeSign = TRUE;
4842     }
4843
4844   if (!rUnsigned)
4845     {
4846       if (AOP_TYPE(right) == AOP_LIT)
4847         {
4848           /* signed literal */
4849           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4850           if (val < 0)
4851             compiletimeSign ^= TRUE;
4852         }
4853       else
4854         /* signed but not literal */
4855         runtimeSign = TRUE;
4856     }
4857
4858   /* initialize F0, which stores the runtime sign */
4859   if (runtimeSign)
4860     {
4861       if (compiletimeSign)
4862         emitcode ("setb", "F0"); /* set sign flag */
4863       else
4864         emitcode ("clr", "F0"); /* reset sign flag */
4865     }
4866
4867   /* save the signs of the operands */
4868   if (AOP_TYPE(right) == AOP_LIT)
4869     {
4870       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4871
4872       if (!rUnsigned && val < 0)
4873         emitcode ("mov", "b,#0x%02x", -val);
4874       else
4875         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4876     }
4877   else /* ! literal */
4878     {
4879       if (rUnsigned)  /* emitcode (";", "signed"); */
4880
4881         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4882       else
4883         {
4884           MOVA (aopGet (right, 0, FALSE, FALSE));
4885           lbl = newiTempLabel (NULL);
4886           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4887           emitcode ("cpl", "F0"); /* complement sign flag */
4888           emitcode ("cpl", "a");  /* 2's complement */
4889           emitcode ("inc", "a");
4890           emitcode ("", "%05d$:", (lbl->key + 100));
4891           emitcode ("mov", "b,a");
4892         }
4893     }
4894
4895   if (AOP_TYPE(left) == AOP_LIT)
4896     {
4897       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4898
4899       if (!lUnsigned && val < 0)
4900         emitcode ("mov", "a,#0x%02x", -val);
4901       else
4902         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4903     }
4904   else /* ! literal */
4905     {
4906       MOVA (aopGet (left, 0, FALSE, FALSE));
4907
4908       if (!lUnsigned)
4909         {
4910           lbl = newiTempLabel (NULL);
4911           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4912           emitcode ("cpl", "F0"); /* complement sign flag */
4913           emitcode ("cpl", "a"); /* 2's complement */
4914           emitcode ("inc", "a");
4915           emitcode ("", "%05d$:", (lbl->key + 100));
4916         }
4917     }
4918
4919   /* now the multiplication */
4920   emitcode ("mul", "ab");
4921   if (runtimeSign || compiletimeSign)
4922     {
4923       lbl = newiTempLabel (NULL);
4924       if (runtimeSign)
4925         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4926       emitcode ("cpl", "a"); /* lsb 2's complement */
4927       if (size != 2)
4928         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4929       else
4930         {
4931           emitcode ("add", "a,#1"); /* this sets carry flag */
4932           emitcode ("xch", "a,b");
4933           emitcode ("cpl", "a"); /* msb 2's complement */
4934           emitcode ("addc", "a,#0");
4935           emitcode ("xch", "a,b");
4936         }
4937       emitcode ("", "%05d$:", (lbl->key + 100));
4938     }
4939   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4940   if (size == 2)
4941     aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4942
4943   popB (pushedB);
4944 }
4945
4946 /*-----------------------------------------------------------------*/
4947 /* genMult - generates code for multiplication                     */
4948 /*-----------------------------------------------------------------*/
4949 static void
4950 genMult (iCode * ic)
4951 {
4952   operand *left = IC_LEFT (ic);
4953   operand *right = IC_RIGHT (ic);
4954   operand *result = IC_RESULT (ic);
4955
4956   D(emitcode (";     genMult",""));
4957
4958   /* assign the asmops */
4959   aopOp (left, ic, FALSE);
4960   aopOp (right, ic, FALSE);
4961   aopOp (result, ic, TRUE);
4962
4963   /* special cases first */
4964   /* both are bits */
4965   if (AOP_TYPE (left) == AOP_CRY &&
4966       AOP_TYPE (right) == AOP_CRY)
4967     {
4968       genMultbits (left, right, result);
4969       goto release;
4970     }
4971
4972   /* if both are of size == 1 */
4973 #if 0 // one of them can be a sloc shared with the result
4974     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4975 #else
4976   if (getSize(operandType(left)) == 1 &&
4977       getSize(operandType(right)) == 1)
4978 #endif
4979     {
4980       genMultOneByte (left, right, result);
4981       goto release;
4982     }
4983
4984   /* should have been converted to function call */
4985     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4986              getSize(OP_SYMBOL(right)->type));
4987   assert (0);
4988
4989 release:
4990   freeAsmop (result, NULL, ic, TRUE);
4991   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4992   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4993 }
4994
4995 /*-----------------------------------------------------------------*/
4996 /* genDivbits :- division of bits                                  */
4997 /*-----------------------------------------------------------------*/
4998 static void
4999 genDivbits (operand * left,
5000             operand * right,
5001             operand * result)
5002 {
5003   char *l;
5004   bool pushedB;
5005
5006   D(emitcode (";     genDivbits",""));
5007
5008   pushedB = pushB ();
5009
5010   /* the result must be bit */
5011   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5012   l = aopGet (left, 0, FALSE, FALSE);
5013
5014   MOVA (l);
5015
5016   emitcode ("div", "ab");
5017   emitcode ("rrc", "a");
5018
5019   popB (pushedB);
5020
5021   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5022 }
5023
5024 /*-----------------------------------------------------------------*/
5025 /* genDivOneByte : 8 bit division                                  */
5026 /*-----------------------------------------------------------------*/
5027 static void
5028 genDivOneByte (operand * left,
5029                operand * right,
5030                operand * result)
5031 {
5032   bool lUnsigned, rUnsigned, pushedB;
5033   bool runtimeSign, compiletimeSign;
5034   bool accuse = FALSE;
5035   bool pushedA = FALSE;
5036   symbol *lbl;
5037   int size, offset;
5038
5039   D(emitcode (";     genDivOneByte",""));
5040
5041   /* Why is it necessary that genDivOneByte() can return an int result?
5042      Have a look at:
5043
5044         volatile unsigned char uc;
5045         volatile signed char sc1, sc2;
5046         volatile int i;
5047
5048         uc  = 255;
5049         sc1 = -1;
5050         i = uc / sc1;
5051
5052      Or:
5053
5054         sc1 = -128;
5055         sc2 = -1;
5056         i = sc1 / sc2;
5057
5058      In all cases a one byte result would overflow, the following cast to int
5059      would return the wrong result.
5060
5061      Two possible solution:
5062         a) cast operands to int, if ((unsigned) / (signed)) or
5063            ((signed) / (signed))
5064         b) return an 16 bit signed int; this is what we're doing here!
5065   */
5066
5067   size = AOP_SIZE (result) - 1;
5068   offset = 1;
5069   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5070   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5071
5072   pushedB = pushB ();
5073
5074   /* signed or unsigned */
5075   if (lUnsigned && rUnsigned)
5076     {
5077       /* unsigned is easy */
5078       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5079       MOVA (aopGet (left, 0, FALSE, FALSE));
5080       emitcode ("div", "ab");
5081       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5082       while (size--)
5083         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5084
5085       popB (pushedB);
5086       return;
5087     }
5088
5089   /* signed is a little bit more difficult */
5090
5091   /* now sign adjust for both left & right */
5092
5093   /* let's see what's needed: */
5094   /* apply negative sign during runtime */
5095   runtimeSign = FALSE;
5096   /* negative sign from literals */
5097   compiletimeSign = FALSE;
5098
5099   if (!lUnsigned)
5100     {
5101       if (AOP_TYPE(left) == AOP_LIT)
5102         {
5103           /* signed literal */
5104           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5105           if (val < 0)
5106             compiletimeSign = TRUE;
5107         }
5108       else
5109         /* signed but not literal */
5110         runtimeSign = TRUE;
5111     }
5112
5113   if (!rUnsigned)
5114     {
5115       if (AOP_TYPE(right) == AOP_LIT)
5116         {
5117           /* signed literal */
5118           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5119           if (val < 0)
5120             compiletimeSign ^= TRUE;
5121         }
5122       else
5123         /* signed but not literal */
5124         runtimeSign = TRUE;
5125     }
5126
5127   /* initialize F0, which stores the runtime sign */
5128   if (runtimeSign)
5129     {
5130       if (compiletimeSign)
5131         emitcode ("setb", "F0"); /* set sign flag */
5132       else
5133         emitcode ("clr", "F0"); /* reset sign flag */
5134     }
5135
5136   /* save the signs of the operands */
5137   if (AOP_TYPE(right) == AOP_LIT)
5138     {
5139       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5140
5141       if (!rUnsigned && val < 0)
5142         emitcode ("mov", "b,#0x%02x", -val);
5143       else
5144         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5145     }
5146   else /* ! literal */
5147     {
5148       if (rUnsigned)
5149         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5150       else
5151         {
5152           MOVA (aopGet (right, 0, FALSE, FALSE));
5153           lbl = newiTempLabel (NULL);
5154           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5155           emitcode ("cpl", "F0"); /* complement sign flag */
5156           emitcode ("cpl", "a");  /* 2's complement */
5157           emitcode ("inc", "a");
5158           emitcode ("", "%05d$:", (lbl->key + 100));
5159           emitcode ("mov", "b,a");
5160         }
5161     }
5162
5163   if (AOP_TYPE(left) == AOP_LIT)
5164     {
5165       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5166
5167       if (!lUnsigned && val < 0)
5168         emitcode ("mov", "a,#0x%02x", -val);
5169       else
5170         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5171     }
5172   else /* ! literal */
5173     {
5174       MOVA (aopGet (left, 0, FALSE, FALSE));
5175
5176       if (!lUnsigned)
5177         {
5178           lbl = newiTempLabel (NULL);
5179           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5180           emitcode ("cpl", "F0"); /* complement sign flag */
5181           emitcode ("cpl", "a");  /* 2's complement */
5182           emitcode ("inc", "a");
5183           emitcode ("", "%05d$:", (lbl->key + 100));
5184         }
5185     }
5186
5187   /* now the division */
5188   emitcode ("div", "ab");
5189
5190   if (runtimeSign || compiletimeSign)
5191     {
5192       lbl = newiTempLabel (NULL);
5193       if (runtimeSign)
5194         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5195       emitcode ("cpl", "a"); /* lsb 2's complement */
5196       emitcode ("inc", "a");
5197       emitcode ("", "%05d$:", (lbl->key + 100));
5198
5199       accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5200       if (size > 0)
5201         {
5202           /* msb is 0x00 or 0xff depending on the sign */
5203           if (runtimeSign)
5204             {
5205               if (accuse)
5206                 {
5207                   emitcode ("push", "acc");
5208                   pushedA = TRUE;
5209                 }
5210               emitcode ("mov", "c,F0");
5211               emitcode ("subb", "a,acc");
5212               while (size--)
5213                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5214             }
5215           else /* compiletimeSign */
5216             {
5217               if (aopPutUsesAcc (result, "#0xFF", offset))
5218                 {
5219                   emitcode ("push", "acc");
5220                   pushedA = TRUE;
5221                 }
5222               while (size--)
5223                 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5224             }
5225         }
5226     }
5227   else
5228     {
5229       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5230       while (size--)
5231         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5232     }
5233
5234   if (pushedA)
5235     emitcode ("pop", "acc");
5236   popB (pushedB);
5237 }
5238
5239 /*-----------------------------------------------------------------*/
5240 /* genDiv - generates code for division                            */
5241 /*-----------------------------------------------------------------*/
5242 static void
5243 genDiv (iCode * ic)
5244 {
5245   operand *left = IC_LEFT (ic);
5246   operand *right = IC_RIGHT (ic);
5247   operand *result = IC_RESULT (ic);
5248
5249   D(emitcode (";     genDiv",""));
5250
5251   /* assign the amsops */
5252   aopOp (left, ic, FALSE);
5253   aopOp (right, ic, FALSE);
5254   aopOp (result, ic, TRUE);
5255
5256   /* special cases first */
5257   /* both are bits */
5258   if (AOP_TYPE (left) == AOP_CRY &&
5259       AOP_TYPE (right) == AOP_CRY)
5260     {
5261       genDivbits (left, right, result);
5262       goto release;
5263     }
5264
5265   /* if both are of size == 1 */
5266   if (AOP_SIZE (left) == 1 &&
5267       AOP_SIZE (right) == 1)
5268     {
5269       genDivOneByte (left, right, result);
5270       goto release;
5271     }
5272
5273   /* should have been converted to function call */
5274   assert (0);
5275 release:
5276   freeAsmop (result, NULL, ic, TRUE);
5277   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5278   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5279 }
5280
5281 /*-----------------------------------------------------------------*/
5282 /* genModbits :- modulus of bits                                   */
5283 /*-----------------------------------------------------------------*/
5284 static void
5285 genModbits (operand * left,
5286             operand * right,
5287             operand * result)
5288 {
5289   char *l;
5290   bool pushedB;
5291
5292   D(emitcode (";     genModbits",""));
5293
5294   pushedB = pushB ();
5295
5296   /* the result must be bit */
5297   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5298   l = aopGet (left, 0, FALSE, FALSE);
5299
5300   MOVA (l);
5301
5302   emitcode ("div", "ab");
5303   emitcode ("mov", "a,b");
5304   emitcode ("rrc", "a");
5305
5306   popB (pushedB);
5307
5308   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5309 }
5310
5311 /*-----------------------------------------------------------------*/
5312 /* genModOneByte : 8 bit modulus                                   */
5313 /*-----------------------------------------------------------------*/
5314 static void
5315 genModOneByte (operand * left,
5316                operand * right,
5317                operand * result)
5318 {
5319   bool lUnsigned, rUnsigned, pushedB;
5320   bool runtimeSign, compiletimeSign;
5321   symbol *lbl;
5322   int size, offset;
5323
5324   D(emitcode (";     genModOneByte",""));
5325
5326   size = AOP_SIZE (result) - 1;
5327   offset = 1;
5328   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5329   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5330
5331   /* if right is a literal, check it for 2^n */
5332   if (AOP_TYPE(right) == AOP_LIT)
5333     {
5334       unsigned char val = abs((int) operandLitValue(right));
5335       symbol *lbl2 = NULL;
5336
5337       switch (val)
5338         {
5339           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5340           case 2:
5341           case 4:
5342           case 8:
5343           case 16:
5344           case 32:
5345           case 64:
5346           case 128:
5347             if (lUnsigned)
5348               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5349                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5350               /* because iCode should have been changed to genAnd  */
5351               /* see file "SDCCopt.c", function "convertToFcall()" */
5352
5353             MOVA (aopGet (left, 0, FALSE, FALSE));
5354             emitcode ("mov", "c,acc.7");
5355             emitcode ("anl", "a,#0x%02x", val - 1);
5356             lbl = newiTempLabel (NULL);
5357             emitcode ("jz", "%05d$", (lbl->key + 100));
5358             emitcode ("jnc", "%05d$", (lbl->key + 100));
5359             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5360             if (size)
5361               {
5362                 int size2 = size;
5363                 int offs2 = offset;
5364
5365                 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5366                 while (size2--)
5367                   aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5368                 lbl2 = newiTempLabel (NULL);
5369                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5370               }
5371             emitcode ("", "%05d$:", (lbl->key + 100));
5372             aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5373             while (size--)
5374               aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5375             if (lbl2)
5376               {
5377                 emitcode ("", "%05d$:", (lbl2->key + 100));
5378               }
5379             return;
5380
5381           default:
5382             break;
5383         }
5384     }
5385
5386   pushedB = pushB ();
5387
5388   /* signed or unsigned */
5389   if (lUnsigned && rUnsigned)
5390     {
5391       /* unsigned is easy */
5392       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5393       MOVA (aopGet (left, 0, FALSE, FALSE));
5394       emitcode ("div", "ab");
5395       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5396       while (size--)
5397         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5398
5399       popB (pushedB);
5400       return;
5401     }
5402
5403   /* signed is a little bit more difficult */
5404
5405   /* now sign adjust for both left & right */
5406
5407   /* modulus: sign of the right operand has no influence on the result! */
5408   if (AOP_TYPE(right) == AOP_LIT)
5409     {
5410       signed char val = (char) operandLitValue(right);
5411
5412       if (!rUnsigned && val < 0)
5413         emitcode ("mov", "b,#0x%02x", -val);
5414       else
5415         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5416     }
5417   else /* not literal */
5418     {
5419       if (rUnsigned)
5420         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5421       else
5422         {
5423           MOVA (aopGet (right, 0, FALSE, FALSE));
5424           lbl = newiTempLabel (NULL);
5425           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5426           emitcode ("cpl", "a"); /* 2's complement */
5427           emitcode ("inc", "a");
5428           emitcode ("", "%05d$:", (lbl->key + 100));
5429           emitcode ("mov", "b,a");
5430         }
5431     }
5432
5433   /* let's see what's needed: */
5434   /* apply negative sign during runtime */
5435   runtimeSign = FALSE;
5436   /* negative sign from literals */
5437   compiletimeSign = FALSE;
5438
5439   /* sign adjust left side */
5440   if (AOP_TYPE(left) == AOP_LIT)
5441     {
5442       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5443
5444       if (!lUnsigned && val < 0)
5445         {
5446           compiletimeSign = TRUE; /* set sign flag */
5447           emitcode ("mov", "a,#0x%02x", -val);
5448         }
5449       else
5450         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5451     }
5452   else /* ! literal */
5453     {
5454       MOVA (aopGet (left, 0, FALSE, FALSE));
5455
5456       if (!lUnsigned)
5457         {
5458           runtimeSign = TRUE;
5459           emitcode ("clr", "F0"); /* clear sign flag */
5460
5461           lbl = newiTempLabel (NULL);
5462           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5463           emitcode ("setb", "F0"); /* set sign flag */
5464           emitcode ("cpl", "a");   /* 2's complement */
5465           emitcode ("inc", "a");
5466           emitcode ("", "%05d$:", (lbl->key + 100));
5467         }
5468     }
5469
5470   /* now the modulus */
5471   emitcode ("div", "ab");
5472
5473   if (runtimeSign || compiletimeSign)
5474     {
5475       emitcode ("mov", "a,b");
5476       lbl = newiTempLabel (NULL);
5477       if (runtimeSign)
5478         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5479       emitcode ("cpl", "a"); /* 2's complement */
5480       emitcode ("inc", "a");
5481       emitcode ("", "%05d$:", (lbl->key + 100));
5482
5483       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5484       if (size > 0)
5485         {
5486           /* msb is 0x00 or 0xff depending on the sign */
5487           if (runtimeSign)
5488             {
5489               emitcode ("mov", "c,F0");
5490               emitcode ("subb", "a,acc");
5491               while (size--)
5492                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5493             }
5494           else /* compiletimeSign */
5495             while (size--)
5496               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5497         }
5498     }
5499   else
5500     {
5501       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5502       while (size--)
5503         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5504     }
5505
5506   popB (pushedB);
5507 }
5508
5509 /*-----------------------------------------------------------------*/
5510 /* genMod - generates code for division                            */
5511 /*-----------------------------------------------------------------*/
5512 static void
5513 genMod (iCode * ic)
5514 {
5515   operand *left = IC_LEFT (ic);
5516   operand *right = IC_RIGHT (ic);
5517   operand *result = IC_RESULT (ic);
5518
5519   D(emitcode (";     genMod",""));
5520
5521   /* assign the asmops */
5522   aopOp (left, ic, FALSE);
5523   aopOp (right, ic, FALSE);
5524   aopOp (result, ic, TRUE);
5525
5526   /* special cases first */
5527   /* both are bits */
5528   if (AOP_TYPE (left) == AOP_CRY &&
5529       AOP_TYPE (right) == AOP_CRY)
5530     {
5531       genModbits (left, right, result);
5532       goto release;
5533     }
5534
5535   /* if both are of size == 1 */
5536   if (AOP_SIZE (left) == 1 &&
5537       AOP_SIZE (right) == 1)
5538     {
5539       genModOneByte (left, right, result);
5540       goto release;
5541     }
5542
5543   /* should have been converted to function call */
5544   assert (0);
5545
5546 release:
5547   freeAsmop (result, NULL, ic, TRUE);
5548   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5549   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5550 }
5551
5552 /*-----------------------------------------------------------------*/
5553 /* genIfxJump :- will create a jump depending on the ifx           */
5554 /*-----------------------------------------------------------------*/
5555 static void
5556 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5557 {
5558   symbol *jlbl;
5559   symbol *tlbl = newiTempLabel (NULL);
5560   char *inst;
5561
5562   D(emitcode (";     genIfxJump",""));
5563
5564   /* if true label then we jump if condition
5565      supplied is true */
5566   if (IC_TRUE (ic))
5567     {
5568       jlbl = IC_TRUE (ic);
5569       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5570                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5571     }
5572   else
5573     {
5574       /* false label is present */
5575       jlbl = IC_FALSE (ic);
5576       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5577                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5578     }
5579   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5580     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5581   else
5582     emitcode (inst, "%05d$", tlbl->key + 100);
5583   freeForBranchAsmop (result);
5584   freeForBranchAsmop (right);
5585   freeForBranchAsmop (left);
5586   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5587   emitcode ("", "%05d$:", tlbl->key + 100);
5588
5589   /* mark the icode as generated */
5590   ic->generated = 1;
5591 }
5592
5593 /*-----------------------------------------------------------------*/
5594 /* genCmp :- greater or less than comparison                       */
5595 /*-----------------------------------------------------------------*/
5596 static void
5597 genCmp (operand * left, operand * right,
5598         operand * result, iCode * ifx, int sign, iCode *ic)
5599 {
5600   int size, offset = 0;
5601   unsigned long lit = 0L;
5602   bool rightInB;
5603
5604   D(emitcode (";     genCmp",""));
5605
5606   /* if left & right are bit variables */
5607   if (AOP_TYPE (left) == AOP_CRY &&
5608       AOP_TYPE (right) == AOP_CRY)
5609     {
5610       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5611       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5612     }
5613   else
5614     {
5615       /* subtract right from left if at the
5616          end the carry flag is set then we know that
5617          left is greater than right */
5618       size = max (AOP_SIZE (left), AOP_SIZE (right));
5619
5620       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5621       if ((size == 1) && !sign &&
5622           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5623         {
5624           symbol *lbl = newiTempLabel (NULL);
5625           emitcode ("cjne", "%s,%s,%05d$",
5626                     aopGet (left, offset, FALSE, FALSE),
5627                     aopGet (right, offset, FALSE, FALSE),
5628                     lbl->key + 100);
5629           emitcode ("", "%05d$:", lbl->key + 100);
5630         }
5631       else
5632         {
5633           if (AOP_TYPE (right) == AOP_LIT)
5634             {
5635               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5636               /* optimize if(x < 0) or if(x >= 0) */
5637               if (lit == 0L)
5638                 {
5639                   if (!sign)
5640                     {
5641                       CLRC;
5642                     }
5643                   else
5644                     {
5645                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5646                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5647                         {
5648                           genIfxJump (ifx, "acc.7", left, right, result);
5649                           freeAsmop (right, NULL, ic, TRUE);
5650                           freeAsmop (left, NULL, ic, TRUE);
5651
5652                           return;
5653                         }
5654                       else
5655                         emitcode ("rlc", "a");
5656                     }
5657                   goto release;
5658                 }
5659             }
5660           CLRC;
5661           while (size--)
5662             {
5663               bool pushedB = FALSE;
5664               rightInB = aopGetUsesAcc(right, offset);
5665               if (rightInB)
5666                 {
5667                   pushedB = pushB ();
5668                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5669                 }
5670               MOVA (aopGet (left, offset, FALSE, FALSE));
5671               if (sign && size == 0)
5672                 {
5673                   emitcode ("xrl", "a,#0x80");
5674                   if (AOP_TYPE (right) == AOP_LIT)
5675                     {
5676                       unsigned long lit = (unsigned long)
5677                       floatFromVal (AOP (right)->aopu.aop_lit);
5678                       emitcode ("subb", "a,#0x%02x",
5679                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5680                     }
5681                   else
5682                     {
5683                       if (!rightInB)
5684                         {
5685                           pushedB = pushB ();
5686                           rightInB++;
5687                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5688                         }
5689                       emitcode ("xrl", "b,#0x80");
5690                       emitcode ("subb", "a,b");
5691                     }
5692                 }
5693               else
5694                 {
5695                   if (rightInB)
5696                     emitcode ("subb", "a,b");
5697                   else
5698                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5699                 }
5700               if (rightInB)
5701                 popB (pushedB);
5702               offset++;
5703             }
5704         }
5705     }
5706
5707 release:
5708   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5710   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5711     {
5712       outBitC (result);
5713     }
5714   else
5715     {
5716       /* if the result is used in the next
5717          ifx conditional branch then generate
5718          code a little differently */
5719       if (ifx)
5720         genIfxJump (ifx, "c", NULL, NULL, result);
5721       else
5722         outBitC (result);
5723       /* leave the result in acc */
5724     }
5725 }
5726
5727 /*-----------------------------------------------------------------*/
5728 /* genCmpGt :- greater than comparison                             */
5729 /*-----------------------------------------------------------------*/
5730 static void
5731 genCmpGt (iCode * ic, iCode * ifx)
5732 {
5733   operand *left, *right, *result;
5734   sym_link *letype, *retype;
5735   int sign;
5736
5737   D(emitcode (";     genCmpGt",""));
5738
5739   left = IC_LEFT (ic);
5740   right = IC_RIGHT (ic);
5741   result = IC_RESULT (ic);
5742
5743   letype = getSpec (operandType (left));
5744   retype = getSpec (operandType (right));
5745   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5746            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5747   /* assign the amsops */
5748   aopOp (result, ic, TRUE);
5749   aopOp (left, ic, FALSE);
5750   aopOp (right, ic, FALSE);
5751
5752   genCmp (right, left, result, ifx, sign, ic);
5753
5754   freeAsmop (result, NULL, ic, TRUE);
5755 }
5756
5757 /*-----------------------------------------------------------------*/
5758 /* genCmpLt - less than comparisons                                */
5759 /*-----------------------------------------------------------------*/
5760 static void
5761 genCmpLt (iCode * ic, iCode * ifx)
5762 {
5763   operand *left, *right, *result;
5764   sym_link *letype, *retype;
5765   int sign;
5766
5767   D(emitcode (";     genCmpLt",""));
5768
5769   left = IC_LEFT (ic);
5770   right = IC_RIGHT (ic);
5771   result = IC_RESULT (ic);
5772
5773   letype = getSpec (operandType (left));
5774   retype = getSpec (operandType (right));
5775   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5776            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5777   /* assign the amsops */
5778   aopOp (result, ic, TRUE);
5779   aopOp (left, ic, FALSE);
5780   aopOp (right, ic, FALSE);
5781
5782   genCmp (left, right, result, ifx, sign, ic);
5783
5784   freeAsmop (result, NULL, ic, TRUE);
5785 }
5786
5787 /*-----------------------------------------------------------------*/
5788 /* gencjneshort - compare and jump if not equal                    */
5789 /*-----------------------------------------------------------------*/
5790 static void
5791 gencjneshort (operand * left, operand * right, symbol * lbl)
5792 {
5793   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5794   int offset = 0;
5795   unsigned long lit = 0L;
5796
5797   /* if the left side is a literal or
5798      if the right is in a pointer register and left
5799      is not */
5800   if ((AOP_TYPE (left) == AOP_LIT) ||
5801       (AOP_TYPE (left) == AOP_IMMD) ||
5802       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5803     {
5804       operand *t = right;
5805       right = left;
5806       left = t;
5807     }
5808
5809   if (AOP_TYPE (right) == AOP_LIT)
5810     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5811
5812   /* if the right side is a literal then anything goes */
5813   if (AOP_TYPE (right) == AOP_LIT &&
5814       AOP_TYPE (left) != AOP_DIR  &&
5815       AOP_TYPE (left) != AOP_IMMD)
5816     {
5817       while (size--)
5818         {
5819           emitcode ("cjne", "%s,%s,%05d$",
5820                     aopGet (left, offset, FALSE, FALSE),
5821                     aopGet (right, offset, FALSE, FALSE),
5822                     lbl->key + 100);
5823           offset++;
5824         }
5825     }
5826
5827   /* if the right side is in a register or in direct space or
5828      if the left is a pointer register & right is not */
5829   else if (AOP_TYPE (right) == AOP_REG ||
5830            AOP_TYPE (right) == AOP_DIR ||
5831            AOP_TYPE (right) == AOP_LIT ||
5832            AOP_TYPE (right) == AOP_IMMD ||
5833            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5834            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5835     {
5836       while (size--)
5837         {
5838           MOVA (aopGet (left, offset, FALSE, FALSE));
5839           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5840               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5841             emitcode ("jnz", "%05d$", lbl->key + 100);
5842           else
5843             emitcode ("cjne", "a,%s,%05d$",
5844                       aopGet (right, offset, FALSE, TRUE),
5845                       lbl->key + 100);
5846           offset++;
5847         }
5848     }
5849   else
5850     {
5851       /* right is a pointer reg need both a & b */
5852       while (size--)
5853         {
5854           char *l;
5855           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5856           wassertl(!BINUSE, "B was in use");
5857           l = aopGet (left, offset, FALSE, FALSE);
5858           if (strcmp (l, "b"))
5859             emitcode ("mov", "b,%s", l);
5860           MOVA (aopGet (right, offset, FALSE, FALSE));
5861           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5862           offset++;
5863         }
5864     }
5865 }
5866
5867 /*-----------------------------------------------------------------*/
5868 /* gencjne - compare and jump if not equal                         */
5869 /*-----------------------------------------------------------------*/
5870 static void
5871 gencjne (operand * left, operand * right, symbol * lbl)
5872 {
5873   symbol *tlbl = newiTempLabel (NULL);
5874
5875   gencjneshort (left, right, lbl);
5876
5877   emitcode ("mov", "a,%s", one);
5878   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5879   emitcode ("", "%05d$:", lbl->key + 100);
5880   emitcode ("clr", "a");
5881   emitcode ("", "%05d$:", tlbl->key + 100);
5882 }
5883
5884 /*-----------------------------------------------------------------*/
5885 /* genCmpEq - generates code for equal to                          */
5886 /*-----------------------------------------------------------------*/
5887 static void
5888 genCmpEq (iCode * ic, iCode * ifx)
5889 {
5890   bool swappedLR = FALSE;
5891   operand *left, *right, *result;
5892
5893   D(emitcode (";     genCmpEq",""));
5894
5895   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5896   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5897   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5898
5899   /* if literal, literal on the right or
5900      if the right is in a pointer register and left
5901      is not */
5902   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5903       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5904     {
5905       operand *t = IC_RIGHT (ic);
5906       IC_RIGHT (ic) = IC_LEFT (ic);
5907       IC_LEFT (ic) = t;
5908           swappedLR = TRUE;
5909     }
5910
5911   if (ifx && !AOP_SIZE (result))
5912     {
5913       symbol *tlbl;
5914       /* if they are both bit variables */
5915       if (AOP_TYPE (left) == AOP_CRY &&
5916           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5917         {
5918           if (AOP_TYPE (right) == AOP_LIT)
5919             {
5920               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5921               if (lit == 0L)
5922                 {
5923                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5924                   emitcode ("cpl", "c");
5925                 }
5926               else if (lit == 1L)
5927                 {
5928                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5929                 }
5930               else
5931                 {
5932                   emitcode ("clr", "c");
5933                 }
5934               /* AOP_TYPE(right) == AOP_CRY */
5935             }
5936           else
5937             {
5938               symbol *lbl = newiTempLabel (NULL);
5939               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5940               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5941               emitcode ("cpl", "c");
5942               emitcode ("", "%05d$:", (lbl->key + 100));
5943             }
5944           /* if true label then we jump if condition
5945              supplied is true */
5946           tlbl = newiTempLabel (NULL);
5947           if (IC_TRUE (ifx))
5948             {
5949               emitcode ("jnc", "%05d$", tlbl->key + 100);
5950               freeForBranchAsmop (result);
5951               freeForBranchAsmop (right);
5952               freeForBranchAsmop (left);
5953               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5954             }
5955           else
5956             {
5957               emitcode ("jc", "%05d$", tlbl->key + 100);
5958               freeForBranchAsmop (result);
5959               freeForBranchAsmop (right);
5960               freeForBranchAsmop (left);
5961               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5962             }
5963           emitcode ("", "%05d$:", tlbl->key + 100);
5964         }
5965       else
5966         {
5967           tlbl = newiTempLabel (NULL);
5968           gencjneshort (left, right, tlbl);
5969           if (IC_TRUE (ifx))
5970             {
5971               freeForBranchAsmop (result);
5972               freeForBranchAsmop (right);
5973               freeForBranchAsmop (left);
5974               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5975               emitcode ("", "%05d$:", tlbl->key + 100);
5976             }
5977           else
5978             {
5979               symbol *lbl = newiTempLabel (NULL);
5980               emitcode ("sjmp", "%05d$", lbl->key + 100);
5981               emitcode ("", "%05d$:", tlbl->key + 100);
5982               freeForBranchAsmop (result);
5983               freeForBranchAsmop (right);
5984               freeForBranchAsmop (left);
5985               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5986               emitcode ("", "%05d$:", lbl->key + 100);
5987             }
5988         }
5989       /* mark the icode as generated */
5990       ifx->generated = 1;
5991       goto release;
5992     }
5993
5994   /* if they are both bit variables */
5995   if (AOP_TYPE (left) == AOP_CRY &&
5996       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5997     {
5998       if (AOP_TYPE (right) == AOP_LIT)
5999         {
6000           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6001           if (lit == 0L)
6002             {
6003               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6004               emitcode ("cpl", "c");
6005             }
6006           else if (lit == 1L)
6007             {
6008               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6009             }
6010           else
6011             {
6012               emitcode ("clr", "c");
6013             }
6014           /* AOP_TYPE(right) == AOP_CRY */
6015         }
6016       else
6017         {
6018           symbol *lbl = newiTempLabel (NULL);
6019           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6020           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6021           emitcode ("cpl", "c");
6022           emitcode ("", "%05d$:", (lbl->key + 100));
6023         }
6024       /* c = 1 if egal */
6025       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6026         {
6027           outBitC (result);
6028           goto release;
6029         }
6030       if (ifx)
6031         {
6032           genIfxJump (ifx, "c", left, right, result);
6033           goto release;
6034         }
6035       /* if the result is used in an arithmetic operation
6036          then put the result in place */
6037       outBitC (result);
6038     }
6039   else
6040     {
6041       gencjne (left, right, newiTempLabel (NULL));
6042       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6043         {
6044           aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6045           goto release;
6046         }
6047       if (ifx)
6048         {
6049           genIfxJump (ifx, "a", left, right, result);
6050           goto release;
6051         }
6052       /* if the result is used in an arithmetic operation
6053          then put the result in place */
6054       if (AOP_TYPE (result) != AOP_CRY)
6055         outAcc (result);
6056       /* leave the result in acc */
6057     }
6058
6059 release:
6060   freeAsmop (result, NULL, ic, TRUE);
6061   if (!swappedLR)
6062     {
6063       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6064       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6065     }
6066   else
6067     {
6068       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6069       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6070     }
6071 }
6072
6073 /*-----------------------------------------------------------------*/
6074 /* ifxForOp - returns the icode containing the ifx for operand     */
6075 /*-----------------------------------------------------------------*/
6076 static iCode *
6077 ifxForOp (operand * op, iCode * ic)
6078 {
6079   /* if true symbol then needs to be assigned */
6080   if (IS_TRUE_SYMOP (op))
6081     return NULL;
6082
6083   /* if this has register type condition and
6084      the next instruction is ifx with the same operand
6085      and live to of the operand is upto the ifx only then */
6086   if (ic->next &&
6087       ic->next->op == IFX &&
6088       IC_COND (ic->next)->key == op->key &&
6089       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6090     return ic->next;
6091
6092   return NULL;
6093 }
6094
6095 /*-----------------------------------------------------------------*/
6096 /* hasInc - operand is incremented before any other use            */
6097 /*-----------------------------------------------------------------*/
6098 static iCode *
6099 hasInc (operand *op, iCode *ic,int osize)
6100 {
6101   sym_link *type = operandType(op);
6102   sym_link *retype = getSpec (type);
6103   iCode *lic = ic->next;
6104   int isize ;
6105
6106   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6107   if (!IS_SYMOP(op)) return NULL;
6108
6109   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6110   if (IS_AGGREGATE(type->next)) return NULL;
6111   if (osize != (isize = getSize(type->next))) return NULL;
6112
6113   while (lic) {
6114     /* if operand of the form op = op + <sizeof *op> */
6115     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6116         isOperandEqual(IC_RESULT(lic),op) &&
6117         isOperandLiteral(IC_RIGHT(lic)) &&
6118         operandLitValue(IC_RIGHT(lic)) == isize) {
6119       return lic;
6120     }
6121     /* if the operand used or deffed */
6122     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6123       return NULL;
6124     }
6125     /* if GOTO or IFX */
6126     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6127     lic = lic->next;
6128   }
6129   return NULL;
6130 }
6131
6132 /*-----------------------------------------------------------------*/
6133 /* genAndOp - for && operation                                     */
6134 /*-----------------------------------------------------------------*/
6135 static void
6136 genAndOp (iCode * ic)
6137 {
6138   operand *left, *right, *result;
6139   symbol *tlbl;
6140
6141   D(emitcode (";     genAndOp",""));
6142
6143   /* note here that && operations that are in an
6144      if statement are taken away by backPatchLabels
6145      only those used in arthmetic operations remain */
6146   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6147   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6148   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6149
6150   /* if both are bit variables */
6151   if (AOP_TYPE (left) == AOP_CRY &&
6152       AOP_TYPE (right) == AOP_CRY)
6153     {
6154       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6155       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6156       outBitC (result);
6157     }
6158   else
6159     {
6160       tlbl = newiTempLabel (NULL);
6161       toBoolean (left);
6162       emitcode ("jz", "%05d$", tlbl->key + 100);
6163       toBoolean (right);
6164       emitcode ("", "%05d$:", tlbl->key + 100);
6165       outBitAcc (result);
6166     }
6167
6168   freeAsmop (result, NULL, ic, TRUE);
6169   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6170   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6171 }
6172
6173
6174 /*-----------------------------------------------------------------*/
6175 /* genOrOp - for || operation                                      */
6176 /*-----------------------------------------------------------------*/
6177 static void
6178 genOrOp (iCode * ic)
6179 {
6180   operand *left, *right, *result;
6181   symbol *tlbl;
6182
6183   D(emitcode (";     genOrOp",""));
6184
6185   /* note here that || operations that are in an
6186      if statement are taken away by backPatchLabels
6187      only those used in arthmetic operations remain */
6188   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6189   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6190   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6191
6192   /* if both are bit variables */
6193   if (AOP_TYPE (left) == AOP_CRY &&
6194       AOP_TYPE (right) == AOP_CRY)
6195     {
6196       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6197       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6198       outBitC (result);
6199     }
6200   else
6201     {
6202       tlbl = newiTempLabel (NULL);
6203       toBoolean (left);
6204       emitcode ("jnz", "%05d$", tlbl->key + 100);
6205       toBoolean (right);
6206       emitcode ("", "%05d$:", tlbl->key + 100);
6207       outBitAcc (result);
6208     }
6209
6210   freeAsmop (result, NULL, ic, TRUE);
6211   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6212   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6213 }
6214
6215 /*-----------------------------------------------------------------*/
6216 /* isLiteralBit - test if lit == 2^n                               */
6217 /*-----------------------------------------------------------------*/
6218 static int
6219 isLiteralBit (unsigned long lit)
6220 {
6221   unsigned long pw[32] =
6222   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6223    0x100L, 0x200L, 0x400L, 0x800L,
6224    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6225    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6226    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6227    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6228    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6229   int idx;
6230
6231   for (idx = 0; idx < 32; idx++)
6232     if (lit == pw[idx])
6233       return idx + 1;
6234   return 0;
6235 }
6236
6237 /*-----------------------------------------------------------------*/
6238 /* continueIfTrue -                                                */
6239 /*-----------------------------------------------------------------*/
6240 static void
6241 continueIfTrue (iCode * ic)
6242 {
6243   if (IC_TRUE (ic))
6244     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6245   ic->generated = 1;
6246 }
6247
6248 /*-----------------------------------------------------------------*/
6249 /* jmpIfTrue -                                                     */
6250 /*-----------------------------------------------------------------*/
6251 static void
6252 jumpIfTrue (iCode * ic)
6253 {
6254   if (!IC_TRUE (ic))
6255     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6256   ic->generated = 1;
6257 }
6258
6259 /*-----------------------------------------------------------------*/
6260 /* jmpTrueOrFalse -                                                */
6261 /*-----------------------------------------------------------------*/
6262 static void
6263 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6264 {
6265   // ugly but optimized by peephole
6266   if (IC_TRUE (ic))
6267     {
6268       symbol *nlbl = newiTempLabel (NULL);
6269       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6270       emitcode ("", "%05d$:", tlbl->key + 100);
6271       freeForBranchAsmop (result);
6272       freeForBranchAsmop (right);
6273       freeForBranchAsmop (left);
6274       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6275       emitcode ("", "%05d$:", nlbl->key + 100);
6276     }
6277   else
6278     {
6279       freeForBranchAsmop (result);
6280       freeForBranchAsmop (right);
6281       freeForBranchAsmop (left);
6282       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6283       emitcode ("", "%05d$:", tlbl->key + 100);
6284     }
6285   ic->generated = 1;
6286 }
6287
6288 /*-----------------------------------------------------------------*/
6289 /* genAnd  - code for and                                          */
6290 /*-----------------------------------------------------------------*/
6291 static void
6292 genAnd (iCode * ic, iCode * ifx)
6293 {
6294   operand *left, *right, *result;
6295   int size, offset = 0;
6296   unsigned long lit = 0L;
6297   int bytelit = 0;
6298   char buffer[10];
6299
6300   D(emitcode (";     genAnd",""));
6301
6302   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6303   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6304   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6305
6306 #ifdef DEBUG_TYPE
6307   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6308             AOP_TYPE (result),
6309             AOP_TYPE (left), AOP_TYPE (right));
6310   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6311             AOP_SIZE (result),
6312             AOP_SIZE (left), AOP_SIZE (right));
6313 #endif
6314
6315   /* if left is a literal & right is not then exchange them */
6316   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6317       AOP_NEEDSACC (left))
6318     {
6319       operand *tmp = right;
6320       right = left;
6321       left = tmp;
6322     }
6323
6324   /* if result = right then exchange left and right */
6325   if (sameRegs (AOP (result), AOP (right)))
6326     {
6327       operand *tmp = right;
6328       right = left;
6329       left = tmp;
6330     }
6331
6332   /* if right is bit then exchange them */
6333   if (AOP_TYPE (right) == AOP_CRY &&
6334       AOP_TYPE (left) != AOP_CRY)
6335     {
6336       operand *tmp = right;
6337       right = left;
6338       left = tmp;
6339     }
6340   if (AOP_TYPE (right) == AOP_LIT)
6341     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6342
6343   size = AOP_SIZE (result);
6344
6345   // if(bit & yy)
6346   // result = bit & yy;
6347   if (AOP_TYPE (left) == AOP_CRY)
6348     {
6349       // c = bit & literal;
6350       if (AOP_TYPE (right) == AOP_LIT)
6351         {
6352           if (lit & 1)
6353             {
6354               if (size && sameRegs (AOP (result), AOP (left)))
6355                 // no change
6356                 goto release;
6357               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6358             }
6359           else
6360             {
6361               // bit(result) = 0;
6362               if (size && (AOP_TYPE (result) == AOP_CRY))
6363                 {
6364                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6365                   goto release;
6366                 }
6367               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6368                 {
6369                   jumpIfTrue (ifx);
6370                   goto release;
6371                 }
6372               emitcode ("clr", "c");
6373             }
6374         }
6375       else
6376         {
6377           if (AOP_TYPE (right) == AOP_CRY)
6378             {
6379               // c = bit & bit;
6380               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6381               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6382             }
6383           else
6384             {
6385               // c = bit & val;
6386               MOVA (aopGet (right, 0, FALSE, FALSE));
6387               // c = lsb
6388               emitcode ("rrc", "a");
6389               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6390             }
6391         }
6392       // bit = c
6393       // val = c
6394       if (size)
6395         outBitC (result);
6396       // if(bit & ...)
6397       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6398         genIfxJump (ifx, "c", left, right, result);
6399       goto release;
6400     }
6401
6402   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6403   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6404   if ((AOP_TYPE (right) == AOP_LIT) &&
6405       (AOP_TYPE (result) == AOP_CRY) &&
6406       (AOP_TYPE (left) != AOP_CRY))
6407     {
6408       int posbit = isLiteralBit (lit);
6409       /* left &  2^n */
6410       if (posbit)
6411         {
6412           posbit--;
6413           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6414           // bit = left & 2^n
6415           if (size)
6416             {
6417               switch (posbit & 0x07)
6418                 {
6419                   case 0: emitcode ("rrc", "a");
6420                           break;
6421                   case 7: emitcode ("rlc", "a");
6422                           break;
6423                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6424                           break;
6425                 }
6426             }
6427           // if(left &  2^n)
6428           else
6429             {
6430               if (ifx)
6431                 {
6432                   SNPRINTF (buffer, sizeof(buffer),
6433                             "acc.%d", posbit & 0x07);
6434                   genIfxJump (ifx, buffer, left, right, result);
6435                 }
6436               else
6437                 {// what is this case? just found it in ds390/gen.c
6438                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6439                 }
6440               goto release;
6441             }
6442         }
6443       else
6444         {
6445           symbol *tlbl = newiTempLabel (NULL);
6446           int sizel = AOP_SIZE (left);
6447           if (size)
6448             emitcode ("setb", "c");
6449           while (sizel--)
6450             {
6451               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6452                 {
6453                   MOVA (aopGet (left, offset, FALSE, FALSE));
6454                   // byte ==  2^n ?
6455                   if ((posbit = isLiteralBit (bytelit)) != 0)
6456                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6457                   else
6458                     {
6459                       if (bytelit != 0x0FFL)
6460                         emitcode ("anl", "a,%s",
6461                                   aopGet (right, offset, FALSE, TRUE));
6462                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6463                     }
6464                 }
6465               offset++;
6466             }
6467           // bit = left & literal
6468           if (size)
6469             {
6470               emitcode ("clr", "c");
6471               emitcode ("", "%05d$:", tlbl->key + 100);
6472             }
6473           // if(left & literal)
6474           else
6475             {
6476               if (ifx)
6477                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6478               else
6479                 emitcode ("", "%05d$:", tlbl->key + 100);
6480               goto release;
6481             }
6482         }
6483       outBitC (result);
6484       goto release;
6485     }
6486
6487   /* if left is same as result */
6488   if (sameRegs (AOP (result), AOP (left)))
6489     {
6490       for (; size--; offset++)
6491         {
6492           if (AOP_TYPE (right) == AOP_LIT)
6493             {
6494               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6495               if (bytelit == 0x0FF)
6496                 {
6497                   /* dummy read of volatile operand */
6498                   if (isOperandVolatile (left, FALSE))
6499                     MOVA (aopGet (left, offset, FALSE, FALSE));
6500                   else
6501                     continue;
6502                 }
6503               else if (bytelit == 0)
6504                 {
6505                   aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6506                 }
6507               else if (IS_AOP_PREG (result))
6508                 {
6509                   MOVA (aopGet (left, offset, FALSE, TRUE));
6510                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6511                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6512                 }
6513               else
6514                 emitcode ("anl", "%s,%s",
6515                           aopGet (left, offset, FALSE, TRUE),
6516                           aopGet (right, offset, FALSE, FALSE));
6517             }
6518           else
6519             {
6520               if (AOP_TYPE (left) == AOP_ACC)
6521                 {
6522                   if (offset)
6523                     emitcode("mov", "a,b");
6524                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6525                 }
6526               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6527                 {
6528                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6529                   MOVA (aopGet (right, offset, FALSE, FALSE));
6530                   emitcode ("anl", "a,b");
6531                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6532                 }
6533               else if (aopGetUsesAcc (left, offset))
6534                 {
6535                   MOVA (aopGet (left, offset, FALSE, FALSE));
6536                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6537                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6538                 }
6539               else
6540                 {
6541                   MOVA (aopGet (right, offset, FALSE, FALSE));
6542                   if (IS_AOP_PREG (result))
6543                     {
6544                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6545                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6546                     }
6547                   else
6548                     emitcode ("anl", "%s,a",
6549                               aopGet (left, offset, FALSE, TRUE));
6550                 }
6551             }
6552         }
6553     }
6554   else
6555     {
6556       // left & result in different registers
6557       if (AOP_TYPE (result) == AOP_CRY)
6558         {
6559           // result = bit
6560           // if(size), result in bit
6561           // if(!size && ifx), conditional oper: if(left & right)
6562           symbol *tlbl = newiTempLabel (NULL);
6563           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6564           if (size)
6565             emitcode ("setb", "c");
6566           while (sizer--)
6567             {
6568               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6569                   && AOP_TYPE(left)==AOP_ACC)
6570                 {
6571                   if (offset)
6572                     emitcode("mov", "a,b");
6573                   emitcode ("anl", "a,%s",
6574                             aopGet (right, offset, FALSE, FALSE));
6575                 } else {
6576                   if (AOP_TYPE(left)==AOP_ACC)
6577                     {
6578                       if (!offset)
6579                         {
6580                           bool pushedB = pushB ();
6581                           emitcode("mov", "b,a");
6582                           MOVA (aopGet (right, offset, FALSE, FALSE));
6583                           emitcode("anl", "a,b");
6584                           popB (pushedB);
6585                         }
6586                       else
6587                         {
6588                           MOVA (aopGet (right, offset, FALSE, FALSE));
6589                           emitcode("anl", "a,b");
6590                         }
6591                     } else {
6592                       MOVA (aopGet (right, offset, FALSE, FALSE));
6593                       emitcode ("anl", "a,%s",
6594                                 aopGet (left, offset, FALSE, FALSE));
6595                     }
6596                 }
6597               emitcode ("jnz", "%05d$", tlbl->key + 100);
6598               offset++;
6599             }
6600           if (size)
6601             {
6602               CLRC;
6603               emitcode ("", "%05d$:", tlbl->key + 100);
6604               outBitC (result);
6605             }
6606           else if (ifx)
6607             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6608           else
6609             emitcode ("", "%05d$:", tlbl->key + 100);
6610         }
6611       else
6612         {
6613           for (; (size--); offset++)
6614             {
6615               // normal case
6616               // result = left & right
6617               if (AOP_TYPE (right) == AOP_LIT)
6618                 {
6619                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6620                   if (bytelit == 0x0FF)
6621                     {
6622                       aopPut (result,
6623                               aopGet (left, offset, FALSE, FALSE),
6624                               offset,
6625                               isOperandVolatile (result, FALSE));
6626                       continue;
6627                     }
6628                   else if (bytelit == 0)
6629                     {
6630                       /* dummy read of volatile operand */
6631                       if (isOperandVolatile (left, FALSE))
6632                         MOVA (aopGet (left, offset, FALSE, FALSE));
6633                       aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6634                       continue;
6635                     }
6636                   else if (AOP_TYPE (left) == AOP_ACC)
6637                     {
6638                       if (!offset)
6639                         {
6640                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6641                           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6642                           continue;
6643                         }
6644                       else
6645                         {
6646                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6647                           aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6648                           continue;
6649                         }
6650                     }
6651                 }
6652               // faster than result <- left, anl result,right
6653               // and better if result is SFR
6654               if (AOP_TYPE (left) == AOP_ACC)
6655                 {
6656                   if (offset)
6657                     emitcode("mov", "a,b");
6658                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6659                 }
6660               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6661                 {
6662                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6663                   MOVA (aopGet (right, offset, FALSE, FALSE));
6664                   emitcode ("anl", "a,b");
6665                 }
6666               else if (aopGetUsesAcc (left, offset))
6667                 {
6668                   MOVA (aopGet (left, offset, FALSE, FALSE));
6669                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6670                 }
6671               else
6672                 {
6673                   MOVA (aopGet (right, offset, FALSE, FALSE));
6674                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6675                 }
6676               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6677             }
6678         }
6679     }
6680
6681 release:
6682   freeAsmop (result, NULL, ic, TRUE);
6683   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6684   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6685 }
6686
6687 /*-----------------------------------------------------------------*/
6688 /* genOr  - code for or                                            */
6689 /*-----------------------------------------------------------------*/
6690 static void
6691 genOr (iCode * ic, iCode * ifx)
6692 {
6693   operand *left, *right, *result;
6694   int size, offset = 0;
6695   unsigned long lit = 0L;
6696   int bytelit = 0;
6697
6698   D(emitcode (";     genOr",""));
6699
6700   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6701   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6702   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6703
6704 #ifdef DEBUG_TYPE
6705   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6706             AOP_TYPE (result),
6707             AOP_TYPE (left), AOP_TYPE (right));
6708   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6709             AOP_SIZE (result),
6710             AOP_SIZE (left), AOP_SIZE (right));
6711 #endif
6712
6713   /* if left is a literal & right is not then exchange them */
6714   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6715       AOP_NEEDSACC (left))
6716     {
6717       operand *tmp = right;
6718       right = left;
6719       left = tmp;
6720     }
6721
6722   /* if result = right then exchange them */
6723   if (sameRegs (AOP (result), AOP (right)))
6724     {
6725       operand *tmp = right;
6726       right = left;
6727       left = tmp;
6728     }
6729
6730   /* if right is bit then exchange them */
6731   if (AOP_TYPE (right) == AOP_CRY &&
6732       AOP_TYPE (left) != AOP_CRY)
6733     {
6734       operand *tmp = right;
6735       right = left;
6736       left = tmp;
6737     }
6738   if (AOP_TYPE (right) == AOP_LIT)
6739     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6740
6741   size = AOP_SIZE (result);
6742
6743   // if(bit | yy)
6744   // xx = bit | yy;
6745   if (AOP_TYPE (left) == AOP_CRY)
6746     {
6747       if (AOP_TYPE (right) == AOP_LIT)
6748         {
6749           // c = bit | literal;
6750           if (lit)
6751             {
6752               // lit != 0 => result = 1
6753               if (AOP_TYPE (result) == AOP_CRY)
6754                 {
6755                   if (size)
6756                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6757                   else if (ifx)
6758                     continueIfTrue (ifx);
6759                   goto release;
6760                 }
6761               emitcode ("setb", "c");
6762             }
6763           else
6764             {
6765               // lit == 0 => result = left
6766               if (size && sameRegs (AOP (result), AOP (left)))
6767                 goto release;
6768               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6769             }
6770         }
6771       else
6772         {
6773           if (AOP_TYPE (right) == AOP_CRY)
6774             {
6775               // c = bit | bit;
6776               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6777               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6778             }
6779           else
6780             {
6781               // c = bit | val;
6782               symbol *tlbl = newiTempLabel (NULL);
6783               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6784                 emitcode ("setb", "c");
6785               emitcode ("jb", "%s,%05d$",
6786                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6787               toBoolean (right);
6788               emitcode ("jnz", "%05d$", tlbl->key + 100);
6789               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6790                 {
6791                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6792                   goto release;
6793                 }
6794               else
6795                 {
6796                   CLRC;
6797                   emitcode ("", "%05d$:", tlbl->key + 100);
6798                 }
6799             }
6800         }
6801       // bit = c
6802       // val = c
6803       if (size)
6804         outBitC (result);
6805       // if(bit | ...)
6806       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6807         genIfxJump (ifx, "c", left, right, result);
6808       goto release;
6809     }
6810
6811   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6812   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6813   if ((AOP_TYPE (right) == AOP_LIT) &&
6814       (AOP_TYPE (result) == AOP_CRY) &&
6815       (AOP_TYPE (left) != AOP_CRY))
6816     {
6817       if (lit)
6818         {
6819           // result = 1
6820           if (size)
6821             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6822           else
6823             continueIfTrue (ifx);
6824           goto release;
6825         }
6826       else
6827         {
6828           // lit = 0, result = boolean(left)
6829           if (size)
6830             emitcode ("setb", "c");
6831           toBoolean (right);
6832           if (size)
6833             {
6834               symbol *tlbl = newiTempLabel (NULL);
6835               emitcode ("jnz", "%05d$", tlbl->key + 100);
6836               CLRC;
6837               emitcode ("", "%05d$:", tlbl->key + 100);
6838             }
6839           else
6840             {
6841               genIfxJump (ifx, "a", left, right, result);
6842               goto release;
6843             }
6844         }
6845       outBitC (result);
6846       goto release;
6847     }
6848
6849   /* if left is same as result */
6850   if (sameRegs (AOP (result), AOP (left)))
6851     {
6852       for (; size--; offset++)
6853         {
6854           if (AOP_TYPE (right) == AOP_LIT)
6855             {
6856               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6857               if (bytelit == 0)
6858                 {
6859                   /* dummy read of volatile operand */
6860                   if (isOperandVolatile (left, FALSE))
6861                     MOVA (aopGet (left, offset, FALSE, FALSE));
6862                   else
6863                     continue;
6864                 }
6865               else if (bytelit == 0x0FF)
6866                 {
6867                   aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6868                 }
6869               else if (IS_AOP_PREG (left))
6870                 {
6871                   MOVA (aopGet (left, offset, FALSE, TRUE));
6872                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6873                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6874                 }
6875               else
6876                 {
6877                   emitcode ("orl", "%s,%s",
6878                             aopGet (left, offset, FALSE, TRUE),
6879                             aopGet (right, offset, FALSE, FALSE));
6880                 }
6881             }
6882           else
6883             {
6884               if (AOP_TYPE (left) == AOP_ACC)
6885                 {
6886                   if (offset)
6887                     emitcode("mov", "a,b");
6888                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6889                 }
6890               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6891                 {
6892                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6893                   MOVA (aopGet (right, offset, FALSE, FALSE));
6894                   emitcode ("orl", "a,b");
6895                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6896                 }
6897               else if (aopGetUsesAcc (left, offset))
6898                 {
6899                   MOVA (aopGet (left, offset, FALSE, FALSE));
6900                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6901                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6902                 }
6903               else
6904                 {
6905                   MOVA (aopGet (right, offset, FALSE, FALSE));
6906                   if (IS_AOP_PREG (left))
6907                     {
6908                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6909                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6910                     }
6911                   else
6912                     {
6913                       emitcode ("orl", "%s,a",
6914                                 aopGet (left, offset, FALSE, TRUE));
6915                     }
6916                 }
6917             }
6918         }
6919     }
6920   else
6921     {
6922       // left & result in different registers
6923       if (AOP_TYPE (result) == AOP_CRY)
6924         {
6925           // result = bit
6926           // if(size), result in bit
6927           // if(!size && ifx), conditional oper: if(left | right)
6928           symbol *tlbl = newiTempLabel (NULL);
6929           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6930           if (size)
6931             emitcode ("setb", "c");
6932           while (sizer--)
6933             {
6934               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6935                 if (offset)
6936                   emitcode("mov", "a,b");
6937                 emitcode ("orl", "a,%s",
6938                           aopGet (right, offset, FALSE, FALSE));
6939               } else {
6940                 MOVA (aopGet (right, offset, FALSE, FALSE));
6941                 emitcode ("orl", "a,%s",
6942                           aopGet (left, offset, FALSE, FALSE));
6943               }
6944               emitcode ("jnz", "%05d$", tlbl->key + 100);
6945               offset++;
6946             }
6947           if (size)
6948             {
6949               CLRC;
6950               emitcode ("", "%05d$:", tlbl->key + 100);
6951               outBitC (result);
6952             }
6953           else if (ifx)
6954             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6955           else
6956             emitcode ("", "%05d$:", tlbl->key + 100);
6957         }
6958       else
6959         {
6960           for (; (size--); offset++)
6961             {
6962               // normal case
6963               // result = left | right
6964               if (AOP_TYPE (right) == AOP_LIT)
6965                 {
6966                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6967                   if (bytelit == 0)
6968                     {
6969                       aopPut (result,
6970                               aopGet (left, offset, FALSE, FALSE),
6971                               offset,
6972                               isOperandVolatile (result, FALSE));
6973                       continue;
6974                     }
6975                   else if (bytelit == 0x0FF)
6976                     {
6977                       /* dummy read of volatile operand */
6978                       if (isOperandVolatile (left, FALSE))
6979                         MOVA (aopGet (left, offset, FALSE, FALSE));
6980                       aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6981                       continue;
6982                     }
6983                 }
6984               // faster than result <- left, anl result,right
6985               // and better if result is SFR
6986               if (AOP_TYPE (left) == AOP_ACC)
6987                 {
6988                   if (offset)
6989                     emitcode("mov", "a,b");
6990                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6991                 }
6992               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6993                 {
6994                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6995                   MOVA (aopGet (right, offset, FALSE, FALSE));
6996                   emitcode ("orl", "a,b");
6997                 }
6998               else if (aopGetUsesAcc (left, offset))
6999                 {
7000                   MOVA (aopGet (left, offset, FALSE, FALSE));
7001                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7002                 }
7003               else
7004                 {
7005                   MOVA (aopGet (right, offset, FALSE, FALSE));
7006                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7007                 }
7008               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7009             }
7010         }
7011     }
7012
7013 release:
7014   freeAsmop (result, NULL, ic, TRUE);
7015   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7016   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7017 }
7018
7019 /*-----------------------------------------------------------------*/
7020 /* genXor - code for xclusive or                                   */
7021 /*-----------------------------------------------------------------*/
7022 static void
7023 genXor (iCode * ic, iCode * ifx)
7024 {
7025   operand *left, *right, *result;
7026   int size, offset = 0;
7027   unsigned long lit = 0L;
7028   int bytelit = 0;
7029
7030   D(emitcode (";     genXor",""));
7031
7032   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7033   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7034   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7035
7036 #ifdef DEBUG_TYPE
7037   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7038             AOP_TYPE (result),
7039             AOP_TYPE (left), AOP_TYPE (right));
7040   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7041             AOP_SIZE (result),
7042             AOP_SIZE (left), AOP_SIZE (right));
7043 #endif
7044
7045   /* if left is a literal & right is not ||
7046      if left needs acc & right does not */
7047   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7048       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7049     {
7050       operand *tmp = right;
7051       right = left;
7052       left = tmp;
7053     }
7054
7055   /* if result = right then exchange them */
7056   if (sameRegs (AOP (result), AOP (right)))
7057     {
7058       operand *tmp = right;
7059       right = left;
7060       left = tmp;
7061     }
7062
7063   /* if right is bit then exchange them */
7064   if (AOP_TYPE (right) == AOP_CRY &&
7065       AOP_TYPE (left) != AOP_CRY)
7066     {
7067       operand *tmp = right;
7068       right = left;
7069       left = tmp;
7070     }
7071   if (AOP_TYPE (right) == AOP_LIT)
7072     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7073
7074   size = AOP_SIZE (result);
7075
7076   // if(bit ^ yy)
7077   // xx = bit ^ yy;
7078   if (AOP_TYPE (left) == AOP_CRY)
7079     {
7080       if (AOP_TYPE (right) == AOP_LIT)
7081         {
7082           // c = bit & literal;
7083           if (lit >> 1)
7084             {
7085               // lit>>1  != 0 => result = 1
7086               if (AOP_TYPE (result) == AOP_CRY)
7087                 {
7088                   if (size)
7089                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7090                   else if (ifx)
7091                     continueIfTrue (ifx);
7092                   goto release;
7093                 }
7094               emitcode ("setb", "c");
7095             }
7096           else
7097             {
7098               // lit == (0 or 1)
7099               if (lit == 0)
7100                 {
7101                   // lit == 0, result = left
7102                   if (size && sameRegs (AOP (result), AOP (left)))
7103                     goto release;
7104                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7105                 }
7106               else
7107                 {
7108                   // lit == 1, result = not(left)
7109                   if (size && sameRegs (AOP (result), AOP (left)))
7110                     {
7111                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7112                       goto release;
7113                     }
7114                   else
7115                     {
7116                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7117                       emitcode ("cpl", "c");
7118                     }
7119                 }
7120             }
7121
7122         }
7123       else
7124         {
7125           // right != literal
7126           symbol *tlbl = newiTempLabel (NULL);
7127           if (AOP_TYPE (right) == AOP_CRY)
7128             {
7129               // c = bit ^ bit;
7130               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7131             }
7132           else
7133             {
7134               int sizer = AOP_SIZE (right);
7135               // c = bit ^ val
7136               // if val>>1 != 0, result = 1
7137               emitcode ("setb", "c");
7138               while (sizer)
7139                 {
7140                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7141                   if (sizer == 1)
7142                     // test the msb of the lsb
7143                     emitcode ("anl", "a,#0xfe");
7144                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7145                   sizer--;
7146                 }
7147               // val = (0,1)
7148               emitcode ("rrc", "a");
7149             }
7150           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7151           emitcode ("cpl", "c");
7152           emitcode ("", "%05d$:", (tlbl->key + 100));
7153         }
7154       // bit = c
7155       // val = c
7156       if (size)
7157         outBitC (result);
7158       // if(bit | ...)
7159       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7160         genIfxJump (ifx, "c", left, right, result);
7161       goto release;
7162     }
7163
7164   /* if left is same as result */
7165   if (sameRegs (AOP (result), AOP (left)))
7166     {
7167       for (; size--; offset++)
7168         {
7169           if (AOP_TYPE (right) == AOP_LIT)
7170             {
7171               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7172               if (bytelit == 0)
7173                 {
7174                   /* dummy read of volatile operand */
7175                   if (isOperandVolatile (left, FALSE))
7176                     MOVA (aopGet (left, offset, FALSE, FALSE));
7177                   else
7178                     continue;
7179                 }
7180               else if (IS_AOP_PREG (left))
7181                 {
7182                   MOVA (aopGet (left, offset, FALSE, TRUE));
7183                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7184                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7185                 }
7186               else
7187                 {
7188                   emitcode ("xrl", "%s,%s",
7189                             aopGet (left, offset, FALSE, TRUE),
7190                             aopGet (right, offset, FALSE, FALSE));
7191                 }
7192             }
7193           else
7194             {
7195               if (AOP_TYPE (left) == AOP_ACC)
7196                 {
7197                   if (offset)
7198                     emitcode("mov", "a,b");
7199                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7200                 }
7201               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7202                 {
7203                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7204                   MOVA (aopGet (right, offset, FALSE, FALSE));
7205                   emitcode ("xrl", "a,b");
7206                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7207                 }
7208               else if (aopGetUsesAcc (left, offset))
7209                 {
7210                   MOVA (aopGet (left, offset, FALSE, FALSE));
7211                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7212                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7213                 }
7214               else
7215                 {
7216                   MOVA (aopGet (right, offset, FALSE, FALSE));
7217                   if (IS_AOP_PREG (left))
7218                     {
7219                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7220                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7221                     }
7222                   else
7223                     emitcode ("xrl", "%s,a",
7224                               aopGet (left, offset, FALSE, TRUE));
7225                 }
7226             }
7227         }
7228     }
7229   else
7230     {
7231       // left & result in different registers
7232       if (AOP_TYPE (result) == AOP_CRY)
7233         {
7234           // result = bit
7235           // if(size), result in bit
7236           // if(!size && ifx), conditional oper: if(left ^ right)
7237           symbol *tlbl = newiTempLabel (NULL);
7238           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7239           if (size)
7240             emitcode ("setb", "c");
7241           while (sizer--)
7242             {
7243               if ((AOP_TYPE (right) == AOP_LIT) &&
7244                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7245                 {
7246                   MOVA (aopGet (left, offset, FALSE, FALSE));
7247                 }
7248               else
7249                 {
7250                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7251                     if (offset)
7252                       emitcode("mov", "a,b");
7253                     emitcode ("xrl", "a,%s",
7254                               aopGet (right, offset, FALSE, FALSE));
7255                   } else {
7256                     MOVA (aopGet (right, offset, FALSE, FALSE));
7257                     emitcode ("xrl", "a,%s",
7258                               aopGet (left, offset, FALSE, FALSE));
7259                   }
7260                 }
7261               emitcode ("jnz", "%05d$", tlbl->key + 100);
7262               offset++;
7263             }
7264           if (size)
7265             {
7266               CLRC;
7267               emitcode ("", "%05d$:", tlbl->key + 100);
7268               outBitC (result);
7269             }
7270           else if (ifx)
7271             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7272         }
7273       else
7274         {
7275           for (; (size--); offset++)
7276             {
7277               // normal case
7278               // result = left & right
7279               if (AOP_TYPE (right) == AOP_LIT)
7280                 {
7281                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7282                   if (bytelit == 0)
7283                     {
7284                       aopPut (result,
7285                               aopGet (left, offset, FALSE, FALSE),
7286                               offset,
7287                               isOperandVolatile (result, FALSE));
7288                       continue;
7289                     }
7290                 }
7291               // faster than result <- left, anl result,right
7292               // and better if result is SFR
7293               if (AOP_TYPE (left) == AOP_ACC)
7294                 {
7295                   if (offset)
7296                     emitcode("mov", "a,b");
7297                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7298                 }
7299               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7300                 {
7301                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7302                   MOVA (aopGet (right, offset, FALSE, FALSE));
7303                   emitcode ("xrl", "a,b");
7304                 }
7305               else if (aopGetUsesAcc (left, offset))
7306                 {
7307                   MOVA (aopGet (left, offset, FALSE, FALSE));
7308                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7309                 }
7310               else
7311                 {
7312                   MOVA (aopGet (right, offset, FALSE, FALSE));
7313                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7314                 }
7315               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7316             }
7317         }
7318     }
7319
7320 release:
7321   freeAsmop (result, NULL, ic, TRUE);
7322   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7323   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7324 }
7325
7326 /*-----------------------------------------------------------------*/
7327 /* genInline - write the inline code out                           */
7328 /*-----------------------------------------------------------------*/
7329 static void
7330 genInline (iCode * ic)
7331 {
7332   char *buffer, *bp, *bp1;
7333
7334   D(emitcode (";     genInline",""));
7335
7336   _G.inLine += (!options.asmpeep);
7337
7338   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7339   strcpy (buffer, IC_INLINE (ic));
7340
7341   /* emit each line as a code */
7342   while (*bp)
7343     {
7344       if (*bp == '\n')
7345         {
7346           *bp++ = '\0';
7347           emitcode (bp1, "");
7348           bp1 = bp;
7349         }
7350       else
7351         {
7352           /* Add \n for labels, not dirs such as c:\mydir */
7353           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7354             {
7355               bp++;
7356               *bp = '\0';
7357               bp++;
7358               emitcode (bp1, "");
7359               bp1 = bp;
7360             }
7361           else
7362             bp++;
7363         }
7364     }
7365   if (bp1 != bp)
7366     emitcode (bp1, "");
7367   /*     emitcode("",buffer); */
7368   _G.inLine -= (!options.asmpeep);
7369 }
7370
7371 /*-----------------------------------------------------------------*/
7372 /* genRRC - rotate right with carry                                */
7373 /*-----------------------------------------------------------------*/
7374 static void
7375 genRRC (iCode * ic)
7376 {
7377   operand *left, *result;
7378   int size, offset = 0;
7379   char *l;
7380
7381   D(emitcode (";     genRRC",""));
7382
7383   /* rotate right with carry */
7384   left = IC_LEFT (ic);
7385   result = IC_RESULT (ic);
7386   aopOp (left, ic, FALSE);
7387   aopOp (result, ic, FALSE);
7388
7389   /* move it to the result */
7390   size = AOP_SIZE (result);
7391   offset = size - 1;
7392   if (size == 1) { /* special case for 1 byte */
7393       l = aopGet (left, offset, FALSE, FALSE);
7394       MOVA (l);
7395       emitcode ("rr", "a");
7396       goto release;
7397   }
7398   /* no need to clear carry, bit7 will be written later */
7399   while (size--)
7400     {
7401       l = aopGet (left, offset, FALSE, FALSE);
7402       MOVA (l);
7403       emitcode ("rrc", "a");
7404       if (AOP_SIZE (result) > 1)
7405         aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7406     }
7407   /* now we need to put the carry into the
7408      highest order byte of the result */
7409   if (AOP_SIZE (result) > 1)
7410     {
7411       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7412       MOVA (l);
7413     }
7414   emitcode ("mov", "acc.7,c");
7415  release:
7416   aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7417   freeAsmop (result, NULL, ic, TRUE);
7418   freeAsmop (left, NULL, ic, TRUE);
7419 }
7420
7421 /*-----------------------------------------------------------------*/
7422 /* genRLC - generate code for rotate left with carry               */
7423 /*-----------------------------------------------------------------*/
7424 static void
7425 genRLC (iCode * ic)
7426 {
7427   operand *left, *result;
7428   int size, offset = 0;
7429   char *l;
7430
7431   D(emitcode (";     genRLC",""));
7432
7433   /* rotate right with carry */
7434   left = IC_LEFT (ic);
7435   result = IC_RESULT (ic);
7436   aopOp (left, ic, FALSE);
7437   aopOp (result, ic, FALSE);
7438
7439   /* move it to the result */
7440   size = AOP_SIZE (result);
7441   offset = 0;
7442   if (size--)
7443     {
7444       l = aopGet (left, offset, FALSE, FALSE);
7445       MOVA (l);
7446       if (size == 0) { /* special case for 1 byte */
7447               emitcode("rl","a");
7448               goto release;
7449       }
7450       emitcode("rlc","a"); /* bit0 will be written later */
7451       if (AOP_SIZE (result) > 1)
7452         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7453       while (size--)
7454         {
7455           l = aopGet (left, offset, FALSE, FALSE);
7456           MOVA (l);
7457           emitcode ("rlc", "a");
7458           if (AOP_SIZE (result) > 1)
7459             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7460         }
7461     }
7462   /* now we need to put the carry into the
7463      highest order byte of the result */
7464   if (AOP_SIZE (result) > 1)
7465     {
7466       l = aopGet (result, 0, FALSE, FALSE);
7467       MOVA (l);
7468     }
7469   emitcode ("mov", "acc.0,c");
7470  release:
7471   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7472   freeAsmop (result, NULL, ic, TRUE);
7473   freeAsmop (left, NULL, ic, TRUE);
7474 }
7475
7476 /*-----------------------------------------------------------------*/
7477 /* genGetHbit - generates code get highest order bit               */
7478 /*-----------------------------------------------------------------*/
7479 static void
7480 genGetHbit (iCode * ic)
7481 {
7482   operand *left, *result;
7483
7484   D(emitcode (";     genGetHbit",""));
7485
7486   left = IC_LEFT (ic);
7487   result = IC_RESULT (ic);
7488   aopOp (left, ic, FALSE);
7489   aopOp (result, ic, FALSE);
7490
7491   /* get the highest order byte into a */
7492   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7493   if (AOP_TYPE (result) == AOP_CRY)
7494     {
7495       emitcode ("rlc", "a");
7496       outBitC (result);
7497     }
7498   else
7499     {
7500       emitcode ("rl", "a");
7501       emitcode ("anl", "a,#0x01");
7502       outAcc (result);
7503     }
7504
7505   freeAsmop (result, NULL, ic, TRUE);
7506   freeAsmop (left, NULL, ic, TRUE);
7507 }
7508
7509 /*-----------------------------------------------------------------*/
7510 /* genGetAbit - generates code get a single bit                    */
7511 /*-----------------------------------------------------------------*/
7512 static void
7513 genGetAbit (iCode * ic)
7514 {
7515   operand *left, *right, *result;
7516   int shCount;
7517
7518   D(emitcode (";     genGetAbit",""));
7519
7520   left = IC_LEFT (ic);
7521   right = IC_RIGHT (ic);
7522   result = IC_RESULT (ic);
7523   aopOp (left, ic, FALSE);
7524   aopOp (right, ic, FALSE);
7525   aopOp (result, ic, FALSE);
7526
7527   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7528
7529   /* get the needed byte into a */
7530   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7531   shCount %= 8;
7532   if (AOP_TYPE (result) == AOP_CRY)
7533     {
7534       if ((shCount) == 7)
7535           emitcode ("rlc", "a");
7536       else if ((shCount) == 0)
7537           emitcode ("rrc", "a");
7538       else
7539           emitcode ("mov", "c,acc[%d]", shCount);
7540       outBitC (result);
7541     }
7542   else
7543     {
7544       switch (shCount)
7545         {
7546         case 2:
7547           emitcode ("rr", "a");
7548           //fallthrough
7549         case 1:
7550           emitcode ("rr", "a");
7551           //fallthrough
7552         case 0:
7553           emitcode ("anl", "a,#0x01");
7554           break;
7555         case 3:
7556         case 5:
7557           emitcode ("mov", "c,acc[%d]", shCount);
7558           emitcode ("clr", "a");
7559           emitcode ("rlc", "a");
7560           break;
7561         case 4:
7562           emitcode ("swap", "a");
7563           emitcode ("anl", "a,#0x01");
7564           break;
7565         case 6:
7566           emitcode ("rl", "a");
7567           //fallthrough
7568         case 7:
7569           emitcode ("rl", "a");
7570           emitcode ("anl", "a,#0x01");
7571           break;
7572         }
7573       outAcc (result);
7574     }
7575
7576   freeAsmop (result, NULL, ic, TRUE);
7577   freeAsmop (right, NULL, ic, TRUE);
7578   freeAsmop (left, NULL, ic, TRUE);
7579 }
7580
7581 /*-----------------------------------------------------------------*/
7582 /* genGetByte - generates code get a single byte                   */
7583 /*-----------------------------------------------------------------*/
7584 static void
7585 genGetByte (iCode * ic)
7586 {
7587   operand *left, *right, *result;
7588   int offset;
7589
7590   D(emitcode (";     genGetByte",""));
7591
7592   left = IC_LEFT (ic);
7593   right = IC_RIGHT (ic);
7594   result = IC_RESULT (ic);
7595   aopOp (left, ic, FALSE);
7596   aopOp (right, ic, FALSE);
7597   aopOp (result, ic, FALSE);
7598
7599   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7600   aopPut (result,
7601           aopGet (left, offset, FALSE, FALSE),
7602           0,
7603           isOperandVolatile (result, FALSE));
7604
7605   freeAsmop (result, NULL, ic, TRUE);
7606   freeAsmop (right, NULL, ic, TRUE);
7607   freeAsmop (left, NULL, ic, TRUE);
7608 }
7609
7610 /*-----------------------------------------------------------------*/
7611 /* genGetWord - generates code get two bytes                       */
7612 /*-----------------------------------------------------------------*/
7613 static void
7614 genGetWord (iCode * ic)
7615 {
7616   operand *left, *right, *result;
7617   int offset;
7618
7619   D(emitcode (";     genGetWord",""));
7620
7621   left = IC_LEFT (ic);
7622   right = IC_RIGHT (ic);
7623   result = IC_RESULT (ic);
7624   aopOp (left, ic, FALSE);
7625   aopOp (right, ic, FALSE);
7626   aopOp (result, ic, FALSE);
7627
7628   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7629   aopPut (result,
7630           aopGet (left, offset, FALSE, FALSE),
7631           0,
7632           isOperandVolatile (result, FALSE));
7633   aopPut (result,
7634           aopGet (left, offset+1, FALSE, FALSE),
7635           1,
7636           isOperandVolatile (result, FALSE));
7637
7638   freeAsmop (result, NULL, ic, TRUE);
7639   freeAsmop (right, NULL, ic, TRUE);
7640   freeAsmop (left, NULL, ic, TRUE);
7641 }
7642
7643 /*-----------------------------------------------------------------*/
7644 /* genSwap - generates code to swap nibbles or bytes               */
7645 /*-----------------------------------------------------------------*/
7646 static void
7647 genSwap (iCode * ic)
7648 {
7649   operand *left, *result;
7650
7651   D(emitcode (";     genSwap",""));
7652
7653   left = IC_LEFT (ic);
7654   result = IC_RESULT (ic);
7655   aopOp (left, ic, FALSE);
7656   aopOp (result, ic, FALSE);
7657
7658   switch (AOP_SIZE (left))
7659     {
7660     case 1: /* swap nibbles in byte */
7661       MOVA (aopGet (left, 0, FALSE, FALSE));
7662       emitcode ("swap", "a");
7663       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7664       break;
7665     case 2: /* swap bytes in word */
7666       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7667         {
7668           MOVA (aopGet (left, 0, FALSE, FALSE));
7669           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7670                   0, isOperandVolatile (result, FALSE));
7671           aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7672         }
7673       else if (operandsEqu (left, result))
7674         {
7675           char * reg = "a";
7676           bool pushedB = FALSE, leftInB = FALSE;
7677
7678           MOVA (aopGet (left, 0, FALSE, FALSE));
7679           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7680             {
7681               pushedB = pushB ();
7682               emitcode ("mov", "b,a");
7683               reg = "b";
7684               leftInB = TRUE;
7685             }
7686           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7687                   0, isOperandVolatile (result, FALSE));
7688           aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7689
7690           if (leftInB)
7691             popB (pushedB);
7692         }
7693       else
7694         {
7695           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7696                   0, isOperandVolatile (result, FALSE));
7697           aopPut (result, aopGet (left, 0, FALSE, FALSE),
7698                   1, isOperandVolatile (result, FALSE));
7699         }
7700       break;
7701     default:
7702       wassertl(FALSE, "unsupported SWAP operand size");
7703     }
7704
7705   freeAsmop (result, NULL, ic, TRUE);
7706   freeAsmop (left, NULL, ic, TRUE);
7707 }
7708
7709
7710 /*-----------------------------------------------------------------*/
7711 /* AccRol - rotate left accumulator by known count                 */
7712 /*-----------------------------------------------------------------*/
7713 static void
7714 AccRol (int shCount)
7715 {
7716   shCount &= 0x0007;            // shCount : 0..7
7717
7718   switch (shCount)
7719     {
7720     case 0:
7721       break;
7722     case 1:
7723       emitcode ("rl", "a");
7724       break;
7725     case 2:
7726       emitcode ("rl", "a");
7727       emitcode ("rl", "a");
7728       break;
7729     case 3:
7730       emitcode ("swap", "a");
7731       emitcode ("rr", "a");
7732       break;
7733     case 4:
7734       emitcode ("swap", "a");
7735       break;
7736     case 5:
7737       emitcode ("swap", "a");
7738       emitcode ("rl", "a");
7739       break;
7740     case 6:
7741       emitcode ("rr", "a");
7742       emitcode ("rr", "a");
7743       break;
7744     case 7:
7745       emitcode ("rr", "a");
7746       break;
7747     }
7748 }
7749
7750 /*-----------------------------------------------------------------*/
7751 /* AccLsh - left shift accumulator by known count                  */
7752 /*-----------------------------------------------------------------*/
7753 static void
7754 AccLsh (int shCount)
7755 {
7756   if (shCount != 0)
7757     {
7758       if (shCount == 1)
7759         emitcode ("add", "a,acc");
7760       else if (shCount == 2)
7761         {
7762           emitcode ("add", "a,acc");
7763           emitcode ("add", "a,acc");
7764         }
7765       else
7766         {
7767           /* rotate left accumulator */
7768           AccRol (shCount);
7769           /* and kill the lower order bits */
7770           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7771         }
7772     }
7773 }
7774
7775 /*-----------------------------------------------------------------*/
7776 /* AccRsh - right shift accumulator by known count                 */
7777 /*-----------------------------------------------------------------*/
7778 static void
7779 AccRsh (int shCount)
7780 {
7781   if (shCount != 0)
7782     {
7783       if (shCount == 1)
7784         {
7785           CLRC;
7786           emitcode ("rrc", "a");
7787         }
7788       else
7789         {
7790           /* rotate right accumulator */
7791           AccRol (8 - shCount);
7792           /* and kill the higher order bits */
7793           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7794         }
7795     }
7796 }
7797
7798 /*-----------------------------------------------------------------*/
7799 /* AccSRsh - signed right shift accumulator by known count                 */
7800 /*-----------------------------------------------------------------*/
7801 static void
7802 AccSRsh (int shCount)
7803 {
7804   symbol *tlbl;
7805   if (shCount != 0)
7806     {
7807       if (shCount == 1)
7808         {
7809           emitcode ("mov", "c,acc.7");
7810           emitcode ("rrc", "a");
7811         }
7812       else if (shCount == 2)
7813         {
7814           emitcode ("mov", "c,acc.7");
7815           emitcode ("rrc", "a");
7816           emitcode ("mov", "c,acc.7");
7817           emitcode ("rrc", "a");
7818         }
7819       else
7820         {
7821           tlbl = newiTempLabel (NULL);
7822           /* rotate right accumulator */
7823           AccRol (8 - shCount);
7824           /* and kill the higher order bits */
7825           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7826           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7827           emitcode ("orl", "a,#0x%02x",
7828                     (unsigned char) ~SRMask[shCount]);
7829           emitcode ("", "%05d$:", tlbl->key + 100);
7830         }
7831     }
7832 }
7833
7834 /*-----------------------------------------------------------------*/
7835 /* shiftR1Left2Result - shift right one byte from left to result   */
7836 /*-----------------------------------------------------------------*/
7837 static void
7838 shiftR1Left2Result (operand * left, int offl,
7839                     operand * result, int offr,
7840                     int shCount, int sign)
7841 {
7842   MOVA (aopGet (left, offl, FALSE, FALSE));
7843   /* shift right accumulator */
7844   if (sign)
7845     AccSRsh (shCount);
7846   else
7847     AccRsh (shCount);
7848   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7849 }
7850
7851 /*-----------------------------------------------------------------*/
7852 /* shiftL1Left2Result - shift left one byte from left to result    */
7853 /*-----------------------------------------------------------------*/
7854 static void
7855 shiftL1Left2Result (operand * left, int offl,
7856                     operand * result, int offr, int shCount)
7857 {
7858   char *l;
7859   l = aopGet (left, offl, FALSE, FALSE);
7860   MOVA (l);
7861   /* shift left accumulator */
7862   AccLsh (shCount);
7863   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7864 }
7865
7866 /*-----------------------------------------------------------------*/
7867 /* movLeft2Result - move byte from left to result                  */
7868 /*-----------------------------------------------------------------*/
7869 static void
7870 movLeft2Result (operand * left, int offl,
7871                 operand * result, int offr, int sign)
7872 {
7873   char *l;
7874   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7875     {
7876       l = aopGet (left, offl, FALSE, FALSE);
7877
7878       if (*l == '@' && (IS_AOP_PREG (result)))
7879         {
7880           emitcode ("mov", "a,%s", l);
7881           aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7882         }
7883       else
7884         {
7885           if (!sign)
7886             aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7887           else
7888             {
7889               /* MSB sign in acc.7 ! */
7890               if (getDataSize (left) == offl + 1)
7891                 {
7892                   MOVA (l);
7893                   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7894                 }
7895             }
7896         }
7897     }
7898 }
7899
7900 /*-----------------------------------------------------------------*/
7901 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7902 /*-----------------------------------------------------------------*/
7903 static void
7904 AccAXRrl1 (char *x)
7905 {
7906   emitcode ("rrc", "a");
7907   emitcode ("xch", "a,%s", x);
7908   emitcode ("rrc", "a");
7909   emitcode ("xch", "a,%s", x);
7910 }
7911
7912 /*-----------------------------------------------------------------*/
7913 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7914 /*-----------------------------------------------------------------*/
7915 static void
7916 AccAXLrl1 (char *x)
7917 {
7918   emitcode ("xch", "a,%s", x);
7919   emitcode ("rlc", "a");
7920   emitcode ("xch", "a,%s", x);
7921   emitcode ("rlc", "a");
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7926 /*-----------------------------------------------------------------*/
7927 static void
7928 AccAXLsh1 (char *x)
7929 {
7930   emitcode ("xch", "a,%s", x);
7931   emitcode ("add", "a,acc");
7932   emitcode ("xch", "a,%s", x);
7933   emitcode ("rlc", "a");
7934 }
7935
7936 /*-----------------------------------------------------------------*/
7937 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7938 /*-----------------------------------------------------------------*/
7939 static void
7940 AccAXLsh (char *x, int shCount)
7941 {
7942   switch (shCount)
7943     {
7944     case 0:
7945       break;
7946     case 1:
7947       AccAXLsh1 (x);
7948       break;
7949     case 2:
7950       AccAXLsh1 (x);
7951       AccAXLsh1 (x);
7952       break;
7953     case 3:
7954     case 4:
7955     case 5:                     // AAAAABBB:CCCCCDDD
7956
7957       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7958
7959       emitcode ("anl", "a,#0x%02x",
7960                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7961
7962       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7963
7964       AccRol (shCount);         // DDDCCCCC:BBB00000
7965
7966       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7967
7968       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7969
7970       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7971
7972       emitcode ("anl", "a,#0x%02x",
7973                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7974
7975       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7976
7977       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7978
7979       break;
7980     case 6:                     // AAAAAABB:CCCCCCDD
7981       emitcode ("anl", "a,#0x%02x",
7982                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7983       emitcode ("mov", "c,acc.0");      // c = B
7984       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7985 #if 0 // REMOVE ME
7986       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7987       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7988 #else
7989       emitcode("rrc","a");
7990       emitcode("xch","a,%s", x);
7991       emitcode("rrc","a");
7992       emitcode("mov","c,acc.0"); //<< get correct bit
7993       emitcode("xch","a,%s", x);
7994
7995       emitcode("rrc","a");
7996       emitcode("xch","a,%s", x);
7997       emitcode("rrc","a");
7998       emitcode("xch","a,%s", x);
7999 #endif
8000       break;
8001     case 7:                     // a:x <<= 7
8002
8003       emitcode ("anl", "a,#0x%02x",
8004                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8005
8006       emitcode ("mov", "c,acc.0");      // c = B
8007
8008       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8009
8010       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8011
8012       break;
8013     default:
8014       break;
8015     }
8016 }
8017
8018 /*-----------------------------------------------------------------*/
8019 /* AccAXRsh - right shift a:x known count (0..7)                   */
8020 /*-----------------------------------------------------------------*/
8021 static void
8022 AccAXRsh (char *x, int shCount)
8023 {
8024   switch (shCount)
8025     {
8026     case 0:
8027       break;
8028     case 1:
8029       CLRC;
8030       AccAXRrl1 (x);            // 0->a:x
8031
8032       break;
8033     case 2:
8034       CLRC;
8035       AccAXRrl1 (x);            // 0->a:x
8036
8037       CLRC;
8038       AccAXRrl1 (x);            // 0->a:x
8039
8040       break;
8041     case 3:
8042     case 4:
8043     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8044
8045       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8046
8047       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8048
8049       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8050
8051       emitcode ("anl", "a,#0x%02x",
8052                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8053
8054       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8055
8056       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8057
8058       emitcode ("anl", "a,#0x%02x",
8059                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8060
8061       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8062
8063       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8064
8065       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8066
8067       break;
8068     case 6:                     // AABBBBBB:CCDDDDDD
8069
8070       emitcode ("mov", "c,acc.7");
8071       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8072
8073       emitcode ("mov", "c,acc.7");
8074       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8075
8076       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8077
8078       emitcode ("anl", "a,#0x%02x",
8079                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8080
8081       break;
8082     case 7:                     // ABBBBBBB:CDDDDDDD
8083
8084       emitcode ("mov", "c,acc.7");      // c = A
8085
8086       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8087
8088       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8089
8090       emitcode ("anl", "a,#0x%02x",
8091                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8092
8093       break;
8094     default:
8095       break;
8096     }
8097 }
8098
8099 /*-----------------------------------------------------------------*/
8100 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8101 /*-----------------------------------------------------------------*/
8102 static void
8103 AccAXRshS (char *x, int shCount)
8104 {
8105   symbol *tlbl;
8106   switch (shCount)
8107     {
8108     case 0:
8109       break;
8110     case 1:
8111       emitcode ("mov", "c,acc.7");
8112       AccAXRrl1 (x);            // s->a:x
8113
8114       break;
8115     case 2:
8116       emitcode ("mov", "c,acc.7");
8117       AccAXRrl1 (x);            // s->a:x
8118
8119       emitcode ("mov", "c,acc.7");
8120       AccAXRrl1 (x);            // s->a:x
8121
8122       break;
8123     case 3:
8124     case 4:
8125     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8126
8127       tlbl = newiTempLabel (NULL);
8128       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8129
8130       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8131
8132       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8133
8134       emitcode ("anl", "a,#0x%02x",
8135                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8136
8137       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8138
8139       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8140
8141       emitcode ("anl", "a,#0x%02x",
8142                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8143
8144       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8145
8146       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8147
8148       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8149
8150       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8151       emitcode ("orl", "a,#0x%02x",
8152                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8153
8154       emitcode ("", "%05d$:", tlbl->key + 100);
8155       break;                    // SSSSAAAA:BBBCCCCC
8156
8157     case 6:                     // AABBBBBB:CCDDDDDD
8158
8159       tlbl = newiTempLabel (NULL);
8160       emitcode ("mov", "c,acc.7");
8161       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8162
8163       emitcode ("mov", "c,acc.7");
8164       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8165
8166       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8167
8168       emitcode ("anl", "a,#0x%02x",
8169                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8170
8171       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8172       emitcode ("orl", "a,#0x%02x",
8173                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8174
8175       emitcode ("", "%05d$:", tlbl->key + 100);
8176       break;
8177     case 7:                     // ABBBBBBB:CDDDDDDD
8178
8179       tlbl = newiTempLabel (NULL);
8180       emitcode ("mov", "c,acc.7");      // c = A
8181
8182       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8183
8184       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8185
8186       emitcode ("anl", "a,#0x%02x",
8187                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8188
8189       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8190       emitcode ("orl", "a,#0x%02x",
8191                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8192
8193       emitcode ("", "%05d$:", tlbl->key + 100);
8194       break;
8195     default:
8196       break;
8197     }
8198 }
8199
8200 /*-----------------------------------------------------------------*/
8201 /* shiftL2Left2Result - shift left two bytes from left to result   */
8202 /*-----------------------------------------------------------------*/
8203 static void
8204 shiftL2Left2Result (operand * left, int offl,
8205                     operand * result, int offr, int shCount)
8206 {
8207   char * x;
8208   bool pushedB = FALSE;
8209   bool usedB = FALSE;
8210
8211   if (sameRegs (AOP (result), AOP (left)) &&
8212       ((offl + MSB16) == offr))
8213     {
8214       /* don't crash result[offr] */
8215       MOVA (aopGet (left, offl, FALSE, FALSE));
8216       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8217       x = aopGet (result, offr, FALSE, FALSE);
8218     }
8219   else if (aopGetUsesAcc (result, offr))
8220     {
8221       movLeft2Result (left, offl, result, offr, 0);
8222       pushedB = pushB ();
8223       usedB = TRUE;
8224       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8225       MOVA (aopGet (result, offr, FALSE, FALSE));
8226       emitcode ("xch", "a,b");
8227       x = "b";
8228     }
8229   else
8230     {
8231       movLeft2Result (left, offl, result, offr, 0);
8232       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8233       x = aopGet (result, offr, FALSE, FALSE);
8234     }
8235   /* ax << shCount (x = lsb(result)) */
8236   AccAXLsh (x, shCount);
8237   if (usedB)
8238     {
8239       emitcode ("xch", "a,b");
8240       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8241       aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8242       popB (pushedB);
8243     }
8244   else
8245     {
8246       aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8247     }
8248 }
8249
8250
8251 /*-----------------------------------------------------------------*/
8252 /* shiftR2Left2Result - shift right two bytes from left to result  */
8253 /*-----------------------------------------------------------------*/
8254 static void
8255 shiftR2Left2Result (operand * left, int offl,
8256                     operand * result, int offr,
8257                     int shCount, int sign)
8258 {
8259   char * x;
8260   bool pushedB = FALSE;
8261   bool usedB = FALSE;
8262
8263   if (sameRegs (AOP (result), AOP (left)) &&
8264       ((offl + MSB16) == offr))
8265     {
8266       /* don't crash result[offr] */
8267       MOVA (aopGet (left, offl, FALSE, FALSE));
8268       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8269       x = aopGet (result, offr, FALSE, FALSE);
8270     }
8271   else if (aopGetUsesAcc (result, offr))
8272     {
8273       movLeft2Result (left, offl, result, offr, 0);
8274       pushedB = pushB ();
8275       usedB = TRUE;
8276       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8277       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8278       x = "b";
8279     }
8280   else
8281     {
8282       movLeft2Result (left, offl, result, offr, 0);
8283       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8284       x = aopGet (result, offr, FALSE, FALSE);
8285     }
8286   /* a:x >> shCount (x = lsb(result)) */
8287   if (sign)
8288     AccAXRshS (x, shCount);
8289   else
8290     AccAXRsh (x, shCount);
8291   if (usedB)
8292     {
8293       emitcode ("xch", "a,b");
8294       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8295       emitcode ("xch", "a,b");
8296       popB (pushedB);
8297     }
8298   if (getDataSize (result) > 1)
8299     aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8300 }
8301
8302 /*-----------------------------------------------------------------*/
8303 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8304 /*-----------------------------------------------------------------*/
8305 static void
8306 shiftLLeftOrResult (operand * left, int offl,
8307                     operand * result, int offr, int shCount)
8308 {
8309   MOVA (aopGet (left, offl, FALSE, FALSE));
8310   /* shift left accumulator */
8311   AccLsh (shCount);
8312   /* or with result */
8313   if (aopGetUsesAcc (result, offr))
8314     {
8315       emitcode ("xch", "a,b");
8316       MOVA (aopGet (result, offr, FALSE, FALSE));
8317       emitcode ("orl", "a,b");
8318     }
8319   else
8320     {
8321       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8322     }
8323   /* back to result */
8324   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8325 }
8326
8327 /*-----------------------------------------------------------------*/
8328 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8329 /*-----------------------------------------------------------------*/
8330 static void
8331 shiftRLeftOrResult (operand * left, int offl,
8332                     operand * result, int offr, int shCount)
8333 {
8334   MOVA (aopGet (left, offl, FALSE, FALSE));
8335   /* shift right accumulator */
8336   AccRsh (shCount);
8337   /* or with result */
8338   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8339   /* back to result */
8340   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8341 }
8342
8343 /*-----------------------------------------------------------------*/
8344 /* genlshOne - left shift a one byte quantity by known count       */
8345 /*-----------------------------------------------------------------*/
8346 static void
8347 genlshOne (operand * result, operand * left, int shCount)
8348 {
8349   D(emitcode (";     genlshOne",""));
8350
8351   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8352 }
8353
8354 /*-----------------------------------------------------------------*/
8355 /* genlshTwo - left shift two bytes by known amount != 0           */
8356 /*-----------------------------------------------------------------*/
8357 static void
8358 genlshTwo (operand * result, operand * left, int shCount)
8359 {
8360   int size;
8361
8362   D(emitcode (";     genlshTwo",""));
8363
8364   size = getDataSize (result);
8365
8366   /* if shCount >= 8 */
8367   if (shCount >= 8)
8368     {
8369       shCount -= 8;
8370
8371       if (size > 1)
8372         {
8373           if (shCount)
8374             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8375           else
8376             movLeft2Result (left, LSB, result, MSB16, 0);
8377         }
8378       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8379     }
8380
8381   /*  1 <= shCount <= 7 */
8382   else
8383     {
8384       if (size == 1)
8385         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8386       else
8387         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8388     }
8389 }
8390
8391 /*-----------------------------------------------------------------*/
8392 /* shiftLLong - shift left one long from left to result            */
8393 /* offl = LSB or MSB16                                             */
8394 /*-----------------------------------------------------------------*/
8395 static void
8396 shiftLLong (operand * left, operand * result, int offr)
8397 {
8398   char *l;
8399   int size = AOP_SIZE (result);
8400
8401   if (size >= LSB + offr)
8402     {
8403       l = aopGet (left, LSB, FALSE, FALSE);
8404       MOVA (l);
8405       emitcode ("add", "a,acc");
8406       if (sameRegs (AOP (left), AOP (result)) &&
8407           size >= MSB16 + offr && offr != LSB)
8408         emitcode ("xch", "a,%s",
8409                   aopGet (left, LSB + offr, FALSE, FALSE));
8410       else
8411         aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8412     }
8413
8414   if (size >= MSB16 + offr)
8415     {
8416       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8417         {
8418           l = aopGet (left, MSB16, FALSE, FALSE);
8419           MOVA (l);
8420         }
8421       emitcode ("rlc", "a");
8422       if (sameRegs (AOP (left), AOP (result)) &&
8423           size >= MSB24 + offr && offr != LSB)
8424         emitcode ("xch", "a,%s",
8425                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8426       else
8427         aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8428     }
8429
8430   if (size >= MSB24 + offr)
8431     {
8432       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8433         {
8434           l = aopGet (left, MSB24, FALSE, FALSE);
8435           MOVA (l);
8436         }
8437       emitcode ("rlc", "a");
8438       if (sameRegs (AOP (left), AOP (result)) &&
8439           size >= MSB32 + offr && offr != LSB)
8440         emitcode ("xch", "a,%s",
8441                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8442       else
8443         aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8444     }
8445
8446   if (size > MSB32 + offr)
8447     {
8448       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8449         {
8450           l = aopGet (left, MSB32, FALSE, FALSE);
8451           MOVA (l);
8452         }
8453       emitcode ("rlc", "a");
8454       aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8455     }
8456   if (offr != LSB)
8457     aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8458 }
8459
8460 /*-----------------------------------------------------------------*/
8461 /* genlshFour - shift four byte by a known amount != 0             */
8462 /*-----------------------------------------------------------------*/
8463 static void
8464 genlshFour (operand * result, operand * left, int shCount)
8465 {
8466   int size;
8467
8468   D(emitcode (";     genlshFour",""));
8469
8470   size = AOP_SIZE (result);
8471
8472   /* if shifting more that 3 bytes */
8473   if (shCount >= 24)
8474     {
8475       shCount -= 24;
8476       if (shCount)
8477         /* lowest order of left goes to the highest
8478            order of the destination */
8479         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8480       else
8481         movLeft2Result (left, LSB, result, MSB32, 0);
8482       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8483       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8484       aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8485       return;
8486     }
8487
8488   /* more than two bytes */
8489   else if (shCount >= 16)
8490     {
8491       /* lower order two bytes goes to higher order two bytes */
8492       shCount -= 16;
8493       /* if some more remaining */
8494       if (shCount)
8495         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8496       else
8497         {
8498           movLeft2Result (left, MSB16, result, MSB32, 0);
8499           movLeft2Result (left, LSB, result, MSB24, 0);
8500         }
8501       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8502       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8503       return;
8504     }
8505
8506   /* if more than 1 byte */
8507   else if (shCount >= 8)
8508     {
8509       /* lower order three bytes goes to higher order  three bytes */
8510       shCount -= 8;
8511       if (size == 2)
8512         {
8513           if (shCount)
8514             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8515           else
8516             movLeft2Result (left, LSB, result, MSB16, 0);
8517         }
8518       else
8519         {                       /* size = 4 */
8520           if (shCount == 0)
8521             {
8522               movLeft2Result (left, MSB24, result, MSB32, 0);
8523               movLeft2Result (left, MSB16, result, MSB24, 0);
8524               movLeft2Result (left, LSB, result, MSB16, 0);
8525               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8526             }
8527           else if (shCount == 1)
8528             shiftLLong (left, result, MSB16);
8529           else
8530             {
8531               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8532               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8533               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8534               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8535             }
8536         }
8537     }
8538
8539   /* 1 <= shCount <= 7 */
8540   else if (shCount <= 2)
8541     {
8542       shiftLLong (left, result, LSB);
8543       if (shCount == 2)
8544         shiftLLong (result, result, LSB);
8545     }
8546   /* 3 <= shCount <= 7, optimize */
8547   else
8548     {
8549       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8550       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8551       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8552     }
8553 }
8554
8555 /*-----------------------------------------------------------------*/
8556 /* genLeftShiftLiteral - left shifting by known count              */
8557 /*-----------------------------------------------------------------*/
8558 static void
8559 genLeftShiftLiteral (operand * left,
8560                      operand * right,
8561                      operand * result,
8562                      iCode * ic)
8563 {
8564   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8565   int size;
8566
8567   D(emitcode (";     genLeftShiftLiteral",""));
8568
8569   freeAsmop (right, NULL, ic, TRUE);
8570
8571   aopOp (left, ic, FALSE);
8572   aopOp (result, ic, FALSE);
8573
8574   size = getSize (operandType (result));
8575
8576 #if VIEW_SIZE
8577   emitcode ("; shift left ", "result %d, left %d", size,
8578             AOP_SIZE (left));
8579 #endif
8580
8581   /* I suppose that the left size >= result size */
8582   if (shCount == 0)
8583     {
8584       while (size--)
8585         {
8586           movLeft2Result (left, size, result, size, 0);
8587         }
8588     }
8589
8590   else if (shCount >= (size * 8))
8591     while (size--)
8592       aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8593   else
8594     {
8595       switch (size)
8596         {
8597         case 1:
8598           genlshOne (result, left, shCount);
8599           break;
8600
8601         case 2:
8602           genlshTwo (result, left, shCount);
8603           break;
8604
8605         case 4:
8606           genlshFour (result, left, shCount);
8607           break;
8608         default:
8609           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8610                   "*** ack! mystery literal shift!\n");
8611           break;
8612         }
8613     }
8614   freeAsmop (result, NULL, ic, TRUE);
8615   freeAsmop (left, NULL, ic, TRUE);
8616 }
8617
8618 /*-----------------------------------------------------------------*/
8619 /* genLeftShift - generates code for left shifting                 */
8620 /*-----------------------------------------------------------------*/
8621 static void
8622 genLeftShift (iCode * ic)
8623 {
8624   operand *left, *right, *result;
8625   int size, offset;
8626   char *l;
8627   symbol *tlbl, *tlbl1;
8628   bool pushedB;
8629
8630   D(emitcode (";     genLeftShift",""));
8631
8632   right = IC_RIGHT (ic);
8633   left = IC_LEFT (ic);
8634   result = IC_RESULT (ic);
8635
8636   aopOp (right, ic, FALSE);
8637
8638   /* if the shift count is known then do it
8639      as efficiently as possible */
8640   if (AOP_TYPE (right) == AOP_LIT)
8641     {
8642       genLeftShiftLiteral (left, right, result, ic);
8643       return;
8644     }
8645
8646   /* shift count is unknown then we have to form
8647      a loop get the loop count in B : Note: we take
8648      only the lower order byte since shifting
8649      more that 32 bits make no sense anyway, ( the
8650      largest size of an object can be only 32 bits ) */
8651
8652   pushedB = pushB ();
8653   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8654   emitcode ("inc", "b");
8655   freeAsmop (right, NULL, ic, TRUE);
8656   aopOp (left, ic, FALSE);
8657   aopOp (result, ic, FALSE);
8658
8659   /* now move the left to the result if they are not the same */
8660   if (!sameRegs (AOP (left), AOP (result)) &&
8661       AOP_SIZE (result) > 1)
8662     {
8663
8664       size = AOP_SIZE (result);
8665       offset = 0;
8666       while (size--)
8667         {
8668           l = aopGet (left, offset, FALSE, TRUE);
8669           if (*l == '@' && (IS_AOP_PREG (result)))
8670             {
8671
8672               emitcode ("mov", "a,%s", l);
8673               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8674             }
8675           else
8676             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8677           offset++;
8678         }
8679     }
8680
8681   tlbl = newiTempLabel (NULL);
8682   size = AOP_SIZE (result);
8683   offset = 0;
8684   tlbl1 = newiTempLabel (NULL);
8685
8686   /* if it is only one byte then */
8687   if (size == 1)
8688     {
8689       symbol *tlbl1 = newiTempLabel (NULL);
8690
8691       l = aopGet (left, 0, FALSE, FALSE);
8692       MOVA (l);
8693       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8694       emitcode ("", "%05d$:", tlbl->key + 100);
8695       emitcode ("add", "a,acc");
8696       emitcode ("", "%05d$:", tlbl1->key + 100);
8697       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8698       popB (pushedB);
8699       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8700       goto release;
8701     }
8702
8703   reAdjustPreg (AOP (result));
8704
8705   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8706   emitcode ("", "%05d$:", tlbl->key + 100);
8707   l = aopGet (result, offset, FALSE, FALSE);
8708   MOVA (l);
8709   emitcode ("add", "a,acc");
8710   aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8711   while (--size)
8712     {
8713       l = aopGet (result, offset, FALSE, FALSE);
8714       MOVA (l);
8715       emitcode ("rlc", "a");
8716       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8717     }
8718   reAdjustPreg (AOP (result));
8719
8720   emitcode ("", "%05d$:", tlbl1->key + 100);
8721   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8722   popB (pushedB);
8723 release:
8724   freeAsmop (result, NULL, ic, TRUE);
8725   freeAsmop (left, NULL, ic, TRUE);
8726 }
8727
8728 /*-----------------------------------------------------------------*/
8729 /* genrshOne - right shift a one byte quantity by known count      */
8730 /*-----------------------------------------------------------------*/
8731 static void
8732 genrshOne (operand * result, operand * left,
8733            int shCount, int sign)
8734 {
8735   D(emitcode (";     genrshOne",""));
8736
8737   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8738 }
8739
8740 /*-----------------------------------------------------------------*/
8741 /* genrshTwo - right shift two bytes by known amount != 0          */
8742 /*-----------------------------------------------------------------*/
8743 static void
8744 genrshTwo (operand * result, operand * left,
8745            int shCount, int sign)
8746 {
8747   D(emitcode (";     genrshTwo",""));
8748
8749   /* if shCount >= 8 */
8750   if (shCount >= 8)
8751     {
8752       shCount -= 8;
8753       if (shCount)
8754         shiftR1Left2Result (left, MSB16, result, LSB,
8755                             shCount, sign);
8756       else
8757         movLeft2Result (left, MSB16, result, LSB, sign);
8758       addSign (result, MSB16, sign);
8759     }
8760
8761   /*  1 <= shCount <= 7 */
8762   else
8763     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8764 }
8765
8766 /*-----------------------------------------------------------------*/
8767 /* shiftRLong - shift right one long from left to result           */
8768 /* offl = LSB or MSB16                                             */
8769 /*-----------------------------------------------------------------*/
8770 static void
8771 shiftRLong (operand * left, int offl,
8772             operand * result, int sign)
8773 {
8774   int isSameRegs = sameRegs (AOP (left), AOP (result));
8775
8776   if (isSameRegs && offl>1) {
8777     // we are in big trouble, but this shouldn't happen
8778     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8779   }
8780
8781   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8782
8783   if (offl==MSB16) {
8784     // shift is > 8
8785     if (sign) {
8786       emitcode ("rlc", "a");
8787       emitcode ("subb", "a,acc");
8788       if (isSameRegs)
8789         emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8790       else {
8791         aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8792         MOVA (aopGet (left, MSB32, FALSE, FALSE));
8793       }
8794     } else {
8795       aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8796     }
8797   }
8798
8799   if (!sign) {
8800     emitcode ("clr", "c");
8801   } else {
8802     emitcode ("mov", "c,acc.7");
8803   }
8804
8805   emitcode ("rrc", "a");
8806
8807   if (isSameRegs && offl==MSB16) {
8808     emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8809   } else {
8810     aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8811     MOVA (aopGet (left, MSB24, FALSE, FALSE));
8812   }
8813
8814   emitcode ("rrc", "a");
8815   if (isSameRegs && offl==1) {
8816     emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8817   } else {
8818     aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8819     MOVA (aopGet (left, MSB16, FALSE, FALSE));
8820   }
8821   emitcode ("rrc", "a");
8822   aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8823
8824   if (offl == LSB)
8825     {
8826       MOVA (aopGet (left, LSB, FALSE, FALSE));
8827       emitcode ("rrc", "a");
8828       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8829     }
8830 }
8831
8832 /*-----------------------------------------------------------------*/
8833 /* genrshFour - shift four byte by a known amount != 0             */
8834 /*-----------------------------------------------------------------*/
8835 static void
8836 genrshFour (operand * result, operand * left,
8837             int shCount, int sign)
8838 {
8839   D(emitcode (";     genrshFour",""));
8840
8841   /* if shifting more that 3 bytes */
8842   if (shCount >= 24)
8843     {
8844       shCount -= 24;
8845       if (shCount)
8846         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8847       else
8848         movLeft2Result (left, MSB32, result, LSB, sign);
8849       addSign (result, MSB16, sign);
8850     }
8851   else if (shCount >= 16)
8852     {
8853       shCount -= 16;
8854       if (shCount)
8855         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8856       else
8857         {
8858           movLeft2Result (left, MSB24, result, LSB, 0);
8859           movLeft2Result (left, MSB32, result, MSB16, sign);
8860         }
8861       addSign (result, MSB24, sign);
8862     }
8863   else if (shCount >= 8)
8864     {
8865       shCount -= 8;
8866       if (shCount == 1)
8867         shiftRLong (left, MSB16, result, sign);
8868       else if (shCount == 0)
8869         {
8870           movLeft2Result (left, MSB16, result, LSB, 0);
8871           movLeft2Result (left, MSB24, result, MSB16, 0);
8872           movLeft2Result (left, MSB32, result, MSB24, sign);
8873           addSign (result, MSB32, sign);
8874         }
8875       else
8876         {
8877           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8878           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8879           /* the last shift is signed */
8880           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8881           addSign (result, MSB32, sign);
8882         }
8883     }
8884   else
8885     {                           /* 1 <= shCount <= 7 */
8886       if (shCount <= 2)
8887         {
8888           shiftRLong (left, LSB, result, sign);
8889           if (shCount == 2)
8890             shiftRLong (result, LSB, result, sign);
8891         }
8892       else
8893         {
8894           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8895           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8896           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8897         }
8898     }
8899 }
8900
8901 /*-----------------------------------------------------------------*/
8902 /* genRightShiftLiteral - right shifting by known count            */
8903 /*-----------------------------------------------------------------*/
8904 static void
8905 genRightShiftLiteral (operand * left,
8906                       operand * right,
8907                       operand * result,
8908                       iCode * ic,
8909                       int sign)
8910 {
8911   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8912   int size;
8913
8914   D(emitcode (";     genRightShiftLiteral",""));
8915
8916   freeAsmop (right, NULL, ic, TRUE);
8917
8918   aopOp (left, ic, FALSE);
8919   aopOp (result, ic, FALSE);
8920
8921 #if VIEW_SIZE
8922   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8923             AOP_SIZE (left));
8924 #endif
8925
8926   size = getDataSize (left);
8927   /* test the LEFT size !!! */
8928
8929   /* I suppose that the left size >= result size */
8930   if (shCount == 0)
8931     {
8932       size = getDataSize (result);
8933       while (size--)
8934         movLeft2Result (left, size, result, size, 0);
8935     }
8936
8937   else if (shCount >= (size * 8))
8938     {
8939       if (sign) {
8940         /* get sign in acc.7 */
8941         MOVA (aopGet (left, size - 1, FALSE, FALSE));
8942       }
8943       addSign (result, LSB, sign);
8944     }
8945   else
8946     {
8947       switch (size)
8948         {
8949         case 1:
8950           genrshOne (result, left, shCount, sign);
8951           break;
8952
8953         case 2:
8954           genrshTwo (result, left, shCount, sign);
8955           break;
8956
8957         case 4:
8958           genrshFour (result, left, shCount, sign);
8959           break;
8960         default:
8961           break;
8962         }
8963     }
8964   freeAsmop (result, NULL, ic, TRUE);
8965   freeAsmop (left, NULL, ic, TRUE);
8966 }
8967
8968 /*-----------------------------------------------------------------*/
8969 /* genSignedRightShift - right shift of signed number              */
8970 /*-----------------------------------------------------------------*/
8971 static void
8972 genSignedRightShift (iCode * ic)
8973 {
8974   operand *right, *left, *result;
8975   int size, offset;
8976   char *l;
8977   symbol *tlbl, *tlbl1;
8978   bool pushedB;
8979
8980   D(emitcode (";     genSignedRightShift",""));
8981
8982   /* we do it the hard way put the shift count in b
8983      and loop thru preserving the sign */
8984
8985   right = IC_RIGHT (ic);
8986   left = IC_LEFT (ic);
8987   result = IC_RESULT (ic);
8988
8989   aopOp (right, ic, FALSE);
8990
8991
8992   if (AOP_TYPE (right) == AOP_LIT)
8993     {
8994       genRightShiftLiteral (left, right, result, ic, 1);
8995       return;
8996     }
8997   /* shift count is unknown then we have to form
8998      a loop get the loop count in B : Note: we take
8999      only the lower order byte since shifting
9000      more that 32 bits make no sense anyway, ( the
9001      largest size of an object can be only 32 bits ) */
9002
9003   pushedB = pushB ();
9004   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9005   emitcode ("inc", "b");
9006   freeAsmop (right, NULL, ic, TRUE);
9007   aopOp (left, ic, FALSE);
9008   aopOp (result, ic, FALSE);
9009
9010   /* now move the left to the result if they are not the
9011      same */
9012   if (!sameRegs (AOP (left), AOP (result)) &&
9013       AOP_SIZE (result) > 1)
9014     {
9015
9016       size = AOP_SIZE (result);
9017       offset = 0;
9018       while (size--)
9019         {
9020           l = aopGet (left, offset, FALSE, TRUE);
9021           if (*l == '@' && IS_AOP_PREG (result))
9022             {
9023
9024               emitcode ("mov", "a,%s", l);
9025               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9026             }
9027           else
9028             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9029           offset++;
9030         }
9031     }
9032
9033   /* mov the highest order bit to OVR */
9034   tlbl = newiTempLabel (NULL);
9035   tlbl1 = newiTempLabel (NULL);
9036
9037   size = AOP_SIZE (result);
9038   offset = size - 1;
9039   MOVA (aopGet (left, offset, FALSE, FALSE));
9040   emitcode ("rlc", "a");
9041   emitcode ("mov", "ov,c");
9042   /* if it is only one byte then */
9043   if (size == 1)
9044     {
9045       l = aopGet (left, 0, FALSE, FALSE);
9046       MOVA (l);
9047       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9048       emitcode ("", "%05d$:", tlbl->key + 100);
9049       emitcode ("mov", "c,ov");
9050       emitcode ("rrc", "a");
9051       emitcode ("", "%05d$:", tlbl1->key + 100);
9052       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9053       popB (pushedB);
9054       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9055       goto release;
9056     }
9057
9058   reAdjustPreg (AOP (result));
9059   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9060   emitcode ("", "%05d$:", tlbl->key + 100);
9061   emitcode ("mov", "c,ov");
9062   while (size--)
9063     {
9064       l = aopGet (result, offset, FALSE, FALSE);
9065       MOVA (l);
9066       emitcode ("rrc", "a");
9067       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9068     }
9069   reAdjustPreg (AOP (result));
9070   emitcode ("", "%05d$:", tlbl1->key + 100);
9071   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9072   popB (pushedB);
9073
9074 release:
9075   freeAsmop (result, NULL, ic, TRUE);
9076   freeAsmop (left, NULL, ic, TRUE);
9077 }
9078
9079 /*-----------------------------------------------------------------*/
9080 /* genRightShift - generate code for right shifting                */
9081 /*-----------------------------------------------------------------*/
9082 static void
9083 genRightShift (iCode * ic)
9084 {
9085   operand *right, *left, *result;
9086   sym_link *letype;
9087   int size, offset;
9088   char *l;
9089   symbol *tlbl, *tlbl1;
9090   bool pushedB;
9091
9092   D(emitcode (";     genRightShift",""));
9093
9094   /* if signed then we do it the hard way preserve the
9095      sign bit moving it inwards */
9096   letype = getSpec (operandType (IC_LEFT (ic)));
9097
9098   if (!SPEC_USIGN (letype))
9099     {
9100       genSignedRightShift (ic);
9101       return;
9102     }
9103
9104   /* signed & unsigned types are treated the same : i.e. the
9105      signed is NOT propagated inwards : quoting from the
9106      ANSI - standard : "for E1 >> E2, is equivalent to division
9107      by 2**E2 if unsigned or if it has a non-negative value,
9108      otherwise the result is implementation defined ", MY definition
9109      is that the sign does not get propagated */
9110
9111   right = IC_RIGHT (ic);
9112   left = IC_LEFT (ic);
9113   result = IC_RESULT (ic);
9114
9115   aopOp (right, ic, FALSE);
9116
9117   /* if the shift count is known then do it
9118      as efficiently as possible */
9119   if (AOP_TYPE (right) == AOP_LIT)
9120     {
9121       genRightShiftLiteral (left, right, result, ic, 0);
9122       return;
9123     }
9124
9125   /* shift count is unknown then we have to form
9126      a loop get the loop count in B : Note: we take
9127      only the lower order byte since shifting
9128      more that 32 bits make no sense anyway, ( the
9129      largest size of an object can be only 32 bits ) */
9130
9131   pushedB = pushB ();
9132   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9133   emitcode ("inc", "b");
9134   freeAsmop (right, NULL, ic, TRUE);
9135   aopOp (left, ic, FALSE);
9136   aopOp (result, ic, FALSE);
9137
9138   /* now move the left to the result if they are not the
9139      same */
9140   if (!sameRegs (AOP (left), AOP (result)) &&
9141       AOP_SIZE (result) > 1)
9142     {
9143
9144       size = AOP_SIZE (result);
9145       offset = 0;
9146       while (size--)
9147         {
9148           l = aopGet (left, offset, FALSE, TRUE);
9149           if (*l == '@' && IS_AOP_PREG (result))
9150             {
9151
9152               emitcode ("mov", "a,%s", l);
9153               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9154             }
9155           else
9156             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9157           offset++;
9158         }
9159     }
9160
9161   tlbl = newiTempLabel (NULL);
9162   tlbl1 = newiTempLabel (NULL);
9163   size = AOP_SIZE (result);
9164   offset = size - 1;
9165
9166   /* if it is only one byte then */
9167   if (size == 1)
9168     {
9169       l = aopGet (left, 0, FALSE, FALSE);
9170       MOVA (l);
9171       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9172       emitcode ("", "%05d$:", tlbl->key + 100);
9173       CLRC;
9174       emitcode ("rrc", "a");
9175       emitcode ("", "%05d$:", tlbl1->key + 100);
9176       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9177       popB (pushedB);
9178       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9179       goto release;
9180     }
9181
9182   reAdjustPreg (AOP (result));
9183   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9184   emitcode ("", "%05d$:", tlbl->key + 100);
9185   CLRC;
9186   while (size--)
9187     {
9188       l = aopGet (result, offset, FALSE, FALSE);
9189       MOVA (l);
9190       emitcode ("rrc", "a");
9191       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9192     }
9193   reAdjustPreg (AOP (result));
9194
9195   emitcode ("", "%05d$:", tlbl1->key + 100);
9196   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9197   popB (pushedB);
9198
9199 release:
9200   freeAsmop (result, NULL, ic, TRUE);
9201   freeAsmop (left, NULL, ic, TRUE);
9202 }
9203
9204 /*-----------------------------------------------------------------*/
9205 /* emitPtrByteGet - emits code to get a byte into A through a      */
9206 /*                  pointer register (R0, R1, or DPTR). The        */
9207 /*                  original value of A can be preserved in B.     */
9208 /*-----------------------------------------------------------------*/
9209 static void
9210 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9211 {
9212   switch (p_type)
9213     {
9214     case IPOINTER:
9215     case POINTER:
9216       if (preserveAinB)
9217         emitcode ("mov", "b,a");
9218       emitcode ("mov", "a,@%s", rname);
9219       break;
9220
9221     case PPOINTER:
9222       if (preserveAinB)
9223         emitcode ("mov", "b,a");
9224       emitcode ("movx", "a,@%s", rname);
9225       break;
9226
9227     case FPOINTER:
9228       if (preserveAinB)
9229         emitcode ("mov", "b,a");
9230       emitcode ("movx", "a,@dptr");
9231       break;
9232
9233     case CPOINTER:
9234       if (preserveAinB)
9235         emitcode ("mov", "b,a");
9236       emitcode ("clr", "a");
9237       emitcode ("movc", "a,@a+dptr");
9238       break;
9239
9240     case GPOINTER:
9241       if (preserveAinB)
9242         {
9243           emitcode ("push", "b");
9244           emitcode ("push", "acc");
9245         }
9246       emitcode ("lcall", "__gptrget");
9247       if (preserveAinB)
9248         emitcode ("pop", "b");
9249       break;
9250     }
9251 }
9252
9253 /*-----------------------------------------------------------------*/
9254 /* emitPtrByteSet - emits code to set a byte from src through a    */
9255 /*                  pointer register (R0, R1, or DPTR).            */
9256 /*-----------------------------------------------------------------*/
9257 static void
9258 emitPtrByteSet (char *rname, int p_type, char *src)
9259 {
9260   switch (p_type)
9261     {
9262     case IPOINTER:
9263     case POINTER:
9264       if (*src=='@')
9265         {
9266           MOVA (src);
9267           emitcode ("mov", "@%s,a", rname);
9268         }
9269       else
9270         emitcode ("mov", "@%s,%s", rname, src);
9271       break;
9272
9273     case PPOINTER:
9274       MOVA (src);
9275       emitcode ("movx", "@%s,a", rname);
9276       break;
9277
9278     case FPOINTER:
9279       MOVA (src);
9280       emitcode ("movx", "@dptr,a");
9281       break;
9282
9283     case GPOINTER:
9284       MOVA (src);
9285       emitcode ("lcall", "__gptrput");
9286       break;
9287     }
9288 }
9289
9290 /*-----------------------------------------------------------------*/
9291 /* genUnpackBits - generates code for unpacking bits               */
9292 /*-----------------------------------------------------------------*/
9293 static void
9294 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9295 {
9296   int offset = 0;       /* result byte offset */
9297   int rsize;            /* result size */
9298   int rlen = 0;         /* remaining bitfield length */
9299   sym_link *etype;      /* bitfield type information */
9300   int blen;             /* bitfield length */
9301   int bstr;             /* bitfield starting bit within byte */
9302   char buffer[10];
9303
9304   D(emitcode (";     genUnpackBits",""));
9305
9306   etype = getSpec (operandType (result));
9307   rsize = getSize (operandType (result));
9308   blen = SPEC_BLEN (etype);
9309   bstr = SPEC_BSTR (etype);
9310
9311   if (ifx && blen <= 8)
9312     {
9313       emitPtrByteGet (rname, ptype, FALSE);
9314       if (blen == 1)
9315         {
9316           SNPRINTF (buffer, sizeof(buffer),
9317                     "acc.%d", bstr);
9318           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9319         }
9320       else
9321         {
9322           if (blen < 8)
9323             emitcode ("anl", "a,#0x%02x",
9324                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9325           genIfxJump (ifx, "a", NULL, NULL, NULL);
9326         }
9327       return;
9328     }
9329   wassert (!ifx);
9330
9331   /* If the bitfield length is less than a byte */
9332   if (blen < 8)
9333     {
9334       emitPtrByteGet (rname, ptype, FALSE);
9335       AccRol (8 - bstr);
9336       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9337       if (!SPEC_USIGN (etype))
9338         {
9339           /* signed bitfield */
9340           symbol *tlbl = newiTempLabel (NULL);
9341
9342           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9343           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9344           emitcode ("", "%05d$:", tlbl->key + 100);
9345         }
9346       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9347       goto finish;
9348     }
9349
9350   /* Bit field did not fit in a byte. Copy all
9351      but the partial byte at the end.  */
9352   for (rlen=blen;rlen>=8;rlen-=8)
9353     {
9354       emitPtrByteGet (rname, ptype, FALSE);
9355       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9356       if (rlen>8)
9357         emitcode ("inc", "%s", rname);
9358     }
9359
9360   /* Handle the partial byte at the end */
9361   if (rlen)
9362     {
9363       emitPtrByteGet (rname, ptype, FALSE);
9364       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9365       if (!SPEC_USIGN (etype))
9366         {
9367           /* signed bitfield */
9368           symbol *tlbl = newiTempLabel (NULL);
9369
9370           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9371           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9372           emitcode ("", "%05d$:", tlbl->key + 100);
9373         }
9374       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9375     }
9376
9377 finish:
9378   if (offset < rsize)
9379     {
9380       char *source;
9381
9382       if (SPEC_USIGN (etype))
9383         source = zero;
9384       else
9385         {
9386           /* signed bitfield: sign extension with 0x00 or 0xff */
9387           emitcode ("rlc", "a");
9388           emitcode ("subb", "a,acc");
9389
9390           source = "a";
9391         }
9392       rsize -= offset;
9393       while (rsize--)
9394         aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9395     }
9396 }
9397
9398
9399 /*-----------------------------------------------------------------*/
9400 /* genDataPointerGet - generates code when ptr offset is known     */
9401 /*-----------------------------------------------------------------*/
9402 static void
9403 genDataPointerGet (operand * left,
9404                    operand * result,
9405                    iCode * ic)
9406 {
9407   char *l;
9408   char buffer[256];
9409   int size, offset = 0;
9410
9411   D(emitcode (";     genDataPointerGet",""));
9412
9413   aopOp (result, ic, TRUE);
9414
9415   /* get the string representation of the name */
9416   l = aopGet (left, 0, FALSE, TRUE);
9417   size = AOP_SIZE (result);
9418   while (size--)
9419     {
9420       if (offset)
9421         sprintf (buffer, "(%s + %d)", l + 1, offset);
9422       else
9423         sprintf (buffer, "%s", l + 1);
9424       aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9425     }
9426
9427   freeAsmop (result, NULL, ic, TRUE);
9428   freeAsmop (left, NULL, ic, TRUE);
9429 }
9430
9431 /*-----------------------------------------------------------------*/
9432 /* genNearPointerGet - emitcode for near pointer fetch             */
9433 /*-----------------------------------------------------------------*/
9434 static void
9435 genNearPointerGet (operand * left,
9436                    operand * result,
9437                    iCode * ic,
9438                    iCode * pi,
9439                    iCode * ifx)
9440 {
9441   asmop *aop = NULL;
9442   regs *preg = NULL;
9443   char *rname;
9444   sym_link *rtype, *retype;
9445   sym_link *ltype = operandType (left);
9446   char buffer[80];
9447
9448   D(emitcode (";     genNearPointerGet",""));
9449
9450   rtype = operandType (result);
9451   retype = getSpec (rtype);
9452
9453   aopOp (left, ic, FALSE);
9454
9455   /* if left is rematerialisable and
9456      result is not bitfield variable type and
9457      the left is pointer to data space i.e
9458      lower 128 bytes of space */
9459   if (AOP_TYPE (left) == AOP_IMMD &&
9460       !IS_BITFIELD (retype) &&
9461       DCL_TYPE (ltype) == POINTER)
9462     {
9463       genDataPointerGet (left, result, ic);
9464       return;
9465     }
9466
9467  /* if the value is already in a pointer register
9468      then don't need anything more */
9469   if (!AOP_INPREG (AOP (left)))
9470     {
9471       if (IS_AOP_PREG (left))
9472         {
9473           // Aha, it is a pointer, just in disguise.
9474           rname = aopGet (left, 0, FALSE, FALSE);
9475           if (*rname != '@')
9476             {
9477               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9478                       __FILE__, __LINE__);
9479             }
9480           else
9481             {
9482               // Expected case.
9483               emitcode ("mov", "a%s,%s", rname + 1, rname);
9484               rname++;  // skip the '@'.
9485             }
9486         }
9487       else
9488         {
9489           /* otherwise get a free pointer register */
9490           aop = newAsmop (0);
9491           preg = getFreePtr (ic, &aop, FALSE);
9492           emitcode ("mov", "%s,%s",
9493                     preg->name,
9494                     aopGet (left, 0, FALSE, TRUE));
9495           rname = preg->name;
9496         }
9497     }
9498   else
9499     rname = aopGet (left, 0, FALSE, FALSE);
9500
9501   //aopOp (result, ic, FALSE);
9502   aopOp (result, ic, result?TRUE:FALSE);
9503
9504   /* if bitfield then unpack the bits */
9505   if (IS_BITFIELD (retype))
9506     genUnpackBits (result, rname, POINTER, ifx);
9507   else
9508     {
9509       /* we have can just get the values */
9510       int size = AOP_SIZE (result);
9511       int offset = 0;
9512
9513       while (size--)
9514         {
9515           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9516             {
9517
9518               emitcode ("mov", "a,@%s", rname);
9519               if (!ifx)
9520               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9521             }
9522           else
9523             {
9524               sprintf (buffer, "@%s", rname);
9525               aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9526             }
9527           offset++;
9528           if (size || pi)
9529             emitcode ("inc", "%s", rname);
9530         }
9531     }
9532
9533   /* now some housekeeping stuff */
9534   if (aop)       /* we had to allocate for this iCode */
9535     {
9536       if (pi) { /* post increment present */
9537         aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9538       }
9539       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9540     }
9541   else
9542     {
9543       /* we did not allocate which means left
9544          already in a pointer register, then
9545          if size > 0 && this could be used again
9546          we have to point it back to where it
9547          belongs */
9548       if ((AOP_SIZE (result) > 1 &&
9549            !OP_SYMBOL (left)->remat &&
9550            (OP_SYMBOL (left)->liveTo > ic->seq ||
9551             ic->depth)) &&
9552           !pi)
9553         {
9554           int size = AOP_SIZE (result) - 1;
9555           while (size--)
9556             emitcode ("dec", "%s", rname);
9557         }
9558     }
9559
9560   if (ifx && !ifx->generated)
9561     {
9562       genIfxJump (ifx, "a", left, NULL, result);
9563     }
9564
9565   /* done */
9566   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9567   freeAsmop (left, NULL, ic, TRUE);
9568   if (pi) pi->generated = 1;
9569 }
9570
9571 /*-----------------------------------------------------------------*/
9572 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9573 /*-----------------------------------------------------------------*/
9574 static void
9575 genPagedPointerGet (operand * left,
9576                     operand * result,
9577                     iCode * ic,
9578                     iCode *pi,
9579                     iCode *ifx)
9580 {
9581   asmop *aop = NULL;
9582   regs *preg = NULL;
9583   char *rname;
9584   sym_link *rtype, *retype;
9585
9586   D(emitcode (";     genPagedPointerGet",""));
9587
9588   rtype = operandType (result);
9589   retype = getSpec (rtype);
9590
9591   aopOp (left, ic, FALSE);
9592
9593   /* if the value is already in a pointer register
9594      then don't need anything more */
9595   if (!AOP_INPREG (AOP (left)))
9596     {
9597       /* otherwise get a free pointer register */
9598       aop = newAsmop (0);
9599       preg = getFreePtr (ic, &aop, FALSE);
9600       emitcode ("mov", "%s,%s",
9601                 preg->name,
9602                 aopGet (left, 0, FALSE, TRUE));
9603       rname = preg->name;
9604     }
9605   else
9606     rname = aopGet (left, 0, FALSE, FALSE);
9607
9608   aopOp (result, ic, FALSE);
9609
9610   /* if bitfield then unpack the bits */
9611   if (IS_BITFIELD (retype))
9612     genUnpackBits (result, rname, PPOINTER, ifx);
9613   else
9614     {
9615       /* we have can just get the values */
9616       int size = AOP_SIZE (result);
9617       int offset = 0;
9618
9619       while (size--)
9620         {
9621
9622           emitcode ("movx", "a,@%s", rname);
9623           if (!ifx)
9624           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9625
9626           offset++;
9627
9628           if (size || pi)
9629             emitcode ("inc", "%s", rname);
9630         }
9631     }
9632
9633   /* now some housekeeping stuff */
9634   if (aop) /* we had to allocate for this iCode */
9635     {
9636       if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9637       freeAsmop (NULL, aop, ic, TRUE);
9638     }
9639   else
9640     {
9641       /* we did not allocate which means left
9642          already in a pointer register, then
9643          if size > 0 && this could be used again
9644          we have to point it back to where it
9645          belongs */
9646       if ((AOP_SIZE (result) > 1 &&
9647            !OP_SYMBOL (left)->remat &&
9648            (OP_SYMBOL (left)->liveTo > ic->seq ||
9649             ic->depth)) &&
9650           !pi)
9651         {
9652           int size = AOP_SIZE (result) - 1;
9653           while (size--)
9654             emitcode ("dec", "%s", rname);
9655         }
9656     }
9657
9658   if (ifx && !ifx->generated)
9659     {
9660       genIfxJump (ifx, "a", left, NULL, result);
9661     }
9662
9663   /* done */
9664   freeAsmop (result, NULL, ic, TRUE);
9665   freeAsmop (left, NULL, ic, TRUE);
9666   if (pi) pi->generated = 1;
9667 }
9668
9669 /*--------------------------------------------------------------------*/
9670 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9671 /*--------------------------------------------------------------------*/
9672 static void
9673 loadDptrFromOperand (operand *op, bool loadBToo)
9674 {
9675   if (AOP_TYPE (op) != AOP_STR)
9676     {
9677       /* if this is rematerializable */
9678       if (AOP_TYPE (op) == AOP_IMMD)
9679         {
9680           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9681           if (loadBToo)
9682             {
9683               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9684                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9685               else
9686                 {
9687                   wassertl(FALSE, "need pointerCode");
9688                   emitcode ("", "; mov b,???");
9689                   /* genPointerGet and genPointerSet originally did different
9690                   ** things for this case. Both seem wrong.
9691                   ** from genPointerGet:
9692                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9693                   ** from genPointerSet:
9694                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9695                   */
9696                 }
9697             }
9698         }
9699       else if (AOP_TYPE (op) == AOP_DPTR)
9700         {
9701           if (loadBToo)
9702             {
9703               MOVA (aopGet (op, 0, FALSE, FALSE));
9704               emitcode ("push", "acc");
9705               MOVA (aopGet (op, 1, FALSE, FALSE));
9706               emitcode ("push", "acc");
9707               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9708               emitcode ("pop", "dph");
9709               emitcode ("pop", "dpl");
9710             }
9711           else
9712             {
9713               MOVA (aopGet (op, 0, FALSE, FALSE));
9714               emitcode ("push", "acc");
9715               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9716               emitcode ("pop", "dpl");
9717             }
9718         }
9719       else
9720         {                       /* we need to get it byte by byte */
9721           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9722           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9723           if (loadBToo)
9724             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9725         }
9726     }
9727 }
9728
9729 /*-----------------------------------------------------------------*/
9730 /* genFarPointerGet - gget value from far space                    */
9731 /*-----------------------------------------------------------------*/
9732 static void
9733 genFarPointerGet (operand * left,
9734                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9735 {
9736   int size, offset;
9737   sym_link *retype = getSpec (operandType (result));
9738
9739   D(emitcode (";     genFarPointerGet",""));
9740
9741   aopOp (left, ic, FALSE);
9742   loadDptrFromOperand (left, FALSE);
9743
9744   /* so dptr now contains the address */
9745   aopOp (result, ic, FALSE);
9746
9747   /* if bit then unpack */
9748   if (IS_BITFIELD (retype))
9749     genUnpackBits (result, "dptr", FPOINTER, ifx);
9750   else
9751     {
9752       size = AOP_SIZE (result);
9753       offset = 0;
9754
9755       while (size--)
9756         {
9757           emitcode ("movx", "a,@dptr");
9758           if (!ifx)
9759             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9760           if (size || pi)
9761             emitcode ("inc", "dptr");
9762         }
9763     }
9764
9765   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9766     {
9767     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9768     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9769     pi->generated = 1;
9770   }
9771
9772   if (ifx && !ifx->generated)
9773     {
9774       genIfxJump (ifx, "a", left, NULL, result);
9775     }
9776
9777   freeAsmop (result, NULL, ic, TRUE);
9778   freeAsmop (left, NULL, ic, TRUE);
9779 }
9780
9781 /*-----------------------------------------------------------------*/
9782 /* genCodePointerGet - gget value from code space                  */
9783 /*-----------------------------------------------------------------*/
9784 static void
9785 genCodePointerGet (operand * left,
9786                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9787 {
9788   int size, offset;
9789   sym_link *retype = getSpec (operandType (result));
9790
9791   D(emitcode (";     genCodePointerGet",""));
9792
9793   aopOp (left, ic, FALSE);
9794   loadDptrFromOperand (left, FALSE);
9795
9796   /* so dptr now contains the address */
9797   aopOp (result, ic, FALSE);
9798
9799   /* if bit then unpack */
9800   if (IS_BITFIELD (retype))
9801     genUnpackBits (result, "dptr", CPOINTER, ifx);
9802   else
9803     {
9804       size = AOP_SIZE (result);
9805       offset = 0;
9806
9807       while (size--)
9808         {
9809           if (pi)
9810             {
9811               emitcode ("clr", "a");
9812               emitcode ("movc", "a,@a+dptr");
9813               if (!ifx)
9814               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9815               emitcode ("inc", "dptr");
9816             }
9817           else
9818             {
9819               emitcode ("mov", "a,#0x%02x", offset);
9820               emitcode ("movc", "a,@a+dptr");
9821               if (!ifx)
9822               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9823             }
9824         }
9825     }
9826
9827   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9828     {
9829     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9830     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9831     pi->generated = 1;
9832   }
9833
9834   if (ifx && !ifx->generated)
9835     {
9836       genIfxJump (ifx, "a", left, NULL, result);
9837     }
9838
9839   freeAsmop (result, NULL, ic, TRUE);
9840   freeAsmop (left, NULL, ic, TRUE);
9841 }
9842
9843 /*-----------------------------------------------------------------*/
9844 /* genGenPointerGet - gget value from generic pointer space        */
9845 /*-----------------------------------------------------------------*/
9846 static void
9847 genGenPointerGet (operand * left,
9848                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9849 {
9850   int size, offset;
9851   sym_link *retype = getSpec (operandType (result));
9852
9853   D(emitcode (";     genGenPointerGet",""));
9854
9855   aopOp (left, ic, FALSE);
9856   loadDptrFromOperand (left, TRUE);
9857
9858   /* so dptr know contains the address */
9859   aopOp (result, ic, FALSE);
9860
9861   /* if bit then unpack */
9862   if (IS_BITFIELD (retype))
9863     genUnpackBits (result, "dptr", GPOINTER, ifx);
9864   else
9865     {
9866       size = AOP_SIZE (result);
9867       offset = 0;
9868
9869       while (size--)
9870         {
9871           emitcode ("lcall", "__gptrget");
9872           if (!ifx)
9873           aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9874           if (size || pi)
9875             emitcode ("inc", "dptr");
9876         }
9877     }
9878
9879   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9880     {
9881     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9882     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9883     pi->generated = 1;
9884   }
9885
9886   if (ifx && !ifx->generated)
9887     {
9888       genIfxJump (ifx, "a", left, NULL, result);
9889     }
9890
9891   freeAsmop (result, NULL, ic, TRUE);
9892   freeAsmop (left, NULL, ic, TRUE);
9893 }
9894
9895 /*-----------------------------------------------------------------*/
9896 /* genPointerGet - generate code for pointer get                   */
9897 /*-----------------------------------------------------------------*/
9898 static void
9899 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9900 {
9901   operand *left, *result;
9902   sym_link *type, *etype;
9903   int p_type;
9904
9905   D(emitcode (";     genPointerGet",""));
9906
9907   left = IC_LEFT (ic);
9908   result = IC_RESULT (ic);
9909
9910   if (getSize (operandType (result))>1)
9911     ifx = NULL;
9912
9913   /* depending on the type of pointer we need to
9914      move it to the correct pointer register */
9915   type = operandType (left);
9916   etype = getSpec (type);
9917   /* if left is of type of pointer then it is simple */
9918   if (IS_PTR (type) && !IS_FUNC (type->next))
9919     p_type = DCL_TYPE (type);
9920   else
9921     {
9922       /* we have to go by the storage class */
9923       p_type = PTR_TYPE (SPEC_OCLS (etype));
9924     }
9925
9926   /* special case when cast remat */
9927   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9928       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9929           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9930           type = operandType (left);
9931           p_type = DCL_TYPE (type);
9932   }
9933   /* now that we have the pointer type we assign
9934      the pointer values */
9935   switch (p_type)
9936     {
9937
9938     case POINTER:
9939     case IPOINTER:
9940       genNearPointerGet (left, result, ic, pi, ifx);
9941       break;
9942
9943     case PPOINTER:
9944       genPagedPointerGet (left, result, ic, pi, ifx);
9945       break;
9946
9947     case FPOINTER:
9948       genFarPointerGet (left, result, ic, pi, ifx);
9949       break;
9950
9951     case CPOINTER:
9952       genCodePointerGet (left, result, ic, pi, ifx);
9953       break;
9954
9955     case GPOINTER:
9956       genGenPointerGet (left, result, ic, pi, ifx);
9957       break;
9958     }
9959
9960 }
9961
9962
9963
9964 /*-----------------------------------------------------------------*/
9965 /* genPackBits - generates code for packed bit storage             */
9966 /*-----------------------------------------------------------------*/
9967 static void
9968 genPackBits (sym_link * etype,
9969              operand * right,
9970              char *rname, int p_type)
9971 {
9972   int offset = 0;       /* source byte offset */
9973   int rlen = 0;         /* remaining bitfield length */
9974   int blen;             /* bitfield length */
9975   int bstr;             /* bitfield starting bit within byte */
9976   int litval;           /* source literal value (if AOP_LIT) */
9977   unsigned char mask;   /* bitmask within current byte */
9978
9979   D(emitcode (";     genPackBits",""));
9980
9981   blen = SPEC_BLEN (etype);
9982   bstr = SPEC_BSTR (etype);
9983
9984   /* If the bitfield length is less than a byte */
9985   if (blen < 8)
9986     {
9987       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9988               (unsigned char) (0xFF >> (8 - bstr)));
9989
9990       if (AOP_TYPE (right) == AOP_LIT)
9991         {
9992           /* Case with a bitfield length <8 and literal source
9993           */
9994           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9995           litval <<= bstr;
9996           litval &= (~mask) & 0xff;
9997           emitPtrByteGet (rname, p_type, FALSE);
9998           if ((mask|litval)!=0xff)
9999             emitcode ("anl","a,#0x%02x", mask);
10000           if (litval)
10001             emitcode ("orl","a,#0x%02x", litval);
10002         }
10003       else
10004         {
10005           if ((blen==1) && (p_type!=GPOINTER))
10006             {
10007               /* Case with a bitfield length == 1 and no generic pointer
10008               */
10009               if (AOP_TYPE (right) == AOP_CRY)
10010                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10011               else
10012                 {
10013                   MOVA (aopGet (right, 0, FALSE, FALSE));
10014                   emitcode ("rrc","a");
10015                 }
10016               emitPtrByteGet (rname, p_type, FALSE);
10017               emitcode ("mov","acc.%d,c",bstr);
10018             }
10019           else
10020             {
10021               bool pushedB;
10022               /* Case with a bitfield length < 8 and arbitrary source
10023               */
10024               MOVA (aopGet (right, 0, FALSE, FALSE));
10025               /* shift and mask source value */
10026               AccLsh (bstr);
10027               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10028
10029               pushedB = pushB ();
10030               /* transfer A to B and get next byte */
10031               emitPtrByteGet (rname, p_type, TRUE);
10032
10033               emitcode ("anl", "a,#0x%02x", mask);
10034               emitcode ("orl", "a,b");
10035               if (p_type == GPOINTER)
10036                 emitcode ("pop", "b");
10037
10038               popB (pushedB);
10039            }
10040         }
10041
10042       emitPtrByteSet (rname, p_type, "a");
10043       return;
10044     }
10045
10046   /* Bit length is greater than 7 bits. In this case, copy  */
10047   /* all except the partial byte at the end                 */
10048   for (rlen=blen;rlen>=8;rlen-=8)
10049     {
10050       emitPtrByteSet (rname, p_type,
10051                       aopGet (right, offset++, FALSE, TRUE) );
10052       if (rlen>8)
10053         emitcode ("inc", "%s", rname);
10054     }
10055
10056   /* If there was a partial byte at the end */
10057   if (rlen)
10058     {
10059       mask = (((unsigned char) -1 << rlen) & 0xff);
10060
10061       if (AOP_TYPE (right) == AOP_LIT)
10062         {
10063           /* Case with partial byte and literal source
10064           */
10065           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10066           litval >>= (blen-rlen);
10067           litval &= (~mask) & 0xff;
10068           emitPtrByteGet (rname, p_type, FALSE);
10069           if ((mask|litval)!=0xff)
10070             emitcode ("anl","a,#0x%02x", mask);
10071           if (litval)
10072             emitcode ("orl","a,#0x%02x", litval);
10073         }
10074       else
10075         {
10076           bool pushedB;
10077           /* Case with partial byte and arbitrary source
10078           */
10079           MOVA (aopGet (right, offset++, FALSE, FALSE));
10080           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10081
10082           pushedB = pushB ();
10083           /* transfer A to B and get next byte */
10084           emitPtrByteGet (rname, p_type, TRUE);
10085
10086           emitcode ("anl", "a,#0x%02x", mask);
10087           emitcode ("orl", "a,b");
10088           if (p_type == GPOINTER)
10089             emitcode ("pop", "b");
10090
10091           popB (pushedB);
10092         }
10093       emitPtrByteSet (rname, p_type, "a");
10094     }
10095
10096 }
10097
10098
10099 /*-----------------------------------------------------------------*/
10100 /* genDataPointerSet - remat pointer to data space                 */
10101 /*-----------------------------------------------------------------*/
10102 static void
10103 genDataPointerSet (operand * right,
10104                    operand * result,
10105                    iCode * ic)
10106 {
10107   int size, offset = 0;
10108   char *l, buffer[256];
10109
10110   D(emitcode (";     genDataPointerSet",""));
10111
10112   aopOp (right, ic, FALSE);
10113
10114   l = aopGet (result, 0, FALSE, TRUE);
10115   size = AOP_SIZE (right);
10116   while (size--)
10117     {
10118       if (offset)
10119         sprintf (buffer, "(%s + %d)", l + 1, offset);
10120       else
10121         sprintf (buffer, "%s", l + 1);
10122       emitcode ("mov", "%s,%s", buffer,
10123                 aopGet (right, offset++, FALSE, FALSE));
10124     }
10125
10126   freeAsmop (result, NULL, ic, TRUE);
10127   freeAsmop (right, NULL, ic, TRUE);
10128 }
10129
10130 /*-----------------------------------------------------------------*/
10131 /* genNearPointerSet - emitcode for near pointer put                */
10132 /*-----------------------------------------------------------------*/
10133 static void
10134 genNearPointerSet (operand * right,
10135                    operand * result,
10136                    iCode * ic,
10137                    iCode * pi)
10138 {
10139   asmop *aop = NULL;
10140   regs *preg = NULL;
10141   char *rname, *l;
10142   sym_link *retype, *letype;
10143   sym_link *ptype = operandType (result);
10144
10145   D(emitcode (";     genNearPointerSet",""));
10146
10147   retype = getSpec (operandType (right));
10148   letype = getSpec (ptype);
10149   aopOp (result, ic, FALSE);
10150
10151   /* if the result is rematerializable &
10152      in data space & not a bit variable */
10153   if (AOP_TYPE (result) == AOP_IMMD &&
10154       DCL_TYPE (ptype) == POINTER &&
10155       !IS_BITVAR (retype) &&
10156       !IS_BITVAR (letype))
10157     {
10158       genDataPointerSet (right, result, ic);
10159       return;
10160     }
10161
10162   /* if the value is already in a pointer register
10163      then don't need anything more */
10164   if (!AOP_INPREG (AOP (result)))
10165     {
10166         if (
10167             //AOP_TYPE (result) == AOP_STK
10168             IS_AOP_PREG(result)
10169             )
10170         {
10171             // Aha, it is a pointer, just in disguise.
10172             rname = aopGet (result, 0, FALSE, FALSE);
10173             if (*rname != '@')
10174             {
10175                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10176                         __FILE__, __LINE__);
10177             }
10178             else
10179             {
10180                 // Expected case.
10181                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10182                 rname++;  // skip the '@'.
10183             }
10184         }
10185         else
10186         {
10187             /* otherwise get a free pointer register */
10188             aop = newAsmop (0);
10189             preg = getFreePtr (ic, &aop, FALSE);
10190             emitcode ("mov", "%s,%s",
10191                       preg->name,
10192                       aopGet (result, 0, FALSE, TRUE));
10193             rname = preg->name;
10194         }
10195     }
10196     else
10197     {
10198         rname = aopGet (result, 0, FALSE, FALSE);
10199     }
10200
10201   aopOp (right, ic, FALSE);
10202
10203   /* if bitfield then unpack the bits */
10204   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10205     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10206   else
10207     {
10208       /* we have can just get the values */
10209       int size = AOP_SIZE (right);
10210       int offset = 0;
10211
10212       while (size--)
10213         {
10214           l = aopGet (right, offset, FALSE, TRUE);
10215           if (*l == '@')
10216             {
10217               MOVA (l);
10218               emitcode ("mov", "@%s,a", rname);
10219             }
10220           else
10221             emitcode ("mov", "@%s,%s", rname, l);
10222           if (size || pi)
10223             emitcode ("inc", "%s", rname);
10224           offset++;
10225         }
10226     }
10227
10228   /* now some housekeeping stuff */
10229   if (aop) /* we had to allocate for this iCode */
10230     {
10231       if (pi)
10232         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10233       freeAsmop (NULL, aop, ic, TRUE);
10234     }
10235   else
10236     {
10237       /* we did not allocate which means left
10238          already in a pointer register, then
10239          if size > 0 && this could be used again
10240          we have to point it back to where it
10241          belongs */
10242       if ((AOP_SIZE (right) > 1 &&
10243            !OP_SYMBOL (result)->remat &&
10244            (OP_SYMBOL (result)->liveTo > ic->seq ||
10245             ic->depth)) &&
10246           !pi)
10247         {
10248           int size = AOP_SIZE (right) - 1;
10249           while (size--)
10250             emitcode ("dec", "%s", rname);
10251         }
10252     }
10253
10254   /* done */
10255   if (pi) pi->generated = 1;
10256   freeAsmop (result, NULL, ic, TRUE);
10257   freeAsmop (right, NULL, ic, TRUE);
10258 }
10259
10260 /*-----------------------------------------------------------------*/
10261 /* genPagedPointerSet - emitcode for Paged pointer put             */
10262 /*-----------------------------------------------------------------*/
10263 static void
10264 genPagedPointerSet (operand * right,
10265                     operand * result,
10266                     iCode * ic,
10267                     iCode * pi)
10268 {
10269   asmop *aop = NULL;
10270   regs *preg = NULL;
10271   char *rname, *l;
10272   sym_link *retype, *letype;
10273
10274   D(emitcode (";     genPagedPointerSet",""));
10275
10276   retype = getSpec (operandType (right));
10277   letype = getSpec (operandType (result));
10278
10279   aopOp (result, ic, FALSE);
10280
10281   /* if the value is already in a pointer register
10282      then don't need anything more */
10283   if (!AOP_INPREG (AOP (result)))
10284     {
10285       /* otherwise get a free pointer register */
10286       aop = newAsmop (0);
10287       preg = getFreePtr (ic, &aop, FALSE);
10288       emitcode ("mov", "%s,%s",
10289                 preg->name,
10290                 aopGet (result, 0, FALSE, TRUE));
10291       rname = preg->name;
10292     }
10293   else
10294     rname = aopGet (result, 0, FALSE, FALSE);
10295
10296   aopOp (right, ic, FALSE);
10297
10298   /* if bitfield then unpack the bits */
10299   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10300     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10301   else
10302     {
10303       /* we have can just get the values */
10304       int size = AOP_SIZE (right);
10305       int offset = 0;
10306
10307       while (size--)
10308         {
10309           l = aopGet (right, offset, FALSE, TRUE);
10310
10311           MOVA (l);
10312           emitcode ("movx", "@%s,a", rname);
10313
10314           if (size || pi)
10315             emitcode ("inc", "%s", rname);
10316
10317           offset++;
10318         }
10319     }
10320
10321   /* now some housekeeping stuff */
10322   if (aop) /* we had to allocate for this iCode */
10323     {
10324       if (pi)
10325         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10326       freeAsmop (NULL, aop, ic, TRUE);
10327     }
10328   else
10329     {
10330       /* we did not allocate which means left
10331          already in a pointer register, then
10332          if size > 0 && this could be used again
10333          we have to point it back to where it
10334          belongs */
10335       if (AOP_SIZE (right) > 1 &&
10336           !OP_SYMBOL (result)->remat &&
10337           (OP_SYMBOL (result)->liveTo > ic->seq ||
10338            ic->depth))
10339         {
10340           int size = AOP_SIZE (right) - 1;
10341           while (size--)
10342             emitcode ("dec", "%s", rname);
10343         }
10344     }
10345
10346   /* done */
10347   if (pi) pi->generated = 1;
10348   freeAsmop (result, NULL, ic, TRUE);
10349   freeAsmop (right, NULL, ic, TRUE);
10350 }
10351
10352 /*-----------------------------------------------------------------*/
10353 /* genFarPointerSet - set value from far space                     */
10354 /*-----------------------------------------------------------------*/
10355 static void
10356 genFarPointerSet (operand * right,
10357                   operand * result, iCode * ic, iCode * pi)
10358 {
10359   int size, offset;
10360   sym_link *retype = getSpec (operandType (right));
10361   sym_link *letype = getSpec (operandType (result));
10362
10363   D(emitcode (";     genFarPointerSet",""));
10364
10365   aopOp (result, ic, FALSE);
10366   loadDptrFromOperand (result, FALSE);
10367
10368   /* so dptr know contains the address */
10369   aopOp (right, ic, FALSE);
10370
10371   /* if bit then unpack */
10372   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10373     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10374   else
10375     {
10376       size = AOP_SIZE (right);
10377       offset = 0;
10378
10379       while (size--)
10380         {
10381           char *l = aopGet (right, offset++, FALSE, FALSE);
10382           MOVA (l);
10383           emitcode ("movx", "@dptr,a");
10384           if (size || pi)
10385             emitcode ("inc", "dptr");
10386         }
10387     }
10388   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10389     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10390     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10391     pi->generated=1;
10392   }
10393   freeAsmop (result, NULL, ic, TRUE);
10394   freeAsmop (right, NULL, ic, TRUE);
10395 }
10396
10397 /*-----------------------------------------------------------------*/
10398 /* genGenPointerSet - set value from generic pointer space         */
10399 /*-----------------------------------------------------------------*/
10400 static void
10401 genGenPointerSet (operand * right,
10402                   operand * result, iCode * ic, iCode * pi)
10403 {
10404   int size, offset;
10405   sym_link *retype = getSpec (operandType (right));
10406   sym_link *letype = getSpec (operandType (result));
10407
10408   D(emitcode (";     genGenPointerSet",""));
10409
10410   aopOp (result, ic, FALSE);
10411   loadDptrFromOperand (result, TRUE);
10412
10413   /* so dptr know contains the address */
10414   aopOp (right, ic, FALSE);
10415
10416   /* if bit then unpack */
10417   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10418     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10419   else
10420     {
10421       size = AOP_SIZE (right);
10422       offset = 0;
10423
10424       while (size--)
10425         {
10426           char *l = aopGet (right, offset++, FALSE, FALSE);
10427           MOVA (l);
10428           emitcode ("lcall", "__gptrput");
10429           if (size || pi)
10430             emitcode ("inc", "dptr");
10431         }
10432     }
10433
10434   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10435     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10436     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10437     pi->generated=1;
10438   }
10439   freeAsmop (result, NULL, ic, TRUE);
10440   freeAsmop (right, NULL, ic, TRUE);
10441 }
10442
10443 /*-----------------------------------------------------------------*/
10444 /* genPointerSet - stores the value into a pointer location        */
10445 /*-----------------------------------------------------------------*/
10446 static void
10447 genPointerSet (iCode * ic, iCode *pi)
10448 {
10449   operand *right, *result;
10450   sym_link *type, *etype;
10451   int p_type;
10452
10453   D(emitcode (";     genPointerSet",""));
10454
10455   right = IC_RIGHT (ic);
10456   result = IC_RESULT (ic);
10457
10458   /* depending on the type of pointer we need to
10459      move it to the correct pointer register */
10460   type = operandType (result);
10461   etype = getSpec (type);
10462   /* if left is of type of pointer then it is simple */
10463   if (IS_PTR (type) && !IS_FUNC (type->next))
10464     {
10465       p_type = DCL_TYPE (type);
10466     }
10467   else
10468     {
10469       /* we have to go by the storage class */
10470       p_type = PTR_TYPE (SPEC_OCLS (etype));
10471     }
10472
10473   /* special case when cast remat */
10474   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10475       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10476           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10477           type = operandType (result);
10478           p_type = DCL_TYPE (type);
10479   }
10480   /* now that we have the pointer type we assign
10481      the pointer values */
10482   switch (p_type)
10483     {
10484
10485     case POINTER:
10486     case IPOINTER:
10487       genNearPointerSet (right, result, ic, pi);
10488       break;
10489
10490     case PPOINTER:
10491       genPagedPointerSet (right, result, ic, pi);
10492       break;
10493
10494     case FPOINTER:
10495       genFarPointerSet (right, result, ic, pi);
10496       break;
10497
10498     case GPOINTER:
10499       genGenPointerSet (right, result, ic, pi);
10500       break;
10501
10502     default:
10503       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10504               "genPointerSet: illegal pointer type");
10505     }
10506
10507 }
10508
10509 /*-----------------------------------------------------------------*/
10510 /* genIfx - generate code for Ifx statement                        */
10511 /*-----------------------------------------------------------------*/
10512 static void
10513 genIfx (iCode * ic, iCode * popIc)
10514 {
10515   operand *cond = IC_COND (ic);
10516   int isbit = 0;
10517   char *dup = NULL;
10518
10519   D(emitcode (";     genIfx",""));
10520
10521   aopOp (cond, ic, FALSE);
10522
10523   /* get the value into acc */
10524   if (AOP_TYPE (cond) != AOP_CRY)
10525     toBoolean (cond);
10526   else
10527     {
10528       isbit = 1;
10529       if (AOP(cond)->aopu.aop_dir)
10530         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10531     }
10532   /* the result is now in the accumulator or a directly addressable bit */
10533   freeAsmop (cond, NULL, ic, TRUE);
10534
10535   /* if there was something to be popped then do it */
10536   if (popIc)
10537     genIpop (popIc);
10538
10539   /* if the condition is a bit variable */
10540   if (isbit && dup)
10541     genIfxJump(ic, dup, NULL, NULL, NULL);
10542   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10543     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10544   else if (isbit && !IS_ITEMP (cond))
10545     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10546   else
10547     genIfxJump (ic, "a", NULL, NULL, NULL);
10548
10549   ic->generated = 1;
10550 }
10551
10552 /*-----------------------------------------------------------------*/
10553 /* genAddrOf - generates code for address of                       */
10554 /*-----------------------------------------------------------------*/
10555 static void
10556 genAddrOf (iCode * ic)
10557 {
10558   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10559   int size, offset;
10560
10561   D(emitcode (";     genAddrOf",""));
10562
10563   aopOp (IC_RESULT (ic), ic, FALSE);
10564
10565   /* if the operand is on the stack then we
10566      need to get the stack offset of this
10567      variable */
10568   if (sym->onStack)
10569     {
10570       /* if it has an offset then we need to compute
10571          it */
10572       if (sym->stack)
10573         {
10574           emitcode ("mov", "a,%s", SYM_BP (sym));
10575           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10576                                          ((char) (sym->stack - _G.nRegsSaved)) :
10577                                          ((char) sym->stack)) & 0xff);
10578           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10579         }
10580       else
10581         {
10582           /* we can just move _bp */
10583           aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10584         }
10585       /* fill the result with zero */
10586       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10587
10588       offset = 1;
10589       while (size--)
10590         {
10591           aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10592         }
10593
10594       goto release;
10595     }
10596
10597   /* object not on stack then we need the name */
10598   size = AOP_SIZE (IC_RESULT (ic));
10599   offset = 0;
10600
10601   while (size--)
10602     {
10603       char s[SDCC_NAME_MAX];
10604       if (offset)
10605         sprintf (s, "#(%s >> %d)",
10606                  sym->rname,
10607                  offset * 8);
10608       else
10609         sprintf (s, "#%s", sym->rname);
10610       aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10611     }
10612
10613 release:
10614   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10615
10616 }
10617
10618 /*-----------------------------------------------------------------*/
10619 /* genFarFarAssign - assignment when both are in far space         */
10620 /*-----------------------------------------------------------------*/
10621 static void
10622 genFarFarAssign (operand * result, operand * right, iCode * ic)
10623 {
10624   int size = AOP_SIZE (right);
10625   int offset = 0;
10626   char *l;
10627
10628   D(emitcode (";     genFarFarAssign",""));
10629
10630   /* first push the right side on to the stack */
10631   while (size--)
10632     {
10633       l = aopGet (right, offset++, FALSE, FALSE);
10634       MOVA (l);
10635       emitcode ("push", "acc");
10636     }
10637
10638   freeAsmop (right, NULL, ic, FALSE);
10639   /* now assign DPTR to result */
10640   aopOp (result, ic, FALSE);
10641   size = AOP_SIZE (result);
10642   while (size--)
10643     {
10644       emitcode ("pop", "acc");
10645       aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10646     }
10647   freeAsmop (result, NULL, ic, FALSE);
10648 }
10649
10650 /*-----------------------------------------------------------------*/
10651 /* genAssign - generate code for assignment                        */
10652 /*-----------------------------------------------------------------*/
10653 static void
10654 genAssign (iCode * ic)
10655 {
10656   operand *result, *right;
10657   int size, offset;
10658   unsigned long lit = 0L;
10659
10660   D(emitcode(";     genAssign",""));
10661
10662   result = IC_RESULT (ic);
10663   right = IC_RIGHT (ic);
10664
10665   /* if they are the same */
10666   if (operandsEqu (result, right) &&
10667       !isOperandVolatile (result, FALSE) &&
10668       !isOperandVolatile (right, FALSE))
10669     return;
10670
10671   aopOp (right, ic, FALSE);
10672
10673   /* special case both in far space */
10674   if (AOP_TYPE (right) == AOP_DPTR &&
10675       IS_TRUE_SYMOP (result) &&
10676       isOperandInFarSpace (result))
10677     {
10678
10679       genFarFarAssign (result, right, ic);
10680       return;
10681     }
10682
10683   aopOp (result, ic, TRUE);
10684
10685   /* if they are the same registers */
10686   if (sameRegs (AOP (right), AOP (result)) &&
10687       !isOperandVolatile (result, FALSE) &&
10688       !isOperandVolatile (right, FALSE))
10689     goto release;
10690
10691   /* if the result is a bit */
10692   if (AOP_TYPE (result) == AOP_CRY)
10693     {
10694
10695       /* if the right size is a literal then
10696          we know what the value is */
10697       if (AOP_TYPE (right) == AOP_LIT)
10698         {
10699           if (((int) operandLitValue (right)))
10700             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10701           else
10702             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10703           goto release;
10704         }
10705
10706       /* the right is also a bit variable */
10707       if (AOP_TYPE (right) == AOP_CRY)
10708         {
10709           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10710           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10711           goto release;
10712         }
10713
10714       /* we need to or */
10715       toBoolean (right);
10716       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10717       goto release;
10718     }
10719
10720   /* bit variables done */
10721   /* general case */
10722   size = AOP_SIZE (result);
10723   offset = 0;
10724   if (AOP_TYPE (right) == AOP_LIT)
10725     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10726   if ((size > 1) &&
10727       (AOP_TYPE (result) != AOP_REG) &&
10728       (AOP_TYPE (right) == AOP_LIT) &&
10729       !IS_FLOAT (operandType (right)) &&
10730       (lit < 256L))
10731     {
10732       while ((size) && (lit))
10733         {
10734           aopPut (result,
10735                   aopGet (right, offset, FALSE, FALSE),
10736                   offset,
10737                   isOperandVolatile (result, FALSE));
10738           lit >>= 8;
10739           offset++;
10740           size--;
10741         }
10742       emitcode ("clr", "a");
10743       while (size--)
10744         {
10745           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10746           offset++;
10747         }
10748     }
10749   else
10750     {
10751       while (size--)
10752         {
10753           aopPut (result,
10754                   aopGet (right, offset, FALSE, FALSE),
10755                   offset,
10756                   isOperandVolatile (result, FALSE));
10757           offset++;
10758         }
10759     }
10760
10761 release:
10762   freeAsmop (result, NULL, ic, TRUE);
10763   freeAsmop (right, NULL, ic, TRUE);
10764 }
10765
10766 /*-----------------------------------------------------------------*/
10767 /* genJumpTab - generates code for jump table                      */
10768 /*-----------------------------------------------------------------*/
10769 static void
10770 genJumpTab (iCode * ic)
10771 {
10772   symbol *jtab,*jtablo,*jtabhi;
10773   char *l;
10774   unsigned int count;
10775
10776   D(emitcode (";     genJumpTab",""));
10777
10778   count = elementsInSet( IC_JTLABELS (ic) );
10779
10780   if( count <= 16 )
10781     {
10782       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10783          if the switch argument is in a register.
10784          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10785       /* (MB) What if peephole converts ljmp to sjmp or ret ???
10786          How will multiply by three be updated ???*/
10787       aopOp (IC_JTCOND (ic), ic, FALSE);
10788       /* get the condition into accumulator */
10789       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10790       MOVA (l);
10791       /* multiply by three */
10792       emitcode ("add", "a,acc");
10793       emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10794       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10795
10796       jtab = newiTempLabel (NULL);
10797       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10798       emitcode ("jmp", "@a+dptr");
10799       emitcode ("", "%05d$:", jtab->key + 100);
10800       /* now generate the jump labels */
10801       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10802            jtab = setNextItem (IC_JTLABELS (ic)))
10803         emitcode ("ljmp", "%05d$", jtab->key + 100);
10804     }
10805   else
10806     {
10807       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10808          if the switch argument is in a register.
10809          For n>6 this algorithm may be more compact */
10810       jtablo = newiTempLabel (NULL);
10811       jtabhi = newiTempLabel (NULL);
10812
10813       /* get the condition into accumulator.
10814          Using b as temporary storage, if register push/pop is needed */
10815       aopOp (IC_JTCOND (ic), ic, FALSE);
10816       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10817       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10818           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10819         {
10820           // (MB) what if B is in use???
10821           wassertl(!BINUSE, "B was in use");
10822           emitcode ("mov", "b,%s", l);
10823           l = "b";
10824         }
10825       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10826       MOVA (l);
10827       if( count <= 112 )
10828         {
10829           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10830           emitcode ("movc", "a,@a+pc");
10831           emitcode ("push", "acc");
10832
10833           MOVA (l);
10834           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10835           emitcode ("movc", "a,@a+pc");
10836           emitcode ("push", "acc");
10837         }
10838       else
10839         {
10840           /* this scales up to n<=255, but needs two more bytes
10841              and changes dptr */
10842           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10843           emitcode ("movc", "a,@a+dptr");
10844           emitcode ("push", "acc");
10845
10846           MOVA (l);
10847           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10848           emitcode ("movc", "a,@a+dptr");
10849           emitcode ("push", "acc");
10850         }
10851
10852       emitcode ("ret", "");
10853
10854       /* now generate jump table, LSB */
10855       emitcode ("", "%05d$:", jtablo->key + 100);
10856       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10857            jtab = setNextItem (IC_JTLABELS (ic)))
10858         emitcode (".db", "%05d$", jtab->key + 100);
10859
10860       /* now generate jump table, MSB */
10861       emitcode ("", "%05d$:", jtabhi->key + 100);
10862       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10863            jtab = setNextItem (IC_JTLABELS (ic)))
10864          emitcode (".db", "%05d$>>8", jtab->key + 100);
10865     }
10866 }
10867
10868 /*-----------------------------------------------------------------*/
10869 /* genCast - gen code for casting                                  */
10870 /*-----------------------------------------------------------------*/
10871 static void
10872 genCast (iCode * ic)
10873 {
10874   operand *result = IC_RESULT (ic);
10875   sym_link *ctype = operandType (IC_LEFT (ic));
10876   sym_link *rtype = operandType (IC_RIGHT (ic));
10877   operand *right = IC_RIGHT (ic);
10878   int size, offset;
10879
10880   D(emitcode(";     genCast",""));
10881
10882   /* if they are equivalent then do nothing */
10883   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10884     return;
10885
10886   aopOp (right, ic, FALSE);
10887   aopOp (result, ic, FALSE);
10888
10889   /* if the result is a bit (and not a bitfield) */
10890   // if (AOP_TYPE (result) == AOP_CRY)
10891   if (IS_BIT (OP_SYMBOL (result)->type))
10892     /* not for bitfields */
10893     {
10894       /* if the right size is a literal then
10895          we know what the value is */
10896       if (AOP_TYPE (right) == AOP_LIT)
10897         {
10898           if (((int) operandLitValue (right)))
10899             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10900           else
10901             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10902
10903           goto release;
10904         }
10905
10906       /* the right is also a bit variable */
10907       if (AOP_TYPE (right) == AOP_CRY)
10908         {
10909           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10910           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10911           goto release;
10912         }
10913
10914       /* we need to or */
10915       toBoolean (right);
10916       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10917       goto release;
10918     }
10919
10920
10921   /* if they are the same size : or less */
10922   if (AOP_SIZE (result) <= AOP_SIZE (right))
10923     {
10924
10925       /* if they are in the same place */
10926       if (sameRegs (AOP (right), AOP (result)))
10927         goto release;
10928
10929       /* if they in different places then copy */
10930       size = AOP_SIZE (result);
10931       offset = 0;
10932       while (size--)
10933         {
10934           aopPut (result,
10935                   aopGet (right, offset, FALSE, FALSE),
10936                   offset,
10937                   isOperandVolatile (result, FALSE));
10938           offset++;
10939         }
10940       goto release;
10941     }
10942
10943
10944   /* if the result is of type pointer */
10945   if (IS_PTR (ctype))
10946     {
10947
10948       int p_type;
10949       sym_link *type = operandType (right);
10950       sym_link *etype = getSpec (type);
10951
10952       /* pointer to generic pointer */
10953       if (IS_GENPTR (ctype))
10954         {
10955           if (IS_PTR (type))
10956             p_type = DCL_TYPE (type);
10957           else
10958             {
10959               if (SPEC_SCLS(etype)==S_REGISTER) {
10960                 // let's assume it is a generic pointer
10961                 p_type=GPOINTER;
10962               } else {
10963                 /* we have to go by the storage class */
10964                 p_type = PTR_TYPE (SPEC_OCLS (etype));
10965               }
10966             }
10967
10968           /* the first two bytes are known */
10969           size = GPTRSIZE - 1;
10970           offset = 0;
10971           while (size--)
10972             {
10973               aopPut (result,
10974                       aopGet (right, offset, FALSE, FALSE),
10975                       offset,
10976                       isOperandVolatile (result, FALSE));
10977               offset++;
10978             }
10979           /* the last byte depending on type */
10980             {
10981                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10982                 char gpValStr[10];
10983
10984                 if (gpVal == -1)
10985                 {
10986                     // pointerTypeToGPByte will have bitched.
10987                     exit(1);
10988                 }
10989
10990                 sprintf(gpValStr, "#0x%x", gpVal);
10991                 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10992             }
10993           goto release;
10994         }
10995
10996       /* just copy the pointers */
10997       size = AOP_SIZE (result);
10998       offset = 0;
10999       while (size--)
11000         {
11001           aopPut (result,
11002                   aopGet (right, offset, FALSE, FALSE),
11003                   offset,
11004                   isOperandVolatile (result, FALSE));
11005           offset++;
11006         }
11007       goto release;
11008     }
11009
11010   /* so we now know that the size of destination is greater
11011      than the size of the source */
11012   /* we move to result for the size of source */
11013   size = AOP_SIZE (right);
11014   offset = 0;
11015   while (size--)
11016     {
11017       aopPut (result,
11018               aopGet (right, offset, FALSE, FALSE),
11019               offset,
11020               isOperandVolatile (result, FALSE));
11021       offset++;
11022     }
11023
11024   /* now depending on the sign of the source && destination */
11025   size = AOP_SIZE (result) - AOP_SIZE (right);
11026   /* if unsigned or not an integral type */
11027   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11028     {
11029       while (size--)
11030         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11031     }
11032   else
11033     {
11034       /* we need to extend the sign :{ */
11035       char *l = aopGet (right, AOP_SIZE (right) - 1,
11036                         FALSE, FALSE);
11037       MOVA (l);
11038       emitcode ("rlc", "a");
11039       emitcode ("subb", "a,acc");
11040       while (size--)
11041         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11042     }
11043
11044   /* we are done hurray !!!! */
11045
11046 release:
11047   freeAsmop (result, NULL, ic, TRUE);
11048   freeAsmop (right, NULL, ic, TRUE);
11049 }
11050
11051 /*-----------------------------------------------------------------*/
11052 /* genDjnz - generate decrement & jump if not zero instrucion      */
11053 /*-----------------------------------------------------------------*/
11054 static int
11055 genDjnz (iCode * ic, iCode * ifx)
11056 {
11057   symbol *lbl, *lbl1;
11058   if (!ifx)
11059     return 0;
11060
11061   D(emitcode (";     genDjnz",""));
11062
11063   /* if the if condition has a false label
11064      then we cannot save */
11065   if (IC_FALSE (ifx))
11066     return 0;
11067
11068   /* if the minus is not of the form
11069      a = a - 1 */
11070   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11071       !IS_OP_LITERAL (IC_RIGHT (ic)))
11072     return 0;
11073
11074   if (operandLitValue (IC_RIGHT (ic)) != 1)
11075     return 0;
11076
11077   /* if the size of this greater than one then no
11078      saving */
11079   if (getSize (operandType (IC_RESULT (ic))) > 1)
11080     return 0;
11081
11082   /* otherwise we can save BIG */
11083   lbl = newiTempLabel (NULL);
11084   lbl1 = newiTempLabel (NULL);
11085
11086   aopOp (IC_RESULT (ic), ic, FALSE);
11087
11088   if (AOP_NEEDSACC(IC_RESULT(ic)))
11089   {
11090       /* If the result is accessed indirectly via
11091        * the accumulator, we must explicitly write
11092        * it back after the decrement.
11093        */
11094       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11095
11096       if (strcmp(rByte, "a"))
11097       {
11098            /* Something is hopelessly wrong */
11099            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11100                    __FILE__, __LINE__);
11101            /* We can just give up; the generated code will be inefficient,
11102             * but what the hey.
11103             */
11104            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11105            return 0;
11106       }
11107       emitcode ("dec", "%s", rByte);
11108       aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11109       emitcode ("jnz", "%05d$", lbl->key + 100);
11110   }
11111   else if (IS_AOP_PREG (IC_RESULT (ic)))
11112     {
11113       emitcode ("dec", "%s",
11114                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11115       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11116       emitcode ("jnz", "%05d$", lbl->key + 100);
11117     }
11118   else
11119     {
11120       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11121                 lbl->key + 100);
11122     }
11123   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11124   emitcode ("", "%05d$:", lbl->key + 100);
11125   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11126   emitcode ("", "%05d$:", lbl1->key + 100);
11127
11128   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11129   ifx->generated = 1;
11130   return 1;
11131 }
11132
11133 /*-----------------------------------------------------------------*/
11134 /* genReceive - generate code for a receive iCode                  */
11135 /*-----------------------------------------------------------------*/
11136 static void
11137 genReceive (iCode * ic)
11138 {
11139   int size = getSize (operandType (IC_RESULT (ic)));
11140   int offset = 0;
11141
11142   D(emitcode (";     genReceive",""));
11143
11144   if (ic->argreg == 1)
11145     { /* first parameter */
11146       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11147            isOperandInPagedSpace (IC_RESULT (ic))) &&
11148           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11149            IS_TRUE_SYMOP (IC_RESULT (ic))))
11150         {
11151           regs *tempRegs[4];
11152           int receivingA = 0;
11153           int roffset = 0;
11154
11155           for (offset = 0; offset<size; offset++)
11156             if (!strcmp (fReturn[offset], "a"))
11157               receivingA = 1;
11158
11159           if (!receivingA)
11160             {
11161               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11162                 {
11163                   for (offset = size-1; offset>0; offset--)
11164                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11165                   emitcode("mov","a,%s", fReturn[0]);
11166                   _G.accInUse++;
11167                   aopOp (IC_RESULT (ic), ic, FALSE);
11168                   _G.accInUse--;
11169                   aopPut (IC_RESULT (ic), "a", offset,
11170                           isOperandVolatile (IC_RESULT (ic), FALSE));
11171                   for (offset = 1; offset<size; offset++)
11172                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11173                             isOperandVolatile (IC_RESULT (ic), FALSE));
11174                   goto release;
11175                 }
11176             }
11177           else
11178             {
11179               if (getTempRegs(tempRegs, size, ic))
11180                 {
11181                   for (offset = 0; offset<size; offset++)
11182                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11183                   aopOp (IC_RESULT (ic), ic, FALSE);
11184                   for (offset = 0; offset<size; offset++)
11185                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11186                             isOperandVolatile (IC_RESULT (ic), FALSE));
11187                   goto release;
11188                 }
11189             }
11190
11191           offset = fReturnSizeMCS51 - size;
11192           while (size--)
11193             {
11194               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11195                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11196               offset++;
11197             }
11198           aopOp (IC_RESULT (ic), ic, FALSE);
11199           size = AOP_SIZE (IC_RESULT (ic));
11200           offset = 0;
11201           while (size--)
11202             {
11203               emitcode ("pop", "acc");
11204               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11205             }
11206         }
11207       else
11208         {
11209           _G.accInUse++;
11210           aopOp (IC_RESULT (ic), ic, FALSE);
11211           _G.accInUse--;
11212           assignResultValue (IC_RESULT (ic), NULL);
11213         }
11214     }
11215   else if (ic->argreg > 12)
11216     { /* bit parameters */
11217       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11218         {
11219           aopOp (IC_RESULT (ic), ic, FALSE);
11220           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11221           outBitC(IC_RESULT (ic));
11222         }
11223     }
11224   else
11225     { /* other parameters */
11226       int rb1off ;
11227       aopOp (IC_RESULT (ic), ic, FALSE);
11228       rb1off = ic->argreg;
11229       while (size--)
11230         {
11231           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11232         }
11233     }
11234
11235 release:
11236   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11237 }
11238
11239 /*-----------------------------------------------------------------*/
11240 /* genDummyRead - generate code for dummy read of volatiles        */
11241 /*-----------------------------------------------------------------*/
11242 static void
11243 genDummyRead (iCode * ic)
11244 {
11245   operand *op;
11246   int size, offset;
11247
11248   D(emitcode(";     genDummyRead",""));
11249
11250   op = IC_RIGHT (ic);
11251   if (op && IS_SYMOP (op))
11252     {
11253       aopOp (op, ic, FALSE);
11254
11255       /* if the result is a bit */
11256       if (AOP_TYPE (op) == AOP_CRY)
11257         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11258       else
11259         {
11260           /* bit variables done */
11261           /* general case */
11262           size = AOP_SIZE (op);
11263           offset = 0;
11264           while (size--)
11265           {
11266             MOVA (aopGet (op, offset, FALSE, FALSE));
11267             offset++;
11268           }
11269         }
11270
11271       freeAsmop (op, NULL, ic, TRUE);
11272     }
11273
11274   op = IC_LEFT (ic);
11275   if (op && IS_SYMOP (op))
11276     {
11277       aopOp (op, ic, FALSE);
11278
11279       /* if the result is a bit */
11280       if (AOP_TYPE (op) == AOP_CRY)
11281         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11282       else
11283         {
11284           /* bit variables done */
11285           /* general case */
11286           size = AOP_SIZE (op);
11287           offset = 0;
11288           while (size--)
11289           {
11290             MOVA (aopGet (op, offset, FALSE, FALSE));
11291             offset++;
11292           }
11293         }
11294
11295       freeAsmop (op, NULL, ic, TRUE);
11296     }
11297 }
11298
11299 /*-----------------------------------------------------------------*/
11300 /* genCritical - generate code for start of a critical sequence    */
11301 /*-----------------------------------------------------------------*/
11302 static void
11303 genCritical (iCode *ic)
11304 {
11305   symbol *tlbl = newiTempLabel (NULL);
11306
11307   D(emitcode(";     genCritical",""));
11308
11309   if (IC_RESULT (ic))
11310     {
11311       aopOp (IC_RESULT (ic), ic, TRUE);
11312       aopPut (IC_RESULT (ic), one, 0, 0);
11313       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11314       aopPut (IC_RESULT (ic), zero, 0, 0);
11315       emitcode ("", "%05d$:", (tlbl->key + 100));
11316       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11317     }
11318   else
11319     {
11320       emitcode ("setb", "c");
11321       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11322       emitcode ("clr", "c");
11323       emitcode ("", "%05d$:", (tlbl->key + 100));
11324       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11325     }
11326 }
11327
11328 /*-----------------------------------------------------------------*/
11329 /* genEndCritical - generate code for end of a critical sequence   */
11330 /*-----------------------------------------------------------------*/
11331 static void
11332 genEndCritical (iCode *ic)
11333 {
11334   D(emitcode(";     genEndCritical",""));
11335
11336   if (IC_RIGHT (ic))
11337     {
11338       aopOp (IC_RIGHT (ic), ic, FALSE);
11339       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11340         {
11341           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11342           emitcode ("mov", "ea,c");
11343         }
11344       else
11345         {
11346           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11347             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11348           emitcode ("rrc", "a");
11349           emitcode ("mov", "ea,c");
11350         }
11351       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11352     }
11353   else
11354     {
11355       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11356       emitcode ("mov", "ea,c");
11357     }
11358 }
11359
11360 /*-----------------------------------------------------------------*/
11361 /* gen51Code - generate code for 8051 based controllers            */
11362 /*-----------------------------------------------------------------*/
11363 void
11364 gen51Code (iCode * lic)
11365 {
11366   iCode *ic;
11367   int cln = 0;
11368   /* int cseq = 0; */
11369
11370   _G.currentFunc = NULL;
11371   lineHead = lineCurr = NULL;
11372
11373   /* print the allocation information */
11374   if (allocInfo && currFunc)
11375     printAllocInfo (currFunc, codeOutFile);
11376   /* if debug information required */
11377   if (options.debug && currFunc)
11378     {
11379       debugFile->writeFunction (currFunc, lic);
11380     }
11381   /* stack pointer name */
11382   if (options.useXstack)
11383     spname = "_spx";
11384   else
11385     spname = "sp";
11386
11387
11388   for (ic = lic; ic; ic = ic->next)
11389     {
11390       _G.current_iCode = ic;
11391
11392       if (ic->lineno && cln != ic->lineno)
11393         {
11394           if (options.debug)
11395             {
11396               debugFile->writeCLine (ic);
11397             }
11398           if (!options.noCcodeInAsm) {
11399             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11400                       printCLine(ic->filename, ic->lineno));
11401           }
11402           cln = ic->lineno;
11403         }
11404       #if 0
11405       if (ic->seqPoint && ic->seqPoint != cseq)
11406         {
11407           emitcode ("", "; sequence point %d", ic->seqPoint);
11408           cseq = ic->seqPoint;
11409         }
11410       #endif
11411       if (options.iCodeInAsm) {
11412         char regsInUse[80];
11413         int i;
11414
11415         #if 0
11416         for (i=0; i<8; i++) {
11417           sprintf (&regsInUse[i],
11418                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11419         regsInUse[i]=0;
11420         #else
11421         strcpy (regsInUse, "--------");
11422         for (i=0; i < 8; i++) {
11423           if (bitVectBitValue (ic->rMask, i))
11424             {
11425               int offset = regs8051[i].offset;
11426               regsInUse[offset] = offset + '0'; /* show rMask */
11427             }
11428         #endif
11429         }
11430         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11431       }
11432       /* if the result is marked as
11433          spilt and rematerializable or code for
11434          this has already been generated then
11435          do nothing */
11436       if (resultRemat (ic) || ic->generated)
11437         continue;
11438
11439       /* depending on the operation */
11440       switch (ic->op)
11441         {
11442         case '!':
11443           genNot (ic);
11444           break;
11445
11446         case '~':
11447           genCpl (ic);
11448           break;
11449
11450         case UNARYMINUS:
11451           genUminus (ic);
11452           break;
11453
11454         case IPUSH:
11455           genIpush (ic);
11456           break;
11457
11458         case IPOP:
11459           /* IPOP happens only when trying to restore a
11460              spilt live range, if there is an ifx statement
11461              following this pop then the if statement might
11462              be using some of the registers being popped which
11463              would destory the contents of the register so
11464              we need to check for this condition and handle it */
11465           if (ic->next &&
11466               ic->next->op == IFX &&
11467               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11468             genIfx (ic->next, ic);
11469           else
11470             genIpop (ic);
11471           break;
11472
11473         case CALL:
11474           genCall (ic);
11475           break;
11476
11477         case PCALL:
11478           genPcall (ic);
11479           break;
11480
11481         case FUNCTION:
11482           genFunction (ic);
11483           break;
11484
11485         case ENDFUNCTION:
11486           genEndFunction (ic);
11487           break;
11488
11489         case RETURN:
11490           genRet (ic);
11491           break;
11492
11493         case LABEL:
11494           genLabel (ic);
11495           break;
11496
11497         case GOTO:
11498           genGoto (ic);
11499           break;
11500
11501         case '+':
11502           genPlus (ic);
11503           break;
11504
11505         case '-':
11506           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11507             genMinus (ic);
11508           break;
11509
11510         case '*':
11511           genMult (ic);
11512           break;
11513
11514         case '/':
11515           genDiv (ic);
11516           break;
11517
11518         case '%':
11519           genMod (ic);
11520           break;
11521
11522         case '>':
11523           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11524           break;
11525
11526         case '<':
11527           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11528           break;
11529
11530         case LE_OP:
11531         case GE_OP:
11532         case NE_OP:
11533
11534           /* note these two are xlated by algebraic equivalence
11535              during parsing SDCC.y */
11536           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11537                   "got '>=' or '<=' shouldn't have come here");
11538           break;
11539
11540         case EQ_OP:
11541           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11542           break;
11543
11544         case AND_OP:
11545           genAndOp (ic);
11546           break;
11547
11548         case OR_OP:
11549           genOrOp (ic);
11550           break;
11551
11552         case '^':
11553           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11554           break;
11555
11556         case '|':
11557           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11558           break;
11559
11560         case BITWISEAND:
11561           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11562           break;
11563
11564         case INLINEASM:
11565           genInline (ic);
11566           break;
11567
11568         case RRC:
11569           genRRC (ic);
11570           break;
11571
11572         case RLC:
11573           genRLC (ic);
11574           break;
11575
11576         case GETHBIT:
11577           genGetHbit (ic);
11578           break;
11579
11580         case GETABIT:
11581           genGetAbit (ic);
11582           break;
11583
11584         case GETBYTE:
11585           genGetByte (ic);
11586           break;
11587
11588         case GETWORD:
11589           genGetWord (ic);
11590           break;
11591
11592         case LEFT_OP:
11593           genLeftShift (ic);
11594           break;
11595
11596         case RIGHT_OP:
11597           genRightShift (ic);
11598           break;
11599
11600         case GET_VALUE_AT_ADDRESS:
11601           genPointerGet (ic,
11602                          hasInc (IC_LEFT (ic), ic,
11603                                  getSize (operandType (IC_RESULT (ic)))),
11604                          ifxForOp (IC_RESULT (ic), ic) );
11605           break;
11606
11607         case '=':
11608           if (POINTER_SET (ic))
11609             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11610           else
11611             genAssign (ic);
11612           break;
11613
11614         case IFX:
11615           genIfx (ic, NULL);
11616           break;
11617
11618         case ADDRESS_OF:
11619           genAddrOf (ic);
11620           break;
11621
11622         case JUMPTABLE:
11623           genJumpTab (ic);
11624           break;
11625
11626         case CAST:
11627           genCast (ic);
11628           break;
11629
11630         case RECEIVE:
11631           genReceive (ic);
11632           break;
11633
11634         case SEND:
11635           addSet (&_G.sendSet, ic);
11636           break;
11637
11638         case DUMMY_READ_VOLATILE:
11639           genDummyRead (ic);
11640           break;
11641
11642         case CRITICAL:
11643           genCritical (ic);
11644           break;
11645
11646         case ENDCRITICAL:
11647           genEndCritical (ic);
11648           break;
11649
11650         case SWAP:
11651           genSwap (ic);
11652           break;
11653
11654         default:
11655           ic = ic;
11656         }
11657     }
11658
11659   _G.current_iCode = NULL;
11660
11661   /* now we are ready to call the
11662      peep hole optimizer */
11663   if (!options.nopeep)
11664     peepHole (&lineHead);
11665
11666   /* now do the actual printing */
11667   printLine (lineHead, codeOutFile);
11668   return;
11669 }