* src/mcs51/gen.c (sameReg): new, checks if two aop regs are the same,
[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 /* sameReg - two asmops have the same register at given offsets    */
814 /*-----------------------------------------------------------------*/
815 static bool
816 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
817 {
818   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
819     return FALSE;
820
821   if (aop1->type != aop2->type)
822     return FALSE;
823
824   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
825     return FALSE;
826
827   return TRUE;
828 }
829
830 /*-----------------------------------------------------------------*/
831 /* sameRegs - two asmops have the same registers                   */
832 /*-----------------------------------------------------------------*/
833 static bool
834 sameRegs (asmop * aop1, asmop * aop2)
835 {
836   int i;
837
838   if (aop1 == aop2)
839     return TRUE;
840
841   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
842     return FALSE;
843
844   if (aop1->type != aop2->type)
845     return FALSE;
846
847   if (aop1->size != aop2->size)
848     return FALSE;
849
850   for (i = 0; i < aop1->size; i++)
851     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
852       return FALSE;
853
854   return TRUE;
855 }
856
857 /*-----------------------------------------------------------------*/
858 /* aopOp - allocates an asmop for an operand  :                    */
859 /*-----------------------------------------------------------------*/
860 static void
861 aopOp (operand * op, iCode * ic, bool result)
862 {
863   asmop *aop;
864   symbol *sym;
865   int i;
866
867   if (!op)
868     return;
869
870   /* if this a literal */
871   if (IS_OP_LITERAL (op))
872     {
873       op->aop = aop = newAsmop (AOP_LIT);
874       aop->aopu.aop_lit = op->operand.valOperand;
875       aop->size = getSize (operandType (op));
876       return;
877     }
878
879   /* if already has a asmop then continue */
880   if (op->aop)
881     {
882           op->aop->allocated++;
883       return;
884     }
885
886   /* if the underlying symbol has a aop */
887   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
888     {
889       op->aop = OP_SYMBOL (op)->aop;
890           op->aop->allocated++;
891       return;
892     }
893
894   /* if this is a true symbol */
895   if (IS_TRUE_SYMOP (op))
896     {
897       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
898       return;
899     }
900
901   /* this is a temporary : this has
902      only five choices :
903      a) register
904      b) spillocation
905      c) rematerialize
906      d) conditional
907      e) can be a return use only */
908
909   sym = OP_SYMBOL (op);
910
911   /* if the type is a conditional */
912   if (sym->regType == REG_CND)
913     {
914       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
915       aop->size = 0;
916       return;
917     }
918
919   /* if it is spilt then two situations
920      a) is rematerialize
921      b) has a spill location */
922   if (sym->isspilt || sym->nRegs == 0)
923     {
924
925       /* rematerialize it NOW */
926       if (sym->remat)
927         {
928           sym->aop = op->aop = aop =
929             aopForRemat (sym);
930           aop->size = getSize (sym->type);
931           return;
932         }
933
934       if (sym->accuse)
935         {
936           int i;
937           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
938           aop->size = getSize (sym->type);
939           for (i = 0; i < 2; i++)
940             aop->aopu.aop_str[i] = accUse[i];
941           return;
942         }
943
944       if (sym->ruonly)
945         {
946           unsigned i;
947
948           aop = op->aop = sym->aop = newAsmop (AOP_STR);
949           aop->size = getSize (sym->type);
950           for (i = 0; i < fReturnSizeMCS51; i++)
951             aop->aopu.aop_str[i] = fReturn[i];
952           return;
953         }
954
955       if (sym->usl.spillLoc)
956         {
957           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
958             {
959               /* force a new aop if sizes differ */
960               sym->usl.spillLoc->aop = NULL;
961             }
962           sym->aop = op->aop = aop =
963                      aopForSym (ic, sym->usl.spillLoc, result);
964           aop->size = getSize (sym->type);
965           return;
966         }
967
968       /* else must be a dummy iTemp */
969       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
970       aop->size = getSize (sym->type);
971       return;
972     }
973
974   /* if the type is a bit register */
975   if (sym->regType == REG_BIT)
976     {
977       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
978       aop->size = sym->nRegs;//1???
979       aop->aopu.aop_reg[0] = sym->regs[0];
980       aop->aopu.aop_dir = sym->regs[0]->name;
981       return;
982     }
983
984   /* must be in a register */
985   sym->aop = op->aop = aop = newAsmop (AOP_REG);
986   aop->size = sym->nRegs;
987   for (i = 0; i < sym->nRegs; i++)
988     aop->aopu.aop_reg[i] = sym->regs[i];
989 }
990
991 /*-----------------------------------------------------------------*/
992 /* freeAsmop - free up the asmop given to an operand               */
993 /*----------------------------------------------------------------*/
994 static void
995 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
996 {
997   asmop *aop;
998
999   if (!op)
1000     aop = aaop;
1001   else
1002     aop = op->aop;
1003
1004   if (!aop)
1005     return;
1006
1007   aop->allocated--;
1008
1009   if (aop->allocated)
1010     goto dealloc;
1011
1012   /* depending on the asmop type only three cases need work
1013      AOP_R0, AOP_R1 & AOP_STK */
1014   switch (aop->type)
1015     {
1016     case AOP_R0:
1017       if (R0INB)
1018         {
1019           emitcode ("mov", "r0,b");
1020           R0INB--;
1021         }
1022       else if (_G.r0Pushed)
1023         {
1024           if (pop)
1025             {
1026               emitcode ("pop", "ar0");
1027               _G.r0Pushed--;
1028             }
1029         }
1030       bitVectUnSetBit (ic->rUsed, R0_IDX);
1031       break;
1032
1033     case AOP_R1:
1034       if (R1INB)
1035         {
1036           emitcode ("mov", "r1,b");
1037           R1INB--;
1038         }
1039       if (_G.r1Pushed)
1040         {
1041           if (pop)
1042             {
1043               emitcode ("pop", "ar1");
1044               _G.r1Pushed--;
1045             }
1046         }
1047       bitVectUnSetBit (ic->rUsed, R1_IDX);
1048       break;
1049
1050     case AOP_STK:
1051       {
1052         int sz = aop->size;
1053         int stk = aop->aopu.aop_stk + aop->size - 1;
1054         bitVectUnSetBit (ic->rUsed, R0_IDX);
1055         bitVectUnSetBit (ic->rUsed, R1_IDX);
1056
1057         getFreePtr (ic, &aop, FALSE);
1058
1059         if (stk)
1060           {
1061             emitcode ("mov", "a,_bp");
1062             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1063             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1064           }
1065         else
1066           {
1067             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1068           }
1069
1070         while (sz--)
1071           {
1072             emitcode ("pop", "acc");
1073             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1074             if (!sz)
1075               break;
1076             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1077           }
1078         op->aop = aop;
1079         freeAsmop (op, NULL, ic, TRUE);
1080         if (_G.r1Pushed)
1081           {
1082             emitcode ("pop", "ar1");
1083             _G.r1Pushed--;
1084           }
1085
1086         if (_G.r0Pushed)
1087           {
1088             emitcode ("pop", "ar0");
1089             _G.r0Pushed--;
1090           }
1091       }
1092     }
1093
1094 dealloc:
1095   /* all other cases just dealloc */
1096   if (op)
1097     {
1098       op->aop = NULL;
1099       if (IS_SYMOP (op))
1100         {
1101           OP_SYMBOL (op)->aop = NULL;
1102           /* if the symbol has a spill */
1103           if (SPIL_LOC (op))
1104             SPIL_LOC (op)->aop = NULL;
1105         }
1106     }
1107 }
1108
1109 /*------------------------------------------------------------------*/
1110 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1111 /*                      pop r0 or r1 off stack if pushed            */
1112 /*------------------------------------------------------------------*/
1113 static void
1114 freeForBranchAsmop (operand * op)
1115 {
1116   asmop *aop;
1117
1118   if (!op)
1119     return;
1120
1121   aop = op->aop;
1122
1123   if (!aop)
1124     return;
1125
1126   if (!aop->allocated)
1127     return;
1128
1129   switch (aop->type)
1130     {
1131     case AOP_R0:
1132       if (R0INB)
1133         {
1134           emitcode ("mov", "r0,b");
1135         }
1136       else if (_G.r0Pushed)
1137         {
1138           emitcode ("pop", "ar0");
1139         }
1140       break;
1141
1142     case AOP_R1:
1143       if (R1INB)
1144         {
1145           emitcode ("mov", "r1,b");
1146         }
1147       else if (_G.r1Pushed)
1148         {
1149           emitcode ("pop", "ar1");
1150         }
1151       break;
1152
1153     case AOP_STK:
1154       {
1155         int sz = aop->size;
1156         int stk = aop->aopu.aop_stk + aop->size - 1;
1157
1158         emitcode ("mov", "b,r0");
1159         if (stk)
1160           {
1161             emitcode ("mov", "a,_bp");
1162             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1163             emitcode ("mov", "r0,a");
1164           }
1165         else
1166           {
1167             emitcode ("mov", "r0,_bp");
1168           }
1169
1170         while (sz--)
1171           {
1172             emitcode ("pop", "acc");
1173             emitcode ("mov", "@r0,a");
1174             if (!sz)
1175               break;
1176             emitcode ("dec", "r0");
1177           }
1178         emitcode ("mov", "r0,b");
1179       }
1180     }
1181
1182 }
1183
1184 /*-----------------------------------------------------------------*/
1185 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1186 /*                 clobber the accumulator                         */
1187 /*-----------------------------------------------------------------*/
1188 static bool
1189 aopGetUsesAcc (operand * oper, int offset)
1190 {
1191   asmop * aop = AOP (oper);
1192
1193   if (offset > (aop->size - 1))
1194     return FALSE;
1195
1196   switch (aop->type)
1197     {
1198
1199     case AOP_R0:
1200     case AOP_R1:
1201       if (aop->paged)
1202         return TRUE;
1203       return FALSE;
1204     case AOP_DPTR:
1205       return TRUE;
1206     case AOP_IMMD:
1207       return FALSE;
1208     case AOP_DIR:
1209       return FALSE;
1210     case AOP_REG:
1211       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1212       return FALSE;
1213     case AOP_CRY:
1214       return TRUE;
1215     case AOP_ACC:
1216       if (offset)
1217         return FALSE;
1218       return TRUE;
1219     case AOP_LIT:
1220       return FALSE;
1221     case AOP_STR:
1222       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1223         return TRUE;
1224       return FALSE;
1225     case AOP_DUMMY:
1226       return FALSE;
1227     default:
1228       /* Error case --- will have been caught already */
1229       wassert(0);
1230       return FALSE;
1231     }
1232 }
1233
1234 /*-----------------------------------------------------------------*/
1235 /* aopGet - for fetching value of the aop                          */
1236 /*-----------------------------------------------------------------*/
1237 static char *
1238 aopGet (operand * oper, int offset, bool bit16, bool dname)
1239 {
1240   char *s = buffer;
1241   char *rs;
1242   asmop * aop = AOP (oper);
1243
1244   /* offset is greater than
1245      size then zero */
1246   if (offset > (aop->size - 1) &&
1247       aop->type != AOP_LIT)
1248     return zero;
1249
1250   /* depending on type */
1251   switch (aop->type)
1252     {
1253     case AOP_DUMMY:
1254       return zero;
1255
1256     case AOP_R0:
1257     case AOP_R1:
1258       /* if we need to increment it */
1259       while (offset > aop->coff)
1260         {
1261           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1262           aop->coff++;
1263         }
1264
1265       while (offset < aop->coff)
1266         {
1267           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1268           aop->coff--;
1269         }
1270
1271       aop->coff = offset;
1272       if (aop->paged)
1273         {
1274           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1275           return (dname ? "acc" : "a");
1276         }
1277       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1278       rs = Safe_calloc (1, strlen (s) + 1);
1279       strcpy (rs, s);
1280       return rs;
1281
1282     case AOP_DPTR:
1283       if (aop->code && aop->coff==0 && offset>=1) {
1284         emitcode ("mov", "a,#0x%02x", offset);
1285         emitcode ("movc", "a,@a+dptr");
1286         return (dname ? "acc" : "a");
1287       }
1288
1289       while (offset > aop->coff)
1290         {
1291           emitcode ("inc", "dptr");
1292           aop->coff++;
1293         }
1294
1295       while (offset < aop->coff)
1296         {
1297           emitcode ("lcall", "__decdptr");
1298           aop->coff--;
1299         }
1300
1301       aop->coff = offset;
1302       if (aop->code)
1303         {
1304           emitcode ("clr", "a");
1305           emitcode ("movc", "a,@a+dptr");
1306         }
1307       else
1308         {
1309           emitcode ("movx", "a,@dptr");
1310         }
1311       return (dname ? "acc" : "a");
1312
1313
1314     case AOP_IMMD:
1315       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1316               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1317       } else if (bit16)
1318         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1319       else if (offset)
1320         sprintf (s, "#(%s >> %d)",
1321                  aop->aopu.aop_immd.aop_immd1,
1322                  offset * 8);
1323       else
1324         sprintf (s, "#%s",
1325                  aop->aopu.aop_immd.aop_immd1);
1326       rs = Safe_calloc (1, strlen (s) + 1);
1327       strcpy (rs, s);
1328       return rs;
1329
1330     case AOP_DIR:
1331       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1332         sprintf (s, "(%s >> %d)",
1333                  aop->aopu.aop_dir, offset * 8);
1334       else if (offset)
1335         sprintf (s, "(%s + %d)",
1336                  aop->aopu.aop_dir,
1337                  offset);
1338       else
1339         sprintf (s, "%s", aop->aopu.aop_dir);
1340       rs = Safe_calloc (1, strlen (s) + 1);
1341       strcpy (rs, s);
1342       return rs;
1343
1344     case AOP_REG:
1345       if (dname)
1346         return aop->aopu.aop_reg[offset]->dname;
1347       else
1348         return aop->aopu.aop_reg[offset]->name;
1349
1350     case AOP_CRY:
1351       emitcode ("clr", "a");
1352       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353       emitcode ("rlc", "a");
1354       return (dname ? "acc" : "a");
1355
1356     case AOP_ACC:
1357       if (!offset && dname)
1358         return "acc";
1359       return aop->aopu.aop_str[offset];
1360
1361     case AOP_LIT:
1362       return aopLiteral (aop->aopu.aop_lit, offset);
1363
1364     case AOP_STR:
1365       aop->coff = offset;
1366       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1367           dname)
1368         return "acc";
1369
1370       return aop->aopu.aop_str[offset];
1371
1372     }
1373
1374   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375           "aopget got unsupported aop->type");
1376   exit (1);
1377 }
1378
1379 /*-----------------------------------------------------------------*/
1380 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1381 /*                 clobber the accumulator                         */
1382 /*-----------------------------------------------------------------*/
1383 static bool
1384 aopPutUsesAcc (operand * oper, const char *s, int offset)
1385 {
1386   asmop * aop = AOP (oper);
1387
1388   if (offset > (aop->size - 1))
1389     return FALSE;
1390
1391   switch (aop->type)
1392     {
1393     case AOP_DUMMY:
1394       return TRUE;
1395     case AOP_DIR:
1396       return FALSE;
1397     case AOP_REG:
1398       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1399       return FALSE;
1400     case AOP_DPTR:
1401       return TRUE;
1402     case AOP_R0:
1403     case AOP_R1:
1404       return ((aop->paged) || (*s == '@'));
1405     case AOP_STK:
1406       return (*s == '@');
1407     case AOP_CRY:
1408       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1409     case AOP_STR:
1410       return FALSE;
1411     case AOP_IMMD:
1412       return FALSE;
1413     case AOP_ACC:
1414       return FALSE;
1415     default:
1416       /* Error case --- will have been caught already */
1417       wassert(0);
1418       return FALSE;
1419     }
1420 }
1421
1422 /*-----------------------------------------------------------------*/
1423 /* aopPut - puts a string for a aop and indicates if acc is in use */
1424 /*-----------------------------------------------------------------*/
1425 static bool
1426 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1427 {
1428   char *d = buffer;
1429   bool accuse = FALSE;
1430   asmop * aop = AOP (result);
1431
1432   if (aop->size && offset > (aop->size - 1))
1433     {
1434       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1435               "aopPut got offset > aop->size");
1436       exit (1);
1437     }
1438
1439   /* will assign value to value */
1440   /* depending on where it is ofcourse */
1441   switch (aop->type)
1442     {
1443     case AOP_DUMMY:
1444       MOVA (s);         /* read s in case it was volatile */
1445       accuse = TRUE;
1446       break;
1447
1448     case AOP_DIR:
1449       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1450         sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1451       else if (offset)
1452         sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1453       else
1454         sprintf (d, "%s", aop->aopu.aop_dir);
1455
1456       if (strcmp (d, s) || bvolatile)
1457           emitcode ("mov", "%s,%s", d, s);
1458       if (!strcmp (d, "acc"))
1459           accuse = TRUE;
1460
1461       break;
1462
1463     case AOP_REG:
1464       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1465           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1466         {
1467           if (*s == '@' ||
1468               strcmp (s, "r0") == 0 ||
1469               strcmp (s, "r1") == 0 ||
1470               strcmp (s, "r2") == 0 ||
1471               strcmp (s, "r3") == 0 ||
1472               strcmp (s, "r4") == 0 ||
1473               strcmp (s, "r5") == 0 ||
1474               strcmp (s, "r6") == 0 ||
1475               strcmp (s, "r7") == 0)
1476             emitcode ("mov", "%s,%s",
1477                       aop->aopu.aop_reg[offset]->dname, s);
1478           else
1479             emitcode ("mov", "%s,%s",
1480                       aop->aopu.aop_reg[offset]->name, s);
1481         }
1482       break;
1483
1484     case AOP_DPTR:
1485       if (aop->code)
1486         {
1487           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1488                   "aopPut writing to code space");
1489           exit (1);
1490         }
1491
1492       while (offset > aop->coff)
1493         {
1494           aop->coff++;
1495           emitcode ("inc", "dptr");
1496         }
1497
1498       while (offset < aop->coff)
1499         {
1500           aop->coff--;
1501           emitcode ("lcall", "__decdptr");
1502         }
1503
1504       aop->coff = offset;
1505
1506       /* if not in accumulator */
1507       MOVA (s);
1508
1509       emitcode ("movx", "@dptr,a");
1510       break;
1511
1512     case AOP_R0:
1513     case AOP_R1:
1514       while (offset > aop->coff)
1515         {
1516           aop->coff++;
1517           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1518         }
1519       while (offset < aop->coff)
1520         {
1521           aop->coff--;
1522           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1523         }
1524       aop->coff = offset;
1525
1526       if (aop->paged)
1527         {
1528           MOVA (s);
1529           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1530         }
1531       else if (*s == '@')
1532         {
1533           MOVA (s);
1534           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1535         }
1536       else if (strcmp (s, "r0") == 0 ||
1537                strcmp (s, "r1") == 0 ||
1538                strcmp (s, "r2") == 0 ||
1539                strcmp (s, "r3") == 0 ||
1540                strcmp (s, "r4") == 0 ||
1541                strcmp (s, "r5") == 0 ||
1542                strcmp (s, "r6") == 0 ||
1543                strcmp (s, "r7") == 0)
1544         {
1545           char buffer[10];
1546           sprintf (buffer, "a%s", s);
1547           emitcode ("mov", "@%s,%s",
1548                     aop->aopu.aop_ptr->name, buffer);
1549         }
1550       else
1551         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1552
1553       break;
1554
1555     case AOP_STK:
1556       if (strcmp (s, "a") == 0)
1557         emitcode ("push", "acc");
1558       else
1559         if (*s=='@') {
1560           MOVA(s);
1561           emitcode ("push", "acc");
1562         } else {
1563           emitcode ("push", s);
1564         }
1565
1566       break;
1567
1568     case AOP_CRY:
1569       /* if not bit variable */
1570       if (!aop->aopu.aop_dir)
1571         {
1572           /* inefficient: move carry into A and use jz/jnz */
1573           emitcode ("clr", "a");
1574           emitcode ("rlc", "a");
1575           accuse = TRUE;
1576         }
1577       else
1578         {
1579           if (s == zero)
1580             emitcode ("clr", "%s", aop->aopu.aop_dir);
1581           else if (s == one)
1582             emitcode ("setb", "%s", aop->aopu.aop_dir);
1583           else if (!strcmp (s, "c"))
1584             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1585           else if (strcmp (s, aop->aopu.aop_dir))
1586             {
1587               MOVA (s);
1588               /* set C, if a >= 1 */
1589               emitcode ("add", "a,#0xff");
1590               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1591             }
1592         }
1593       break;
1594
1595     case AOP_STR:
1596       aop->coff = offset;
1597       if (strcmp (aop->aopu.aop_str[offset], s) ||
1598           bvolatile)
1599         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1600       break;
1601
1602     case AOP_ACC:
1603       accuse = TRUE;
1604       aop->coff = offset;
1605       if (!offset && (strcmp (s, "acc") == 0) &&
1606           !bvolatile)
1607         break;
1608
1609       if (strcmp (aop->aopu.aop_str[offset], s) &&
1610           !bvolatile)
1611         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1612       break;
1613
1614     default:
1615       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1616               "aopPut got unsupported aop->type");
1617       exit (1);
1618     }
1619
1620     return accuse;
1621 }
1622
1623
1624 #if 0
1625 /*-----------------------------------------------------------------*/
1626 /* pointToEnd :- points to the last byte of the operand            */
1627 /*-----------------------------------------------------------------*/
1628 static void
1629 pointToEnd (asmop * aop)
1630 {
1631   int count;
1632   if (!aop)
1633     return;
1634
1635   aop->coff = count = (aop->size - 1);
1636   switch (aop->type)
1637     {
1638     case AOP_R0:
1639     case AOP_R1:
1640       while (count--)
1641         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1642       break;
1643     case AOP_DPTR:
1644       while (count--)
1645         emitcode ("inc", "dptr");
1646       break;
1647     }
1648
1649 }
1650 #endif
1651
1652 /*-----------------------------------------------------------------*/
1653 /* reAdjustPreg - points a register back to where it should        */
1654 /*-----------------------------------------------------------------*/
1655 static void
1656 reAdjustPreg (asmop * aop)
1657 {
1658   if ((aop->coff==0) || aop->size <= 1)
1659     return;
1660
1661   switch (aop->type)
1662     {
1663     case AOP_R0:
1664     case AOP_R1:
1665       while (aop->coff--)
1666         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1667       break;
1668     case AOP_DPTR:
1669       while (aop->coff--)
1670         {
1671           emitcode ("lcall", "__decdptr");
1672         }
1673       break;
1674     }
1675   aop->coff = 0;
1676 }
1677
1678 /*-----------------------------------------------------------------*/
1679 /* opIsGptr: returns non-zero if the passed operand is       */
1680 /* a generic pointer type.             */
1681 /*-----------------------------------------------------------------*/
1682 static int
1683 opIsGptr (operand * op)
1684 {
1685   sym_link *type = operandType (op);
1686
1687   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1688     {
1689       return 1;
1690     }
1691   return 0;
1692 }
1693
1694 /*-----------------------------------------------------------------*/
1695 /* getDataSize - get the operand data size                         */
1696 /*-----------------------------------------------------------------*/
1697 static int
1698 getDataSize (operand * op)
1699 {
1700   int size;
1701   size = AOP_SIZE (op);
1702   if (size == GPTRSIZE)
1703     {
1704       sym_link *type = operandType (op);
1705       if (IS_GENPTR (type))
1706         {
1707           /* generic pointer; arithmetic operations
1708            * should ignore the high byte (pointer type).
1709            */
1710           size--;
1711         }
1712     }
1713   return size;
1714 }
1715
1716 /*-----------------------------------------------------------------*/
1717 /* outAcc - output Acc                                             */
1718 /*-----------------------------------------------------------------*/
1719 static void
1720 outAcc (operand * result)
1721 {
1722   int size, offset;
1723   size = getDataSize (result);
1724   if (size)
1725     {
1726       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1727       size--;
1728       offset = 1;
1729       /* unsigned or positive */
1730       while (size--)
1731         {
1732           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1733         }
1734     }
1735 }
1736
1737 /*-----------------------------------------------------------------*/
1738 /* outBitC - output a bit C                                        */
1739 /*-----------------------------------------------------------------*/
1740 static void
1741 outBitC (operand * result)
1742 {
1743   /* if the result is bit */
1744   if (AOP_TYPE (result) == AOP_CRY)
1745     aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1746   else
1747     {
1748       emitcode ("clr", "a");
1749       emitcode ("rlc", "a");
1750       outAcc (result);
1751     }
1752 }
1753
1754 /*-----------------------------------------------------------------*/
1755 /* toBoolean - emit code for orl a,operator(sizeop)                */
1756 /*-----------------------------------------------------------------*/
1757 static void
1758 toBoolean (operand * oper)
1759 {
1760   int size = AOP_SIZE (oper) - 1;
1761   int offset = 1;
1762   bool AccUsed = FALSE;
1763   bool pushedB;
1764
1765   while (!AccUsed && size--)
1766     {
1767       AccUsed |= aopGetUsesAcc(oper, offset++);
1768     }
1769
1770   size = AOP_SIZE (oper) - 1;
1771   offset = 1;
1772   MOVA (aopGet (oper, 0, FALSE, FALSE));
1773   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1774     {
1775       pushedB = pushB ();
1776       emitcode("mov", "b,a");
1777       while (--size)
1778         {
1779           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1780           emitcode ("orl", "b,a");
1781         }
1782       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1783       emitcode ("orl", "a,b");
1784       popB (pushedB);
1785     }
1786   else
1787     {
1788       while (size--)
1789         {
1790           emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1791         }
1792     }
1793 }
1794
1795
1796 /*-----------------------------------------------------------------*/
1797 /* genNot - generate code for ! operation                          */
1798 /*-----------------------------------------------------------------*/
1799 static void
1800 genNot (iCode * ic)
1801 {
1802   symbol *tlbl;
1803
1804   D(emitcode (";     genNot",""));
1805
1806   /* assign asmOps to operand & result */
1807   aopOp (IC_LEFT (ic), ic, FALSE);
1808   aopOp (IC_RESULT (ic), ic, TRUE);
1809
1810   /* if in bit space then a special case */
1811   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1812     {
1813       /* if left==result then cpl bit */
1814       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1815         {
1816           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1817         }
1818       else
1819         {
1820           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1821           emitcode ("cpl", "c");
1822           outBitC (IC_RESULT (ic));
1823         }
1824       goto release;
1825     }
1826
1827   toBoolean (IC_LEFT (ic));
1828
1829   /* set C, if a == 0 */
1830   tlbl = newiTempLabel (NULL);
1831   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1832   emitcode ("", "%05d$:", tlbl->key + 100);
1833   outBitC (IC_RESULT (ic));
1834
1835 release:
1836   /* release the aops */
1837   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1838   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1839 }
1840
1841
1842 /*-----------------------------------------------------------------*/
1843 /* genCpl - generate code for complement                           */
1844 /*-----------------------------------------------------------------*/
1845 static void
1846 genCpl (iCode * ic)
1847 {
1848   int offset = 0;
1849   int size;
1850   symbol *tlbl;
1851   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1852
1853   D(emitcode (";", "genCpl"));
1854
1855   /* assign asmOps to operand & result */
1856   aopOp (IC_LEFT (ic), ic, FALSE);
1857   aopOp (IC_RESULT (ic), ic, TRUE);
1858
1859   /* special case if in bit space */
1860   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1861     {
1862       char *l;
1863
1864       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1865           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1866         {
1867           /* promotion rules are responsible for this strange result:
1868              bit -> int -> ~int -> bit
1869              uchar -> int -> ~int -> bit
1870           */
1871           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1872           goto release;
1873         }
1874
1875       tlbl=newiTempLabel(NULL);
1876       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1877       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1878           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1879           IS_AOP_PREG (IC_LEFT (ic)))
1880         {
1881           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1882         }
1883       else
1884         {
1885           MOVA (l);
1886           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1887         }
1888       emitcode ("", "%05d$:", tlbl->key + 100);
1889       outBitC (IC_RESULT(ic));
1890       goto release;
1891     }
1892
1893   size = AOP_SIZE (IC_RESULT (ic));
1894   while (size--)
1895     {
1896       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1897       MOVA (l);
1898       emitcode ("cpl", "a");
1899       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1900     }
1901
1902
1903 release:
1904   /* release the aops */
1905   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1906   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1907 }
1908
1909 /*-----------------------------------------------------------------*/
1910 /* genUminusFloat - unary minus for floating points                */
1911 /*-----------------------------------------------------------------*/
1912 static void
1913 genUminusFloat (operand * op, operand * result)
1914 {
1915   int size, offset = 0;
1916   char *l;
1917
1918   D(emitcode (";     genUminusFloat",""));
1919
1920   /* for this we just copy and then flip the bit */
1921
1922   size = AOP_SIZE (op) - 1;
1923
1924   while (size--)
1925     {
1926       aopPut (result,
1927               aopGet (op, offset, FALSE, FALSE),
1928               offset,
1929               isOperandVolatile (result, FALSE));
1930       offset++;
1931     }
1932
1933   l = aopGet (op, offset, FALSE, FALSE);
1934
1935   MOVA (l);
1936
1937   emitcode ("cpl", "acc.7");
1938   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1939 }
1940
1941 /*-----------------------------------------------------------------*/
1942 /* genUminus - unary minus code generation                         */
1943 /*-----------------------------------------------------------------*/
1944 static void
1945 genUminus (iCode * ic)
1946 {
1947   int offset, size;
1948   sym_link *optype, *rtype;
1949
1950
1951   D(emitcode (";     genUminus",""));
1952
1953   /* assign asmops */
1954   aopOp (IC_LEFT (ic), ic, FALSE);
1955   aopOp (IC_RESULT (ic), ic, TRUE);
1956
1957   /* if both in bit space then special
1958      case */
1959   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1960       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1961     {
1962
1963       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1964       emitcode ("cpl", "c");
1965       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1966       goto release;
1967     }
1968
1969   optype = operandType (IC_LEFT (ic));
1970   rtype = operandType (IC_RESULT (ic));
1971
1972   /* if float then do float stuff */
1973   if (IS_FLOAT (optype))
1974     {
1975       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1976       goto release;
1977     }
1978
1979   /* otherwise subtract from zero */
1980   size = AOP_SIZE (IC_LEFT (ic));
1981   offset = 0;
1982   //CLRC ;
1983   while (size--)
1984     {
1985       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1986       if (!strcmp (l, "a"))
1987         {
1988           if (offset == 0)
1989             SETC;
1990           emitcode ("cpl", "a");
1991           emitcode ("addc", "a,#0");
1992         }
1993       else
1994         {
1995           if (offset == 0)
1996             CLRC;
1997           emitcode ("clr", "a");
1998           emitcode ("subb", "a,%s", l);
1999         }
2000       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2001     }
2002
2003   /* if any remaining bytes in the result */
2004   /* we just need to propagate the sign   */
2005   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2006     {
2007       emitcode ("rlc", "a");
2008       emitcode ("subb", "a,acc");
2009       while (size--)
2010         aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2011     }
2012
2013 release:
2014   /* release the aops */
2015   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2017 }
2018
2019 /*-----------------------------------------------------------------*/
2020 /* saveRegisters - will look for a call and save the registers     */
2021 /*-----------------------------------------------------------------*/
2022 static void
2023 saveRegisters (iCode * lic)
2024 {
2025   int i;
2026   iCode *ic;
2027   bitVect *rsave;
2028
2029   /* look for call */
2030   for (ic = lic; ic; ic = ic->next)
2031     if (ic->op == CALL || ic->op == PCALL)
2032       break;
2033
2034   if (!ic)
2035     {
2036       fprintf (stderr, "found parameter push with no function call\n");
2037       return;
2038     }
2039
2040   /* if the registers have been saved already or don't need to be then
2041      do nothing */
2042   if (ic->regsSaved)
2043     return;
2044   if (IS_SYMOP(IC_LEFT(ic)) &&
2045       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2046        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2047     return;
2048
2049   /* save the registers in use at this time but skip the
2050      ones for the result */
2051   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2052                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2053
2054   ic->regsSaved = 1;
2055   if (options.useXstack)
2056     {
2057       int count = bitVectnBitsOn (rsave);
2058
2059       if (count == 1)
2060         {
2061           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2062           if (reg->type == REG_BIT)
2063             {
2064               emitcode ("mov", "a,%s", reg->base);
2065             }
2066           else
2067             {
2068               emitcode ("mov", "a,%s", reg->name);
2069             }
2070           emitcode ("mov", "r0,%s", spname);
2071           emitcode ("inc", "%s", spname);// allocate before use
2072           emitcode ("movx", "@r0,a");
2073           if (bitVectBitValue (rsave, R0_IDX))
2074             emitcode ("mov", "r0,a");
2075         }
2076       else if (count != 0)
2077         {
2078           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2079           int nBits = bitVectnBitsOn (rsavebits);
2080
2081           if (nBits != 0)
2082             {
2083               count = count - nBits + 1;
2084               /* remove all but the first bits as they are pushed all at once */
2085               rsave = bitVectCplAnd (rsave, rsavebits);
2086               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2087             }
2088
2089           if (bitVectBitValue (rsave, R0_IDX))
2090             {
2091               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2092             }
2093           emitcode ("mov", "r0,%s", spname);
2094           MOVA ("r0");
2095           emitcode ("add", "a,#%d", count);
2096           emitcode ("mov", "%s,a", spname);
2097           for (i = 0; i < mcs51_nRegs; i++)
2098             {
2099               if (bitVectBitValue (rsave, i))
2100                 {
2101                   regs * reg = mcs51_regWithIdx (i);
2102                   if (i == R0_IDX)
2103                     {
2104                       emitcode ("pop", "acc");
2105                       emitcode ("push", "acc");
2106                     }
2107                   else if (reg->type == REG_BIT)
2108                     {
2109                       emitcode ("mov", "a,%s", reg->base);
2110                     }
2111                   else
2112                     {
2113                       emitcode ("mov", "a,%s", reg->name);
2114                     }
2115                   emitcode ("movx", "@r0,a");
2116                   if (--count)
2117                     {
2118                       emitcode ("inc", "r0");
2119                     }
2120                 }
2121             }
2122           if (bitVectBitValue (rsave, R0_IDX))
2123             {
2124               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2125             }
2126         }
2127     }
2128   else
2129     {
2130       bool bits_pushed = FALSE;
2131       for (i = 0; i < mcs51_nRegs; i++)
2132         {
2133           if (bitVectBitValue (rsave, i))
2134             {
2135               bits_pushed = pushReg (i, bits_pushed);
2136             }
2137         }
2138     }
2139 }
2140
2141 /*-----------------------------------------------------------------*/
2142 /* unsaveRegisters - pop the pushed registers                      */
2143 /*-----------------------------------------------------------------*/
2144 static void
2145 unsaveRegisters (iCode * ic)
2146 {
2147   int i;
2148   bitVect *rsave;
2149
2150   /* restore the registers in use at this time but skip the
2151      ones for the result */
2152   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2153                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2154
2155   if (options.useXstack)
2156     {
2157       int count = bitVectnBitsOn (rsave);
2158
2159       if (count == 1)
2160         {
2161           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2162           emitcode ("mov", "r0,%s", spname);
2163           emitcode ("dec", "r0");
2164           emitcode ("movx", "a,@r0");
2165           if (reg->type == REG_BIT)
2166             {
2167               emitcode ("mov", "%s,a", reg->base);
2168             }
2169           else
2170             {
2171               emitcode ("mov", "%s,a", reg->name);
2172             }
2173           emitcode ("dec", "%s", spname);
2174         }
2175       else if (count != 0)
2176         {
2177           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2178           int nBits = bitVectnBitsOn (rsavebits);
2179
2180           if (nBits != 0)
2181             {
2182               count = count - nBits + 1;
2183               /* remove all but the first bits as they are popped all at once */
2184               rsave = bitVectCplAnd (rsave, rsavebits);
2185               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2186             }
2187
2188           emitcode ("mov", "r0,%s", spname);
2189           for (i = mcs51_nRegs; i >= 0; i--)
2190             {
2191               if (bitVectBitValue (rsave, i))
2192                 {
2193                   regs * reg = mcs51_regWithIdx (i);
2194                   emitcode ("dec", "r0");
2195                   emitcode ("movx", "a,@r0");
2196                   if (i == R0_IDX)
2197                     {
2198                       emitcode ("push", "acc");
2199                     }
2200                   else if (reg->type == REG_BIT)
2201                     {
2202                       emitcode ("mov", "%s,a", reg->base);
2203                     }
2204                   else
2205                     {
2206                       emitcode ("mov", "%s,a", reg->name);
2207                     }
2208                 }
2209             }
2210           emitcode ("mov", "%s,r0", spname);
2211           if (bitVectBitValue (rsave, R0_IDX))
2212             {
2213               emitcode ("pop", "ar0");
2214             }
2215         }
2216     }
2217   else
2218     {
2219       bool bits_popped = FALSE;
2220       for (i = mcs51_nRegs; i >= 0; i--)
2221         {
2222           if (bitVectBitValue (rsave, i))
2223             {
2224               bits_popped = popReg (i, bits_popped);
2225             }
2226         }
2227     }
2228 }
2229
2230
2231 /*-----------------------------------------------------------------*/
2232 /* pushSide -                                                      */
2233 /*-----------------------------------------------------------------*/
2234 static void
2235 pushSide (operand * oper, int size)
2236 {
2237   int offset = 0;
2238   while (size--)
2239     {
2240       char *l = aopGet (oper, offset++, FALSE, TRUE);
2241       if (AOP_TYPE (oper) != AOP_REG &&
2242           AOP_TYPE (oper) != AOP_DIR &&
2243           strcmp (l, "a"))
2244         {
2245           MOVA (l);
2246           emitcode ("push", "acc");
2247         }
2248       else
2249         {
2250           emitcode ("push", "%s", l);
2251         }
2252     }
2253 }
2254
2255 /*-----------------------------------------------------------------*/
2256 /* assignResultValue - also indicates if acc is in use afterwards  */
2257 /*-----------------------------------------------------------------*/
2258 static bool
2259 assignResultValue (operand * oper, operand * func)
2260 {
2261   int offset = 0;
2262   int size = AOP_SIZE (oper);
2263   bool accuse = FALSE;
2264   bool pushedA = FALSE;
2265
2266   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2267     {
2268       outBitC (oper);
2269       return FALSE;
2270     }
2271
2272   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2273     {
2274       emitcode ("push", "acc");
2275       pushedA = TRUE;
2276     }
2277   while (size--)
2278     {
2279       if ((offset == 3) && pushedA)
2280         emitcode ("pop", "acc");
2281       accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2282       offset++;
2283     }
2284   return accuse;
2285 }
2286
2287
2288 /*-----------------------------------------------------------------*/
2289 /* genXpush - pushes onto the external stack                       */
2290 /*-----------------------------------------------------------------*/
2291 static void
2292 genXpush (iCode * ic)
2293 {
2294   asmop *aop = newAsmop (0);
2295   regs *r;
2296   int size, offset = 0;
2297
2298   D(emitcode (";     genXpush",""));
2299
2300   aopOp (IC_LEFT (ic), ic, FALSE);
2301   r = getFreePtr (ic, &aop, FALSE);
2302
2303   size = AOP_SIZE (IC_LEFT (ic));
2304
2305   if (size == 1)
2306     {
2307       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2308       emitcode ("mov", "%s,%s", r->name, spname);
2309       emitcode ("inc", "%s", spname); // allocate space first
2310       emitcode ("movx", "@%s,a", r->name);
2311     }
2312   else
2313     {
2314       // allocate space first
2315       emitcode ("mov", "%s,%s", r->name, spname);
2316       MOVA (r->name);
2317       emitcode ("add", "a,#%d", size);
2318       emitcode ("mov", "%s,a", spname);
2319
2320       while (size--)
2321         {
2322           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2323           emitcode ("movx", "@%s,a", r->name);
2324           emitcode ("inc", "%s", r->name);
2325         }
2326     }
2327
2328   freeAsmop (NULL, aop, ic, TRUE);
2329   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2330 }
2331
2332 /*-----------------------------------------------------------------*/
2333 /* genIpush - generate code for pushing this gets a little complex */
2334 /*-----------------------------------------------------------------*/
2335 static void
2336 genIpush (iCode * ic)
2337 {
2338   int size, offset = 0;
2339   char *l;
2340   char *prev = "";
2341
2342   D(emitcode (";     genIpush",""));
2343
2344   /* if this is not a parm push : ie. it is spill push
2345      and spill push is always done on the local stack */
2346   if (!ic->parmPush)
2347     {
2348
2349       /* and the item is spilt then do nothing */
2350       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2351         return;
2352
2353       aopOp (IC_LEFT (ic), ic, FALSE);
2354       size = AOP_SIZE (IC_LEFT (ic));
2355       /* push it on the stack */
2356       while (size--)
2357         {
2358           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2359           if (*l == '#')
2360             {
2361               MOVA (l);
2362               l = "acc";
2363             }
2364           emitcode ("push", "%s", l);
2365         }
2366       return;
2367     }
2368
2369   /* this is a parameter push: in this case we call
2370      the routine to find the call and save those
2371      registers that need to be saved */
2372   saveRegisters (ic);
2373
2374   /* if use external stack then call the external
2375      stack pushing routine */
2376   if (options.useXstack)
2377     {
2378       genXpush (ic);
2379       return;
2380     }
2381
2382   /* then do the push */
2383   aopOp (IC_LEFT (ic), ic, FALSE);
2384
2385   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2386   size = AOP_SIZE (IC_LEFT (ic));
2387
2388   while (size--)
2389     {
2390       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2391       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2392           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2393           strcmp (l, "a"))
2394         {
2395           if (strcmp (l, prev) || *l == '@')
2396             MOVA (l);
2397           emitcode ("push", "acc");
2398         }
2399       else
2400         {
2401           emitcode ("push", "%s", l);
2402         }
2403       prev = l;
2404     }
2405
2406   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2407 }
2408
2409 /*-----------------------------------------------------------------*/
2410 /* genIpop - recover the registers: can happen only for spilling   */
2411 /*-----------------------------------------------------------------*/
2412 static void
2413 genIpop (iCode * ic)
2414 {
2415   int size, offset;
2416
2417   D(emitcode (";     genIpop",""));
2418
2419   /* if the temp was not pushed then */
2420   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2421     return;
2422
2423   aopOp (IC_LEFT (ic), ic, FALSE);
2424   size = AOP_SIZE (IC_LEFT (ic));
2425   offset = (size - 1);
2426   while (size--)
2427     emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2428                                    FALSE, TRUE));
2429
2430   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* saveRBank - saves an entire register bank on the stack          */
2435 /*-----------------------------------------------------------------*/
2436 static void
2437 saveRBank (int bank, iCode * ic, bool pushPsw)
2438 {
2439   int i;
2440   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2441   asmop *aop = NULL;
2442   regs *r = NULL;
2443
2444   if (options.useXstack)
2445     {
2446       if (!ic)
2447       {
2448           /* Assume r0 is available for use. */
2449           r = mcs51_regWithIdx (R0_IDX);;
2450       }
2451       else
2452       {
2453           aop = newAsmop (0);
2454           r = getFreePtr (ic, &aop, FALSE);
2455       }
2456       // allocate space first
2457       emitcode ("mov", "%s,%s", r->name, spname);
2458       MOVA (r->name);
2459       emitcode ("add", "a,#%d", count);
2460       emitcode ("mov", "%s,a", spname);
2461     }
2462
2463   for (i = 0; i < 8; i++)
2464     {
2465       if (options.useXstack)
2466         {
2467           emitcode ("mov", "a,(%s+%d)",
2468                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2469           emitcode ("movx", "@%s,a", r->name);
2470           if (--count)
2471             emitcode ("inc", "%s", r->name);
2472         }
2473       else
2474         emitcode ("push", "(%s+%d)",
2475                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2476     }
2477
2478   if (mcs51_nRegs > 8)
2479     {
2480       if (options.useXstack)
2481         {
2482           emitcode ("mov", "a,bits");
2483           emitcode ("movx", "@%s,a", r->name);
2484           if (--count)
2485             emitcode ("inc", "%s", r->name);
2486         }
2487       else
2488         {
2489           emitcode ("push", "bits");
2490         }
2491       BitBankUsed = 1;
2492     }
2493
2494   if (pushPsw)
2495     {
2496       if (options.useXstack)
2497         {
2498           emitcode ("mov", "a,psw");
2499           emitcode ("movx", "@%s,a", r->name);
2500
2501         }
2502       else
2503         {
2504           emitcode ("push", "psw");
2505         }
2506
2507       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2508     }
2509
2510   if (aop)
2511     {
2512       freeAsmop (NULL, aop, ic, TRUE);
2513     }
2514
2515   if (ic)
2516   {
2517     ic->bankSaved = 1;
2518   }
2519 }
2520
2521 /*-----------------------------------------------------------------*/
2522 /* unsaveRBank - restores the register bank from stack             */
2523 /*-----------------------------------------------------------------*/
2524 static void
2525 unsaveRBank (int bank, iCode * ic, bool popPsw)
2526 {
2527   int i;
2528   asmop *aop = NULL;
2529   regs *r = NULL;
2530
2531   if (options.useXstack)
2532     {
2533       if (!ic)
2534         {
2535           /* Assume r0 is available for use. */
2536           r = mcs51_regWithIdx (R0_IDX);;
2537         }
2538       else
2539         {
2540           aop = newAsmop (0);
2541           r = getFreePtr (ic, &aop, FALSE);
2542         }
2543       emitcode ("mov", "%s,%s", r->name, spname);
2544     }
2545
2546   if (popPsw)
2547     {
2548       if (options.useXstack)
2549         {
2550           emitcode ("dec", "%s", r->name);
2551           emitcode ("movx", "a,@%s", r->name);
2552           emitcode ("mov", "psw,a");
2553         }
2554       else
2555         {
2556           emitcode ("pop", "psw");
2557         }
2558     }
2559
2560   if (mcs51_nRegs > 8)
2561     {
2562       if (options.useXstack)
2563         {
2564           emitcode ("dec", "%s", r->name);
2565           emitcode ("movx", "a,@%s", r->name);
2566           emitcode ("mov", "bits,a");
2567         }
2568       else
2569         {
2570           emitcode ("pop", "bits");
2571         }
2572     }
2573
2574   for (i = 7; i >= 0; i--)
2575     {
2576       if (options.useXstack)
2577         {
2578           emitcode ("dec", "%s", r->name);
2579           emitcode ("movx", "a,@%s", r->name);
2580           emitcode ("mov", "(%s+%d),a",
2581                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2582         }
2583       else
2584         {
2585           emitcode ("pop", "(%s+%d)",
2586                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2587         }
2588     }
2589
2590   if (options.useXstack)
2591     {
2592       emitcode ("mov", "%s,%s", spname, r->name);
2593     }
2594
2595   if (aop)
2596     {
2597       freeAsmop (NULL, aop, ic, TRUE);
2598     }
2599 }
2600
2601 /*-----------------------------------------------------------------*/
2602 /* genSend - gen code for SEND                                     */
2603 /*-----------------------------------------------------------------*/
2604 static void genSend(set *sendSet)
2605 {
2606   iCode *sic;
2607   int bit_count = 0;
2608
2609   /* first we do all bit parameters */
2610   for (sic = setFirstItem (sendSet); sic;
2611        sic = setNextItem (sendSet))
2612     {
2613       if (sic->argreg > 12)
2614         {
2615           int bit = sic->argreg-13;
2616
2617           aopOp (IC_LEFT (sic), sic, FALSE);
2618
2619           /* if left is a literal then
2620              we know what the value is */
2621           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2622             {
2623               if (((int) operandLitValue (IC_LEFT (sic))))
2624                   emitcode ("setb", "b[%d]", bit);
2625               else
2626                   emitcode ("clr", "b[%d]", bit);
2627             }
2628           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2629             {
2630               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2631                 if (strcmp (l, "c"))
2632                     emitcode ("mov", "c,%s", l);
2633                 emitcode ("mov", "b[%d],c", bit);
2634             }
2635           else
2636             {
2637               /* we need to or */
2638               toBoolean (IC_LEFT (sic));
2639               /* set C, if a >= 1 */
2640               emitcode ("add", "a,#0xff");
2641               emitcode ("mov", "b[%d],c", bit);
2642             }
2643           bit_count++;
2644           BitBankUsed = 1;
2645
2646           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2647         }
2648     }
2649
2650   if (bit_count)
2651     {
2652       saveRegisters (setFirstItem (sendSet));
2653       emitcode ("mov", "bits,b");
2654     }
2655
2656   /* then we do all other parameters */
2657   for (sic = setFirstItem (sendSet); sic;
2658        sic = setNextItem (sendSet))
2659     {
2660       if (sic->argreg <= 12)
2661         {
2662           int size, offset = 0;
2663           aopOp (IC_LEFT (sic), sic, FALSE);
2664           size = AOP_SIZE (IC_LEFT (sic));
2665
2666           if (sic->argreg == 1)
2667             {
2668               while (size--)
2669                 {
2670                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2671                   if (strcmp (l, fReturn[offset]))
2672                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2673                   offset++;
2674                 }
2675             }
2676           else
2677             {
2678               while (size--)
2679                 {
2680                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2681                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2682                   offset++;
2683                 }
2684             }
2685           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2686         }
2687     }
2688 }
2689
2690 /*-----------------------------------------------------------------*/
2691 /* selectRegBank - emit code to select the register bank           */
2692 /*-----------------------------------------------------------------*/
2693 static void
2694 selectRegBank (short bank, bool keepFlags)
2695 {
2696   /* if f.e. result is in carry */
2697   if (keepFlags)
2698     {
2699       emitcode ("anl", "psw,#0xE7");
2700       if (bank)
2701         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2702     }
2703   else
2704     {
2705       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2706     }
2707 }
2708
2709 /*-----------------------------------------------------------------*/
2710 /* genCall - generates a call statement                            */
2711 /*-----------------------------------------------------------------*/
2712 static void
2713 genCall (iCode * ic)
2714 {
2715   sym_link *dtype;
2716   sym_link *etype;
2717 //  bool restoreBank = FALSE;
2718   bool swapBanks = FALSE;
2719   bool accuse = FALSE;
2720   bool accPushed = FALSE;
2721   bool resultInF0 = FALSE;
2722
2723   D(emitcode(";     genCall",""));
2724
2725   dtype = operandType (IC_LEFT (ic));
2726   etype = getSpec(dtype);
2727   /* if send set is not empty then assign */
2728   if (_G.sendSet)
2729     {
2730         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2731             genSend(reverseSet(_G.sendSet));
2732         } else {
2733             genSend(_G.sendSet);
2734         }
2735
2736       _G.sendSet = NULL;
2737     }
2738
2739   /* if we are calling a not _naked function that is not using
2740      the same register bank then we need to save the
2741      destination registers on the stack */
2742   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2743       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2744        !IFFUNC_ISISR (dtype))
2745     {
2746       swapBanks = TRUE;
2747     }
2748
2749   /* if caller saves & we have not saved then */
2750   if (!ic->regsSaved)
2751       saveRegisters (ic);
2752
2753   if (swapBanks)
2754     {
2755         emitcode ("mov", "psw,#0x%02x",
2756            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2757     }
2758
2759   /* make the call */
2760   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2761     {
2762       if (IFFUNC_CALLEESAVES(dtype))
2763         {
2764           werror (E_BANKED_WITH_CALLEESAVES);
2765         }
2766       else
2767         {
2768           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2769                      OP_SYMBOL (IC_LEFT (ic))->rname :
2770                      OP_SYMBOL (IC_LEFT (ic))->name);
2771
2772           emitcode ("mov", "r0,#%s", l);
2773           emitcode ("mov", "r1,#(%s >> 8)", l);
2774           emitcode ("mov", "r2,#(%s >> 16)", l);
2775           emitcode ("lcall", "__sdcc_banked_call");
2776         }
2777     }
2778   else
2779     {
2780       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2781                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2782                                 OP_SYMBOL (IC_LEFT (ic))->name));
2783     }
2784
2785   if (swapBanks)
2786     {
2787       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2788     }
2789
2790   /* if we need assign a result value */
2791   if ((IS_ITEMP (IC_RESULT (ic)) &&
2792        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2793        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2794         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2795         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2796       IS_TRUE_SYMOP (IC_RESULT (ic)))
2797     {
2798
2799       _G.accInUse++;
2800       aopOp (IC_RESULT (ic), ic, FALSE);
2801       _G.accInUse--;
2802
2803       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2804
2805       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2806     }
2807
2808   /* adjust the stack for parameters if required */
2809   if (ic->parmBytes)
2810     {
2811       int i;
2812       if (ic->parmBytes > 3)
2813         {
2814           if (accuse)
2815             {
2816               emitcode ("push", "acc");
2817               accPushed = TRUE;
2818             }
2819           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2820               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2821             {
2822               emitcode ("mov", "F0,c");
2823               resultInF0 = TRUE;
2824             }
2825
2826           emitcode ("mov", "a,%s", spname);
2827           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2828           emitcode ("mov", "%s,a", spname);
2829
2830           /* unsaveRegisters from xstack needs acc, but */
2831           /* unsaveRegisters from stack needs this popped */
2832           if (accPushed && !options.useXstack)
2833             {
2834               emitcode ("pop", "acc");
2835               accPushed = FALSE;
2836             }
2837         }
2838       else
2839         for (i = 0; i < ic->parmBytes; i++)
2840           emitcode ("dec", "%s", spname);
2841     }
2842
2843   /* if we had saved some registers then unsave them */
2844   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2845     {
2846       if (accuse && !accPushed && options.useXstack)
2847         {
2848           /* xstack needs acc, but doesn't touch normal stack */
2849           emitcode ("push", "acc");
2850           accPushed = TRUE;
2851         }
2852       unsaveRegisters (ic);
2853     }
2854
2855 //  /* if register bank was saved then pop them */
2856 //  if (restoreBank)
2857 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2858
2859   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2860     {
2861       if (resultInF0)
2862           emitcode ("mov", "c,F0");
2863
2864       aopOp (IC_RESULT (ic), ic, FALSE);
2865       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2866       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2867     }
2868
2869   if (accPushed)
2870     emitcode ("pop", "acc");
2871 }
2872
2873 /*-----------------------------------------------------------------*/
2874 /* -10l - generates a call by pointer statement                */
2875 /*-----------------------------------------------------------------*/
2876 static void
2877 genPcall (iCode * ic)
2878 {
2879   sym_link *dtype;
2880   sym_link *etype;
2881   symbol *rlbl = newiTempLabel (NULL);
2882 //  bool restoreBank=FALSE;
2883   bool swapBanks = FALSE;
2884   bool resultInF0 = FALSE;
2885
2886   D(emitcode(";     genPCall",""));
2887
2888   dtype = operandType (IC_LEFT (ic))->next;
2889   etype = getSpec(dtype);
2890   /* if caller saves & we have not saved then */
2891   if (!ic->regsSaved)
2892     saveRegisters (ic);
2893
2894   /* if we are calling a not _naked function that is not using
2895      the same register bank then we need to save the
2896      destination registers on the stack */
2897   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2898       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2899       !IFFUNC_ISISR (dtype))
2900     {
2901 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2902 //    restoreBank=TRUE;
2903       swapBanks = TRUE;
2904       // need caution message to user here
2905     }
2906
2907   if (IS_LITERAL(etype))
2908     {
2909       /* if send set is not empty then assign */
2910       if (_G.sendSet)
2911         {
2912           genSend(reverseSet(_G.sendSet));
2913           _G.sendSet = NULL;
2914         }
2915
2916       if (swapBanks)
2917         {
2918           emitcode ("mov", "psw,#0x%02x",
2919            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2920         }
2921
2922       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2923         {
2924           if (IFFUNC_CALLEESAVES(dtype))
2925             {
2926               werror (E_BANKED_WITH_CALLEESAVES);
2927             }
2928           else
2929             {
2930               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2931
2932               emitcode ("mov", "r0,#%s", l);
2933               emitcode ("mov", "r1,#(%s >> 8)", l);
2934               emitcode ("mov", "r2,#(%s >> 16)", l);
2935               emitcode ("lcall", "__sdcc_banked_call");
2936             }
2937         }
2938       else
2939         {
2940           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2941         }
2942     }
2943   else
2944     {
2945       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2946         {
2947           if (IFFUNC_CALLEESAVES(dtype))
2948             {
2949               werror (E_BANKED_WITH_CALLEESAVES);
2950             }
2951           else
2952             {
2953               aopOp (IC_LEFT (ic), ic, FALSE);
2954
2955               if (!swapBanks)
2956                 {
2957                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2958                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2959                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2960                 }
2961               else
2962                 {
2963                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2964                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2965                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2966                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2967                 }
2968
2969               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2970
2971               /* if send set is not empty then assign */
2972               if (_G.sendSet)
2973                 {
2974                   genSend(reverseSet(_G.sendSet));
2975                   _G.sendSet = NULL;
2976                 }
2977
2978               if (swapBanks)
2979                 {
2980                   emitcode ("mov", "psw,#0x%02x",
2981                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2982                 }
2983
2984               /* make the call */
2985               emitcode ("lcall", "__sdcc_banked_call");
2986             }
2987         }
2988       else
2989         {
2990           /* push the return address on to the stack */
2991           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2992           emitcode ("push", "acc");
2993           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2994           emitcode ("push", "acc");
2995
2996           /* now push the calling address */
2997           aopOp (IC_LEFT (ic), ic, FALSE);
2998
2999           pushSide (IC_LEFT (ic), FPTRSIZE);
3000
3001           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3002
3003           /* if send set is not empty the assign */
3004           if (_G.sendSet)
3005             {
3006               genSend(reverseSet(_G.sendSet));
3007               _G.sendSet = NULL;
3008             }
3009
3010           if (swapBanks)
3011             {
3012               emitcode ("mov", "psw,#0x%02x",
3013                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3014             }
3015
3016           /* make the call */
3017           emitcode ("ret", "");
3018           emitcode ("", "%05d$:", (rlbl->key + 100));
3019         }
3020     }
3021   if (swapBanks)
3022     {
3023       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3024     }
3025
3026   /* if we need assign a result value */
3027   if ((IS_ITEMP (IC_RESULT (ic)) &&
3028        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3029        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3030         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3031       IS_TRUE_SYMOP (IC_RESULT (ic)))
3032     {
3033
3034       _G.accInUse++;
3035       aopOp (IC_RESULT (ic), ic, FALSE);
3036       _G.accInUse--;
3037
3038       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3039
3040       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3041     }
3042
3043   /* adjust the stack for parameters if required */
3044   if (ic->parmBytes)
3045     {
3046       int i;
3047       if (ic->parmBytes > 3)
3048         {
3049           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3050               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3051             {
3052               emitcode ("mov", "F0,c");
3053               resultInF0 = TRUE;
3054             }
3055
3056           emitcode ("mov", "a,%s", spname);
3057           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3058           emitcode ("mov", "%s,a", spname);
3059         }
3060       else
3061         for (i = 0; i < ic->parmBytes; i++)
3062           emitcode ("dec", "%s", spname);
3063
3064     }
3065
3066 //  /* if register bank was saved then unsave them */
3067 //  if (restoreBank)
3068 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3069
3070   /* if we had saved some registers then unsave them */
3071   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3072     unsaveRegisters (ic);
3073
3074   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3075     {
3076       if (resultInF0)
3077           emitcode ("mov", "c,F0");
3078
3079       aopOp (IC_RESULT (ic), ic, FALSE);
3080       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3081       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3082     }
3083 }
3084
3085 /*-----------------------------------------------------------------*/
3086 /* resultRemat - result  is rematerializable                       */
3087 /*-----------------------------------------------------------------*/
3088 static int
3089 resultRemat (iCode * ic)
3090 {
3091   if (SKIP_IC (ic) || ic->op == IFX)
3092     return 0;
3093
3094   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3095     {
3096       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3097       if (sym->remat && !POINTER_SET (ic))
3098         return 1;
3099     }
3100
3101   return 0;
3102 }
3103
3104 #if defined(__BORLANDC__) || defined(_MSC_VER)
3105 #define STRCASECMP stricmp
3106 #else
3107 #define STRCASECMP strcasecmp
3108 #endif
3109
3110 /*-----------------------------------------------------------------*/
3111 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3112 /*-----------------------------------------------------------------*/
3113 static int
3114 regsCmp(void *p1, void *p2)
3115 {
3116   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3117 }
3118
3119 static bool
3120 inExcludeList (char *s)
3121 {
3122   const char *p = setFirstItem(options.excludeRegsSet);
3123
3124   if (p == NULL || STRCASECMP(p, "none") == 0)
3125     return FALSE;
3126
3127
3128   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3129 }
3130
3131 /*-----------------------------------------------------------------*/
3132 /* genFunction - generated code for function entry                 */
3133 /*-----------------------------------------------------------------*/
3134 static void
3135 genFunction (iCode * ic)
3136 {
3137   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3138   sym_link *ftype;
3139   bool     switchedPSW = FALSE;
3140   int      calleesaves_saved_register = -1;
3141   int      stackAdjust = sym->stack;
3142   int      accIsFree = sym->recvSize < 4;
3143   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3144   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3145
3146   _G.nRegsSaved = 0;
3147   /* create the function header */
3148   emitcode (";", "-----------------------------------------");
3149   emitcode (";", " function %s", sym->name);
3150   emitcode (";", "-----------------------------------------");
3151
3152   emitcode ("", "%s:", sym->rname);
3153   ftype = operandType (IC_LEFT (ic));
3154   _G.currentFunc = sym;
3155
3156   if (IFFUNC_ISNAKED(ftype))
3157   {
3158       emitcode(";", "naked function: no prologue.");
3159       return;
3160   }
3161
3162   /* here we need to generate the equates for the
3163      register bank if required */
3164   if (FUNC_REGBANK (ftype) != rbank)
3165     {
3166       int i;
3167
3168       rbank = FUNC_REGBANK (ftype);
3169       for (i = 0; i < mcs51_nRegs; i++)
3170         {
3171           if (regs8051[i].type != REG_BIT)
3172             {
3173               if (strcmp (regs8051[i].base, "0") == 0)
3174                 emitcode ("", "%s = 0x%02x",
3175                           regs8051[i].dname,
3176                           8 * rbank + regs8051[i].offset);
3177               else
3178                 emitcode ("", "%s = %s + 0x%02x",
3179                           regs8051[i].dname,
3180                           regs8051[i].base,
3181                           8 * rbank + regs8051[i].offset);
3182             }
3183         }
3184     }
3185
3186   /* if this is an interrupt service routine then
3187      save acc, b, dpl, dph  */
3188   if (IFFUNC_ISISR (sym->type))
3189     {
3190
3191       if (!inExcludeList ("acc"))
3192         emitcode ("push", "acc");
3193       if (!inExcludeList ("b"))
3194         emitcode ("push", "b");
3195       if (!inExcludeList ("dpl"))
3196         emitcode ("push", "dpl");
3197       if (!inExcludeList ("dph"))
3198         emitcode ("push", "dph");
3199       /* if this isr has no bank i.e. is going to
3200          run with bank 0 , then we need to save more
3201          registers :-) */
3202       if (!FUNC_REGBANK (sym->type))
3203         {
3204
3205           /* if this function does not call any other
3206              function then we can be economical and
3207              save only those registers that are used */
3208           if (!IFFUNC_HASFCALL(sym->type))
3209             {
3210               int i;
3211
3212               /* if any registers used */
3213               if (sym->regsUsed)
3214                 {
3215                   bool bits_pushed = FALSE;
3216                   /* save the registers used */
3217                   for (i = 0; i < sym->regsUsed->size; i++)
3218                     {
3219                       if (bitVectBitValue (sym->regsUsed, i))
3220                         bits_pushed = pushReg (i, bits_pushed);
3221                     }
3222                 }
3223             }
3224           else
3225             {
3226
3227               /* this function has a function call. We cannot
3228                  determines register usage so we will have to push the
3229                  entire bank */
3230                 saveRBank (0, ic, FALSE);
3231                 if (options.parms_in_bank1) {
3232                     int i;
3233                     for (i=0; i < 8 ; i++ ) {
3234                         emitcode ("push","%s",rb1regs[i]);
3235                     }
3236                 }
3237             }
3238         }
3239         else
3240         {
3241             /* This ISR uses a non-zero bank.
3242              *
3243              * We assume that the bank is available for our
3244              * exclusive use.
3245              *
3246              * However, if this ISR calls a function which uses some
3247              * other bank, we must save that bank entirely.
3248              */
3249             unsigned long banksToSave = 0;
3250
3251             if (IFFUNC_HASFCALL(sym->type))
3252             {
3253
3254 #define MAX_REGISTER_BANKS 4
3255
3256                 iCode *i;
3257                 int ix;
3258
3259                 for (i = ic; i; i = i->next)
3260                 {
3261                     if (i->op == ENDFUNCTION)
3262                     {
3263                         /* we got to the end OK. */
3264                         break;
3265                     }
3266
3267                     if (i->op == CALL)
3268                     {
3269                         sym_link *dtype;
3270
3271                         dtype = operandType (IC_LEFT(i));
3272                         if (dtype
3273                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3274                         {
3275                              /* Mark this bank for saving. */
3276                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3277                              {
3278                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3279                              }
3280                              else
3281                              {
3282                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3283                              }
3284
3285                              /* And note that we don't need to do it in
3286                               * genCall.
3287                               */
3288                              i->bankSaved = 1;
3289                         }
3290                     }
3291                     if (i->op == PCALL)
3292                     {
3293                         /* This is a mess; we have no idea what
3294                          * register bank the called function might
3295                          * use.
3296                          *
3297                          * The only thing I can think of to do is
3298                          * throw a warning and hope.
3299                          */
3300                         werror(W_FUNCPTR_IN_USING_ISR);
3301                     }
3302                 }
3303
3304                 if (banksToSave && options.useXstack)
3305                 {
3306                     /* Since we aren't passing it an ic,
3307                      * saveRBank will assume r0 is available to abuse.
3308                      *
3309                      * So switch to our (trashable) bank now, so
3310                      * the caller's R0 isn't trashed.
3311                      */
3312                     emitcode ("push", "psw");
3313                     emitcode ("mov", "psw,#0x%02x",
3314                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3315                     switchedPSW = TRUE;
3316                 }
3317
3318                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3319                 {
3320                      if (banksToSave & (1 << ix))
3321                      {
3322                          saveRBank(ix, NULL, FALSE);
3323                      }
3324                 }
3325             }
3326             // TODO: this needs a closer look
3327             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3328         }
3329
3330       /* Set the register bank to the desired value if nothing else */
3331       /* has done so yet. */
3332       if (!switchedPSW)
3333         {
3334           emitcode ("push", "psw");
3335           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3336         }
3337     }
3338   else
3339     {
3340       /* This is a non-ISR function. The caller has already switched register */
3341       /* banks, if necessary, so just handle the callee-saves option. */
3342
3343       /* if callee-save to be used for this function
3344          then save the registers being used in this function */
3345       if (IFFUNC_CALLEESAVES(sym->type))
3346         {
3347           int i;
3348
3349           /* if any registers used */
3350           if (sym->regsUsed)
3351             {
3352               bool bits_pushed = FALSE;
3353               /* save the registers used */
3354               for (i = 0; i < sym->regsUsed->size; i++)
3355                 {
3356                   if (bitVectBitValue (sym->regsUsed, i))
3357                     {
3358                       /* remember one saved register for later usage */
3359                       if (calleesaves_saved_register < 0)
3360                         calleesaves_saved_register = i;
3361                       bits_pushed = pushReg (i, bits_pushed);
3362                       _G.nRegsSaved++;
3363                     }
3364                 }
3365             }
3366         }
3367     }
3368
3369
3370   if (fReentrant)
3371     {
3372       if (options.useXstack)
3373         {
3374           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3375             {
3376               emitcode ("mov", "r0,%s", spname);
3377               emitcode ("inc", "%s", spname);
3378               emitcode ("xch", "a,_bpx");
3379               emitcode ("movx", "@r0,a");
3380               emitcode ("inc", "r0");
3381               emitcode ("mov", "a,r0");
3382               emitcode ("xch", "a,_bpx");
3383             }
3384           if (sym->stack)
3385             {
3386               emitcode ("push", "_bp");     /* save the callers stack  */
3387               emitcode ("mov", "_bp,sp");
3388             }
3389         }
3390       else
3391         {
3392           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3393             {
3394               /* set up the stack */
3395               emitcode ("push", "_bp");     /* save the callers stack  */
3396               emitcode ("mov", "_bp,sp");
3397             }
3398         }
3399     }
3400
3401   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3402   /* before setting up the stack frame completely. */
3403   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3404     {
3405       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3406
3407       if (rsym->isitmp)
3408         {
3409           if (rsym && rsym->regType == REG_CND)
3410             rsym = NULL;
3411           if (rsym && (rsym->accuse || rsym->ruonly))
3412             rsym = NULL;
3413           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3414             rsym = rsym->usl.spillLoc;
3415         }
3416
3417       /* If the RECEIVE operand immediately spills to the first entry on the */
3418       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3419       /* rather than the usual @r0/r1 machinations. */
3420       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3421         {
3422           int ofs;
3423
3424           _G.current_iCode = ric;
3425           D(emitcode (";     genReceive",""));
3426           for (ofs=0; ofs < sym->recvSize; ofs++)
3427             {
3428               if (!strcmp (fReturn[ofs], "a"))
3429                 emitcode ("push", "acc");
3430               else
3431                 emitcode ("push", fReturn[ofs]);
3432             }
3433           stackAdjust -= sym->recvSize;
3434           if (stackAdjust<0)
3435             {
3436               assert (stackAdjust>=0);
3437               stackAdjust = 0;
3438             }
3439           _G.current_iCode = ic;
3440           ric->generated = 1;
3441           accIsFree = 1;
3442         }
3443       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3444       /* to free up the accumulator. */
3445       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3446         {
3447           int ofs;
3448
3449           _G.current_iCode = ric;
3450           D(emitcode (";     genReceive",""));
3451           for (ofs=0; ofs < sym->recvSize; ofs++)
3452             {
3453               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3454             }
3455           _G.current_iCode = ic;
3456           ric->generated = 1;
3457           accIsFree = 1;
3458         }
3459     }
3460
3461   /* adjust the stack for the function */
3462   if (stackAdjust)
3463     {
3464       int i = stackAdjust;
3465       if (i > 256)
3466         werror (W_STACK_OVERFLOW, sym->name);
3467
3468       if (i > 3 && accIsFree)
3469         {
3470           emitcode ("mov", "a,sp");
3471           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3472           emitcode ("mov", "sp,a");
3473         }
3474       else if (i > 5)
3475         {
3476           /* The accumulator is not free, so we will need another register */
3477           /* to clobber. No need to worry about a possible conflict with */
3478           /* the above early RECEIVE optimizations since they would have */
3479           /* freed the accumulator if they were generated. */
3480
3481           if (IFFUNC_CALLEESAVES(sym->type))
3482             {
3483               /* if it's a callee-saves function we need a saved register */
3484               if (calleesaves_saved_register >= 0)
3485                 {
3486                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3487                   emitcode ("mov", "a,sp");
3488                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3489                   emitcode ("mov", "sp,a");
3490                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3491                 }
3492               else
3493                 /* do it the hard way */
3494                 while (i--)
3495                   emitcode ("inc", "sp");
3496             }
3497           else
3498             {
3499               /* not callee-saves, we can clobber r0 */
3500               emitcode ("mov", "r0,a");
3501               emitcode ("mov", "a,sp");
3502               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3503               emitcode ("mov", "sp,a");
3504               emitcode ("mov", "a,r0");
3505             }
3506         }
3507       else
3508         while (i--)
3509           emitcode ("inc", "sp");
3510     }
3511
3512   if (sym->xstack)
3513     {
3514       char i = ((char) sym->xstack & 0xff);
3515
3516       if (i > 3 && accIsFree)
3517         {
3518           emitcode ("mov", "a,_spx");
3519           emitcode ("add", "a,#0x%02x", i);
3520           emitcode ("mov", "_spx,a");
3521         }
3522       else if (i > 5)
3523         {
3524           emitcode ("push", "acc");
3525           emitcode ("mov", "a,_spx");
3526           emitcode ("add", "a,#0x%02x", i);
3527           emitcode ("mov", "_spx,a");
3528           emitcode ("pop", "acc");
3529         }
3530       else
3531         {
3532           while (i--)
3533             emitcode ("inc", "_spx");
3534         }
3535     }
3536
3537   /* if critical function then turn interrupts off */
3538   if (IFFUNC_ISCRITICAL (ftype))
3539     {
3540       symbol *tlbl = newiTempLabel (NULL);
3541       emitcode ("setb", "c");
3542       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3543       emitcode ("clr", "c");
3544       emitcode ("", "%05d$:", (tlbl->key + 100));
3545       emitcode ("push", "psw"); /* save old ea via c in psw */
3546     }
3547 }
3548
3549 /*-----------------------------------------------------------------*/
3550 /* genEndFunction - generates epilogue for functions               */
3551 /*-----------------------------------------------------------------*/
3552 static void
3553 genEndFunction (iCode * ic)
3554 {
3555   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3556   lineNode *lnp = lineCurr;
3557   bitVect  *regsUsed;
3558   bitVect  *regsUsedPrologue;
3559   bitVect  *regsUnneeded;
3560   int      idx;
3561
3562   _G.currentFunc = NULL;
3563   if (IFFUNC_ISNAKED(sym->type))
3564   {
3565       emitcode(";", "naked function: no epilogue.");
3566       if (options.debug && currFunc)
3567         debugFile->writeEndFunction (currFunc, ic, 0);
3568       return;
3569   }
3570
3571   if (IFFUNC_ISCRITICAL (sym->type))
3572     {
3573       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3574         {
3575           emitcode ("rlc", "a");   /* save c in a */
3576           emitcode ("pop", "psw"); /* restore ea via c in psw */
3577           emitcode ("mov", "ea,c");
3578           emitcode ("rrc", "a");   /* restore c from a */
3579         }
3580       else
3581         {
3582           emitcode ("pop", "psw"); /* restore ea via c in psw */
3583           emitcode ("mov", "ea,c");
3584         }
3585     }
3586
3587   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3588     {
3589       if (options.useXstack)
3590         {
3591           if (sym->stack)
3592             {
3593               emitcode ("mov", "sp,_bp");
3594               emitcode ("pop", "_bp");
3595             }
3596           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3597             {
3598               emitcode ("xch", "a,_bpx");
3599               emitcode ("mov", "r0,a");
3600               emitcode ("dec", "r0");
3601               emitcode ("movx", "a,@r0");
3602               emitcode ("xch", "a,_bpx");
3603               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3604             }
3605         }
3606       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3607         {
3608           emitcode ("mov", "sp,_bp");
3609           emitcode ("pop", "_bp");
3610         }
3611     }
3612
3613   /* restore the register bank  */
3614   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3615   {
3616     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3617      || !options.useXstack)
3618     {
3619         /* Special case of ISR using non-zero bank with useXstack
3620          * is handled below.
3621          */
3622         emitcode ("pop", "psw");
3623     }
3624   }
3625
3626   if (IFFUNC_ISISR (sym->type))
3627     {
3628
3629       /* now we need to restore the registers */
3630       /* if this isr has no bank i.e. is going to
3631          run with bank 0 , then we need to save more
3632          registers :-) */
3633       if (!FUNC_REGBANK (sym->type))
3634         {
3635           /* if this function does not call any other
3636              function then we can be economical and
3637              save only those registers that are used */
3638           if (!IFFUNC_HASFCALL(sym->type))
3639             {
3640               int i;
3641
3642               /* if any registers used */
3643               if (sym->regsUsed)
3644                 {
3645                   bool bits_popped = FALSE;
3646                   /* save the registers used */
3647                   for (i = sym->regsUsed->size; i >= 0; i--)
3648                     {
3649                       if (bitVectBitValue (sym->regsUsed, i))
3650                         bits_popped = popReg (i, bits_popped);
3651                     }
3652                 }
3653             }
3654           else
3655             {
3656               if (options.parms_in_bank1) {
3657                   int i;
3658                   for (i = 7 ; i >= 0 ; i-- ) {
3659                       emitcode ("pop","%s",rb1regs[i]);
3660                   }
3661               }
3662               /* this function has  a function call cannot
3663                  determines register usage so we will have to pop the
3664                  entire bank */
3665               unsaveRBank (0, ic, FALSE);
3666             }
3667         }
3668         else
3669         {
3670             /* This ISR uses a non-zero bank.
3671              *
3672              * Restore any register banks saved by genFunction
3673              * in reverse order.
3674              */
3675             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3676             int ix;
3677
3678             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3679             {
3680                 if (savedBanks & (1 << ix))
3681                 {
3682                     unsaveRBank(ix, NULL, FALSE);
3683                 }
3684             }
3685
3686             if (options.useXstack)
3687             {
3688                 /* Restore bank AFTER calling unsaveRBank,
3689                  * since it can trash r0.
3690                  */
3691                 emitcode ("pop", "psw");
3692             }
3693         }
3694
3695       if (!inExcludeList ("dph"))
3696         emitcode ("pop", "dph");
3697       if (!inExcludeList ("dpl"))
3698         emitcode ("pop", "dpl");
3699       if (!inExcludeList ("b"))
3700         emitcode ("pop", "b");
3701       if (!inExcludeList ("acc"))
3702         emitcode ("pop", "acc");
3703
3704       /* if debug then send end of function */
3705       if (options.debug && currFunc)
3706         {
3707           debugFile->writeEndFunction (currFunc, ic, 1);
3708         }
3709
3710       emitcode ("reti", "");
3711     }
3712   else
3713     {
3714       if (IFFUNC_CALLEESAVES(sym->type))
3715         {
3716           int i;
3717
3718           /* if any registers used */
3719           if (sym->regsUsed)
3720             {
3721               /* save the registers used */
3722               for (i = sym->regsUsed->size; i >= 0; i--)
3723                 {
3724                   if (bitVectBitValue (sym->regsUsed, i) ||
3725                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3726                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3727                 }
3728             }
3729           else if (mcs51_ptrRegReq)
3730             {
3731               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3732               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3733             }
3734
3735         }
3736
3737       /* if debug then send end of function */
3738       if (options.debug && currFunc)
3739         {
3740           debugFile->writeEndFunction (currFunc, ic, 1);
3741         }
3742
3743       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3744         {
3745           emitcode ("ljmp", "__sdcc_banked_ret");
3746         }
3747       else
3748         {
3749           emitcode ("ret", "");
3750         }
3751     }
3752
3753   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3754     return;
3755
3756   /* If this was an interrupt handler using bank 0 that called another */
3757   /* function, then all registers must be saved; nothing to optimized. */
3758   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3759       && !FUNC_REGBANK(sym->type))
3760     return;
3761
3762   /* There are no push/pops to optimize if not callee-saves or ISR */
3763   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3764     return;
3765
3766   /* If there were stack parameters, we cannot optimize without also    */
3767   /* fixing all of the stack offsets; this is too dificult to consider. */
3768   if (FUNC_HASSTACKPARM(sym->type))
3769     return;
3770
3771   /* Compute the registers actually used */
3772   regsUsed = newBitVect (mcs51_nRegs);
3773   regsUsedPrologue = newBitVect (mcs51_nRegs);
3774   while (lnp)
3775     {
3776       if (lnp->ic && lnp->ic->op == FUNCTION)
3777         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3778       else
3779         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3780
3781       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3782           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3783         break;
3784       if (!lnp->prev)
3785         break;
3786       lnp = lnp->prev;
3787     }
3788
3789   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3790       && !bitVectBitValue (regsUsed, CND_IDX))
3791     {
3792       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3793       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3794           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3795         bitVectUnSetBit (regsUsed, CND_IDX);
3796     }
3797   else
3798     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3799
3800   /* If this was an interrupt handler that called another function */
3801   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3802   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3803     {
3804       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3805       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3806       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3807       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3808       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3809     }
3810
3811   /* Remove the unneeded push/pops */
3812   regsUnneeded = newBitVect (mcs51_nRegs);
3813   while (lnp)
3814     {
3815       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3816         {
3817           if (!strncmp(lnp->line, "push", 4))
3818             {
3819               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3820               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3821                 {
3822                   connectLine (lnp->prev, lnp->next);
3823                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3824                 }
3825             }
3826           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3827             {
3828               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3829               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3830                 {
3831                   connectLine (lnp->prev, lnp->next);
3832                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3833                 }
3834             }
3835         }
3836       lnp = lnp->next;
3837     }
3838
3839   for (idx = 0; idx < regsUnneeded->size; idx++)
3840     if (bitVectBitValue (regsUnneeded, idx))
3841       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3842
3843   freeBitVect (regsUnneeded);
3844   freeBitVect (regsUsed);
3845   freeBitVect (regsUsedPrologue);
3846 }
3847
3848 /*-----------------------------------------------------------------*/
3849 /* genRet - generate code for return statement                     */
3850 /*-----------------------------------------------------------------*/
3851 static void
3852 genRet (iCode * ic)
3853 {
3854   int size, offset = 0, pushed = 0;
3855
3856   D(emitcode (";     genRet",""));
3857
3858   /* if we have no return value then
3859      just generate the "ret" */
3860   if (!IC_LEFT (ic))
3861     goto jumpret;
3862
3863   /* we have something to return then
3864      move the return value into place */
3865   aopOp (IC_LEFT (ic), ic, FALSE);
3866   size = AOP_SIZE (IC_LEFT (ic));
3867
3868
3869   if (IS_BIT(_G.currentFunc->etype))
3870     {
3871       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3872       size = 0;
3873     }
3874
3875   while (size--)
3876     {
3877       char *l;
3878       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3879         {
3880           /* #NOCHANGE */
3881           l = aopGet (IC_LEFT (ic), offset++,
3882                       FALSE, TRUE);
3883           emitcode ("push", "%s", l);
3884           pushed++;
3885         }
3886       else
3887         {
3888           l = aopGet (IC_LEFT (ic), offset,
3889                       FALSE, FALSE);
3890           if (strcmp (fReturn[offset], l))
3891             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3892         }
3893     }
3894
3895   while (pushed)
3896     {
3897       pushed--;
3898       if (strcmp (fReturn[pushed], "a"))
3899         emitcode ("pop", fReturn[pushed]);
3900       else
3901         emitcode ("pop", "acc");
3902     }
3903   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3904
3905 jumpret:
3906   /* generate a jump to the return label
3907      if the next is not the return statement */
3908   if (!(ic->next && ic->next->op == LABEL &&
3909         IC_LABEL (ic->next) == returnLabel))
3910
3911     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3912
3913 }
3914
3915 /*-----------------------------------------------------------------*/
3916 /* genLabel - generates a label                                    */
3917 /*-----------------------------------------------------------------*/
3918 static void
3919 genLabel (iCode * ic)
3920 {
3921   /* special case never generate */
3922   if (IC_LABEL (ic) == entryLabel)
3923     return;
3924
3925   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3926 }
3927
3928 /*-----------------------------------------------------------------*/
3929 /* genGoto - generates a ljmp                                      */
3930 /*-----------------------------------------------------------------*/
3931 static void
3932 genGoto (iCode * ic)
3933 {
3934   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3935 }
3936
3937 /*-----------------------------------------------------------------*/
3938 /* findLabelBackwards: walks back through the iCode chain looking  */
3939 /* for the given label. Returns number of iCode instructions     */
3940 /* between that label and given ic.          */
3941 /* Returns zero if label not found.          */
3942 /*-----------------------------------------------------------------*/
3943 static int
3944 findLabelBackwards (iCode * ic, int key)
3945 {
3946   int count = 0;
3947
3948   while (ic->prev)
3949     {
3950       ic = ic->prev;
3951       count++;
3952
3953       /* If we have any pushes or pops, we cannot predict the distance.
3954          I don't like this at all, this should be dealt with in the
3955          back-end */
3956       if (ic->op == IPUSH || ic->op == IPOP) {
3957         return 0;
3958       }
3959
3960       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3961         {
3962           return count;
3963         }
3964     }
3965
3966   return 0;
3967 }
3968
3969 /*-----------------------------------------------------------------*/
3970 /* genPlusIncr :- does addition with increment if possible         */
3971 /*-----------------------------------------------------------------*/
3972 static bool
3973 genPlusIncr (iCode * ic)
3974 {
3975   unsigned int icount;
3976   unsigned int size = getDataSize (IC_RESULT (ic));
3977
3978   /* will try to generate an increment */
3979   /* if the right side is not a literal
3980      we cannot */
3981   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3982     return FALSE;
3983
3984   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3985
3986   D(emitcode (";     genPlusIncr",""));
3987
3988   /* if increment >=16 bits in register or direct space */
3989   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3990       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3991       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3992       (size > 1) &&
3993       (icount == 1))
3994     {
3995       symbol *tlbl;
3996       int emitTlbl;
3997       int labelRange;
3998
3999       /* If the next instruction is a goto and the goto target
4000        * is < 10 instructions previous to this, we can generate
4001        * jumps straight to that target.
4002        */
4003       if (ic->next && ic->next->op == GOTO
4004           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4005           && labelRange <= 10)
4006         {
4007           emitcode (";", "tail increment optimized");
4008           tlbl = IC_LABEL (ic->next);
4009           emitTlbl = 0;
4010         }
4011       else
4012         {
4013           tlbl = newiTempLabel (NULL);
4014           emitTlbl = 1;
4015         }
4016       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4017       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4018           IS_AOP_PREG (IC_RESULT (ic)))
4019         emitcode ("cjne", "%s,#0x00,%05d$",
4020                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4021                   tlbl->key + 100);
4022       else
4023         {
4024           emitcode ("clr", "a");
4025           emitcode ("cjne", "a,%s,%05d$",
4026                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4027                     tlbl->key + 100);
4028         }
4029
4030       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4031       if (size > 2)
4032         {
4033           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4034               IS_AOP_PREG (IC_RESULT (ic)))
4035             emitcode ("cjne", "%s,#0x00,%05d$",
4036                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4037                       tlbl->key + 100);
4038           else
4039             emitcode ("cjne", "a,%s,%05d$",
4040                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4041                       tlbl->key + 100);
4042
4043           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4044         }
4045       if (size > 3)
4046         {
4047           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4048               IS_AOP_PREG (IC_RESULT (ic)))
4049             emitcode ("cjne", "%s,#0x00,%05d$",
4050                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4051                       tlbl->key + 100);
4052           else
4053             {
4054               emitcode ("cjne", "a,%s,%05d$",
4055                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4056                         tlbl->key + 100);
4057             }
4058           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4059         }
4060
4061       if (emitTlbl)
4062         {
4063           emitcode ("", "%05d$:", tlbl->key + 100);
4064         }
4065       return TRUE;
4066     }
4067
4068   /* if result is dptr */
4069   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4070       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4071       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4072       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4073     {
4074       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4075         return FALSE;
4076
4077       if (icount > 9)
4078         return FALSE;
4079
4080       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4081         return FALSE;
4082
4083       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4084       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4085       while (icount--)
4086         emitcode ("inc", "dptr");
4087
4088       return TRUE;
4089     }
4090
4091   /* if the literal value of the right hand side
4092      is greater than 4 then it is not worth it */
4093   if (icount > 4)
4094     return FALSE;
4095
4096   /* if the sizes are greater than 1 then we cannot */
4097   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4098       AOP_SIZE (IC_LEFT (ic)) > 1)
4099     return FALSE;
4100
4101   /* we can if the aops of the left & result match or
4102      if they are in registers and the registers are the
4103      same */
4104   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4105     {
4106
4107       if (icount > 3)
4108         {
4109           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4110           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4111           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4112         }
4113       else
4114         {
4115
4116           while (icount--)
4117             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4118         }
4119
4120       return TRUE;
4121     }
4122
4123   return FALSE;
4124 }
4125
4126 /*-----------------------------------------------------------------*/
4127 /* outBitAcc - output a bit in acc                                 */
4128 /*-----------------------------------------------------------------*/
4129 static void
4130 outBitAcc (operand * result)
4131 {
4132   symbol *tlbl = newiTempLabel (NULL);
4133   /* if the result is a bit */
4134   if (AOP_TYPE (result) == AOP_CRY)
4135     {
4136       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4137     }
4138   else
4139     {
4140       emitcode ("jz", "%05d$", tlbl->key + 100);
4141       emitcode ("mov", "a,%s", one);
4142       emitcode ("", "%05d$:", tlbl->key + 100);
4143       outAcc (result);
4144     }
4145 }
4146
4147 /*-----------------------------------------------------------------*/
4148 /* genPlusBits - generates code for addition of two bits           */
4149 /*-----------------------------------------------------------------*/
4150 static void
4151 genPlusBits (iCode * ic)
4152 {
4153   D(emitcode (";     genPlusBits",""));
4154
4155   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4156     {
4157       symbol *lbl = newiTempLabel (NULL);
4158       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4159       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4160       emitcode ("cpl", "c");
4161       emitcode ("", "%05d$:", (lbl->key + 100));
4162       outBitC (IC_RESULT (ic));
4163     }
4164   else
4165     {
4166       emitcode ("clr", "a");
4167       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4168       emitcode ("rlc", "a");
4169       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4170       emitcode ("addc", "a,#0x00");
4171       outAcc (IC_RESULT (ic));
4172     }
4173 }
4174
4175 #if 0
4176 /* This is the original version of this code.
4177
4178  * This is being kept around for reference,
4179  * because I am not entirely sure I got it right...
4180  */
4181 static void
4182 adjustArithmeticResult (iCode * ic)
4183 {
4184   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4185       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4186       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4187     aopPut (IC_RESULT (ic),
4188             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4189             2,
4190             isOperandVolatile (IC_RESULT (ic), FALSE));
4191
4192   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4193       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4194       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4195     aopPut (IC_RESULT (ic),
4196             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4197             2,
4198             isOperandVolatile (IC_RESULT (ic), FALSE));
4199
4200   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4201       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4202       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4203       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4204       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4205     {
4206       char buffer[5];
4207       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4208       aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4209     }
4210 }
4211 #else
4212 /* This is the pure and virtuous version of this code.
4213  * I'm pretty certain it's right, but not enough to toss the old
4214  * code just yet...
4215  */
4216 static void
4217 adjustArithmeticResult (iCode * ic)
4218 {
4219   if (opIsGptr (IC_RESULT (ic)) &&
4220       opIsGptr (IC_LEFT (ic)) &&
4221       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4222     {
4223       aopPut (IC_RESULT (ic),
4224               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4225               GPTRSIZE - 1,
4226               isOperandVolatile (IC_RESULT (ic), FALSE));
4227     }
4228
4229   if (opIsGptr (IC_RESULT (ic)) &&
4230       opIsGptr (IC_RIGHT (ic)) &&
4231       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4232     {
4233       aopPut (IC_RESULT (ic),
4234               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4235               GPTRSIZE - 1,
4236               isOperandVolatile (IC_RESULT (ic), FALSE));
4237     }
4238
4239   if (opIsGptr (IC_RESULT (ic)) &&
4240       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4241       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4242       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4243       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4244     {
4245       char buffer[5];
4246       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4247       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4248     }
4249 }
4250 #endif
4251
4252 /*-----------------------------------------------------------------*/
4253 /* genPlus - generates code for addition                           */
4254 /*-----------------------------------------------------------------*/
4255 static void
4256 genPlus (iCode * ic)
4257 {
4258   int size, offset = 0;
4259   int skip_bytes = 0;
4260   char *add = "add";
4261   bool swappedLR = FALSE;
4262   operand *leftOp, *rightOp;
4263   operand * op;
4264
4265   /* special cases :- */
4266
4267   D(emitcode (";     genPlus",""));
4268
4269   aopOp (IC_LEFT (ic), ic, FALSE);
4270   aopOp (IC_RIGHT (ic), ic, FALSE);
4271   aopOp (IC_RESULT (ic), ic, TRUE);
4272
4273   /* if literal, literal on the right or
4274      if left requires ACC or right is already
4275      in ACC */
4276   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4277       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4278       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4279     {
4280       operand *t = IC_RIGHT (ic);
4281       IC_RIGHT (ic) = IC_LEFT (ic);
4282       IC_LEFT (ic) = t;
4283           swappedLR = TRUE;
4284     }
4285
4286   /* if both left & right are in bit
4287      space */
4288   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4289       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4290     {
4291       genPlusBits (ic);
4292       goto release;
4293     }
4294
4295   /* if left in bit space & right literal */
4296   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4297       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4298     {
4299       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4300       /* if result in bit space */
4301       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4302         {
4303           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4304             emitcode ("cpl", "c");
4305           outBitC (IC_RESULT (ic));
4306         }
4307       else
4308         {
4309           size = getDataSize (IC_RESULT (ic));
4310           while (size--)
4311             {
4312               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4313               emitcode ("addc", "a,#00");
4314               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4315             }
4316         }
4317       goto release;
4318     }
4319
4320   /* if I can do an increment instead
4321      of add then GOOD for ME */
4322   if (genPlusIncr (ic) == TRUE)
4323     goto release;
4324
4325   size = getDataSize (IC_RESULT (ic));
4326   leftOp = IC_LEFT(ic);
4327   rightOp = IC_RIGHT(ic);
4328   op = IC_LEFT(ic);
4329
4330   /* if this is an add for an array access
4331      at a 256 byte boundary */
4332   if ( 2 == size
4333        && AOP_TYPE (op) == AOP_IMMD
4334        && IS_SYMOP (op)
4335        && IS_SPEC (OP_SYM_ETYPE (op))
4336        && SPEC_ABSA (OP_SYM_ETYPE (op))
4337        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4338      )
4339     {
4340       D(emitcode (";     genPlus aligned array",""));
4341       aopPut (IC_RESULT (ic),
4342               aopGet (rightOp, 0, FALSE, FALSE),
4343               0,
4344               isOperandVolatile (IC_RESULT (ic), FALSE));
4345
4346       if( 1 == getDataSize (IC_RIGHT (ic)) )
4347         {
4348           aopPut (IC_RESULT (ic),
4349                   aopGet (leftOp, 1, FALSE, FALSE),
4350                   1,
4351                   isOperandVolatile (IC_RESULT (ic), FALSE));
4352         }
4353       else
4354         {
4355           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4356           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4357           aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4358         }
4359       goto release;
4360     }
4361
4362   /* if the lower bytes of a literal are zero skip the addition */
4363   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4364     {
4365        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4366               (skip_bytes+1 < size))
4367          {
4368            skip_bytes++;
4369          }
4370        if (skip_bytes)
4371          D(emitcode (";     genPlus shortcut",""));
4372     }
4373
4374   while (size--)
4375     {
4376       if( offset >= skip_bytes )
4377         {
4378           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4379             {
4380               bool pushedB;
4381               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4382               pushedB = pushB ();
4383               emitcode("xch", "a,b");
4384               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4385               emitcode (add, "a,b");
4386               popB (pushedB);
4387             }
4388           else if (aopGetUsesAcc (leftOp, offset))
4389             {
4390               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4391               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4392             }
4393           else
4394             {
4395               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4396               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4397             }
4398           aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4399           add = "addc";  /* further adds must propagate carry */
4400         }
4401       else
4402         {
4403           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4404               isOperandVolatile (IC_RESULT (ic), FALSE))
4405             {
4406               /* just move */
4407               aopPut (IC_RESULT (ic),
4408                       aopGet (leftOp, offset, FALSE, FALSE),
4409                       offset,
4410                       isOperandVolatile (IC_RESULT (ic), FALSE));
4411             }
4412         }
4413       offset++;
4414     }
4415
4416   adjustArithmeticResult (ic);
4417
4418 release:
4419   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4420   if (!swappedLR)
4421     {
4422       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4423       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4424     }
4425   else
4426     {
4427       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4429     }
4430 }
4431
4432 /*-----------------------------------------------------------------*/
4433 /* genMinusDec :- does subtraction with decrement if possible      */
4434 /*-----------------------------------------------------------------*/
4435 static bool
4436 genMinusDec (iCode * ic)
4437 {
4438   unsigned int icount;
4439   unsigned int size = getDataSize (IC_RESULT (ic));
4440
4441   /* will try to generate an increment */
4442   /* if the right side is not a literal
4443      we cannot */
4444   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4445     return FALSE;
4446
4447   /* if the literal value of the right hand side
4448      is greater than 4 then it is not worth it */
4449   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4450     return FALSE;
4451
4452   D(emitcode (";     genMinusDec",""));
4453
4454   /* if decrement >=16 bits in register or direct space */
4455   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4456       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4457       (size > 1) &&
4458       (icount == 1))
4459     {
4460       symbol *tlbl;
4461       int emitTlbl;
4462       int labelRange;
4463
4464       /* If the next instruction is a goto and the goto target
4465        * is <= 10 instructions previous to this, we can generate
4466        * jumps straight to that target.
4467        */
4468       if (ic->next && ic->next->op == GOTO
4469           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4470           && labelRange <= 10)
4471         {
4472           emitcode (";", "tail decrement optimized");
4473           tlbl = IC_LABEL (ic->next);
4474           emitTlbl = 0;
4475         }
4476       else
4477         {
4478           tlbl = newiTempLabel (NULL);
4479           emitTlbl = 1;
4480         }
4481
4482       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4483       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4484           IS_AOP_PREG (IC_RESULT (ic)))
4485         emitcode ("cjne", "%s,#0xff,%05d$"
4486                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4487                   ,tlbl->key + 100);
4488       else
4489         {
4490           emitcode ("mov", "a,#0xff");
4491           emitcode ("cjne", "a,%s,%05d$"
4492                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4493                     ,tlbl->key + 100);
4494         }
4495       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4496       if (size > 2)
4497         {
4498           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4499               IS_AOP_PREG (IC_RESULT (ic)))
4500             emitcode ("cjne", "%s,#0xff,%05d$"
4501                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4502                       ,tlbl->key + 100);
4503           else
4504             {
4505               emitcode ("cjne", "a,%s,%05d$"
4506                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4507                         ,tlbl->key + 100);
4508             }
4509           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4510         }
4511       if (size > 3)
4512         {
4513           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4514               IS_AOP_PREG (IC_RESULT (ic)))
4515             emitcode ("cjne", "%s,#0xff,%05d$"
4516                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4517                       ,tlbl->key + 100);
4518           else
4519             {
4520               emitcode ("cjne", "a,%s,%05d$"
4521                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4522                         ,tlbl->key + 100);
4523             }
4524           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4525         }
4526       if (emitTlbl)
4527         {
4528           emitcode ("", "%05d$:", tlbl->key + 100);
4529         }
4530       return TRUE;
4531     }
4532
4533   /* if the sizes are greater than 1 then we cannot */
4534   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4535       AOP_SIZE (IC_LEFT (ic)) > 1)
4536     return FALSE;
4537
4538   /* we can if the aops of the left & result match or
4539      if they are in registers and the registers are the
4540      same */
4541   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4542     {
4543       char *l;
4544
4545       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4546         {
4547           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4548           l = "a";
4549         }
4550       else
4551         {
4552           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4553         }
4554
4555       while (icount--)
4556         emitcode ("dec", "%s", l);
4557
4558       if (AOP_NEEDSACC (IC_RESULT (ic)))
4559         aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4560
4561       return TRUE;
4562     }
4563
4564   return FALSE;
4565 }
4566
4567 /*-----------------------------------------------------------------*/
4568 /* addSign - complete with sign                                    */
4569 /*-----------------------------------------------------------------*/
4570 static void
4571 addSign (operand * result, int offset, int sign)
4572 {
4573   int size = (getDataSize (result) - offset);
4574   if (size > 0)
4575     {
4576       if (sign)
4577         {
4578           emitcode ("rlc", "a");
4579           emitcode ("subb", "a,acc");
4580           while (size--)
4581             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4582         }
4583       else
4584         while (size--)
4585           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4586     }
4587 }
4588
4589 /*-----------------------------------------------------------------*/
4590 /* genMinusBits - generates code for subtraction  of two bits      */
4591 /*-----------------------------------------------------------------*/
4592 static void
4593 genMinusBits (iCode * ic)
4594 {
4595   symbol *lbl = newiTempLabel (NULL);
4596
4597   D(emitcode (";     genMinusBits",""));
4598
4599   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4600     {
4601       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4602       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4603       emitcode ("cpl", "c");
4604       emitcode ("", "%05d$:", (lbl->key + 100));
4605       outBitC (IC_RESULT (ic));
4606     }
4607   else
4608     {
4609       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4610       emitcode ("subb", "a,acc");
4611       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4612       emitcode ("inc", "a");
4613       emitcode ("", "%05d$:", (lbl->key + 100));
4614       aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4615       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4616     }
4617 }
4618
4619 /*-----------------------------------------------------------------*/
4620 /* genMinus - generates code for subtraction                       */
4621 /*-----------------------------------------------------------------*/
4622 static void
4623 genMinus (iCode * ic)
4624 {
4625   int size, offset = 0;
4626
4627   D(emitcode (";     genMinus",""));
4628
4629   aopOp (IC_LEFT (ic), ic, FALSE);
4630   aopOp (IC_RIGHT (ic), ic, FALSE);
4631   aopOp (IC_RESULT (ic), ic, TRUE);
4632
4633   /* special cases :- */
4634   /* if both left & right are in bit space */
4635   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4636       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4637     {
4638       genMinusBits (ic);
4639       goto release;
4640     }
4641
4642   /* if I can do an decrement instead
4643      of subtract then GOOD for ME */
4644   if (genMinusDec (ic) == TRUE)
4645     goto release;
4646
4647   size = getDataSize (IC_RESULT (ic));
4648
4649   /* if literal, add a,#-lit, else normal subb */
4650   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4651     {
4652       unsigned long lit = 0L;
4653       bool useCarry = FALSE;
4654
4655       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4656       lit = -(long) lit;
4657
4658       while (size--)
4659         {
4660           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4661             {
4662             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4663               if (!offset && !size && lit== (unsigned long) -1)
4664                 {
4665                   emitcode ("dec", "a");
4666                 }
4667               else if (!useCarry)
4668                 {
4669                   /* first add without previous c */
4670                   emitcode ("add", "a,#0x%02x",
4671                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4672                   useCarry = TRUE;
4673                 }
4674               else
4675                 {
4676                   emitcode ("addc", "a,#0x%02x",
4677                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4678                 }
4679               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4680             }
4681           else
4682             {
4683               /* no need to add zeroes */
4684               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4685                 {
4686                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4687                           offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4688                 }
4689               offset++;
4690             }
4691         }
4692     }
4693   else
4694     {
4695       operand *leftOp, *rightOp;
4696
4697       leftOp = IC_LEFT(ic);
4698       rightOp = IC_RIGHT(ic);
4699
4700       while (size--)
4701         {
4702           if (aopGetUsesAcc(rightOp, offset)) {
4703             if (aopGetUsesAcc(leftOp, offset)) {
4704               bool pushedB;
4705
4706               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4707               pushedB = pushB ();
4708               emitcode ("mov", "b,a");
4709               if (offset == 0)
4710                 CLRC;
4711               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4712               emitcode ("subb", "a,b");
4713               popB (pushedB);
4714             } else {
4715               /* reverse subtraction with 2's complement */
4716               if (offset == 0)
4717                 emitcode( "setb", "c");
4718                else
4719                 emitcode( "cpl", "c");
4720               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4721               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4722               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4723               emitcode("cpl", "a");
4724               if (size) /* skip if last byte */
4725                 emitcode( "cpl", "c");
4726             }
4727           } else {
4728             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4729             if (offset == 0)
4730               CLRC;
4731             emitcode ("subb", "a,%s",
4732                       aopGet(rightOp, offset, FALSE, TRUE));
4733           }
4734
4735           aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4736         }
4737     }
4738
4739
4740   adjustArithmeticResult (ic);
4741
4742 release:
4743   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4744   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4745   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4746 }
4747
4748
4749 /*-----------------------------------------------------------------*/
4750 /* genMultbits :- multiplication of bits                           */
4751 /*-----------------------------------------------------------------*/
4752 static void
4753 genMultbits (operand * left,
4754              operand * right,
4755              operand * result)
4756 {
4757   D(emitcode (";     genMultbits",""));
4758
4759   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4760   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4761   outBitC (result);
4762 }
4763
4764 /*-----------------------------------------------------------------*/
4765 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4766 /*-----------------------------------------------------------------*/
4767 static void
4768 genMultOneByte (operand * left,
4769                 operand * right,
4770                 operand * result)
4771 {
4772   symbol *lbl;
4773   int size = AOP_SIZE (result);
4774   bool runtimeSign, compiletimeSign;
4775   bool lUnsigned, rUnsigned, pushedB;
4776
4777   D(emitcode (";     genMultOneByte",""));
4778
4779   if (size < 1 || size > 2)
4780     {
4781       /* this should never happen */
4782       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4783                AOP_SIZE(result), __FILE__, lineno);
4784       exit (1);
4785     }
4786
4787   /* (if two literals: the value is computed before) */
4788   /* if one literal, literal on the right */
4789   if (AOP_TYPE (left) == AOP_LIT)
4790     {
4791       operand *t = right;
4792       right = left;
4793       left = t;
4794       /* emitcode (";", "swapped left and right"); */
4795     }
4796   /* if no literal, unsigned on the right: shorter code */
4797   if (   AOP_TYPE (right) != AOP_LIT
4798       && SPEC_USIGN (getSpec (operandType (left))))
4799     {
4800       operand *t = right;
4801       right = left;
4802       left = t;
4803     }
4804
4805   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4806   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4807
4808   pushedB = pushB ();
4809
4810   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4811                    no need to take care about the signedness! */
4812       || (lUnsigned && rUnsigned))
4813     {
4814       /* just an unsigned 8 * 8 = 8 multiply
4815          or 8u * 8u = 16u */
4816       /* emitcode (";","unsigned"); */
4817       /* TODO: check for accumulator clash between left & right aops? */
4818
4819       if (AOP_TYPE (right) == AOP_LIT)
4820         {
4821           /* moving to accumulator first helps peepholes */
4822           MOVA (aopGet (left, 0, FALSE, FALSE));
4823           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4824         }
4825       else
4826         {
4827           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4828           MOVA (aopGet (left, 0, FALSE, FALSE));
4829         }
4830
4831       emitcode ("mul", "ab");
4832       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4833       if (size == 2)
4834         aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4835
4836       popB (pushedB);
4837       return;
4838     }
4839
4840   /* we have to do a signed multiply */
4841   /* emitcode (";", "signed"); */
4842
4843   /* now sign adjust for both left & right */
4844
4845   /* let's see what's needed: */
4846   /* apply negative sign during runtime */
4847   runtimeSign = FALSE;
4848   /* negative sign from literals */
4849   compiletimeSign = FALSE;
4850
4851   if (!lUnsigned)
4852     {
4853       if (AOP_TYPE(left) == AOP_LIT)
4854         {
4855           /* signed literal */
4856           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4857           if (val < 0)
4858             compiletimeSign = TRUE;
4859         }
4860       else
4861         /* signed but not literal */
4862         runtimeSign = TRUE;
4863     }
4864
4865   if (!rUnsigned)
4866     {
4867       if (AOP_TYPE(right) == AOP_LIT)
4868         {
4869           /* signed literal */
4870           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4871           if (val < 0)
4872             compiletimeSign ^= TRUE;
4873         }
4874       else
4875         /* signed but not literal */
4876         runtimeSign = TRUE;
4877     }
4878
4879   /* initialize F0, which stores the runtime sign */
4880   if (runtimeSign)
4881     {
4882       if (compiletimeSign)
4883         emitcode ("setb", "F0"); /* set sign flag */
4884       else
4885         emitcode ("clr", "F0"); /* reset sign flag */
4886     }
4887
4888   /* save the signs of the operands */
4889   if (AOP_TYPE(right) == AOP_LIT)
4890     {
4891       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4892
4893       if (!rUnsigned && val < 0)
4894         emitcode ("mov", "b,#0x%02x", -val);
4895       else
4896         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4897     }
4898   else /* ! literal */
4899     {
4900       if (rUnsigned)  /* emitcode (";", "signed"); */
4901
4902         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4903       else
4904         {
4905           MOVA (aopGet (right, 0, FALSE, FALSE));
4906           lbl = newiTempLabel (NULL);
4907           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4908           emitcode ("cpl", "F0"); /* complement sign flag */
4909           emitcode ("cpl", "a");  /* 2's complement */
4910           emitcode ("inc", "a");
4911           emitcode ("", "%05d$:", (lbl->key + 100));
4912           emitcode ("mov", "b,a");
4913         }
4914     }
4915
4916   if (AOP_TYPE(left) == AOP_LIT)
4917     {
4918       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4919
4920       if (!lUnsigned && val < 0)
4921         emitcode ("mov", "a,#0x%02x", -val);
4922       else
4923         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4924     }
4925   else /* ! literal */
4926     {
4927       MOVA (aopGet (left, 0, FALSE, FALSE));
4928
4929       if (!lUnsigned)
4930         {
4931           lbl = newiTempLabel (NULL);
4932           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4933           emitcode ("cpl", "F0"); /* complement sign flag */
4934           emitcode ("cpl", "a"); /* 2's complement */
4935           emitcode ("inc", "a");
4936           emitcode ("", "%05d$:", (lbl->key + 100));
4937         }
4938     }
4939
4940   /* now the multiplication */
4941   emitcode ("mul", "ab");
4942   if (runtimeSign || compiletimeSign)
4943     {
4944       lbl = newiTempLabel (NULL);
4945       if (runtimeSign)
4946         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4947       emitcode ("cpl", "a"); /* lsb 2's complement */
4948       if (size != 2)
4949         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4950       else
4951         {
4952           emitcode ("add", "a,#1"); /* this sets carry flag */
4953           emitcode ("xch", "a,b");
4954           emitcode ("cpl", "a"); /* msb 2's complement */
4955           emitcode ("addc", "a,#0");
4956           emitcode ("xch", "a,b");
4957         }
4958       emitcode ("", "%05d$:", (lbl->key + 100));
4959     }
4960   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4961   if (size == 2)
4962     aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4963
4964   popB (pushedB);
4965 }
4966
4967 /*-----------------------------------------------------------------*/
4968 /* genMult - generates code for multiplication                     */
4969 /*-----------------------------------------------------------------*/
4970 static void
4971 genMult (iCode * ic)
4972 {
4973   operand *left = IC_LEFT (ic);
4974   operand *right = IC_RIGHT (ic);
4975   operand *result = IC_RESULT (ic);
4976
4977   D(emitcode (";     genMult",""));
4978
4979   /* assign the asmops */
4980   aopOp (left, ic, FALSE);
4981   aopOp (right, ic, FALSE);
4982   aopOp (result, ic, TRUE);
4983
4984   /* special cases first */
4985   /* both are bits */
4986   if (AOP_TYPE (left) == AOP_CRY &&
4987       AOP_TYPE (right) == AOP_CRY)
4988     {
4989       genMultbits (left, right, result);
4990       goto release;
4991     }
4992
4993   /* if both are of size == 1 */
4994 #if 0 // one of them can be a sloc shared with the result
4995     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4996 #else
4997   if (getSize(operandType(left)) == 1 &&
4998       getSize(operandType(right)) == 1)
4999 #endif
5000     {
5001       genMultOneByte (left, right, result);
5002       goto release;
5003     }
5004
5005   /* should have been converted to function call */
5006     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5007              getSize(OP_SYMBOL(right)->type));
5008   assert (0);
5009
5010 release:
5011   freeAsmop (result, NULL, ic, TRUE);
5012   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5013   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5014 }
5015
5016 /*-----------------------------------------------------------------*/
5017 /* genDivbits :- division of bits                                  */
5018 /*-----------------------------------------------------------------*/
5019 static void
5020 genDivbits (operand * left,
5021             operand * right,
5022             operand * result)
5023 {
5024   char *l;
5025   bool pushedB;
5026
5027   D(emitcode (";     genDivbits",""));
5028
5029   pushedB = pushB ();
5030
5031   /* the result must be bit */
5032   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5033   l = aopGet (left, 0, FALSE, FALSE);
5034
5035   MOVA (l);
5036
5037   emitcode ("div", "ab");
5038   emitcode ("rrc", "a");
5039
5040   popB (pushedB);
5041
5042   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5043 }
5044
5045 /*-----------------------------------------------------------------*/
5046 /* genDivOneByte : 8 bit division                                  */
5047 /*-----------------------------------------------------------------*/
5048 static void
5049 genDivOneByte (operand * left,
5050                operand * right,
5051                operand * result)
5052 {
5053   bool lUnsigned, rUnsigned, pushedB;
5054   bool runtimeSign, compiletimeSign;
5055   bool accuse = FALSE;
5056   bool pushedA = FALSE;
5057   symbol *lbl;
5058   int size, offset;
5059
5060   D(emitcode (";     genDivOneByte",""));
5061
5062   /* Why is it necessary that genDivOneByte() can return an int result?
5063      Have a look at:
5064
5065         volatile unsigned char uc;
5066         volatile signed char sc1, sc2;
5067         volatile int i;
5068
5069         uc  = 255;
5070         sc1 = -1;
5071         i = uc / sc1;
5072
5073      Or:
5074
5075         sc1 = -128;
5076         sc2 = -1;
5077         i = sc1 / sc2;
5078
5079      In all cases a one byte result would overflow, the following cast to int
5080      would return the wrong result.
5081
5082      Two possible solution:
5083         a) cast operands to int, if ((unsigned) / (signed)) or
5084            ((signed) / (signed))
5085         b) return an 16 bit signed int; this is what we're doing here!
5086   */
5087
5088   size = AOP_SIZE (result) - 1;
5089   offset = 1;
5090   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5091   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5092
5093   pushedB = pushB ();
5094
5095   /* signed or unsigned */
5096   if (lUnsigned && rUnsigned)
5097     {
5098       /* unsigned is easy */
5099       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5100       MOVA (aopGet (left, 0, FALSE, FALSE));
5101       emitcode ("div", "ab");
5102       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5103       while (size--)
5104         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5105
5106       popB (pushedB);
5107       return;
5108     }
5109
5110   /* signed is a little bit more difficult */
5111
5112   /* now sign adjust for both left & right */
5113
5114   /* let's see what's needed: */
5115   /* apply negative sign during runtime */
5116   runtimeSign = FALSE;
5117   /* negative sign from literals */
5118   compiletimeSign = FALSE;
5119
5120   if (!lUnsigned)
5121     {
5122       if (AOP_TYPE(left) == AOP_LIT)
5123         {
5124           /* signed literal */
5125           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5126           if (val < 0)
5127             compiletimeSign = TRUE;
5128         }
5129       else
5130         /* signed but not literal */
5131         runtimeSign = TRUE;
5132     }
5133
5134   if (!rUnsigned)
5135     {
5136       if (AOP_TYPE(right) == AOP_LIT)
5137         {
5138           /* signed literal */
5139           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5140           if (val < 0)
5141             compiletimeSign ^= TRUE;
5142         }
5143       else
5144         /* signed but not literal */
5145         runtimeSign = TRUE;
5146     }
5147
5148   /* initialize F0, which stores the runtime sign */
5149   if (runtimeSign)
5150     {
5151       if (compiletimeSign)
5152         emitcode ("setb", "F0"); /* set sign flag */
5153       else
5154         emitcode ("clr", "F0"); /* reset sign flag */
5155     }
5156
5157   /* save the signs of the operands */
5158   if (AOP_TYPE(right) == AOP_LIT)
5159     {
5160       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5161
5162       if (!rUnsigned && val < 0)
5163         emitcode ("mov", "b,#0x%02x", -val);
5164       else
5165         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5166     }
5167   else /* ! literal */
5168     {
5169       if (rUnsigned)
5170         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5171       else
5172         {
5173           MOVA (aopGet (right, 0, FALSE, FALSE));
5174           lbl = newiTempLabel (NULL);
5175           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5176           emitcode ("cpl", "F0"); /* complement sign flag */
5177           emitcode ("cpl", "a");  /* 2's complement */
5178           emitcode ("inc", "a");
5179           emitcode ("", "%05d$:", (lbl->key + 100));
5180           emitcode ("mov", "b,a");
5181         }
5182     }
5183
5184   if (AOP_TYPE(left) == AOP_LIT)
5185     {
5186       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5187
5188       if (!lUnsigned && val < 0)
5189         emitcode ("mov", "a,#0x%02x", -val);
5190       else
5191         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5192     }
5193   else /* ! literal */
5194     {
5195       MOVA (aopGet (left, 0, FALSE, FALSE));
5196
5197       if (!lUnsigned)
5198         {
5199           lbl = newiTempLabel (NULL);
5200           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5201           emitcode ("cpl", "F0"); /* complement sign flag */
5202           emitcode ("cpl", "a");  /* 2's complement */
5203           emitcode ("inc", "a");
5204           emitcode ("", "%05d$:", (lbl->key + 100));
5205         }
5206     }
5207
5208   /* now the division */
5209   emitcode ("div", "ab");
5210
5211   if (runtimeSign || compiletimeSign)
5212     {
5213       lbl = newiTempLabel (NULL);
5214       if (runtimeSign)
5215         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5216       emitcode ("cpl", "a"); /* lsb 2's complement */
5217       emitcode ("inc", "a");
5218       emitcode ("", "%05d$:", (lbl->key + 100));
5219
5220       accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5221       if (size > 0)
5222         {
5223           /* msb is 0x00 or 0xff depending on the sign */
5224           if (runtimeSign)
5225             {
5226               if (accuse)
5227                 {
5228                   emitcode ("push", "acc");
5229                   pushedA = TRUE;
5230                 }
5231               emitcode ("mov", "c,F0");
5232               emitcode ("subb", "a,acc");
5233               while (size--)
5234                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5235             }
5236           else /* compiletimeSign */
5237             {
5238               if (aopPutUsesAcc (result, "#0xFF", offset))
5239                 {
5240                   emitcode ("push", "acc");
5241                   pushedA = TRUE;
5242                 }
5243               while (size--)
5244                 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5245             }
5246         }
5247     }
5248   else
5249     {
5250       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5251       while (size--)
5252         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5253     }
5254
5255   if (pushedA)
5256     emitcode ("pop", "acc");
5257   popB (pushedB);
5258 }
5259
5260 /*-----------------------------------------------------------------*/
5261 /* genDiv - generates code for division                            */
5262 /*-----------------------------------------------------------------*/
5263 static void
5264 genDiv (iCode * ic)
5265 {
5266   operand *left = IC_LEFT (ic);
5267   operand *right = IC_RIGHT (ic);
5268   operand *result = IC_RESULT (ic);
5269
5270   D(emitcode (";     genDiv",""));
5271
5272   /* assign the amsops */
5273   aopOp (left, ic, FALSE);
5274   aopOp (right, ic, FALSE);
5275   aopOp (result, ic, TRUE);
5276
5277   /* special cases first */
5278   /* both are bits */
5279   if (AOP_TYPE (left) == AOP_CRY &&
5280       AOP_TYPE (right) == AOP_CRY)
5281     {
5282       genDivbits (left, right, result);
5283       goto release;
5284     }
5285
5286   /* if both are of size == 1 */
5287   if (AOP_SIZE (left) == 1 &&
5288       AOP_SIZE (right) == 1)
5289     {
5290       genDivOneByte (left, right, result);
5291       goto release;
5292     }
5293
5294   /* should have been converted to function call */
5295   assert (0);
5296 release:
5297   freeAsmop (result, NULL, ic, TRUE);
5298   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5299   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5300 }
5301
5302 /*-----------------------------------------------------------------*/
5303 /* genModbits :- modulus of bits                                   */
5304 /*-----------------------------------------------------------------*/
5305 static void
5306 genModbits (operand * left,
5307             operand * right,
5308             operand * result)
5309 {
5310   char *l;
5311   bool pushedB;
5312
5313   D(emitcode (";     genModbits",""));
5314
5315   pushedB = pushB ();
5316
5317   /* the result must be bit */
5318   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5319   l = aopGet (left, 0, FALSE, FALSE);
5320
5321   MOVA (l);
5322
5323   emitcode ("div", "ab");
5324   emitcode ("mov", "a,b");
5325   emitcode ("rrc", "a");
5326
5327   popB (pushedB);
5328
5329   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5330 }
5331
5332 /*-----------------------------------------------------------------*/
5333 /* genModOneByte : 8 bit modulus                                   */
5334 /*-----------------------------------------------------------------*/
5335 static void
5336 genModOneByte (operand * left,
5337                operand * right,
5338                operand * result)
5339 {
5340   bool lUnsigned, rUnsigned, pushedB;
5341   bool runtimeSign, compiletimeSign;
5342   symbol *lbl;
5343   int size, offset;
5344
5345   D(emitcode (";     genModOneByte",""));
5346
5347   size = AOP_SIZE (result) - 1;
5348   offset = 1;
5349   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5350   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5351
5352   /* if right is a literal, check it for 2^n */
5353   if (AOP_TYPE(right) == AOP_LIT)
5354     {
5355       unsigned char val = abs((int) operandLitValue(right));
5356       symbol *lbl2 = NULL;
5357
5358       switch (val)
5359         {
5360           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5361           case 2:
5362           case 4:
5363           case 8:
5364           case 16:
5365           case 32:
5366           case 64:
5367           case 128:
5368             if (lUnsigned)
5369               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5370                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5371               /* because iCode should have been changed to genAnd  */
5372               /* see file "SDCCopt.c", function "convertToFcall()" */
5373
5374             MOVA (aopGet (left, 0, FALSE, FALSE));
5375             emitcode ("mov", "c,acc.7");
5376             emitcode ("anl", "a,#0x%02x", val - 1);
5377             lbl = newiTempLabel (NULL);
5378             emitcode ("jz", "%05d$", (lbl->key + 100));
5379             emitcode ("jnc", "%05d$", (lbl->key + 100));
5380             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5381             if (size)
5382               {
5383                 int size2 = size;
5384                 int offs2 = offset;
5385
5386                 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5387                 while (size2--)
5388                   aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5389                 lbl2 = newiTempLabel (NULL);
5390                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5391               }
5392             emitcode ("", "%05d$:", (lbl->key + 100));
5393             aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5394             while (size--)
5395               aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5396             if (lbl2)
5397               {
5398                 emitcode ("", "%05d$:", (lbl2->key + 100));
5399               }
5400             return;
5401
5402           default:
5403             break;
5404         }
5405     }
5406
5407   pushedB = pushB ();
5408
5409   /* signed or unsigned */
5410   if (lUnsigned && rUnsigned)
5411     {
5412       /* unsigned is easy */
5413       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5414       MOVA (aopGet (left, 0, FALSE, FALSE));
5415       emitcode ("div", "ab");
5416       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5417       while (size--)
5418         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5419
5420       popB (pushedB);
5421       return;
5422     }
5423
5424   /* signed is a little bit more difficult */
5425
5426   /* now sign adjust for both left & right */
5427
5428   /* modulus: sign of the right operand has no influence on the result! */
5429   if (AOP_TYPE(right) == AOP_LIT)
5430     {
5431       signed char val = (char) operandLitValue(right);
5432
5433       if (!rUnsigned && val < 0)
5434         emitcode ("mov", "b,#0x%02x", -val);
5435       else
5436         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5437     }
5438   else /* not literal */
5439     {
5440       if (rUnsigned)
5441         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5442       else
5443         {
5444           MOVA (aopGet (right, 0, FALSE, FALSE));
5445           lbl = newiTempLabel (NULL);
5446           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5447           emitcode ("cpl", "a"); /* 2's complement */
5448           emitcode ("inc", "a");
5449           emitcode ("", "%05d$:", (lbl->key + 100));
5450           emitcode ("mov", "b,a");
5451         }
5452     }
5453
5454   /* let's see what's needed: */
5455   /* apply negative sign during runtime */
5456   runtimeSign = FALSE;
5457   /* negative sign from literals */
5458   compiletimeSign = FALSE;
5459
5460   /* sign adjust left side */
5461   if (AOP_TYPE(left) == AOP_LIT)
5462     {
5463       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5464
5465       if (!lUnsigned && val < 0)
5466         {
5467           compiletimeSign = TRUE; /* set sign flag */
5468           emitcode ("mov", "a,#0x%02x", -val);
5469         }
5470       else
5471         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5472     }
5473   else /* ! literal */
5474     {
5475       MOVA (aopGet (left, 0, FALSE, FALSE));
5476
5477       if (!lUnsigned)
5478         {
5479           runtimeSign = TRUE;
5480           emitcode ("clr", "F0"); /* clear sign flag */
5481
5482           lbl = newiTempLabel (NULL);
5483           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5484           emitcode ("setb", "F0"); /* set sign flag */
5485           emitcode ("cpl", "a");   /* 2's complement */
5486           emitcode ("inc", "a");
5487           emitcode ("", "%05d$:", (lbl->key + 100));
5488         }
5489     }
5490
5491   /* now the modulus */
5492   emitcode ("div", "ab");
5493
5494   if (runtimeSign || compiletimeSign)
5495     {
5496       emitcode ("mov", "a,b");
5497       lbl = newiTempLabel (NULL);
5498       if (runtimeSign)
5499         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5500       emitcode ("cpl", "a"); /* 2's complement */
5501       emitcode ("inc", "a");
5502       emitcode ("", "%05d$:", (lbl->key + 100));
5503
5504       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5505       if (size > 0)
5506         {
5507           /* msb is 0x00 or 0xff depending on the sign */
5508           if (runtimeSign)
5509             {
5510               emitcode ("mov", "c,F0");
5511               emitcode ("subb", "a,acc");
5512               while (size--)
5513                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5514             }
5515           else /* compiletimeSign */
5516             while (size--)
5517               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5518         }
5519     }
5520   else
5521     {
5522       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5523       while (size--)
5524         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5525     }
5526
5527   popB (pushedB);
5528 }
5529
5530 /*-----------------------------------------------------------------*/
5531 /* genMod - generates code for division                            */
5532 /*-----------------------------------------------------------------*/
5533 static void
5534 genMod (iCode * ic)
5535 {
5536   operand *left = IC_LEFT (ic);
5537   operand *right = IC_RIGHT (ic);
5538   operand *result = IC_RESULT (ic);
5539
5540   D(emitcode (";     genMod",""));
5541
5542   /* assign the asmops */
5543   aopOp (left, ic, FALSE);
5544   aopOp (right, ic, FALSE);
5545   aopOp (result, ic, TRUE);
5546
5547   /* special cases first */
5548   /* both are bits */
5549   if (AOP_TYPE (left) == AOP_CRY &&
5550       AOP_TYPE (right) == AOP_CRY)
5551     {
5552       genModbits (left, right, result);
5553       goto release;
5554     }
5555
5556   /* if both are of size == 1 */
5557   if (AOP_SIZE (left) == 1 &&
5558       AOP_SIZE (right) == 1)
5559     {
5560       genModOneByte (left, right, result);
5561       goto release;
5562     }
5563
5564   /* should have been converted to function call */
5565   assert (0);
5566
5567 release:
5568   freeAsmop (result, NULL, ic, TRUE);
5569   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5570   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5571 }
5572
5573 /*-----------------------------------------------------------------*/
5574 /* genIfxJump :- will create a jump depending on the ifx           */
5575 /*-----------------------------------------------------------------*/
5576 static void
5577 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5578 {
5579   symbol *jlbl;
5580   symbol *tlbl = newiTempLabel (NULL);
5581   char *inst;
5582
5583   D(emitcode (";     genIfxJump",""));
5584
5585   /* if true label then we jump if condition
5586      supplied is true */
5587   if (IC_TRUE (ic))
5588     {
5589       jlbl = IC_TRUE (ic);
5590       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5591                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5592     }
5593   else
5594     {
5595       /* false label is present */
5596       jlbl = IC_FALSE (ic);
5597       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5598                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5599     }
5600   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5601     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5602   else
5603     emitcode (inst, "%05d$", tlbl->key + 100);
5604   freeForBranchAsmop (result);
5605   freeForBranchAsmop (right);
5606   freeForBranchAsmop (left);
5607   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5608   emitcode ("", "%05d$:", tlbl->key + 100);
5609
5610   /* mark the icode as generated */
5611   ic->generated = 1;
5612 }
5613
5614 /*-----------------------------------------------------------------*/
5615 /* genCmp :- greater or less than comparison                       */
5616 /*-----------------------------------------------------------------*/
5617 static void
5618 genCmp (operand * left, operand * right,
5619         operand * result, iCode * ifx, int sign, iCode *ic)
5620 {
5621   int size, offset = 0;
5622   unsigned long lit = 0L;
5623   bool rightInB;
5624
5625   D(emitcode (";     genCmp",""));
5626
5627   /* if left & right are bit variables */
5628   if (AOP_TYPE (left) == AOP_CRY &&
5629       AOP_TYPE (right) == AOP_CRY)
5630     {
5631       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5632       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5633     }
5634   else
5635     {
5636       /* subtract right from left if at the
5637          end the carry flag is set then we know that
5638          left is greater than right */
5639       size = max (AOP_SIZE (left), AOP_SIZE (right));
5640
5641       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5642       if ((size == 1) && !sign &&
5643           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5644         {
5645           symbol *lbl = newiTempLabel (NULL);
5646           emitcode ("cjne", "%s,%s,%05d$",
5647                     aopGet (left, offset, FALSE, FALSE),
5648                     aopGet (right, offset, FALSE, FALSE),
5649                     lbl->key + 100);
5650           emitcode ("", "%05d$:", lbl->key + 100);
5651         }
5652       else
5653         {
5654           if (AOP_TYPE (right) == AOP_LIT)
5655             {
5656               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5657               /* optimize if(x < 0) or if(x >= 0) */
5658               if (lit == 0L)
5659                 {
5660                   if (!sign)
5661                     {
5662                       CLRC;
5663                     }
5664                   else
5665                     {
5666                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5667                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5668                         {
5669                           genIfxJump (ifx, "acc.7", left, right, result);
5670                           freeAsmop (right, NULL, ic, TRUE);
5671                           freeAsmop (left, NULL, ic, TRUE);
5672
5673                           return;
5674                         }
5675                       else
5676                         emitcode ("rlc", "a");
5677                     }
5678                   goto release;
5679                 }
5680             }
5681           CLRC;
5682           while (size--)
5683             {
5684               bool pushedB = FALSE;
5685               rightInB = aopGetUsesAcc(right, offset);
5686               if (rightInB)
5687                 {
5688                   pushedB = pushB ();
5689                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5690                 }
5691               MOVA (aopGet (left, offset, FALSE, FALSE));
5692               if (sign && size == 0)
5693                 {
5694                   emitcode ("xrl", "a,#0x80");
5695                   if (AOP_TYPE (right) == AOP_LIT)
5696                     {
5697                       unsigned long lit = (unsigned long)
5698                       floatFromVal (AOP (right)->aopu.aop_lit);
5699                       emitcode ("subb", "a,#0x%02x",
5700                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5701                     }
5702                   else
5703                     {
5704                       if (!rightInB)
5705                         {
5706                           pushedB = pushB ();
5707                           rightInB++;
5708                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5709                         }
5710                       emitcode ("xrl", "b,#0x80");
5711                       emitcode ("subb", "a,b");
5712                     }
5713                 }
5714               else
5715                 {
5716                   if (rightInB)
5717                     emitcode ("subb", "a,b");
5718                   else
5719                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5720                 }
5721               if (rightInB)
5722                 popB (pushedB);
5723               offset++;
5724             }
5725         }
5726     }
5727
5728 release:
5729   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5730   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5731   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5732     {
5733       outBitC (result);
5734     }
5735   else
5736     {
5737       /* if the result is used in the next
5738          ifx conditional branch then generate
5739          code a little differently */
5740       if (ifx)
5741         genIfxJump (ifx, "c", NULL, NULL, result);
5742       else
5743         outBitC (result);
5744       /* leave the result in acc */
5745     }
5746 }
5747
5748 /*-----------------------------------------------------------------*/
5749 /* genCmpGt :- greater than comparison                             */
5750 /*-----------------------------------------------------------------*/
5751 static void
5752 genCmpGt (iCode * ic, iCode * ifx)
5753 {
5754   operand *left, *right, *result;
5755   sym_link *letype, *retype;
5756   int sign;
5757
5758   D(emitcode (";     genCmpGt",""));
5759
5760   left = IC_LEFT (ic);
5761   right = IC_RIGHT (ic);
5762   result = IC_RESULT (ic);
5763
5764   letype = getSpec (operandType (left));
5765   retype = getSpec (operandType (right));
5766   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5767            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5768   /* assign the amsops */
5769   aopOp (result, ic, TRUE);
5770   aopOp (left, ic, FALSE);
5771   aopOp (right, ic, FALSE);
5772
5773   genCmp (right, left, result, ifx, sign, ic);
5774
5775   freeAsmop (result, NULL, ic, TRUE);
5776 }
5777
5778 /*-----------------------------------------------------------------*/
5779 /* genCmpLt - less than comparisons                                */
5780 /*-----------------------------------------------------------------*/
5781 static void
5782 genCmpLt (iCode * ic, iCode * ifx)
5783 {
5784   operand *left, *right, *result;
5785   sym_link *letype, *retype;
5786   int sign;
5787
5788   D(emitcode (";     genCmpLt",""));
5789
5790   left = IC_LEFT (ic);
5791   right = IC_RIGHT (ic);
5792   result = IC_RESULT (ic);
5793
5794   letype = getSpec (operandType (left));
5795   retype = getSpec (operandType (right));
5796   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5797            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5798   /* assign the amsops */
5799   aopOp (result, ic, TRUE);
5800   aopOp (left, ic, FALSE);
5801   aopOp (right, ic, FALSE);
5802
5803   genCmp (left, right, result, ifx, sign, ic);
5804
5805   freeAsmop (result, NULL, ic, TRUE);
5806 }
5807
5808 /*-----------------------------------------------------------------*/
5809 /* gencjneshort - compare and jump if not equal                    */
5810 /*-----------------------------------------------------------------*/
5811 static void
5812 gencjneshort (operand * left, operand * right, symbol * lbl)
5813 {
5814   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5815   int offset = 0;
5816   unsigned long lit = 0L;
5817
5818   /* if the left side is a literal or
5819      if the right is in a pointer register and left
5820      is not */
5821   if ((AOP_TYPE (left) == AOP_LIT) ||
5822       (AOP_TYPE (left) == AOP_IMMD) ||
5823       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5824     {
5825       operand *t = right;
5826       right = left;
5827       left = t;
5828     }
5829
5830   if (AOP_TYPE (right) == AOP_LIT)
5831     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5832
5833   /* if the right side is a literal then anything goes */
5834   if (AOP_TYPE (right) == AOP_LIT &&
5835       AOP_TYPE (left) != AOP_DIR  &&
5836       AOP_TYPE (left) != AOP_IMMD)
5837     {
5838       while (size--)
5839         {
5840           emitcode ("cjne", "%s,%s,%05d$",
5841                     aopGet (left, offset, FALSE, FALSE),
5842                     aopGet (right, offset, FALSE, FALSE),
5843                     lbl->key + 100);
5844           offset++;
5845         }
5846     }
5847
5848   /* if the right side is in a register or in direct space or
5849      if the left is a pointer register & right is not */
5850   else if (AOP_TYPE (right) == AOP_REG ||
5851            AOP_TYPE (right) == AOP_DIR ||
5852            AOP_TYPE (right) == AOP_LIT ||
5853            AOP_TYPE (right) == AOP_IMMD ||
5854            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5855            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5856     {
5857       while (size--)
5858         {
5859           MOVA (aopGet (left, offset, FALSE, FALSE));
5860           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5861               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5862             emitcode ("jnz", "%05d$", lbl->key + 100);
5863           else
5864             emitcode ("cjne", "a,%s,%05d$",
5865                       aopGet (right, offset, FALSE, TRUE),
5866                       lbl->key + 100);
5867           offset++;
5868         }
5869     }
5870   else
5871     {
5872       /* right is a pointer reg need both a & b */
5873       while (size--)
5874         {
5875           char *l;
5876           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5877           wassertl(!BINUSE, "B was in use");
5878           l = aopGet (left, offset, FALSE, FALSE);
5879           if (strcmp (l, "b"))
5880             emitcode ("mov", "b,%s", l);
5881           MOVA (aopGet (right, offset, FALSE, FALSE));
5882           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5883           offset++;
5884         }
5885     }
5886 }
5887
5888 /*-----------------------------------------------------------------*/
5889 /* gencjne - compare and jump if not equal                         */
5890 /*-----------------------------------------------------------------*/
5891 static void
5892 gencjne (operand * left, operand * right, symbol * lbl)
5893 {
5894   symbol *tlbl = newiTempLabel (NULL);
5895
5896   gencjneshort (left, right, lbl);
5897
5898   emitcode ("mov", "a,%s", one);
5899   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5900   emitcode ("", "%05d$:", lbl->key + 100);
5901   emitcode ("clr", "a");
5902   emitcode ("", "%05d$:", tlbl->key + 100);
5903 }
5904
5905 /*-----------------------------------------------------------------*/
5906 /* genCmpEq - generates code for equal to                          */
5907 /*-----------------------------------------------------------------*/
5908 static void
5909 genCmpEq (iCode * ic, iCode * ifx)
5910 {
5911   bool swappedLR = FALSE;
5912   operand *left, *right, *result;
5913
5914   D(emitcode (";     genCmpEq",""));
5915
5916   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5917   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5918   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5919
5920   /* if literal, literal on the right or
5921      if the right is in a pointer register and left
5922      is not */
5923   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5924       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5925     {
5926       operand *t = IC_RIGHT (ic);
5927       IC_RIGHT (ic) = IC_LEFT (ic);
5928       IC_LEFT (ic) = t;
5929           swappedLR = TRUE;
5930     }
5931
5932   if (ifx && !AOP_SIZE (result))
5933     {
5934       symbol *tlbl;
5935       /* if they are both bit variables */
5936       if (AOP_TYPE (left) == AOP_CRY &&
5937           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5938         {
5939           if (AOP_TYPE (right) == AOP_LIT)
5940             {
5941               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5942               if (lit == 0L)
5943                 {
5944                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5945                   emitcode ("cpl", "c");
5946                 }
5947               else if (lit == 1L)
5948                 {
5949                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5950                 }
5951               else
5952                 {
5953                   emitcode ("clr", "c");
5954                 }
5955               /* AOP_TYPE(right) == AOP_CRY */
5956             }
5957           else
5958             {
5959               symbol *lbl = newiTempLabel (NULL);
5960               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5961               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5962               emitcode ("cpl", "c");
5963               emitcode ("", "%05d$:", (lbl->key + 100));
5964             }
5965           /* if true label then we jump if condition
5966              supplied is true */
5967           tlbl = newiTempLabel (NULL);
5968           if (IC_TRUE (ifx))
5969             {
5970               emitcode ("jnc", "%05d$", tlbl->key + 100);
5971               freeForBranchAsmop (result);
5972               freeForBranchAsmop (right);
5973               freeForBranchAsmop (left);
5974               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5975             }
5976           else
5977             {
5978               emitcode ("jc", "%05d$", tlbl->key + 100);
5979               freeForBranchAsmop (result);
5980               freeForBranchAsmop (right);
5981               freeForBranchAsmop (left);
5982               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5983             }
5984           emitcode ("", "%05d$:", tlbl->key + 100);
5985         }
5986       else
5987         {
5988           tlbl = newiTempLabel (NULL);
5989           gencjneshort (left, right, tlbl);
5990           if (IC_TRUE (ifx))
5991             {
5992               freeForBranchAsmop (result);
5993               freeForBranchAsmop (right);
5994               freeForBranchAsmop (left);
5995               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5996               emitcode ("", "%05d$:", tlbl->key + 100);
5997             }
5998           else
5999             {
6000               symbol *lbl = newiTempLabel (NULL);
6001               emitcode ("sjmp", "%05d$", lbl->key + 100);
6002               emitcode ("", "%05d$:", tlbl->key + 100);
6003               freeForBranchAsmop (result);
6004               freeForBranchAsmop (right);
6005               freeForBranchAsmop (left);
6006               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6007               emitcode ("", "%05d$:", lbl->key + 100);
6008             }
6009         }
6010       /* mark the icode as generated */
6011       ifx->generated = 1;
6012       goto release;
6013     }
6014
6015   /* if they are both bit variables */
6016   if (AOP_TYPE (left) == AOP_CRY &&
6017       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6018     {
6019       if (AOP_TYPE (right) == AOP_LIT)
6020         {
6021           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6022           if (lit == 0L)
6023             {
6024               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6025               emitcode ("cpl", "c");
6026             }
6027           else if (lit == 1L)
6028             {
6029               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6030             }
6031           else
6032             {
6033               emitcode ("clr", "c");
6034             }
6035           /* AOP_TYPE(right) == AOP_CRY */
6036         }
6037       else
6038         {
6039           symbol *lbl = newiTempLabel (NULL);
6040           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6041           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6042           emitcode ("cpl", "c");
6043           emitcode ("", "%05d$:", (lbl->key + 100));
6044         }
6045       /* c = 1 if egal */
6046       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6047         {
6048           outBitC (result);
6049           goto release;
6050         }
6051       if (ifx)
6052         {
6053           genIfxJump (ifx, "c", left, right, result);
6054           goto release;
6055         }
6056       /* if the result is used in an arithmetic operation
6057          then put the result in place */
6058       outBitC (result);
6059     }
6060   else
6061     {
6062       gencjne (left, right, newiTempLabel (NULL));
6063       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6064         {
6065           aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6066           goto release;
6067         }
6068       if (ifx)
6069         {
6070           genIfxJump (ifx, "a", left, right, result);
6071           goto release;
6072         }
6073       /* if the result is used in an arithmetic operation
6074          then put the result in place */
6075       if (AOP_TYPE (result) != AOP_CRY)
6076         outAcc (result);
6077       /* leave the result in acc */
6078     }
6079
6080 release:
6081   freeAsmop (result, NULL, ic, TRUE);
6082   if (!swappedLR)
6083     {
6084       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6085       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6086     }
6087   else
6088     {
6089       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6090       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6091     }
6092 }
6093
6094 /*-----------------------------------------------------------------*/
6095 /* ifxForOp - returns the icode containing the ifx for operand     */
6096 /*-----------------------------------------------------------------*/
6097 static iCode *
6098 ifxForOp (operand * op, iCode * ic)
6099 {
6100   /* if true symbol then needs to be assigned */
6101   if (IS_TRUE_SYMOP (op))
6102     return NULL;
6103
6104   /* if this has register type condition and
6105      the next instruction is ifx with the same operand
6106      and live to of the operand is upto the ifx only then */
6107   if (ic->next &&
6108       ic->next->op == IFX &&
6109       IC_COND (ic->next)->key == op->key &&
6110       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6111     return ic->next;
6112
6113   return NULL;
6114 }
6115
6116 /*-----------------------------------------------------------------*/
6117 /* hasInc - operand is incremented before any other use            */
6118 /*-----------------------------------------------------------------*/
6119 static iCode *
6120 hasInc (operand *op, iCode *ic,int osize)
6121 {
6122   sym_link *type = operandType(op);
6123   sym_link *retype = getSpec (type);
6124   iCode *lic = ic->next;
6125   int isize ;
6126
6127   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6128   if (!IS_SYMOP(op)) return NULL;
6129
6130   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6131   if (IS_AGGREGATE(type->next)) return NULL;
6132   if (osize != (isize = getSize(type->next))) return NULL;
6133
6134   while (lic) {
6135     /* if operand of the form op = op + <sizeof *op> */
6136     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6137         isOperandEqual(IC_RESULT(lic),op) &&
6138         isOperandLiteral(IC_RIGHT(lic)) &&
6139         operandLitValue(IC_RIGHT(lic)) == isize) {
6140       return lic;
6141     }
6142     /* if the operand used or deffed */
6143     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6144       return NULL;
6145     }
6146     /* if GOTO or IFX */
6147     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6148     lic = lic->next;
6149   }
6150   return NULL;
6151 }
6152
6153 /*-----------------------------------------------------------------*/
6154 /* genAndOp - for && operation                                     */
6155 /*-----------------------------------------------------------------*/
6156 static void
6157 genAndOp (iCode * ic)
6158 {
6159   operand *left, *right, *result;
6160   symbol *tlbl;
6161
6162   D(emitcode (";     genAndOp",""));
6163
6164   /* note here that && operations that are in an
6165      if statement are taken away by backPatchLabels
6166      only those used in arthmetic operations remain */
6167   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6168   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6169   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6170
6171   /* if both are bit variables */
6172   if (AOP_TYPE (left) == AOP_CRY &&
6173       AOP_TYPE (right) == AOP_CRY)
6174     {
6175       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6176       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6177       outBitC (result);
6178     }
6179   else
6180     {
6181       tlbl = newiTempLabel (NULL);
6182       toBoolean (left);
6183       emitcode ("jz", "%05d$", tlbl->key + 100);
6184       toBoolean (right);
6185       emitcode ("", "%05d$:", tlbl->key + 100);
6186       outBitAcc (result);
6187     }
6188
6189   freeAsmop (result, NULL, ic, TRUE);
6190   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6191   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6192 }
6193
6194
6195 /*-----------------------------------------------------------------*/
6196 /* genOrOp - for || operation                                      */
6197 /*-----------------------------------------------------------------*/
6198 static void
6199 genOrOp (iCode * ic)
6200 {
6201   operand *left, *right, *result;
6202   symbol *tlbl;
6203
6204   D(emitcode (";     genOrOp",""));
6205
6206   /* note here that || operations that are in an
6207      if statement are taken away by backPatchLabels
6208      only those used in arthmetic operations remain */
6209   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6210   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6211   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6212
6213   /* if both are bit variables */
6214   if (AOP_TYPE (left) == AOP_CRY &&
6215       AOP_TYPE (right) == AOP_CRY)
6216     {
6217       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6218       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6219       outBitC (result);
6220     }
6221   else
6222     {
6223       tlbl = newiTempLabel (NULL);
6224       toBoolean (left);
6225       emitcode ("jnz", "%05d$", tlbl->key + 100);
6226       toBoolean (right);
6227       emitcode ("", "%05d$:", tlbl->key + 100);
6228       outBitAcc (result);
6229     }
6230
6231   freeAsmop (result, NULL, ic, TRUE);
6232   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6234 }
6235
6236 /*-----------------------------------------------------------------*/
6237 /* isLiteralBit - test if lit == 2^n                               */
6238 /*-----------------------------------------------------------------*/
6239 static int
6240 isLiteralBit (unsigned long lit)
6241 {
6242   unsigned long pw[32] =
6243   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6244    0x100L, 0x200L, 0x400L, 0x800L,
6245    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6246    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6247    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6248    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6249    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6250   int idx;
6251
6252   for (idx = 0; idx < 32; idx++)
6253     if (lit == pw[idx])
6254       return idx + 1;
6255   return 0;
6256 }
6257
6258 /*-----------------------------------------------------------------*/
6259 /* continueIfTrue -                                                */
6260 /*-----------------------------------------------------------------*/
6261 static void
6262 continueIfTrue (iCode * ic)
6263 {
6264   if (IC_TRUE (ic))
6265     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6266   ic->generated = 1;
6267 }
6268
6269 /*-----------------------------------------------------------------*/
6270 /* jmpIfTrue -                                                     */
6271 /*-----------------------------------------------------------------*/
6272 static void
6273 jumpIfTrue (iCode * ic)
6274 {
6275   if (!IC_TRUE (ic))
6276     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6277   ic->generated = 1;
6278 }
6279
6280 /*-----------------------------------------------------------------*/
6281 /* jmpTrueOrFalse -                                                */
6282 /*-----------------------------------------------------------------*/
6283 static void
6284 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6285 {
6286   // ugly but optimized by peephole
6287   if (IC_TRUE (ic))
6288     {
6289       symbol *nlbl = newiTempLabel (NULL);
6290       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6291       emitcode ("", "%05d$:", tlbl->key + 100);
6292       freeForBranchAsmop (result);
6293       freeForBranchAsmop (right);
6294       freeForBranchAsmop (left);
6295       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6296       emitcode ("", "%05d$:", nlbl->key + 100);
6297     }
6298   else
6299     {
6300       freeForBranchAsmop (result);
6301       freeForBranchAsmop (right);
6302       freeForBranchAsmop (left);
6303       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6304       emitcode ("", "%05d$:", tlbl->key + 100);
6305     }
6306   ic->generated = 1;
6307 }
6308
6309 /*-----------------------------------------------------------------*/
6310 /* genAnd  - code for and                                          */
6311 /*-----------------------------------------------------------------*/
6312 static void
6313 genAnd (iCode * ic, iCode * ifx)
6314 {
6315   operand *left, *right, *result;
6316   int size, offset = 0;
6317   unsigned long lit = 0L;
6318   int bytelit = 0;
6319   char buffer[10];
6320
6321   D(emitcode (";     genAnd",""));
6322
6323   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6324   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6325   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6326
6327 #ifdef DEBUG_TYPE
6328   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6329             AOP_TYPE (result),
6330             AOP_TYPE (left), AOP_TYPE (right));
6331   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6332             AOP_SIZE (result),
6333             AOP_SIZE (left), AOP_SIZE (right));
6334 #endif
6335
6336   /* if left is a literal & right is not then exchange them */
6337   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6338       AOP_NEEDSACC (left))
6339     {
6340       operand *tmp = right;
6341       right = left;
6342       left = tmp;
6343     }
6344
6345   /* if result = right then exchange left and right */
6346   if (sameRegs (AOP (result), AOP (right)))
6347     {
6348       operand *tmp = right;
6349       right = left;
6350       left = tmp;
6351     }
6352
6353   /* if right is bit then exchange them */
6354   if (AOP_TYPE (right) == AOP_CRY &&
6355       AOP_TYPE (left) != AOP_CRY)
6356     {
6357       operand *tmp = right;
6358       right = left;
6359       left = tmp;
6360     }
6361   if (AOP_TYPE (right) == AOP_LIT)
6362     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6363
6364   size = AOP_SIZE (result);
6365
6366   // if(bit & yy)
6367   // result = bit & yy;
6368   if (AOP_TYPE (left) == AOP_CRY)
6369     {
6370       // c = bit & literal;
6371       if (AOP_TYPE (right) == AOP_LIT)
6372         {
6373           if (lit & 1)
6374             {
6375               if (size && sameRegs (AOP (result), AOP (left)))
6376                 // no change
6377                 goto release;
6378               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6379             }
6380           else
6381             {
6382               // bit(result) = 0;
6383               if (size && (AOP_TYPE (result) == AOP_CRY))
6384                 {
6385                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6386                   goto release;
6387                 }
6388               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6389                 {
6390                   jumpIfTrue (ifx);
6391                   goto release;
6392                 }
6393               emitcode ("clr", "c");
6394             }
6395         }
6396       else
6397         {
6398           if (AOP_TYPE (right) == AOP_CRY)
6399             {
6400               // c = bit & bit;
6401               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6402               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6403             }
6404           else
6405             {
6406               // c = bit & val;
6407               MOVA (aopGet (right, 0, FALSE, FALSE));
6408               // c = lsb
6409               emitcode ("rrc", "a");
6410               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6411             }
6412         }
6413       // bit = c
6414       // val = c
6415       if (size)
6416         outBitC (result);
6417       // if(bit & ...)
6418       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6419         genIfxJump (ifx, "c", left, right, result);
6420       goto release;
6421     }
6422
6423   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6424   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6425   if ((AOP_TYPE (right) == AOP_LIT) &&
6426       (AOP_TYPE (result) == AOP_CRY) &&
6427       (AOP_TYPE (left) != AOP_CRY))
6428     {
6429       int posbit = isLiteralBit (lit);
6430       /* left &  2^n */
6431       if (posbit)
6432         {
6433           posbit--;
6434           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6435           // bit = left & 2^n
6436           if (size)
6437             {
6438               switch (posbit & 0x07)
6439                 {
6440                   case 0: emitcode ("rrc", "a");
6441                           break;
6442                   case 7: emitcode ("rlc", "a");
6443                           break;
6444                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6445                           break;
6446                 }
6447             }
6448           // if(left &  2^n)
6449           else
6450             {
6451               if (ifx)
6452                 {
6453                   SNPRINTF (buffer, sizeof(buffer),
6454                             "acc.%d", posbit & 0x07);
6455                   genIfxJump (ifx, buffer, left, right, result);
6456                 }
6457               else
6458                 {// what is this case? just found it in ds390/gen.c
6459                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6460                 }
6461               goto release;
6462             }
6463         }
6464       else
6465         {
6466           symbol *tlbl = newiTempLabel (NULL);
6467           int sizel = AOP_SIZE (left);
6468           if (size)
6469             emitcode ("setb", "c");
6470           while (sizel--)
6471             {
6472               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6473                 {
6474                   MOVA (aopGet (left, offset, FALSE, FALSE));
6475                   // byte ==  2^n ?
6476                   if ((posbit = isLiteralBit (bytelit)) != 0)
6477                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6478                   else
6479                     {
6480                       if (bytelit != 0x0FFL)
6481                         emitcode ("anl", "a,%s",
6482                                   aopGet (right, offset, FALSE, TRUE));
6483                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6484                     }
6485                 }
6486               offset++;
6487             }
6488           // bit = left & literal
6489           if (size)
6490             {
6491               emitcode ("clr", "c");
6492               emitcode ("", "%05d$:", tlbl->key + 100);
6493             }
6494           // if(left & literal)
6495           else
6496             {
6497               if (ifx)
6498                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6499               else
6500                 emitcode ("", "%05d$:", tlbl->key + 100);
6501               goto release;
6502             }
6503         }
6504       outBitC (result);
6505       goto release;
6506     }
6507
6508   /* if left is same as result */
6509   if (sameRegs (AOP (result), AOP (left)))
6510     {
6511       for (; size--; offset++)
6512         {
6513           if (AOP_TYPE (right) == AOP_LIT)
6514             {
6515               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6516               if (bytelit == 0x0FF)
6517                 {
6518                   /* dummy read of volatile operand */
6519                   if (isOperandVolatile (left, FALSE))
6520                     MOVA (aopGet (left, offset, FALSE, FALSE));
6521                   else
6522                     continue;
6523                 }
6524               else if (bytelit == 0)
6525                 {
6526                   aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6527                 }
6528               else if (IS_AOP_PREG (result))
6529                 {
6530                   MOVA (aopGet (left, offset, FALSE, TRUE));
6531                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6532                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6533                 }
6534               else
6535                 emitcode ("anl", "%s,%s",
6536                           aopGet (left, offset, FALSE, TRUE),
6537                           aopGet (right, offset, FALSE, FALSE));
6538             }
6539           else
6540             {
6541               if (AOP_TYPE (left) == AOP_ACC)
6542                 {
6543                   if (offset)
6544                     emitcode("mov", "a,b");
6545                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6546                 }
6547               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6548                 {
6549                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6550                   MOVA (aopGet (right, offset, FALSE, FALSE));
6551                   emitcode ("anl", "a,b");
6552                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6553                 }
6554               else if (aopGetUsesAcc (left, offset))
6555                 {
6556                   MOVA (aopGet (left, offset, FALSE, FALSE));
6557                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6558                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6559                 }
6560               else
6561                 {
6562                   MOVA (aopGet (right, offset, FALSE, FALSE));
6563                   if (IS_AOP_PREG (result))
6564                     {
6565                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6566                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6567                     }
6568                   else
6569                     emitcode ("anl", "%s,a",
6570                               aopGet (left, offset, FALSE, TRUE));
6571                 }
6572             }
6573         }
6574     }
6575   else
6576     {
6577       // left & result in different registers
6578       if (AOP_TYPE (result) == AOP_CRY)
6579         {
6580           // result = bit
6581           // if(size), result in bit
6582           // if(!size && ifx), conditional oper: if(left & right)
6583           symbol *tlbl = newiTempLabel (NULL);
6584           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6585           if (size)
6586             emitcode ("setb", "c");
6587           while (sizer--)
6588             {
6589               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6590                   && AOP_TYPE(left)==AOP_ACC)
6591                 {
6592                   if (offset)
6593                     emitcode("mov", "a,b");
6594                   emitcode ("anl", "a,%s",
6595                             aopGet (right, offset, FALSE, FALSE));
6596                 } else {
6597                   if (AOP_TYPE(left)==AOP_ACC)
6598                     {
6599                       if (!offset)
6600                         {
6601                           bool pushedB = pushB ();
6602                           emitcode("mov", "b,a");
6603                           MOVA (aopGet (right, offset, FALSE, FALSE));
6604                           emitcode("anl", "a,b");
6605                           popB (pushedB);
6606                         }
6607                       else
6608                         {
6609                           MOVA (aopGet (right, offset, FALSE, FALSE));
6610                           emitcode("anl", "a,b");
6611                         }
6612                     } else {
6613                       MOVA (aopGet (right, offset, FALSE, FALSE));
6614                       emitcode ("anl", "a,%s",
6615                                 aopGet (left, offset, FALSE, FALSE));
6616                     }
6617                 }
6618               emitcode ("jnz", "%05d$", tlbl->key + 100);
6619               offset++;
6620             }
6621           if (size)
6622             {
6623               CLRC;
6624               emitcode ("", "%05d$:", tlbl->key + 100);
6625               outBitC (result);
6626             }
6627           else if (ifx)
6628             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6629           else
6630             emitcode ("", "%05d$:", tlbl->key + 100);
6631         }
6632       else
6633         {
6634           for (; (size--); offset++)
6635             {
6636               // normal case
6637               // result = left & right
6638               if (AOP_TYPE (right) == AOP_LIT)
6639                 {
6640                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6641                   if (bytelit == 0x0FF)
6642                     {
6643                       aopPut (result,
6644                               aopGet (left, offset, FALSE, FALSE),
6645                               offset,
6646                               isOperandVolatile (result, FALSE));
6647                       continue;
6648                     }
6649                   else if (bytelit == 0)
6650                     {
6651                       /* dummy read of volatile operand */
6652                       if (isOperandVolatile (left, FALSE))
6653                         MOVA (aopGet (left, offset, FALSE, FALSE));
6654                       aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6655                       continue;
6656                     }
6657                   else if (AOP_TYPE (left) == AOP_ACC)
6658                     {
6659                       if (!offset)
6660                         {
6661                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6662                           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6663                           continue;
6664                         }
6665                       else
6666                         {
6667                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6668                           aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6669                           continue;
6670                         }
6671                     }
6672                 }
6673               // faster than result <- left, anl result,right
6674               // and better if result is SFR
6675               if (AOP_TYPE (left) == AOP_ACC)
6676                 {
6677                   if (offset)
6678                     emitcode("mov", "a,b");
6679                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6680                 }
6681               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6682                 {
6683                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6684                   MOVA (aopGet (right, offset, FALSE, FALSE));
6685                   emitcode ("anl", "a,b");
6686                 }
6687               else if (aopGetUsesAcc (left, offset))
6688                 {
6689                   MOVA (aopGet (left, offset, FALSE, FALSE));
6690                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6691                 }
6692               else
6693                 {
6694                   MOVA (aopGet (right, offset, FALSE, FALSE));
6695                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6696                 }
6697               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6698             }
6699         }
6700     }
6701
6702 release:
6703   freeAsmop (result, NULL, ic, TRUE);
6704   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6705   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6706 }
6707
6708 /*-----------------------------------------------------------------*/
6709 /* genOr  - code for or                                            */
6710 /*-----------------------------------------------------------------*/
6711 static void
6712 genOr (iCode * ic, iCode * ifx)
6713 {
6714   operand *left, *right, *result;
6715   int size, offset = 0;
6716   unsigned long lit = 0L;
6717   int bytelit = 0;
6718
6719   D(emitcode (";     genOr",""));
6720
6721   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6722   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6723   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6724
6725 #ifdef DEBUG_TYPE
6726   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6727             AOP_TYPE (result),
6728             AOP_TYPE (left), AOP_TYPE (right));
6729   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6730             AOP_SIZE (result),
6731             AOP_SIZE (left), AOP_SIZE (right));
6732 #endif
6733
6734   /* if left is a literal & right is not then exchange them */
6735   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6736       AOP_NEEDSACC (left))
6737     {
6738       operand *tmp = right;
6739       right = left;
6740       left = tmp;
6741     }
6742
6743   /* if result = right then exchange them */
6744   if (sameRegs (AOP (result), AOP (right)))
6745     {
6746       operand *tmp = right;
6747       right = left;
6748       left = tmp;
6749     }
6750
6751   /* if right is bit then exchange them */
6752   if (AOP_TYPE (right) == AOP_CRY &&
6753       AOP_TYPE (left) != AOP_CRY)
6754     {
6755       operand *tmp = right;
6756       right = left;
6757       left = tmp;
6758     }
6759   if (AOP_TYPE (right) == AOP_LIT)
6760     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6761
6762   size = AOP_SIZE (result);
6763
6764   // if(bit | yy)
6765   // xx = bit | yy;
6766   if (AOP_TYPE (left) == AOP_CRY)
6767     {
6768       if (AOP_TYPE (right) == AOP_LIT)
6769         {
6770           // c = bit | literal;
6771           if (lit)
6772             {
6773               // lit != 0 => result = 1
6774               if (AOP_TYPE (result) == AOP_CRY)
6775                 {
6776                   if (size)
6777                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6778                   else if (ifx)
6779                     continueIfTrue (ifx);
6780                   goto release;
6781                 }
6782               emitcode ("setb", "c");
6783             }
6784           else
6785             {
6786               // lit == 0 => result = left
6787               if (size && sameRegs (AOP (result), AOP (left)))
6788                 goto release;
6789               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6790             }
6791         }
6792       else
6793         {
6794           if (AOP_TYPE (right) == AOP_CRY)
6795             {
6796               // c = bit | bit;
6797               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6798               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6799             }
6800           else
6801             {
6802               // c = bit | val;
6803               symbol *tlbl = newiTempLabel (NULL);
6804               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6805                 emitcode ("setb", "c");
6806               emitcode ("jb", "%s,%05d$",
6807                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6808               toBoolean (right);
6809               emitcode ("jnz", "%05d$", tlbl->key + 100);
6810               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6811                 {
6812                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6813                   goto release;
6814                 }
6815               else
6816                 {
6817                   CLRC;
6818                   emitcode ("", "%05d$:", tlbl->key + 100);
6819                 }
6820             }
6821         }
6822       // bit = c
6823       // val = c
6824       if (size)
6825         outBitC (result);
6826       // if(bit | ...)
6827       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6828         genIfxJump (ifx, "c", left, right, result);
6829       goto release;
6830     }
6831
6832   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6833   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6834   if ((AOP_TYPE (right) == AOP_LIT) &&
6835       (AOP_TYPE (result) == AOP_CRY) &&
6836       (AOP_TYPE (left) != AOP_CRY))
6837     {
6838       if (lit)
6839         {
6840           // result = 1
6841           if (size)
6842             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6843           else
6844             continueIfTrue (ifx);
6845           goto release;
6846         }
6847       else
6848         {
6849           // lit = 0, result = boolean(left)
6850           if (size)
6851             emitcode ("setb", "c");
6852           toBoolean (right);
6853           if (size)
6854             {
6855               symbol *tlbl = newiTempLabel (NULL);
6856               emitcode ("jnz", "%05d$", tlbl->key + 100);
6857               CLRC;
6858               emitcode ("", "%05d$:", tlbl->key + 100);
6859             }
6860           else
6861             {
6862               genIfxJump (ifx, "a", left, right, result);
6863               goto release;
6864             }
6865         }
6866       outBitC (result);
6867       goto release;
6868     }
6869
6870   /* if left is same as result */
6871   if (sameRegs (AOP (result), AOP (left)))
6872     {
6873       for (; size--; offset++)
6874         {
6875           if (AOP_TYPE (right) == AOP_LIT)
6876             {
6877               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6878               if (bytelit == 0)
6879                 {
6880                   /* dummy read of volatile operand */
6881                   if (isOperandVolatile (left, FALSE))
6882                     MOVA (aopGet (left, offset, FALSE, FALSE));
6883                   else
6884                     continue;
6885                 }
6886               else if (bytelit == 0x0FF)
6887                 {
6888                   aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6889                 }
6890               else if (IS_AOP_PREG (left))
6891                 {
6892                   MOVA (aopGet (left, offset, FALSE, TRUE));
6893                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6894                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6895                 }
6896               else
6897                 {
6898                   emitcode ("orl", "%s,%s",
6899                             aopGet (left, offset, FALSE, TRUE),
6900                             aopGet (right, offset, FALSE, FALSE));
6901                 }
6902             }
6903           else
6904             {
6905               if (AOP_TYPE (left) == AOP_ACC)
6906                 {
6907                   if (offset)
6908                     emitcode("mov", "a,b");
6909                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6910                 }
6911               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6912                 {
6913                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6914                   MOVA (aopGet (right, offset, FALSE, FALSE));
6915                   emitcode ("orl", "a,b");
6916                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6917                 }
6918               else if (aopGetUsesAcc (left, offset))
6919                 {
6920                   MOVA (aopGet (left, offset, FALSE, FALSE));
6921                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6922                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6923                 }
6924               else
6925                 {
6926                   MOVA (aopGet (right, offset, FALSE, FALSE));
6927                   if (IS_AOP_PREG (left))
6928                     {
6929                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6930                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6931                     }
6932                   else
6933                     {
6934                       emitcode ("orl", "%s,a",
6935                                 aopGet (left, offset, FALSE, TRUE));
6936                     }
6937                 }
6938             }
6939         }
6940     }
6941   else
6942     {
6943       // left & result in different registers
6944       if (AOP_TYPE (result) == AOP_CRY)
6945         {
6946           // result = bit
6947           // if(size), result in bit
6948           // if(!size && ifx), conditional oper: if(left | right)
6949           symbol *tlbl = newiTempLabel (NULL);
6950           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6951           if (size)
6952             emitcode ("setb", "c");
6953           while (sizer--)
6954             {
6955               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6956                 if (offset)
6957                   emitcode("mov", "a,b");
6958                 emitcode ("orl", "a,%s",
6959                           aopGet (right, offset, FALSE, FALSE));
6960               } else {
6961                 MOVA (aopGet (right, offset, FALSE, FALSE));
6962                 emitcode ("orl", "a,%s",
6963                           aopGet (left, offset, FALSE, FALSE));
6964               }
6965               emitcode ("jnz", "%05d$", tlbl->key + 100);
6966               offset++;
6967             }
6968           if (size)
6969             {
6970               CLRC;
6971               emitcode ("", "%05d$:", tlbl->key + 100);
6972               outBitC (result);
6973             }
6974           else if (ifx)
6975             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6976           else
6977             emitcode ("", "%05d$:", tlbl->key + 100);
6978         }
6979       else
6980         {
6981           for (; (size--); offset++)
6982             {
6983               // normal case
6984               // result = left | right
6985               if (AOP_TYPE (right) == AOP_LIT)
6986                 {
6987                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6988                   if (bytelit == 0)
6989                     {
6990                       aopPut (result,
6991                               aopGet (left, offset, FALSE, FALSE),
6992                               offset,
6993                               isOperandVolatile (result, FALSE));
6994                       continue;
6995                     }
6996                   else if (bytelit == 0x0FF)
6997                     {
6998                       /* dummy read of volatile operand */
6999                       if (isOperandVolatile (left, FALSE))
7000                         MOVA (aopGet (left, offset, FALSE, FALSE));
7001                       aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
7002                       continue;
7003                     }
7004                 }
7005               // faster than result <- left, anl result,right
7006               // and better if result is SFR
7007               if (AOP_TYPE (left) == AOP_ACC)
7008                 {
7009                   if (offset)
7010                     emitcode("mov", "a,b");
7011                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7012                 }
7013               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7014                 {
7015                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7016                   MOVA (aopGet (right, offset, FALSE, FALSE));
7017                   emitcode ("orl", "a,b");
7018                 }
7019               else if (aopGetUsesAcc (left, offset))
7020                 {
7021                   MOVA (aopGet (left, offset, FALSE, FALSE));
7022                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7023                 }
7024               else
7025                 {
7026                   MOVA (aopGet (right, offset, FALSE, FALSE));
7027                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7028                 }
7029               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7030             }
7031         }
7032     }
7033
7034 release:
7035   freeAsmop (result, NULL, ic, TRUE);
7036   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7037   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7038 }
7039
7040 /*-----------------------------------------------------------------*/
7041 /* genXor - code for xclusive or                                   */
7042 /*-----------------------------------------------------------------*/
7043 static void
7044 genXor (iCode * ic, iCode * ifx)
7045 {
7046   operand *left, *right, *result;
7047   int size, offset = 0;
7048   unsigned long lit = 0L;
7049   int bytelit = 0;
7050
7051   D(emitcode (";     genXor",""));
7052
7053   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7054   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7055   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7056
7057 #ifdef DEBUG_TYPE
7058   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7059             AOP_TYPE (result),
7060             AOP_TYPE (left), AOP_TYPE (right));
7061   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7062             AOP_SIZE (result),
7063             AOP_SIZE (left), AOP_SIZE (right));
7064 #endif
7065
7066   /* if left is a literal & right is not ||
7067      if left needs acc & right does not */
7068   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7069       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7070     {
7071       operand *tmp = right;
7072       right = left;
7073       left = tmp;
7074     }
7075
7076   /* if result = right then exchange them */
7077   if (sameRegs (AOP (result), AOP (right)))
7078     {
7079       operand *tmp = right;
7080       right = left;
7081       left = tmp;
7082     }
7083
7084   /* if right is bit then exchange them */
7085   if (AOP_TYPE (right) == AOP_CRY &&
7086       AOP_TYPE (left) != AOP_CRY)
7087     {
7088       operand *tmp = right;
7089       right = left;
7090       left = tmp;
7091     }
7092   if (AOP_TYPE (right) == AOP_LIT)
7093     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7094
7095   size = AOP_SIZE (result);
7096
7097   // if(bit ^ yy)
7098   // xx = bit ^ yy;
7099   if (AOP_TYPE (left) == AOP_CRY)
7100     {
7101       if (AOP_TYPE (right) == AOP_LIT)
7102         {
7103           // c = bit & literal;
7104           if (lit >> 1)
7105             {
7106               // lit>>1  != 0 => result = 1
7107               if (AOP_TYPE (result) == AOP_CRY)
7108                 {
7109                   if (size)
7110                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7111                   else if (ifx)
7112                     continueIfTrue (ifx);
7113                   goto release;
7114                 }
7115               emitcode ("setb", "c");
7116             }
7117           else
7118             {
7119               // lit == (0 or 1)
7120               if (lit == 0)
7121                 {
7122                   // lit == 0, result = left
7123                   if (size && sameRegs (AOP (result), AOP (left)))
7124                     goto release;
7125                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7126                 }
7127               else
7128                 {
7129                   // lit == 1, result = not(left)
7130                   if (size && sameRegs (AOP (result), AOP (left)))
7131                     {
7132                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7133                       goto release;
7134                     }
7135                   else
7136                     {
7137                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7138                       emitcode ("cpl", "c");
7139                     }
7140                 }
7141             }
7142
7143         }
7144       else
7145         {
7146           // right != literal
7147           symbol *tlbl = newiTempLabel (NULL);
7148           if (AOP_TYPE (right) == AOP_CRY)
7149             {
7150               // c = bit ^ bit;
7151               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7152             }
7153           else
7154             {
7155               int sizer = AOP_SIZE (right);
7156               // c = bit ^ val
7157               // if val>>1 != 0, result = 1
7158               emitcode ("setb", "c");
7159               while (sizer)
7160                 {
7161                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7162                   if (sizer == 1)
7163                     // test the msb of the lsb
7164                     emitcode ("anl", "a,#0xfe");
7165                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7166                   sizer--;
7167                 }
7168               // val = (0,1)
7169               emitcode ("rrc", "a");
7170             }
7171           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7172           emitcode ("cpl", "c");
7173           emitcode ("", "%05d$:", (tlbl->key + 100));
7174         }
7175       // bit = c
7176       // val = c
7177       if (size)
7178         outBitC (result);
7179       // if(bit | ...)
7180       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7181         genIfxJump (ifx, "c", left, right, result);
7182       goto release;
7183     }
7184
7185   /* if left is same as result */
7186   if (sameRegs (AOP (result), AOP (left)))
7187     {
7188       for (; size--; offset++)
7189         {
7190           if (AOP_TYPE (right) == AOP_LIT)
7191             {
7192               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7193               if (bytelit == 0)
7194                 {
7195                   /* dummy read of volatile operand */
7196                   if (isOperandVolatile (left, FALSE))
7197                     MOVA (aopGet (left, offset, FALSE, FALSE));
7198                   else
7199                     continue;
7200                 }
7201               else if (IS_AOP_PREG (left))
7202                 {
7203                   MOVA (aopGet (left, offset, FALSE, TRUE));
7204                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7205                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7206                 }
7207               else
7208                 {
7209                   emitcode ("xrl", "%s,%s",
7210                             aopGet (left, offset, FALSE, TRUE),
7211                             aopGet (right, offset, FALSE, FALSE));
7212                 }
7213             }
7214           else
7215             {
7216               if (AOP_TYPE (left) == AOP_ACC)
7217                 {
7218                   if (offset)
7219                     emitcode("mov", "a,b");
7220                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7221                 }
7222               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7223                 {
7224                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7225                   MOVA (aopGet (right, offset, FALSE, FALSE));
7226                   emitcode ("xrl", "a,b");
7227                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7228                 }
7229               else if (aopGetUsesAcc (left, offset))
7230                 {
7231                   MOVA (aopGet (left, offset, FALSE, FALSE));
7232                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7233                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7234                 }
7235               else
7236                 {
7237                   MOVA (aopGet (right, offset, FALSE, FALSE));
7238                   if (IS_AOP_PREG (left))
7239                     {
7240                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7241                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7242                     }
7243                   else
7244                     emitcode ("xrl", "%s,a",
7245                               aopGet (left, offset, FALSE, TRUE));
7246                 }
7247             }
7248         }
7249     }
7250   else
7251     {
7252       // left & result in different registers
7253       if (AOP_TYPE (result) == AOP_CRY)
7254         {
7255           // result = bit
7256           // if(size), result in bit
7257           // if(!size && ifx), conditional oper: if(left ^ right)
7258           symbol *tlbl = newiTempLabel (NULL);
7259           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7260           if (size)
7261             emitcode ("setb", "c");
7262           while (sizer--)
7263             {
7264               if ((AOP_TYPE (right) == AOP_LIT) &&
7265                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7266                 {
7267                   MOVA (aopGet (left, offset, FALSE, FALSE));
7268                 }
7269               else
7270                 {
7271                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7272                     if (offset)
7273                       emitcode("mov", "a,b");
7274                     emitcode ("xrl", "a,%s",
7275                               aopGet (right, offset, FALSE, FALSE));
7276                   } else {
7277                     MOVA (aopGet (right, offset, FALSE, FALSE));
7278                     emitcode ("xrl", "a,%s",
7279                               aopGet (left, offset, FALSE, FALSE));
7280                   }
7281                 }
7282               emitcode ("jnz", "%05d$", tlbl->key + 100);
7283               offset++;
7284             }
7285           if (size)
7286             {
7287               CLRC;
7288               emitcode ("", "%05d$:", tlbl->key + 100);
7289               outBitC (result);
7290             }
7291           else if (ifx)
7292             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7293         }
7294       else
7295         {
7296           for (; (size--); offset++)
7297             {
7298               // normal case
7299               // result = left & right
7300               if (AOP_TYPE (right) == AOP_LIT)
7301                 {
7302                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7303                   if (bytelit == 0)
7304                     {
7305                       aopPut (result,
7306                               aopGet (left, offset, FALSE, FALSE),
7307                               offset,
7308                               isOperandVolatile (result, FALSE));
7309                       continue;
7310                     }
7311                 }
7312               // faster than result <- left, anl result,right
7313               // and better if result is SFR
7314               if (AOP_TYPE (left) == AOP_ACC)
7315                 {
7316                   if (offset)
7317                     emitcode("mov", "a,b");
7318                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7319                 }
7320               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7321                 {
7322                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7323                   MOVA (aopGet (right, offset, FALSE, FALSE));
7324                   emitcode ("xrl", "a,b");
7325                 }
7326               else if (aopGetUsesAcc (left, offset))
7327                 {
7328                   MOVA (aopGet (left, offset, FALSE, FALSE));
7329                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7330                 }
7331               else
7332                 {
7333                   MOVA (aopGet (right, offset, FALSE, FALSE));
7334                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7335                 }
7336               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7337             }
7338         }
7339     }
7340
7341 release:
7342   freeAsmop (result, NULL, ic, TRUE);
7343   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7344   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7345 }
7346
7347 /*-----------------------------------------------------------------*/
7348 /* genInline - write the inline code out                           */
7349 /*-----------------------------------------------------------------*/
7350 static void
7351 genInline (iCode * ic)
7352 {
7353   char *buffer, *bp, *bp1;
7354
7355   D(emitcode (";     genInline",""));
7356
7357   _G.inLine += (!options.asmpeep);
7358
7359   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7360   strcpy (buffer, IC_INLINE (ic));
7361
7362   /* emit each line as a code */
7363   while (*bp)
7364     {
7365       if (*bp == '\n')
7366         {
7367           *bp++ = '\0';
7368           emitcode (bp1, "");
7369           bp1 = bp;
7370         }
7371       else
7372         {
7373           /* Add \n for labels, not dirs such as c:\mydir */
7374           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7375             {
7376               bp++;
7377               *bp = '\0';
7378               bp++;
7379               emitcode (bp1, "");
7380               bp1 = bp;
7381             }
7382           else
7383             bp++;
7384         }
7385     }
7386   if (bp1 != bp)
7387     emitcode (bp1, "");
7388   /*     emitcode("",buffer); */
7389   _G.inLine -= (!options.asmpeep);
7390 }
7391
7392 /*-----------------------------------------------------------------*/
7393 /* genRRC - rotate right with carry                                */
7394 /*-----------------------------------------------------------------*/
7395 static void
7396 genRRC (iCode * ic)
7397 {
7398   operand *left, *result;
7399   int size, offset = 0;
7400   char *l;
7401
7402   D(emitcode (";     genRRC",""));
7403
7404   /* rotate right with carry */
7405   left = IC_LEFT (ic);
7406   result = IC_RESULT (ic);
7407   aopOp (left, ic, FALSE);
7408   aopOp (result, ic, FALSE);
7409
7410   /* move it to the result */
7411   size = AOP_SIZE (result);
7412   offset = size - 1;
7413   if (size == 1) { /* special case for 1 byte */
7414       l = aopGet (left, offset, FALSE, FALSE);
7415       MOVA (l);
7416       emitcode ("rr", "a");
7417       goto release;
7418   }
7419   /* no need to clear carry, bit7 will be written later */
7420   while (size--)
7421     {
7422       l = aopGet (left, offset, FALSE, FALSE);
7423       MOVA (l);
7424       emitcode ("rrc", "a");
7425       if (AOP_SIZE (result) > 1)
7426         aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7427     }
7428   /* now we need to put the carry into the
7429      highest order byte of the result */
7430   if (AOP_SIZE (result) > 1)
7431     {
7432       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7433       MOVA (l);
7434     }
7435   emitcode ("mov", "acc.7,c");
7436  release:
7437   aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7438   freeAsmop (result, NULL, ic, TRUE);
7439   freeAsmop (left, NULL, ic, TRUE);
7440 }
7441
7442 /*-----------------------------------------------------------------*/
7443 /* genRLC - generate code for rotate left with carry               */
7444 /*-----------------------------------------------------------------*/
7445 static void
7446 genRLC (iCode * ic)
7447 {
7448   operand *left, *result;
7449   int size, offset = 0;
7450   char *l;
7451
7452   D(emitcode (";     genRLC",""));
7453
7454   /* rotate right with carry */
7455   left = IC_LEFT (ic);
7456   result = IC_RESULT (ic);
7457   aopOp (left, ic, FALSE);
7458   aopOp (result, ic, FALSE);
7459
7460   /* move it to the result */
7461   size = AOP_SIZE (result);
7462   offset = 0;
7463   if (size--)
7464     {
7465       l = aopGet (left, offset, FALSE, FALSE);
7466       MOVA (l);
7467       if (size == 0) { /* special case for 1 byte */
7468               emitcode("rl","a");
7469               goto release;
7470       }
7471       emitcode("rlc","a"); /* bit0 will be written later */
7472       if (AOP_SIZE (result) > 1)
7473         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7474       while (size--)
7475         {
7476           l = aopGet (left, offset, FALSE, FALSE);
7477           MOVA (l);
7478           emitcode ("rlc", "a");
7479           if (AOP_SIZE (result) > 1)
7480             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7481         }
7482     }
7483   /* now we need to put the carry into the
7484      highest order byte of the result */
7485   if (AOP_SIZE (result) > 1)
7486     {
7487       l = aopGet (result, 0, FALSE, FALSE);
7488       MOVA (l);
7489     }
7490   emitcode ("mov", "acc.0,c");
7491  release:
7492   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7493   freeAsmop (result, NULL, ic, TRUE);
7494   freeAsmop (left, NULL, ic, TRUE);
7495 }
7496
7497 /*-----------------------------------------------------------------*/
7498 /* genGetHbit - generates code get highest order bit               */
7499 /*-----------------------------------------------------------------*/
7500 static void
7501 genGetHbit (iCode * ic)
7502 {
7503   operand *left, *result;
7504
7505   D(emitcode (";     genGetHbit",""));
7506
7507   left = IC_LEFT (ic);
7508   result = IC_RESULT (ic);
7509   aopOp (left, ic, FALSE);
7510   aopOp (result, ic, FALSE);
7511
7512   /* get the highest order byte into a */
7513   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7514   if (AOP_TYPE (result) == AOP_CRY)
7515     {
7516       emitcode ("rlc", "a");
7517       outBitC (result);
7518     }
7519   else
7520     {
7521       emitcode ("rl", "a");
7522       emitcode ("anl", "a,#0x01");
7523       outAcc (result);
7524     }
7525
7526   freeAsmop (result, NULL, ic, TRUE);
7527   freeAsmop (left, NULL, ic, TRUE);
7528 }
7529
7530 /*-----------------------------------------------------------------*/
7531 /* genGetAbit - generates code get a single bit                    */
7532 /*-----------------------------------------------------------------*/
7533 static void
7534 genGetAbit (iCode * ic)
7535 {
7536   operand *left, *right, *result;
7537   int shCount;
7538
7539   D(emitcode (";     genGetAbit",""));
7540
7541   left = IC_LEFT (ic);
7542   right = IC_RIGHT (ic);
7543   result = IC_RESULT (ic);
7544   aopOp (left, ic, FALSE);
7545   aopOp (right, ic, FALSE);
7546   aopOp (result, ic, FALSE);
7547
7548   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7549
7550   /* get the needed byte into a */
7551   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7552   shCount %= 8;
7553   if (AOP_TYPE (result) == AOP_CRY)
7554     {
7555       if ((shCount) == 7)
7556           emitcode ("rlc", "a");
7557       else if ((shCount) == 0)
7558           emitcode ("rrc", "a");
7559       else
7560           emitcode ("mov", "c,acc[%d]", shCount);
7561       outBitC (result);
7562     }
7563   else
7564     {
7565       switch (shCount)
7566         {
7567         case 2:
7568           emitcode ("rr", "a");
7569           //fallthrough
7570         case 1:
7571           emitcode ("rr", "a");
7572           //fallthrough
7573         case 0:
7574           emitcode ("anl", "a,#0x01");
7575           break;
7576         case 3:
7577         case 5:
7578           emitcode ("mov", "c,acc[%d]", shCount);
7579           emitcode ("clr", "a");
7580           emitcode ("rlc", "a");
7581           break;
7582         case 4:
7583           emitcode ("swap", "a");
7584           emitcode ("anl", "a,#0x01");
7585           break;
7586         case 6:
7587           emitcode ("rl", "a");
7588           //fallthrough
7589         case 7:
7590           emitcode ("rl", "a");
7591           emitcode ("anl", "a,#0x01");
7592           break;
7593         }
7594       outAcc (result);
7595     }
7596
7597   freeAsmop (result, NULL, ic, TRUE);
7598   freeAsmop (right, NULL, ic, TRUE);
7599   freeAsmop (left, NULL, ic, TRUE);
7600 }
7601
7602 /*-----------------------------------------------------------------*/
7603 /* genGetByte - generates code get a single byte                   */
7604 /*-----------------------------------------------------------------*/
7605 static void
7606 genGetByte (iCode * ic)
7607 {
7608   operand *left, *right, *result;
7609   int offset;
7610
7611   D(emitcode (";     genGetByte",""));
7612
7613   left = IC_LEFT (ic);
7614   right = IC_RIGHT (ic);
7615   result = IC_RESULT (ic);
7616   aopOp (left, ic, FALSE);
7617   aopOp (right, ic, FALSE);
7618   aopOp (result, ic, FALSE);
7619
7620   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7621   aopPut (result,
7622           aopGet (left, offset, FALSE, FALSE),
7623           0,
7624           isOperandVolatile (result, FALSE));
7625
7626   freeAsmop (result, NULL, ic, TRUE);
7627   freeAsmop (right, NULL, ic, TRUE);
7628   freeAsmop (left, NULL, ic, TRUE);
7629 }
7630
7631 /*-----------------------------------------------------------------*/
7632 /* genGetWord - generates code get two bytes                       */
7633 /*-----------------------------------------------------------------*/
7634 static void
7635 genGetWord (iCode * ic)
7636 {
7637   operand *left, *right, *result;
7638   int offset;
7639
7640   D(emitcode (";     genGetWord",""));
7641
7642   left = IC_LEFT (ic);
7643   right = IC_RIGHT (ic);
7644   result = IC_RESULT (ic);
7645   aopOp (left, ic, FALSE);
7646   aopOp (right, ic, FALSE);
7647   aopOp (result, ic, FALSE);
7648
7649   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7650   aopPut (result,
7651           aopGet (left, offset, FALSE, FALSE),
7652           0,
7653           isOperandVolatile (result, FALSE));
7654   aopPut (result,
7655           aopGet (left, offset+1, FALSE, FALSE),
7656           1,
7657           isOperandVolatile (result, FALSE));
7658
7659   freeAsmop (result, NULL, ic, TRUE);
7660   freeAsmop (right, NULL, ic, TRUE);
7661   freeAsmop (left, NULL, ic, TRUE);
7662 }
7663
7664 /*-----------------------------------------------------------------*/
7665 /* genSwap - generates code to swap nibbles or bytes               */
7666 /*-----------------------------------------------------------------*/
7667 static void
7668 genSwap (iCode * ic)
7669 {
7670   operand *left, *result;
7671
7672   D(emitcode (";     genSwap",""));
7673
7674   left = IC_LEFT (ic);
7675   result = IC_RESULT (ic);
7676   aopOp (left, ic, FALSE);
7677   aopOp (result, ic, FALSE);
7678
7679   switch (AOP_SIZE (left))
7680     {
7681     case 1: /* swap nibbles in byte */
7682       MOVA (aopGet (left, 0, FALSE, FALSE));
7683       emitcode ("swap", "a");
7684       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7685       break;
7686     case 2: /* swap bytes in word */
7687       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7688         {
7689           MOVA (aopGet (left, 0, FALSE, FALSE));
7690           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7691                   0, isOperandVolatile (result, FALSE));
7692           aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7693         }
7694       else if (operandsEqu (left, result))
7695         {
7696           char * reg = "a";
7697           bool pushedB = FALSE, leftInB = FALSE;
7698
7699           MOVA (aopGet (left, 0, FALSE, FALSE));
7700           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7701             {
7702               pushedB = pushB ();
7703               emitcode ("mov", "b,a");
7704               reg = "b";
7705               leftInB = TRUE;
7706             }
7707           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7708                   0, isOperandVolatile (result, FALSE));
7709           aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7710
7711           if (leftInB)
7712             popB (pushedB);
7713         }
7714       else
7715         {
7716           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7717                   0, isOperandVolatile (result, FALSE));
7718           aopPut (result, aopGet (left, 0, FALSE, FALSE),
7719                   1, isOperandVolatile (result, FALSE));
7720         }
7721       break;
7722     default:
7723       wassertl(FALSE, "unsupported SWAP operand size");
7724     }
7725
7726   freeAsmop (result, NULL, ic, TRUE);
7727   freeAsmop (left, NULL, ic, TRUE);
7728 }
7729
7730
7731 /*-----------------------------------------------------------------*/
7732 /* AccRol - rotate left accumulator by known count                 */
7733 /*-----------------------------------------------------------------*/
7734 static void
7735 AccRol (int shCount)
7736 {
7737   shCount &= 0x0007;            // shCount : 0..7
7738
7739   switch (shCount)
7740     {
7741     case 0:
7742       break;
7743     case 1:
7744       emitcode ("rl", "a");
7745       break;
7746     case 2:
7747       emitcode ("rl", "a");
7748       emitcode ("rl", "a");
7749       break;
7750     case 3:
7751       emitcode ("swap", "a");
7752       emitcode ("rr", "a");
7753       break;
7754     case 4:
7755       emitcode ("swap", "a");
7756       break;
7757     case 5:
7758       emitcode ("swap", "a");
7759       emitcode ("rl", "a");
7760       break;
7761     case 6:
7762       emitcode ("rr", "a");
7763       emitcode ("rr", "a");
7764       break;
7765     case 7:
7766       emitcode ("rr", "a");
7767       break;
7768     }
7769 }
7770
7771 /*-----------------------------------------------------------------*/
7772 /* AccLsh - left shift accumulator by known count                  */
7773 /*-----------------------------------------------------------------*/
7774 static void
7775 AccLsh (int shCount)
7776 {
7777   if (shCount != 0)
7778     {
7779       if (shCount == 1)
7780         emitcode ("add", "a,acc");
7781       else if (shCount == 2)
7782         {
7783           emitcode ("add", "a,acc");
7784           emitcode ("add", "a,acc");
7785         }
7786       else
7787         {
7788           /* rotate left accumulator */
7789           AccRol (shCount);
7790           /* and kill the lower order bits */
7791           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7792         }
7793     }
7794 }
7795
7796 /*-----------------------------------------------------------------*/
7797 /* AccRsh - right shift accumulator by known count                 */
7798 /*-----------------------------------------------------------------*/
7799 static void
7800 AccRsh (int shCount)
7801 {
7802   if (shCount != 0)
7803     {
7804       if (shCount == 1)
7805         {
7806           CLRC;
7807           emitcode ("rrc", "a");
7808         }
7809       else
7810         {
7811           /* rotate right accumulator */
7812           AccRol (8 - shCount);
7813           /* and kill the higher order bits */
7814           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7815         }
7816     }
7817 }
7818
7819 /*-----------------------------------------------------------------*/
7820 /* AccSRsh - signed right shift accumulator by known count                 */
7821 /*-----------------------------------------------------------------*/
7822 static void
7823 AccSRsh (int shCount)
7824 {
7825   symbol *tlbl;
7826   if (shCount != 0)
7827     {
7828       if (shCount == 1)
7829         {
7830           emitcode ("mov", "c,acc.7");
7831           emitcode ("rrc", "a");
7832         }
7833       else if (shCount == 2)
7834         {
7835           emitcode ("mov", "c,acc.7");
7836           emitcode ("rrc", "a");
7837           emitcode ("mov", "c,acc.7");
7838           emitcode ("rrc", "a");
7839         }
7840       else
7841         {
7842           tlbl = newiTempLabel (NULL);
7843           /* rotate right accumulator */
7844           AccRol (8 - shCount);
7845           /* and kill the higher order bits */
7846           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7847           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7848           emitcode ("orl", "a,#0x%02x",
7849                     (unsigned char) ~SRMask[shCount]);
7850           emitcode ("", "%05d$:", tlbl->key + 100);
7851         }
7852     }
7853 }
7854
7855 /*-----------------------------------------------------------------*/
7856 /* shiftR1Left2Result - shift right one byte from left to result   */
7857 /*-----------------------------------------------------------------*/
7858 static void
7859 shiftR1Left2Result (operand * left, int offl,
7860                     operand * result, int offr,
7861                     int shCount, int sign)
7862 {
7863   MOVA (aopGet (left, offl, FALSE, FALSE));
7864   /* shift right accumulator */
7865   if (sign)
7866     AccSRsh (shCount);
7867   else
7868     AccRsh (shCount);
7869   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7870 }
7871
7872 /*-----------------------------------------------------------------*/
7873 /* shiftL1Left2Result - shift left one byte from left to result    */
7874 /*-----------------------------------------------------------------*/
7875 static void
7876 shiftL1Left2Result (operand * left, int offl,
7877                     operand * result, int offr, int shCount)
7878 {
7879   char *l;
7880   l = aopGet (left, offl, FALSE, FALSE);
7881   MOVA (l);
7882   /* shift left accumulator */
7883   AccLsh (shCount);
7884   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7885 }
7886
7887 /*-----------------------------------------------------------------*/
7888 /* movLeft2Result - move byte from left to result                  */
7889 /*-----------------------------------------------------------------*/
7890 static void
7891 movLeft2Result (operand * left, int offl,
7892                 operand * result, int offr, int sign)
7893 {
7894   char *l;
7895   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7896     {
7897       l = aopGet (left, offl, FALSE, FALSE);
7898
7899       if (*l == '@' && (IS_AOP_PREG (result)))
7900         {
7901           emitcode ("mov", "a,%s", l);
7902           aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7903         }
7904       else
7905         {
7906           if (!sign)
7907             aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7908           else
7909             {
7910               /* MSB sign in acc.7 ! */
7911               if (getDataSize (left) == offl + 1)
7912                 {
7913                   MOVA (l);
7914                   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7915                 }
7916             }
7917         }
7918     }
7919 }
7920
7921 /*-----------------------------------------------------------------*/
7922 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7923 /*-----------------------------------------------------------------*/
7924 static void
7925 AccAXRrl1 (char *x)
7926 {
7927   emitcode ("rrc", "a");
7928   emitcode ("xch", "a,%s", x);
7929   emitcode ("rrc", "a");
7930   emitcode ("xch", "a,%s", x);
7931 }
7932
7933 /*-----------------------------------------------------------------*/
7934 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7935 /*-----------------------------------------------------------------*/
7936 static void
7937 AccAXLrl1 (char *x)
7938 {
7939   emitcode ("xch", "a,%s", x);
7940   emitcode ("rlc", "a");
7941   emitcode ("xch", "a,%s", x);
7942   emitcode ("rlc", "a");
7943 }
7944
7945 /*-----------------------------------------------------------------*/
7946 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7947 /*-----------------------------------------------------------------*/
7948 static void
7949 AccAXLsh1 (char *x)
7950 {
7951   emitcode ("xch", "a,%s", x);
7952   emitcode ("add", "a,acc");
7953   emitcode ("xch", "a,%s", x);
7954   emitcode ("rlc", "a");
7955 }
7956
7957 /*-----------------------------------------------------------------*/
7958 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7959 /*-----------------------------------------------------------------*/
7960 static void
7961 AccAXLsh (char *x, int shCount)
7962 {
7963   switch (shCount)
7964     {
7965     case 0:
7966       break;
7967     case 1:
7968       AccAXLsh1 (x);
7969       break;
7970     case 2:
7971       AccAXLsh1 (x);
7972       AccAXLsh1 (x);
7973       break;
7974     case 3:
7975     case 4:
7976     case 5:                     // AAAAABBB:CCCCCDDD
7977
7978       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7979
7980       emitcode ("anl", "a,#0x%02x",
7981                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7982
7983       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7984
7985       AccRol (shCount);         // DDDCCCCC:BBB00000
7986
7987       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7988
7989       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7990
7991       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7992
7993       emitcode ("anl", "a,#0x%02x",
7994                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7995
7996       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7997
7998       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7999
8000       break;
8001     case 6:                     // AAAAAABB:CCCCCCDD
8002       emitcode ("anl", "a,#0x%02x",
8003                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8004       emitcode ("mov", "c,acc.0");      // c = B
8005       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8006 #if 0 // REMOVE ME
8007       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8008       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8009 #else
8010       emitcode("rrc","a");
8011       emitcode("xch","a,%s", x);
8012       emitcode("rrc","a");
8013       emitcode("mov","c,acc.0"); //<< get correct bit
8014       emitcode("xch","a,%s", x);
8015
8016       emitcode("rrc","a");
8017       emitcode("xch","a,%s", x);
8018       emitcode("rrc","a");
8019       emitcode("xch","a,%s", x);
8020 #endif
8021       break;
8022     case 7:                     // a:x <<= 7
8023
8024       emitcode ("anl", "a,#0x%02x",
8025                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8026
8027       emitcode ("mov", "c,acc.0");      // c = B
8028
8029       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8030
8031       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8032
8033       break;
8034     default:
8035       break;
8036     }
8037 }
8038
8039 /*-----------------------------------------------------------------*/
8040 /* AccAXRsh - right shift a:x known count (0..7)                   */
8041 /*-----------------------------------------------------------------*/
8042 static void
8043 AccAXRsh (char *x, int shCount)
8044 {
8045   switch (shCount)
8046     {
8047     case 0:
8048       break;
8049     case 1:
8050       CLRC;
8051       AccAXRrl1 (x);            // 0->a:x
8052
8053       break;
8054     case 2:
8055       CLRC;
8056       AccAXRrl1 (x);            // 0->a:x
8057
8058       CLRC;
8059       AccAXRrl1 (x);            // 0->a:x
8060
8061       break;
8062     case 3:
8063     case 4:
8064     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8065
8066       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8067
8068       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8069
8070       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8071
8072       emitcode ("anl", "a,#0x%02x",
8073                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8074
8075       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8076
8077       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8078
8079       emitcode ("anl", "a,#0x%02x",
8080                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8081
8082       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8083
8084       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8085
8086       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8087
8088       break;
8089     case 6:                     // AABBBBBB:CCDDDDDD
8090
8091       emitcode ("mov", "c,acc.7");
8092       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8093
8094       emitcode ("mov", "c,acc.7");
8095       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8096
8097       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8098
8099       emitcode ("anl", "a,#0x%02x",
8100                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8101
8102       break;
8103     case 7:                     // ABBBBBBB:CDDDDDDD
8104
8105       emitcode ("mov", "c,acc.7");      // c = A
8106
8107       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8108
8109       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8110
8111       emitcode ("anl", "a,#0x%02x",
8112                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8113
8114       break;
8115     default:
8116       break;
8117     }
8118 }
8119
8120 /*-----------------------------------------------------------------*/
8121 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8122 /*-----------------------------------------------------------------*/
8123 static void
8124 AccAXRshS (char *x, int shCount)
8125 {
8126   symbol *tlbl;
8127   switch (shCount)
8128     {
8129     case 0:
8130       break;
8131     case 1:
8132       emitcode ("mov", "c,acc.7");
8133       AccAXRrl1 (x);            // s->a:x
8134
8135       break;
8136     case 2:
8137       emitcode ("mov", "c,acc.7");
8138       AccAXRrl1 (x);            // s->a:x
8139
8140       emitcode ("mov", "c,acc.7");
8141       AccAXRrl1 (x);            // s->a:x
8142
8143       break;
8144     case 3:
8145     case 4:
8146     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8147
8148       tlbl = newiTempLabel (NULL);
8149       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8150
8151       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8152
8153       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8154
8155       emitcode ("anl", "a,#0x%02x",
8156                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8157
8158       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8159
8160       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8161
8162       emitcode ("anl", "a,#0x%02x",
8163                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8164
8165       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8166
8167       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8168
8169       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8170
8171       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8172       emitcode ("orl", "a,#0x%02x",
8173                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8174
8175       emitcode ("", "%05d$:", tlbl->key + 100);
8176       break;                    // SSSSAAAA:BBBCCCCC
8177
8178     case 6:                     // AABBBBBB:CCDDDDDD
8179
8180       tlbl = newiTempLabel (NULL);
8181       emitcode ("mov", "c,acc.7");
8182       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8183
8184       emitcode ("mov", "c,acc.7");
8185       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8186
8187       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8188
8189       emitcode ("anl", "a,#0x%02x",
8190                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8191
8192       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8193       emitcode ("orl", "a,#0x%02x",
8194                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8195
8196       emitcode ("", "%05d$:", tlbl->key + 100);
8197       break;
8198     case 7:                     // ABBBBBBB:CDDDDDDD
8199
8200       tlbl = newiTempLabel (NULL);
8201       emitcode ("mov", "c,acc.7");      // c = A
8202
8203       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8204
8205       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8206
8207       emitcode ("anl", "a,#0x%02x",
8208                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8209
8210       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8211       emitcode ("orl", "a,#0x%02x",
8212                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8213
8214       emitcode ("", "%05d$:", tlbl->key + 100);
8215       break;
8216     default:
8217       break;
8218     }
8219 }
8220
8221 /*-----------------------------------------------------------------*/
8222 /* shiftL2Left2Result - shift left two bytes from left to result   */
8223 /*-----------------------------------------------------------------*/
8224 static void
8225 shiftL2Left2Result (operand * left, int offl,
8226                     operand * result, int offr, int shCount)
8227 {
8228   char * x;
8229   bool pushedB = FALSE;
8230   bool usedB = FALSE;
8231
8232   if (sameRegs (AOP (result), AOP (left)) &&
8233       ((offl + MSB16) == offr))
8234     {
8235       /* don't crash result[offr] */
8236       MOVA (aopGet (left, offl, FALSE, FALSE));
8237       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8238       x = aopGet (result, offr, FALSE, FALSE);
8239     }
8240   else if (aopGetUsesAcc (result, offr))
8241     {
8242       movLeft2Result (left, offl, result, offr, 0);
8243       pushedB = pushB ();
8244       usedB = TRUE;
8245       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8246       MOVA (aopGet (result, offr, FALSE, FALSE));
8247       emitcode ("xch", "a,b");
8248       x = "b";
8249     }
8250   else
8251     {
8252       movLeft2Result (left, offl, result, offr, 0);
8253       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8254       x = aopGet (result, offr, FALSE, FALSE);
8255     }
8256   /* ax << shCount (x = lsb(result)) */
8257   AccAXLsh (x, shCount);
8258   if (usedB)
8259     {
8260       emitcode ("xch", "a,b");
8261       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8262       aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8263       popB (pushedB);
8264     }
8265   else
8266     {
8267       aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8268     }
8269 }
8270
8271
8272 /*-----------------------------------------------------------------*/
8273 /* shiftR2Left2Result - shift right two bytes from left to result  */
8274 /*-----------------------------------------------------------------*/
8275 static void
8276 shiftR2Left2Result (operand * left, int offl,
8277                     operand * result, int offr,
8278                     int shCount, int sign)
8279 {
8280   char * x;
8281   bool pushedB = FALSE;
8282   bool usedB = FALSE;
8283
8284   if (sameRegs (AOP (result), AOP (left)) &&
8285       ((offl + MSB16) == offr))
8286     {
8287       /* don't crash result[offr] */
8288       MOVA (aopGet (left, offl, FALSE, FALSE));
8289       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8290       x = aopGet (result, offr, FALSE, FALSE);
8291     }
8292   else if (aopGetUsesAcc (result, offr))
8293     {
8294       movLeft2Result (left, offl, result, offr, 0);
8295       pushedB = pushB ();
8296       usedB = TRUE;
8297       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8298       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8299       x = "b";
8300     }
8301   else
8302     {
8303       movLeft2Result (left, offl, result, offr, 0);
8304       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8305       x = aopGet (result, offr, FALSE, FALSE);
8306     }
8307   /* a:x >> shCount (x = lsb(result)) */
8308   if (sign)
8309     AccAXRshS (x, shCount);
8310   else
8311     AccAXRsh (x, shCount);
8312   if (usedB)
8313     {
8314       emitcode ("xch", "a,b");
8315       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8316       emitcode ("xch", "a,b");
8317       popB (pushedB);
8318     }
8319   if (getDataSize (result) > 1)
8320     aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8321 }
8322
8323 /*-----------------------------------------------------------------*/
8324 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8325 /*-----------------------------------------------------------------*/
8326 static void
8327 shiftLLeftOrResult (operand * left, int offl,
8328                     operand * result, int offr, int shCount)
8329 {
8330   MOVA (aopGet (left, offl, FALSE, FALSE));
8331   /* shift left accumulator */
8332   AccLsh (shCount);
8333   /* or with result */
8334   if (aopGetUsesAcc (result, offr))
8335     {
8336       emitcode ("xch", "a,b");
8337       MOVA (aopGet (result, offr, FALSE, FALSE));
8338       emitcode ("orl", "a,b");
8339     }
8340   else
8341     {
8342       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8343     }
8344   /* back to result */
8345   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8346 }
8347
8348 /*-----------------------------------------------------------------*/
8349 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8350 /*-----------------------------------------------------------------*/
8351 static void
8352 shiftRLeftOrResult (operand * left, int offl,
8353                     operand * result, int offr, int shCount)
8354 {
8355   MOVA (aopGet (left, offl, FALSE, FALSE));
8356   /* shift right accumulator */
8357   AccRsh (shCount);
8358   /* or with result */
8359   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8360   /* back to result */
8361   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8362 }
8363
8364 /*-----------------------------------------------------------------*/
8365 /* genlshOne - left shift a one byte quantity by known count       */
8366 /*-----------------------------------------------------------------*/
8367 static void
8368 genlshOne (operand * result, operand * left, int shCount)
8369 {
8370   D(emitcode (";     genlshOne",""));
8371
8372   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8373 }
8374
8375 /*-----------------------------------------------------------------*/
8376 /* genlshTwo - left shift two bytes by known amount != 0           */
8377 /*-----------------------------------------------------------------*/
8378 static void
8379 genlshTwo (operand * result, operand * left, int shCount)
8380 {
8381   int size;
8382
8383   D(emitcode (";     genlshTwo",""));
8384
8385   size = getDataSize (result);
8386
8387   /* if shCount >= 8 */
8388   if (shCount >= 8)
8389     {
8390       shCount -= 8;
8391
8392       if (size > 1)
8393         {
8394           if (shCount)
8395             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8396           else
8397             movLeft2Result (left, LSB, result, MSB16, 0);
8398         }
8399       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8400     }
8401
8402   /*  1 <= shCount <= 7 */
8403   else
8404     {
8405       if (size == 1)
8406         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8407       else
8408         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8409     }
8410 }
8411
8412 /*-----------------------------------------------------------------*/
8413 /* shiftLLong - shift left one long from left to result            */
8414 /* offl = LSB or MSB16                                             */
8415 /*-----------------------------------------------------------------*/
8416 static void
8417 shiftLLong (operand * left, operand * result, int offr)
8418 {
8419   char *l;
8420   int size = AOP_SIZE (result);
8421
8422   if (size >= LSB + offr)
8423     {
8424       l = aopGet (left, LSB, FALSE, FALSE);
8425       MOVA (l);
8426       emitcode ("add", "a,acc");
8427       if (sameRegs (AOP (left), AOP (result)) &&
8428           size >= MSB16 + offr && offr != LSB)
8429         emitcode ("xch", "a,%s",
8430                   aopGet (left, LSB + offr, FALSE, FALSE));
8431       else
8432         aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8433     }
8434
8435   if (size >= MSB16 + offr)
8436     {
8437       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8438         {
8439           l = aopGet (left, MSB16, FALSE, FALSE);
8440           MOVA (l);
8441         }
8442       emitcode ("rlc", "a");
8443       if (sameRegs (AOP (left), AOP (result)) &&
8444           size >= MSB24 + offr && offr != LSB)
8445         emitcode ("xch", "a,%s",
8446                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8447       else
8448         aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8449     }
8450
8451   if (size >= MSB24 + offr)
8452     {
8453       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8454         {
8455           l = aopGet (left, MSB24, FALSE, FALSE);
8456           MOVA (l);
8457         }
8458       emitcode ("rlc", "a");
8459       if (sameRegs (AOP (left), AOP (result)) &&
8460           size >= MSB32 + offr && offr != LSB)
8461         emitcode ("xch", "a,%s",
8462                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8463       else
8464         aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8465     }
8466
8467   if (size > MSB32 + offr)
8468     {
8469       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8470         {
8471           l = aopGet (left, MSB32, FALSE, FALSE);
8472           MOVA (l);
8473         }
8474       emitcode ("rlc", "a");
8475       aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8476     }
8477   if (offr != LSB)
8478     aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8479 }
8480
8481 /*-----------------------------------------------------------------*/
8482 /* genlshFour - shift four byte by a known amount != 0             */
8483 /*-----------------------------------------------------------------*/
8484 static void
8485 genlshFour (operand * result, operand * left, int shCount)
8486 {
8487   int size;
8488
8489   D(emitcode (";     genlshFour",""));
8490
8491   size = AOP_SIZE (result);
8492
8493   /* if shifting more that 3 bytes */
8494   if (shCount >= 24)
8495     {
8496       shCount -= 24;
8497       if (shCount)
8498         /* lowest order of left goes to the highest
8499            order of the destination */
8500         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8501       else
8502         movLeft2Result (left, LSB, result, MSB32, 0);
8503       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8504       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8505       aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8506       return;
8507     }
8508
8509   /* more than two bytes */
8510   else if (shCount >= 16)
8511     {
8512       /* lower order two bytes goes to higher order two bytes */
8513       shCount -= 16;
8514       /* if some more remaining */
8515       if (shCount)
8516         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8517       else
8518         {
8519           movLeft2Result (left, MSB16, result, MSB32, 0);
8520           movLeft2Result (left, LSB, result, MSB24, 0);
8521         }
8522       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8523       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8524       return;
8525     }
8526
8527   /* if more than 1 byte */
8528   else if (shCount >= 8)
8529     {
8530       /* lower order three bytes goes to higher order  three bytes */
8531       shCount -= 8;
8532       if (size == 2)
8533         {
8534           if (shCount)
8535             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8536           else
8537             movLeft2Result (left, LSB, result, MSB16, 0);
8538         }
8539       else
8540         {                       /* size = 4 */
8541           if (shCount == 0)
8542             {
8543               movLeft2Result (left, MSB24, result, MSB32, 0);
8544               movLeft2Result (left, MSB16, result, MSB24, 0);
8545               movLeft2Result (left, LSB, result, MSB16, 0);
8546               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8547             }
8548           else if (shCount == 1)
8549             shiftLLong (left, result, MSB16);
8550           else
8551             {
8552               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8553               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8554               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8555               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8556             }
8557         }
8558     }
8559
8560   /* 1 <= shCount <= 7 */
8561   else if (shCount <= 2)
8562     {
8563       shiftLLong (left, result, LSB);
8564       if (shCount == 2)
8565         shiftLLong (result, result, LSB);
8566     }
8567   /* 3 <= shCount <= 7, optimize */
8568   else
8569     {
8570       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8571       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8572       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8573     }
8574 }
8575
8576 /*-----------------------------------------------------------------*/
8577 /* genLeftShiftLiteral - left shifting by known count              */
8578 /*-----------------------------------------------------------------*/
8579 static void
8580 genLeftShiftLiteral (operand * left,
8581                      operand * right,
8582                      operand * result,
8583                      iCode * ic)
8584 {
8585   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8586   int size;
8587
8588   D(emitcode (";     genLeftShiftLiteral",""));
8589
8590   freeAsmop (right, NULL, ic, TRUE);
8591
8592   aopOp (left, ic, FALSE);
8593   aopOp (result, ic, FALSE);
8594
8595   size = getSize (operandType (result));
8596
8597 #if VIEW_SIZE
8598   emitcode ("; shift left ", "result %d, left %d", size,
8599             AOP_SIZE (left));
8600 #endif
8601
8602   /* I suppose that the left size >= result size */
8603   if (shCount == 0)
8604     {
8605       while (size--)
8606         {
8607           movLeft2Result (left, size, result, size, 0);
8608         }
8609     }
8610
8611   else if (shCount >= (size * 8))
8612     while (size--)
8613       aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8614   else
8615     {
8616       switch (size)
8617         {
8618         case 1:
8619           genlshOne (result, left, shCount);
8620           break;
8621
8622         case 2:
8623           genlshTwo (result, left, shCount);
8624           break;
8625
8626         case 4:
8627           genlshFour (result, left, shCount);
8628           break;
8629         default:
8630           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8631                   "*** ack! mystery literal shift!\n");
8632           break;
8633         }
8634     }
8635   freeAsmop (result, NULL, ic, TRUE);
8636   freeAsmop (left, NULL, ic, TRUE);
8637 }
8638
8639 /*-----------------------------------------------------------------*/
8640 /* genLeftShift - generates code for left shifting                 */
8641 /*-----------------------------------------------------------------*/
8642 static void
8643 genLeftShift (iCode * ic)
8644 {
8645   operand *left, *right, *result;
8646   int size, offset;
8647   char *l;
8648   symbol *tlbl, *tlbl1;
8649   bool pushedB;
8650
8651   D(emitcode (";     genLeftShift",""));
8652
8653   right = IC_RIGHT (ic);
8654   left = IC_LEFT (ic);
8655   result = IC_RESULT (ic);
8656
8657   aopOp (right, ic, FALSE);
8658
8659   /* if the shift count is known then do it
8660      as efficiently as possible */
8661   if (AOP_TYPE (right) == AOP_LIT)
8662     {
8663       genLeftShiftLiteral (left, right, result, ic);
8664       return;
8665     }
8666
8667   /* shift count is unknown then we have to form
8668      a loop get the loop count in B : Note: we take
8669      only the lower order byte since shifting
8670      more that 32 bits make no sense anyway, ( the
8671      largest size of an object can be only 32 bits ) */
8672
8673   pushedB = pushB ();
8674   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8675   emitcode ("inc", "b");
8676   freeAsmop (right, NULL, ic, TRUE);
8677   aopOp (left, ic, FALSE);
8678   aopOp (result, ic, FALSE);
8679
8680   /* now move the left to the result if they are not the same */
8681   if (!sameRegs (AOP (left), AOP (result)) &&
8682       AOP_SIZE (result) > 1)
8683     {
8684
8685       size = AOP_SIZE (result);
8686       offset = 0;
8687       while (size--)
8688         {
8689           l = aopGet (left, offset, FALSE, TRUE);
8690           if (*l == '@' && (IS_AOP_PREG (result)))
8691             {
8692
8693               emitcode ("mov", "a,%s", l);
8694               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8695             }
8696           else
8697             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8698           offset++;
8699         }
8700     }
8701
8702   tlbl = newiTempLabel (NULL);
8703   size = AOP_SIZE (result);
8704   offset = 0;
8705   tlbl1 = newiTempLabel (NULL);
8706
8707   /* if it is only one byte then */
8708   if (size == 1)
8709     {
8710       symbol *tlbl1 = newiTempLabel (NULL);
8711
8712       l = aopGet (left, 0, FALSE, FALSE);
8713       MOVA (l);
8714       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8715       emitcode ("", "%05d$:", tlbl->key + 100);
8716       emitcode ("add", "a,acc");
8717       emitcode ("", "%05d$:", tlbl1->key + 100);
8718       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8719       popB (pushedB);
8720       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8721       goto release;
8722     }
8723
8724   reAdjustPreg (AOP (result));
8725
8726   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8727   emitcode ("", "%05d$:", tlbl->key + 100);
8728   l = aopGet (result, offset, FALSE, FALSE);
8729   MOVA (l);
8730   emitcode ("add", "a,acc");
8731   aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8732   while (--size)
8733     {
8734       l = aopGet (result, offset, FALSE, FALSE);
8735       MOVA (l);
8736       emitcode ("rlc", "a");
8737       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8738     }
8739   reAdjustPreg (AOP (result));
8740
8741   emitcode ("", "%05d$:", tlbl1->key + 100);
8742   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8743   popB (pushedB);
8744 release:
8745   freeAsmop (result, NULL, ic, TRUE);
8746   freeAsmop (left, NULL, ic, TRUE);
8747 }
8748
8749 /*-----------------------------------------------------------------*/
8750 /* genrshOne - right shift a one byte quantity by known count      */
8751 /*-----------------------------------------------------------------*/
8752 static void
8753 genrshOne (operand * result, operand * left,
8754            int shCount, int sign)
8755 {
8756   D(emitcode (";     genrshOne",""));
8757
8758   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8759 }
8760
8761 /*-----------------------------------------------------------------*/
8762 /* genrshTwo - right shift two bytes by known amount != 0          */
8763 /*-----------------------------------------------------------------*/
8764 static void
8765 genrshTwo (operand * result, operand * left,
8766            int shCount, int sign)
8767 {
8768   D(emitcode (";     genrshTwo",""));
8769
8770   /* if shCount >= 8 */
8771   if (shCount >= 8)
8772     {
8773       shCount -= 8;
8774       if (shCount)
8775         shiftR1Left2Result (left, MSB16, result, LSB,
8776                             shCount, sign);
8777       else
8778         movLeft2Result (left, MSB16, result, LSB, sign);
8779       addSign (result, MSB16, sign);
8780     }
8781
8782   /*  1 <= shCount <= 7 */
8783   else
8784     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8785 }
8786
8787 /*-----------------------------------------------------------------*/
8788 /* shiftRLong - shift right one long from left to result           */
8789 /* offl = LSB or MSB16                                             */
8790 /*-----------------------------------------------------------------*/
8791 static void
8792 shiftRLong (operand * left, int offl,
8793             operand * result, int sign)
8794 {
8795   bool useSameRegs = regsInCommon (left, result);
8796
8797   if (useSameRegs && offl>1)
8798     {
8799       // we are in big trouble, but this shouldn't happen
8800       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8801     }
8802
8803   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8804
8805   if (offl==MSB16)
8806     {
8807       // shift is > 8
8808       if (sign)
8809             {
8810           emitcode ("rlc", "a");
8811           emitcode ("subb", "a,acc");
8812           if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8813                     {
8814               emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8815                     }
8816           else
8817                     {
8818               aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8819               MOVA (aopGet (left, MSB32, FALSE, FALSE));
8820                     }
8821             }
8822           else
8823             {
8824           aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8825             }
8826     }
8827
8828   if (!sign)
8829     {
8830       emitcode ("clr", "c");
8831     }
8832   else
8833     {
8834       emitcode ("mov", "c,acc.7");
8835     }
8836
8837   emitcode ("rrc", "a");
8838
8839   if (useSameRegs && offl==MSB16 &&
8840       sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8841     {
8842       emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8843     }
8844   else
8845     {
8846       aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8847       MOVA (aopGet (left, MSB24, FALSE, FALSE));
8848     }
8849
8850   emitcode ("rrc", "a");
8851   if (useSameRegs && offl==1 &&
8852       sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8853     {
8854       emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8855     }
8856   else
8857     {
8858       aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8859       MOVA (aopGet (left, MSB16, FALSE, FALSE));
8860     }
8861   emitcode ("rrc", "a");
8862   if (offl != LSB)
8863     {
8864       aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8865     }
8866   else
8867     {
8868       if (useSameRegs &&
8869           sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8870         {
8871           emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8872         }
8873       else
8874         {
8875           aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8876           MOVA (aopGet (left, LSB, FALSE, FALSE));
8877             }
8878       emitcode ("rrc", "a");
8879       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8880     }
8881 }
8882
8883 /*-----------------------------------------------------------------*/
8884 /* genrshFour - shift four byte by a known amount != 0             */
8885 /*-----------------------------------------------------------------*/
8886 static void
8887 genrshFour (operand * result, operand * left,
8888             int shCount, int sign)
8889 {
8890   D(emitcode (";     genrshFour",""));
8891
8892   /* if shifting more that 3 bytes */
8893   if (shCount >= 24)
8894     {
8895       shCount -= 24;
8896       if (shCount)
8897         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8898       else
8899         movLeft2Result (left, MSB32, result, LSB, sign);
8900       addSign (result, MSB16, sign);
8901     }
8902   else if (shCount >= 16)
8903     {
8904       shCount -= 16;
8905       if (shCount)
8906         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8907       else
8908         {
8909           movLeft2Result (left, MSB24, result, LSB, 0);
8910           movLeft2Result (left, MSB32, result, MSB16, sign);
8911         }
8912       addSign (result, MSB24, sign);
8913     }
8914   else if (shCount >= 8)
8915     {
8916       shCount -= 8;
8917       if (shCount == 1)
8918         shiftRLong (left, MSB16, result, sign);
8919       else if (shCount == 0)
8920         {
8921           movLeft2Result (left, MSB16, result, LSB, 0);
8922           movLeft2Result (left, MSB24, result, MSB16, 0);
8923           movLeft2Result (left, MSB32, result, MSB24, sign);
8924           addSign (result, MSB32, sign);
8925         }
8926       else
8927         {
8928           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8929           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8930           /* the last shift is signed */
8931           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8932           addSign (result, MSB32, sign);
8933         }
8934     }
8935   else
8936     {                           /* 1 <= shCount <= 7 */
8937       if (shCount <= 2)
8938         {
8939           shiftRLong (left, LSB, result, sign);
8940           if (shCount == 2)
8941             shiftRLong (result, LSB, result, sign);
8942         }
8943       else
8944         {
8945           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8946           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8947           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8948         }
8949     }
8950 }
8951
8952 /*-----------------------------------------------------------------*/
8953 /* genRightShiftLiteral - right shifting by known count            */
8954 /*-----------------------------------------------------------------*/
8955 static void
8956 genRightShiftLiteral (operand * left,
8957                       operand * right,
8958                       operand * result,
8959                       iCode * ic,
8960                       int sign)
8961 {
8962   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8963   int size;
8964
8965   D(emitcode (";     genRightShiftLiteral",""));
8966
8967   freeAsmop (right, NULL, ic, TRUE);
8968
8969   aopOp (left, ic, FALSE);
8970   aopOp (result, ic, FALSE);
8971
8972 #if VIEW_SIZE
8973   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8974             AOP_SIZE (left));
8975 #endif
8976
8977   size = getDataSize (left);
8978   /* test the LEFT size !!! */
8979
8980   /* I suppose that the left size >= result size */
8981   if (shCount == 0)
8982     {
8983       size = getDataSize (result);
8984       while (size--)
8985         movLeft2Result (left, size, result, size, 0);
8986     }
8987
8988   else if (shCount >= (size * 8))
8989     {
8990       if (sign) {
8991         /* get sign in acc.7 */
8992         MOVA (aopGet (left, size - 1, FALSE, FALSE));
8993       }
8994       addSign (result, LSB, sign);
8995     }
8996   else
8997     {
8998       switch (size)
8999         {
9000         case 1:
9001           genrshOne (result, left, shCount, sign);
9002           break;
9003
9004         case 2:
9005           genrshTwo (result, left, shCount, sign);
9006           break;
9007
9008         case 4:
9009           genrshFour (result, left, shCount, sign);
9010           break;
9011         default:
9012           break;
9013         }
9014     }
9015   freeAsmop (result, NULL, ic, TRUE);
9016   freeAsmop (left, NULL, ic, TRUE);
9017 }
9018
9019 /*-----------------------------------------------------------------*/
9020 /* genSignedRightShift - right shift of signed number              */
9021 /*-----------------------------------------------------------------*/
9022 static void
9023 genSignedRightShift (iCode * ic)
9024 {
9025   operand *right, *left, *result;
9026   int size, offset;
9027   char *l;
9028   symbol *tlbl, *tlbl1;
9029   bool pushedB;
9030
9031   D(emitcode (";     genSignedRightShift",""));
9032
9033   /* we do it the hard way put the shift count in b
9034      and loop thru preserving the sign */
9035
9036   right = IC_RIGHT (ic);
9037   left = IC_LEFT (ic);
9038   result = IC_RESULT (ic);
9039
9040   aopOp (right, ic, FALSE);
9041
9042
9043   if (AOP_TYPE (right) == AOP_LIT)
9044     {
9045       genRightShiftLiteral (left, right, result, ic, 1);
9046       return;
9047     }
9048   /* shift count is unknown then we have to form
9049      a loop get the loop count in B : Note: we take
9050      only the lower order byte since shifting
9051      more that 32 bits make no sense anyway, ( the
9052      largest size of an object can be only 32 bits ) */
9053
9054   pushedB = pushB ();
9055   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9056   emitcode ("inc", "b");
9057   freeAsmop (right, NULL, ic, TRUE);
9058   aopOp (left, ic, FALSE);
9059   aopOp (result, ic, FALSE);
9060
9061   /* now move the left to the result if they are not the
9062      same */
9063   if (!sameRegs (AOP (left), AOP (result)) &&
9064       AOP_SIZE (result) > 1)
9065     {
9066
9067       size = AOP_SIZE (result);
9068       offset = 0;
9069       while (size--)
9070         {
9071           l = aopGet (left, offset, FALSE, TRUE);
9072           if (*l == '@' && IS_AOP_PREG (result))
9073             {
9074
9075               emitcode ("mov", "a,%s", l);
9076               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9077             }
9078           else
9079             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9080           offset++;
9081         }
9082     }
9083
9084   /* mov the highest order bit to OVR */
9085   tlbl = newiTempLabel (NULL);
9086   tlbl1 = newiTempLabel (NULL);
9087
9088   size = AOP_SIZE (result);
9089   offset = size - 1;
9090   MOVA (aopGet (left, offset, FALSE, FALSE));
9091   emitcode ("rlc", "a");
9092   emitcode ("mov", "ov,c");
9093   /* if it is only one byte then */
9094   if (size == 1)
9095     {
9096       l = aopGet (left, 0, FALSE, FALSE);
9097       MOVA (l);
9098       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9099       emitcode ("", "%05d$:", tlbl->key + 100);
9100       emitcode ("mov", "c,ov");
9101       emitcode ("rrc", "a");
9102       emitcode ("", "%05d$:", tlbl1->key + 100);
9103       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9104       popB (pushedB);
9105       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9106       goto release;
9107     }
9108
9109   reAdjustPreg (AOP (result));
9110   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9111   emitcode ("", "%05d$:", tlbl->key + 100);
9112   emitcode ("mov", "c,ov");
9113   while (size--)
9114     {
9115       l = aopGet (result, offset, FALSE, FALSE);
9116       MOVA (l);
9117       emitcode ("rrc", "a");
9118       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9119     }
9120   reAdjustPreg (AOP (result));
9121   emitcode ("", "%05d$:", tlbl1->key + 100);
9122   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9123   popB (pushedB);
9124
9125 release:
9126   freeAsmop (result, NULL, ic, TRUE);
9127   freeAsmop (left, NULL, ic, TRUE);
9128 }
9129
9130 /*-----------------------------------------------------------------*/
9131 /* genRightShift - generate code for right shifting                */
9132 /*-----------------------------------------------------------------*/
9133 static void
9134 genRightShift (iCode * ic)
9135 {
9136   operand *right, *left, *result;
9137   sym_link *letype;
9138   int size, offset;
9139   char *l;
9140   symbol *tlbl, *tlbl1;
9141   bool pushedB;
9142
9143   D(emitcode (";     genRightShift",""));
9144
9145   /* if signed then we do it the hard way preserve the
9146      sign bit moving it inwards */
9147   letype = getSpec (operandType (IC_LEFT (ic)));
9148
9149   if (!SPEC_USIGN (letype))
9150     {
9151       genSignedRightShift (ic);
9152       return;
9153     }
9154
9155   /* signed & unsigned types are treated the same : i.e. the
9156      signed is NOT propagated inwards : quoting from the
9157      ANSI - standard : "for E1 >> E2, is equivalent to division
9158      by 2**E2 if unsigned or if it has a non-negative value,
9159      otherwise the result is implementation defined ", MY definition
9160      is that the sign does not get propagated */
9161
9162   right = IC_RIGHT (ic);
9163   left = IC_LEFT (ic);
9164   result = IC_RESULT (ic);
9165
9166   aopOp (right, ic, FALSE);
9167
9168   /* if the shift count is known then do it
9169      as efficiently as possible */
9170   if (AOP_TYPE (right) == AOP_LIT)
9171     {
9172       genRightShiftLiteral (left, right, result, ic, 0);
9173       return;
9174     }
9175
9176   /* shift count is unknown then we have to form
9177      a loop get the loop count in B : Note: we take
9178      only the lower order byte since shifting
9179      more that 32 bits make no sense anyway, ( the
9180      largest size of an object can be only 32 bits ) */
9181
9182   pushedB = pushB ();
9183   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9184   emitcode ("inc", "b");
9185   freeAsmop (right, NULL, ic, TRUE);
9186   aopOp (left, ic, FALSE);
9187   aopOp (result, ic, FALSE);
9188
9189   /* now move the left to the result if they are not the
9190      same */
9191   if (!sameRegs (AOP (left), AOP (result)) &&
9192       AOP_SIZE (result) > 1)
9193     {
9194
9195       size = AOP_SIZE (result);
9196       offset = 0;
9197       while (size--)
9198         {
9199           l = aopGet (left, offset, FALSE, TRUE);
9200           if (*l == '@' && IS_AOP_PREG (result))
9201             {
9202
9203               emitcode ("mov", "a,%s", l);
9204               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9205             }
9206           else
9207             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9208           offset++;
9209         }
9210     }
9211
9212   tlbl = newiTempLabel (NULL);
9213   tlbl1 = newiTempLabel (NULL);
9214   size = AOP_SIZE (result);
9215   offset = size - 1;
9216
9217   /* if it is only one byte then */
9218   if (size == 1)
9219     {
9220       l = aopGet (left, 0, FALSE, FALSE);
9221       MOVA (l);
9222       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9223       emitcode ("", "%05d$:", tlbl->key + 100);
9224       CLRC;
9225       emitcode ("rrc", "a");
9226       emitcode ("", "%05d$:", tlbl1->key + 100);
9227       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9228       popB (pushedB);
9229       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9230       goto release;
9231     }
9232
9233   reAdjustPreg (AOP (result));
9234   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9235   emitcode ("", "%05d$:", tlbl->key + 100);
9236   CLRC;
9237   while (size--)
9238     {
9239       l = aopGet (result, offset, FALSE, FALSE);
9240       MOVA (l);
9241       emitcode ("rrc", "a");
9242       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9243     }
9244   reAdjustPreg (AOP (result));
9245
9246   emitcode ("", "%05d$:", tlbl1->key + 100);
9247   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9248   popB (pushedB);
9249
9250 release:
9251   freeAsmop (result, NULL, ic, TRUE);
9252   freeAsmop (left, NULL, ic, TRUE);
9253 }
9254
9255 /*-----------------------------------------------------------------*/
9256 /* emitPtrByteGet - emits code to get a byte into A through a      */
9257 /*                  pointer register (R0, R1, or DPTR). The        */
9258 /*                  original value of A can be preserved in B.     */
9259 /*-----------------------------------------------------------------*/
9260 static void
9261 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9262 {
9263   switch (p_type)
9264     {
9265     case IPOINTER:
9266     case POINTER:
9267       if (preserveAinB)
9268         emitcode ("mov", "b,a");
9269       emitcode ("mov", "a,@%s", rname);
9270       break;
9271
9272     case PPOINTER:
9273       if (preserveAinB)
9274         emitcode ("mov", "b,a");
9275       emitcode ("movx", "a,@%s", rname);
9276       break;
9277
9278     case FPOINTER:
9279       if (preserveAinB)
9280         emitcode ("mov", "b,a");
9281       emitcode ("movx", "a,@dptr");
9282       break;
9283
9284     case CPOINTER:
9285       if (preserveAinB)
9286         emitcode ("mov", "b,a");
9287       emitcode ("clr", "a");
9288       emitcode ("movc", "a,@a+dptr");
9289       break;
9290
9291     case GPOINTER:
9292       if (preserveAinB)
9293         {
9294           emitcode ("push", "b");
9295           emitcode ("push", "acc");
9296         }
9297       emitcode ("lcall", "__gptrget");
9298       if (preserveAinB)
9299         emitcode ("pop", "b");
9300       break;
9301     }
9302 }
9303
9304 /*-----------------------------------------------------------------*/
9305 /* emitPtrByteSet - emits code to set a byte from src through a    */
9306 /*                  pointer register (R0, R1, or DPTR).            */
9307 /*-----------------------------------------------------------------*/
9308 static void
9309 emitPtrByteSet (char *rname, int p_type, char *src)
9310 {
9311   switch (p_type)
9312     {
9313     case IPOINTER:
9314     case POINTER:
9315       if (*src=='@')
9316         {
9317           MOVA (src);
9318           emitcode ("mov", "@%s,a", rname);
9319         }
9320       else
9321         emitcode ("mov", "@%s,%s", rname, src);
9322       break;
9323
9324     case PPOINTER:
9325       MOVA (src);
9326       emitcode ("movx", "@%s,a", rname);
9327       break;
9328
9329     case FPOINTER:
9330       MOVA (src);
9331       emitcode ("movx", "@dptr,a");
9332       break;
9333
9334     case GPOINTER:
9335       MOVA (src);
9336       emitcode ("lcall", "__gptrput");
9337       break;
9338     }
9339 }
9340
9341 /*-----------------------------------------------------------------*/
9342 /* genUnpackBits - generates code for unpacking bits               */
9343 /*-----------------------------------------------------------------*/
9344 static void
9345 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9346 {
9347   int offset = 0;       /* result byte offset */
9348   int rsize;            /* result size */
9349   int rlen = 0;         /* remaining bitfield length */
9350   sym_link *etype;      /* bitfield type information */
9351   int blen;             /* bitfield length */
9352   int bstr;             /* bitfield starting bit within byte */
9353   char buffer[10];
9354
9355   D(emitcode (";     genUnpackBits",""));
9356
9357   etype = getSpec (operandType (result));
9358   rsize = getSize (operandType (result));
9359   blen = SPEC_BLEN (etype);
9360   bstr = SPEC_BSTR (etype);
9361
9362   if (ifx && blen <= 8)
9363     {
9364       emitPtrByteGet (rname, ptype, FALSE);
9365       if (blen == 1)
9366         {
9367           SNPRINTF (buffer, sizeof(buffer),
9368                     "acc.%d", bstr);
9369           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9370         }
9371       else
9372         {
9373           if (blen < 8)
9374             emitcode ("anl", "a,#0x%02x",
9375                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9376           genIfxJump (ifx, "a", NULL, NULL, NULL);
9377         }
9378       return;
9379     }
9380   wassert (!ifx);
9381
9382   /* If the bitfield length is less than a byte */
9383   if (blen < 8)
9384     {
9385       emitPtrByteGet (rname, ptype, FALSE);
9386       AccRol (8 - bstr);
9387       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9388       if (!SPEC_USIGN (etype))
9389         {
9390           /* signed bitfield */
9391           symbol *tlbl = newiTempLabel (NULL);
9392
9393           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9394           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9395           emitcode ("", "%05d$:", tlbl->key + 100);
9396         }
9397       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9398       goto finish;
9399     }
9400
9401   /* Bit field did not fit in a byte. Copy all
9402      but the partial byte at the end.  */
9403   for (rlen=blen;rlen>=8;rlen-=8)
9404     {
9405       emitPtrByteGet (rname, ptype, FALSE);
9406       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9407       if (rlen>8)
9408         emitcode ("inc", "%s", rname);
9409     }
9410
9411   /* Handle the partial byte at the end */
9412   if (rlen)
9413     {
9414       emitPtrByteGet (rname, ptype, FALSE);
9415       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9416       if (!SPEC_USIGN (etype))
9417         {
9418           /* signed bitfield */
9419           symbol *tlbl = newiTempLabel (NULL);
9420
9421           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9422           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9423           emitcode ("", "%05d$:", tlbl->key + 100);
9424         }
9425       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9426     }
9427
9428 finish:
9429   if (offset < rsize)
9430     {
9431       char *source;
9432
9433       if (SPEC_USIGN (etype))
9434         source = zero;
9435       else
9436         {
9437           /* signed bitfield: sign extension with 0x00 or 0xff */
9438           emitcode ("rlc", "a");
9439           emitcode ("subb", "a,acc");
9440
9441           source = "a";
9442         }
9443       rsize -= offset;
9444       while (rsize--)
9445         aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9446     }
9447 }
9448
9449
9450 /*-----------------------------------------------------------------*/
9451 /* genDataPointerGet - generates code when ptr offset is known     */
9452 /*-----------------------------------------------------------------*/
9453 static void
9454 genDataPointerGet (operand * left,
9455                    operand * result,
9456                    iCode * ic)
9457 {
9458   char *l;
9459   char buffer[256];
9460   int size, offset = 0;
9461
9462   D(emitcode (";     genDataPointerGet",""));
9463
9464   aopOp (result, ic, TRUE);
9465
9466   /* get the string representation of the name */
9467   l = aopGet (left, 0, FALSE, TRUE);
9468   size = AOP_SIZE (result);
9469   while (size--)
9470     {
9471       if (offset)
9472         sprintf (buffer, "(%s + %d)", l + 1, offset);
9473       else
9474         sprintf (buffer, "%s", l + 1);
9475       aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9476     }
9477
9478   freeAsmop (result, NULL, ic, TRUE);
9479   freeAsmop (left, NULL, ic, TRUE);
9480 }
9481
9482 /*-----------------------------------------------------------------*/
9483 /* genNearPointerGet - emitcode for near pointer fetch             */
9484 /*-----------------------------------------------------------------*/
9485 static void
9486 genNearPointerGet (operand * left,
9487                    operand * result,
9488                    iCode * ic,
9489                    iCode * pi,
9490                    iCode * ifx)
9491 {
9492   asmop *aop = NULL;
9493   regs *preg = NULL;
9494   char *rname;
9495   sym_link *rtype, *retype;
9496   sym_link *ltype = operandType (left);
9497   char buffer[80];
9498
9499   D(emitcode (";     genNearPointerGet",""));
9500
9501   rtype = operandType (result);
9502   retype = getSpec (rtype);
9503
9504   aopOp (left, ic, FALSE);
9505
9506   /* if left is rematerialisable and
9507      result is not bitfield variable type and
9508      the left is pointer to data space i.e
9509      lower 128 bytes of space */
9510   if (AOP_TYPE (left) == AOP_IMMD &&
9511       !IS_BITFIELD (retype) &&
9512       DCL_TYPE (ltype) == POINTER)
9513     {
9514       genDataPointerGet (left, result, ic);
9515       return;
9516     }
9517
9518  /* if the value is already in a pointer register
9519      then don't need anything more */
9520   if (!AOP_INPREG (AOP (left)))
9521     {
9522       if (IS_AOP_PREG (left))
9523         {
9524           // Aha, it is a pointer, just in disguise.
9525           rname = aopGet (left, 0, FALSE, FALSE);
9526           if (*rname != '@')
9527             {
9528               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9529                       __FILE__, __LINE__);
9530             }
9531           else
9532             {
9533               // Expected case.
9534               emitcode ("mov", "a%s,%s", rname + 1, rname);
9535               rname++;  // skip the '@'.
9536             }
9537         }
9538       else
9539         {
9540           /* otherwise get a free pointer register */
9541           aop = newAsmop (0);
9542           preg = getFreePtr (ic, &aop, FALSE);
9543           emitcode ("mov", "%s,%s",
9544                     preg->name,
9545                     aopGet (left, 0, FALSE, TRUE));
9546           rname = preg->name;
9547         }
9548     }
9549   else
9550     rname = aopGet (left, 0, FALSE, FALSE);
9551
9552   //aopOp (result, ic, FALSE);
9553   aopOp (result, ic, result?TRUE:FALSE);
9554
9555   /* if bitfield then unpack the bits */
9556   if (IS_BITFIELD (retype))
9557     genUnpackBits (result, rname, POINTER, ifx);
9558   else
9559     {
9560       /* we have can just get the values */
9561       int size = AOP_SIZE (result);
9562       int offset = 0;
9563
9564       while (size--)
9565         {
9566           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9567             {
9568
9569               emitcode ("mov", "a,@%s", rname);
9570               if (!ifx)
9571               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9572             }
9573           else
9574             {
9575               sprintf (buffer, "@%s", rname);
9576               aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9577             }
9578           offset++;
9579           if (size || pi)
9580             emitcode ("inc", "%s", rname);
9581         }
9582     }
9583
9584   /* now some housekeeping stuff */
9585   if (aop)       /* we had to allocate for this iCode */
9586     {
9587       if (pi) { /* post increment present */
9588         aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9589       }
9590       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9591     }
9592   else
9593     {
9594       /* we did not allocate which means left
9595          already in a pointer register, then
9596          if size > 0 && this could be used again
9597          we have to point it back to where it
9598          belongs */
9599       if ((AOP_SIZE (result) > 1 &&
9600            !OP_SYMBOL (left)->remat &&
9601            (OP_SYMBOL (left)->liveTo > ic->seq ||
9602             ic->depth)) &&
9603           !pi)
9604         {
9605           int size = AOP_SIZE (result) - 1;
9606           while (size--)
9607             emitcode ("dec", "%s", rname);
9608         }
9609     }
9610
9611   if (ifx && !ifx->generated)
9612     {
9613       genIfxJump (ifx, "a", left, NULL, result);
9614     }
9615
9616   /* done */
9617   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9618   freeAsmop (left, NULL, ic, TRUE);
9619   if (pi) pi->generated = 1;
9620 }
9621
9622 /*-----------------------------------------------------------------*/
9623 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9624 /*-----------------------------------------------------------------*/
9625 static void
9626 genPagedPointerGet (operand * left,
9627                     operand * result,
9628                     iCode * ic,
9629                     iCode *pi,
9630                     iCode *ifx)
9631 {
9632   asmop *aop = NULL;
9633   regs *preg = NULL;
9634   char *rname;
9635   sym_link *rtype, *retype;
9636
9637   D(emitcode (";     genPagedPointerGet",""));
9638
9639   rtype = operandType (result);
9640   retype = getSpec (rtype);
9641
9642   aopOp (left, ic, FALSE);
9643
9644   /* if the value is already in a pointer register
9645      then don't need anything more */
9646   if (!AOP_INPREG (AOP (left)))
9647     {
9648       /* otherwise get a free pointer register */
9649       aop = newAsmop (0);
9650       preg = getFreePtr (ic, &aop, FALSE);
9651       emitcode ("mov", "%s,%s",
9652                 preg->name,
9653                 aopGet (left, 0, FALSE, TRUE));
9654       rname = preg->name;
9655     }
9656   else
9657     rname = aopGet (left, 0, FALSE, FALSE);
9658
9659   aopOp (result, ic, FALSE);
9660
9661   /* if bitfield then unpack the bits */
9662   if (IS_BITFIELD (retype))
9663     genUnpackBits (result, rname, PPOINTER, ifx);
9664   else
9665     {
9666       /* we have can just get the values */
9667       int size = AOP_SIZE (result);
9668       int offset = 0;
9669
9670       while (size--)
9671         {
9672
9673           emitcode ("movx", "a,@%s", rname);
9674           if (!ifx)
9675           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9676
9677           offset++;
9678
9679           if (size || pi)
9680             emitcode ("inc", "%s", rname);
9681         }
9682     }
9683
9684   /* now some housekeeping stuff */
9685   if (aop) /* we had to allocate for this iCode */
9686     {
9687       if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9688       freeAsmop (NULL, aop, ic, TRUE);
9689     }
9690   else
9691     {
9692       /* we did not allocate which means left
9693          already in a pointer register, then
9694          if size > 0 && this could be used again
9695          we have to point it back to where it
9696          belongs */
9697       if ((AOP_SIZE (result) > 1 &&
9698            !OP_SYMBOL (left)->remat &&
9699            (OP_SYMBOL (left)->liveTo > ic->seq ||
9700             ic->depth)) &&
9701           !pi)
9702         {
9703           int size = AOP_SIZE (result) - 1;
9704           while (size--)
9705             emitcode ("dec", "%s", rname);
9706         }
9707     }
9708
9709   if (ifx && !ifx->generated)
9710     {
9711       genIfxJump (ifx, "a", left, NULL, result);
9712     }
9713
9714   /* done */
9715   freeAsmop (result, NULL, ic, TRUE);
9716   freeAsmop (left, NULL, ic, TRUE);
9717   if (pi) pi->generated = 1;
9718 }
9719
9720 /*--------------------------------------------------------------------*/
9721 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9722 /*--------------------------------------------------------------------*/
9723 static void
9724 loadDptrFromOperand (operand *op, bool loadBToo)
9725 {
9726   if (AOP_TYPE (op) != AOP_STR)
9727     {
9728       /* if this is rematerializable */
9729       if (AOP_TYPE (op) == AOP_IMMD)
9730         {
9731           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9732           if (loadBToo)
9733             {
9734               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9735                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9736               else
9737                 {
9738                   wassertl(FALSE, "need pointerCode");
9739                   emitcode ("", "; mov b,???");
9740                   /* genPointerGet and genPointerSet originally did different
9741                   ** things for this case. Both seem wrong.
9742                   ** from genPointerGet:
9743                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9744                   ** from genPointerSet:
9745                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9746                   */
9747                 }
9748             }
9749         }
9750       else if (AOP_TYPE (op) == AOP_DPTR)
9751         {
9752           if (loadBToo)
9753             {
9754               MOVA (aopGet (op, 0, FALSE, FALSE));
9755               emitcode ("push", "acc");
9756               MOVA (aopGet (op, 1, FALSE, FALSE));
9757               emitcode ("push", "acc");
9758               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9759               emitcode ("pop", "dph");
9760               emitcode ("pop", "dpl");
9761             }
9762           else
9763             {
9764               MOVA (aopGet (op, 0, FALSE, FALSE));
9765               emitcode ("push", "acc");
9766               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9767               emitcode ("pop", "dpl");
9768             }
9769         }
9770       else
9771         {                       /* we need to get it byte by byte */
9772           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9773           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9774           if (loadBToo)
9775             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9776         }
9777     }
9778 }
9779
9780 /*-----------------------------------------------------------------*/
9781 /* genFarPointerGet - gget value from far space                    */
9782 /*-----------------------------------------------------------------*/
9783 static void
9784 genFarPointerGet (operand * left,
9785                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9786 {
9787   int size, offset;
9788   sym_link *retype = getSpec (operandType (result));
9789
9790   D(emitcode (";     genFarPointerGet",""));
9791
9792   aopOp (left, ic, FALSE);
9793   loadDptrFromOperand (left, FALSE);
9794
9795   /* so dptr now contains the address */
9796   aopOp (result, ic, FALSE);
9797
9798   /* if bit then unpack */
9799   if (IS_BITFIELD (retype))
9800     genUnpackBits (result, "dptr", FPOINTER, ifx);
9801   else
9802     {
9803       size = AOP_SIZE (result);
9804       offset = 0;
9805
9806       while (size--)
9807         {
9808           emitcode ("movx", "a,@dptr");
9809           if (!ifx)
9810             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9811           if (size || pi)
9812             emitcode ("inc", "dptr");
9813         }
9814     }
9815
9816   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9817     {
9818     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9819     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9820     pi->generated = 1;
9821   }
9822
9823   if (ifx && !ifx->generated)
9824     {
9825       genIfxJump (ifx, "a", left, NULL, result);
9826     }
9827
9828   freeAsmop (result, NULL, ic, TRUE);
9829   freeAsmop (left, NULL, ic, TRUE);
9830 }
9831
9832 /*-----------------------------------------------------------------*/
9833 /* genCodePointerGet - gget value from code space                  */
9834 /*-----------------------------------------------------------------*/
9835 static void
9836 genCodePointerGet (operand * left,
9837                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9838 {
9839   int size, offset;
9840   sym_link *retype = getSpec (operandType (result));
9841
9842   D(emitcode (";     genCodePointerGet",""));
9843
9844   aopOp (left, ic, FALSE);
9845   loadDptrFromOperand (left, FALSE);
9846
9847   /* so dptr now contains the address */
9848   aopOp (result, ic, FALSE);
9849
9850   /* if bit then unpack */
9851   if (IS_BITFIELD (retype))
9852     genUnpackBits (result, "dptr", CPOINTER, ifx);
9853   else
9854     {
9855       size = AOP_SIZE (result);
9856       offset = 0;
9857
9858       while (size--)
9859         {
9860           if (pi)
9861             {
9862               emitcode ("clr", "a");
9863               emitcode ("movc", "a,@a+dptr");
9864               if (!ifx)
9865               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9866               emitcode ("inc", "dptr");
9867             }
9868           else
9869             {
9870               emitcode ("mov", "a,#0x%02x", offset);
9871               emitcode ("movc", "a,@a+dptr");
9872               if (!ifx)
9873               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9874             }
9875         }
9876     }
9877
9878   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9879     {
9880     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9881     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9882     pi->generated = 1;
9883   }
9884
9885   if (ifx && !ifx->generated)
9886     {
9887       genIfxJump (ifx, "a", left, NULL, result);
9888     }
9889
9890   freeAsmop (result, NULL, ic, TRUE);
9891   freeAsmop (left, NULL, ic, TRUE);
9892 }
9893
9894 /*-----------------------------------------------------------------*/
9895 /* genGenPointerGet - gget value from generic pointer space        */
9896 /*-----------------------------------------------------------------*/
9897 static void
9898 genGenPointerGet (operand * left,
9899                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9900 {
9901   int size, offset;
9902   sym_link *retype = getSpec (operandType (result));
9903
9904   D(emitcode (";     genGenPointerGet",""));
9905
9906   aopOp (left, ic, FALSE);
9907   loadDptrFromOperand (left, TRUE);
9908
9909   /* so dptr know contains the address */
9910   aopOp (result, ic, FALSE);
9911
9912   /* if bit then unpack */
9913   if (IS_BITFIELD (retype))
9914     genUnpackBits (result, "dptr", GPOINTER, ifx);
9915   else
9916     {
9917       size = AOP_SIZE (result);
9918       offset = 0;
9919
9920       while (size--)
9921         {
9922           emitcode ("lcall", "__gptrget");
9923           if (!ifx)
9924           aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9925           if (size || pi)
9926             emitcode ("inc", "dptr");
9927         }
9928     }
9929
9930   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9931     {
9932     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9933     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9934     pi->generated = 1;
9935   }
9936
9937   if (ifx && !ifx->generated)
9938     {
9939       genIfxJump (ifx, "a", left, NULL, result);
9940     }
9941
9942   freeAsmop (result, NULL, ic, TRUE);
9943   freeAsmop (left, NULL, ic, TRUE);
9944 }
9945
9946 /*-----------------------------------------------------------------*/
9947 /* genPointerGet - generate code for pointer get                   */
9948 /*-----------------------------------------------------------------*/
9949 static void
9950 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9951 {
9952   operand *left, *result;
9953   sym_link *type, *etype;
9954   int p_type;
9955
9956   D(emitcode (";     genPointerGet",""));
9957
9958   left = IC_LEFT (ic);
9959   result = IC_RESULT (ic);
9960
9961   if (getSize (operandType (result))>1)
9962     ifx = NULL;
9963
9964   /* depending on the type of pointer we need to
9965      move it to the correct pointer register */
9966   type = operandType (left);
9967   etype = getSpec (type);
9968   /* if left is of type of pointer then it is simple */
9969   if (IS_PTR (type) && !IS_FUNC (type->next))
9970     p_type = DCL_TYPE (type);
9971   else
9972     {
9973       /* we have to go by the storage class */
9974       p_type = PTR_TYPE (SPEC_OCLS (etype));
9975     }
9976
9977   /* special case when cast remat */
9978   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9979       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9980           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9981           type = operandType (left);
9982           p_type = DCL_TYPE (type);
9983   }
9984   /* now that we have the pointer type we assign
9985      the pointer values */
9986   switch (p_type)
9987     {
9988
9989     case POINTER:
9990     case IPOINTER:
9991       genNearPointerGet (left, result, ic, pi, ifx);
9992       break;
9993
9994     case PPOINTER:
9995       genPagedPointerGet (left, result, ic, pi, ifx);
9996       break;
9997
9998     case FPOINTER:
9999       genFarPointerGet (left, result, ic, pi, ifx);
10000       break;
10001
10002     case CPOINTER:
10003       genCodePointerGet (left, result, ic, pi, ifx);
10004       break;
10005
10006     case GPOINTER:
10007       genGenPointerGet (left, result, ic, pi, ifx);
10008       break;
10009     }
10010
10011 }
10012
10013
10014
10015 /*-----------------------------------------------------------------*/
10016 /* genPackBits - generates code for packed bit storage             */
10017 /*-----------------------------------------------------------------*/
10018 static void
10019 genPackBits (sym_link * etype,
10020              operand * right,
10021              char *rname, int p_type)
10022 {
10023   int offset = 0;       /* source byte offset */
10024   int rlen = 0;         /* remaining bitfield length */
10025   int blen;             /* bitfield length */
10026   int bstr;             /* bitfield starting bit within byte */
10027   int litval;           /* source literal value (if AOP_LIT) */
10028   unsigned char mask;   /* bitmask within current byte */
10029
10030   D(emitcode (";     genPackBits",""));
10031
10032   blen = SPEC_BLEN (etype);
10033   bstr = SPEC_BSTR (etype);
10034
10035   /* If the bitfield length is less than a byte */
10036   if (blen < 8)
10037     {
10038       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10039               (unsigned char) (0xFF >> (8 - bstr)));
10040
10041       if (AOP_TYPE (right) == AOP_LIT)
10042         {
10043           /* Case with a bitfield length <8 and literal source
10044           */
10045           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10046           litval <<= bstr;
10047           litval &= (~mask) & 0xff;
10048           emitPtrByteGet (rname, p_type, FALSE);
10049           if ((mask|litval)!=0xff)
10050             emitcode ("anl","a,#0x%02x", mask);
10051           if (litval)
10052             emitcode ("orl","a,#0x%02x", litval);
10053         }
10054       else
10055         {
10056           if ((blen==1) && (p_type!=GPOINTER))
10057             {
10058               /* Case with a bitfield length == 1 and no generic pointer
10059               */
10060               if (AOP_TYPE (right) == AOP_CRY)
10061                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10062               else
10063                 {
10064                   MOVA (aopGet (right, 0, FALSE, FALSE));
10065                   emitcode ("rrc","a");
10066                 }
10067               emitPtrByteGet (rname, p_type, FALSE);
10068               emitcode ("mov","acc.%d,c",bstr);
10069             }
10070           else
10071             {
10072               bool pushedB;
10073               /* Case with a bitfield length < 8 and arbitrary source
10074               */
10075               MOVA (aopGet (right, 0, FALSE, FALSE));
10076               /* shift and mask source value */
10077               AccLsh (bstr);
10078               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10079
10080               pushedB = pushB ();
10081               /* transfer A to B and get next byte */
10082               emitPtrByteGet (rname, p_type, TRUE);
10083
10084               emitcode ("anl", "a,#0x%02x", mask);
10085               emitcode ("orl", "a,b");
10086               if (p_type == GPOINTER)
10087                 emitcode ("pop", "b");
10088
10089               popB (pushedB);
10090            }
10091         }
10092
10093       emitPtrByteSet (rname, p_type, "a");
10094       return;
10095     }
10096
10097   /* Bit length is greater than 7 bits. In this case, copy  */
10098   /* all except the partial byte at the end                 */
10099   for (rlen=blen;rlen>=8;rlen-=8)
10100     {
10101       emitPtrByteSet (rname, p_type,
10102                       aopGet (right, offset++, FALSE, TRUE) );
10103       if (rlen>8)
10104         emitcode ("inc", "%s", rname);
10105     }
10106
10107   /* If there was a partial byte at the end */
10108   if (rlen)
10109     {
10110       mask = (((unsigned char) -1 << rlen) & 0xff);
10111
10112       if (AOP_TYPE (right) == AOP_LIT)
10113         {
10114           /* Case with partial byte and literal source
10115           */
10116           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10117           litval >>= (blen-rlen);
10118           litval &= (~mask) & 0xff;
10119           emitPtrByteGet (rname, p_type, FALSE);
10120           if ((mask|litval)!=0xff)
10121             emitcode ("anl","a,#0x%02x", mask);
10122           if (litval)
10123             emitcode ("orl","a,#0x%02x", litval);
10124         }
10125       else
10126         {
10127           bool pushedB;
10128           /* Case with partial byte and arbitrary source
10129           */
10130           MOVA (aopGet (right, offset++, FALSE, FALSE));
10131           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10132
10133           pushedB = pushB ();
10134           /* transfer A to B and get next byte */
10135           emitPtrByteGet (rname, p_type, TRUE);
10136
10137           emitcode ("anl", "a,#0x%02x", mask);
10138           emitcode ("orl", "a,b");
10139           if (p_type == GPOINTER)
10140             emitcode ("pop", "b");
10141
10142           popB (pushedB);
10143         }
10144       emitPtrByteSet (rname, p_type, "a");
10145     }
10146
10147 }
10148
10149
10150 /*-----------------------------------------------------------------*/
10151 /* genDataPointerSet - remat pointer to data space                 */
10152 /*-----------------------------------------------------------------*/
10153 static void
10154 genDataPointerSet (operand * right,
10155                    operand * result,
10156                    iCode * ic)
10157 {
10158   int size, offset = 0;
10159   char *l, buffer[256];
10160
10161   D(emitcode (";     genDataPointerSet",""));
10162
10163   aopOp (right, ic, FALSE);
10164
10165   l = aopGet (result, 0, FALSE, TRUE);
10166   size = AOP_SIZE (right);
10167   while (size--)
10168     {
10169       if (offset)
10170         sprintf (buffer, "(%s + %d)", l + 1, offset);
10171       else
10172         sprintf (buffer, "%s", l + 1);
10173       emitcode ("mov", "%s,%s", buffer,
10174                 aopGet (right, offset++, FALSE, FALSE));
10175     }
10176
10177   freeAsmop (result, NULL, ic, TRUE);
10178   freeAsmop (right, NULL, ic, TRUE);
10179 }
10180
10181 /*-----------------------------------------------------------------*/
10182 /* genNearPointerSet - emitcode for near pointer put                */
10183 /*-----------------------------------------------------------------*/
10184 static void
10185 genNearPointerSet (operand * right,
10186                    operand * result,
10187                    iCode * ic,
10188                    iCode * pi)
10189 {
10190   asmop *aop = NULL;
10191   regs *preg = NULL;
10192   char *rname, *l;
10193   sym_link *retype, *letype;
10194   sym_link *ptype = operandType (result);
10195
10196   D(emitcode (";     genNearPointerSet",""));
10197
10198   retype = getSpec (operandType (right));
10199   letype = getSpec (ptype);
10200   aopOp (result, ic, FALSE);
10201
10202   /* if the result is rematerializable &
10203      in data space & not a bit variable */
10204   if (AOP_TYPE (result) == AOP_IMMD &&
10205       DCL_TYPE (ptype) == POINTER &&
10206       !IS_BITVAR (retype) &&
10207       !IS_BITVAR (letype))
10208     {
10209       genDataPointerSet (right, result, ic);
10210       return;
10211     }
10212
10213   /* if the value is already in a pointer register
10214      then don't need anything more */
10215   if (!AOP_INPREG (AOP (result)))
10216     {
10217         if (
10218             //AOP_TYPE (result) == AOP_STK
10219             IS_AOP_PREG(result)
10220             )
10221         {
10222             // Aha, it is a pointer, just in disguise.
10223             rname = aopGet (result, 0, FALSE, FALSE);
10224             if (*rname != '@')
10225             {
10226                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10227                         __FILE__, __LINE__);
10228             }
10229             else
10230             {
10231                 // Expected case.
10232                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10233                 rname++;  // skip the '@'.
10234             }
10235         }
10236         else
10237         {
10238             /* otherwise get a free pointer register */
10239             aop = newAsmop (0);
10240             preg = getFreePtr (ic, &aop, FALSE);
10241             emitcode ("mov", "%s,%s",
10242                       preg->name,
10243                       aopGet (result, 0, FALSE, TRUE));
10244             rname = preg->name;
10245         }
10246     }
10247     else
10248     {
10249         rname = aopGet (result, 0, FALSE, FALSE);
10250     }
10251
10252   aopOp (right, ic, FALSE);
10253
10254   /* if bitfield then unpack the bits */
10255   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10256     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10257   else
10258     {
10259       /* we have can just get the values */
10260       int size = AOP_SIZE (right);
10261       int offset = 0;
10262
10263       while (size--)
10264         {
10265           l = aopGet (right, offset, FALSE, TRUE);
10266           if (*l == '@')
10267             {
10268               MOVA (l);
10269               emitcode ("mov", "@%s,a", rname);
10270             }
10271           else
10272             emitcode ("mov", "@%s,%s", rname, l);
10273           if (size || pi)
10274             emitcode ("inc", "%s", rname);
10275           offset++;
10276         }
10277     }
10278
10279   /* now some housekeeping stuff */
10280   if (aop) /* we had to allocate for this iCode */
10281     {
10282       if (pi)
10283         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10284       freeAsmop (NULL, aop, ic, TRUE);
10285     }
10286   else
10287     {
10288       /* we did not allocate which means left
10289          already in a pointer register, then
10290          if size > 0 && this could be used again
10291          we have to point it back to where it
10292          belongs */
10293       if ((AOP_SIZE (right) > 1 &&
10294            !OP_SYMBOL (result)->remat &&
10295            (OP_SYMBOL (result)->liveTo > ic->seq ||
10296             ic->depth)) &&
10297           !pi)
10298         {
10299           int size = AOP_SIZE (right) - 1;
10300           while (size--)
10301             emitcode ("dec", "%s", rname);
10302         }
10303     }
10304
10305   /* done */
10306   if (pi) pi->generated = 1;
10307   freeAsmop (result, NULL, ic, TRUE);
10308   freeAsmop (right, NULL, ic, TRUE);
10309 }
10310
10311 /*-----------------------------------------------------------------*/
10312 /* genPagedPointerSet - emitcode for Paged pointer put             */
10313 /*-----------------------------------------------------------------*/
10314 static void
10315 genPagedPointerSet (operand * right,
10316                     operand * result,
10317                     iCode * ic,
10318                     iCode * pi)
10319 {
10320   asmop *aop = NULL;
10321   regs *preg = NULL;
10322   char *rname, *l;
10323   sym_link *retype, *letype;
10324
10325   D(emitcode (";     genPagedPointerSet",""));
10326
10327   retype = getSpec (operandType (right));
10328   letype = getSpec (operandType (result));
10329
10330   aopOp (result, ic, FALSE);
10331
10332   /* if the value is already in a pointer register
10333      then don't need anything more */
10334   if (!AOP_INPREG (AOP (result)))
10335     {
10336       /* otherwise get a free pointer register */
10337       aop = newAsmop (0);
10338       preg = getFreePtr (ic, &aop, FALSE);
10339       emitcode ("mov", "%s,%s",
10340                 preg->name,
10341                 aopGet (result, 0, FALSE, TRUE));
10342       rname = preg->name;
10343     }
10344   else
10345     rname = aopGet (result, 0, FALSE, FALSE);
10346
10347   aopOp (right, ic, FALSE);
10348
10349   /* if bitfield then unpack the bits */
10350   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10351     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10352   else
10353     {
10354       /* we have can just get the values */
10355       int size = AOP_SIZE (right);
10356       int offset = 0;
10357
10358       while (size--)
10359         {
10360           l = aopGet (right, offset, FALSE, TRUE);
10361
10362           MOVA (l);
10363           emitcode ("movx", "@%s,a", rname);
10364
10365           if (size || pi)
10366             emitcode ("inc", "%s", rname);
10367
10368           offset++;
10369         }
10370     }
10371
10372   /* now some housekeeping stuff */
10373   if (aop) /* we had to allocate for this iCode */
10374     {
10375       if (pi)
10376         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10377       freeAsmop (NULL, aop, ic, TRUE);
10378     }
10379   else
10380     {
10381       /* we did not allocate which means left
10382          already in a pointer register, then
10383          if size > 0 && this could be used again
10384          we have to point it back to where it
10385          belongs */
10386       if (AOP_SIZE (right) > 1 &&
10387           !OP_SYMBOL (result)->remat &&
10388           (OP_SYMBOL (result)->liveTo > ic->seq ||
10389            ic->depth))
10390         {
10391           int size = AOP_SIZE (right) - 1;
10392           while (size--)
10393             emitcode ("dec", "%s", rname);
10394         }
10395     }
10396
10397   /* done */
10398   if (pi) pi->generated = 1;
10399   freeAsmop (result, NULL, ic, TRUE);
10400   freeAsmop (right, NULL, ic, TRUE);
10401 }
10402
10403 /*-----------------------------------------------------------------*/
10404 /* genFarPointerSet - set value from far space                     */
10405 /*-----------------------------------------------------------------*/
10406 static void
10407 genFarPointerSet (operand * right,
10408                   operand * result, iCode * ic, iCode * pi)
10409 {
10410   int size, offset;
10411   sym_link *retype = getSpec (operandType (right));
10412   sym_link *letype = getSpec (operandType (result));
10413
10414   D(emitcode (";     genFarPointerSet",""));
10415
10416   aopOp (result, ic, FALSE);
10417   loadDptrFromOperand (result, FALSE);
10418
10419   /* so dptr know contains the address */
10420   aopOp (right, ic, FALSE);
10421
10422   /* if bit then unpack */
10423   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10424     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10425   else
10426     {
10427       size = AOP_SIZE (right);
10428       offset = 0;
10429
10430       while (size--)
10431         {
10432           char *l = aopGet (right, offset++, FALSE, FALSE);
10433           MOVA (l);
10434           emitcode ("movx", "@dptr,a");
10435           if (size || pi)
10436             emitcode ("inc", "dptr");
10437         }
10438     }
10439   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10440     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10441     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10442     pi->generated=1;
10443   }
10444   freeAsmop (result, NULL, ic, TRUE);
10445   freeAsmop (right, NULL, ic, TRUE);
10446 }
10447
10448 /*-----------------------------------------------------------------*/
10449 /* genGenPointerSet - set value from generic pointer space         */
10450 /*-----------------------------------------------------------------*/
10451 static void
10452 genGenPointerSet (operand * right,
10453                   operand * result, iCode * ic, iCode * pi)
10454 {
10455   int size, offset;
10456   sym_link *retype = getSpec (operandType (right));
10457   sym_link *letype = getSpec (operandType (result));
10458
10459   D(emitcode (";     genGenPointerSet",""));
10460
10461   aopOp (result, ic, FALSE);
10462   loadDptrFromOperand (result, TRUE);
10463
10464   /* so dptr know contains the address */
10465   aopOp (right, ic, FALSE);
10466
10467   /* if bit then unpack */
10468   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10469     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10470   else
10471     {
10472       size = AOP_SIZE (right);
10473       offset = 0;
10474
10475       while (size--)
10476         {
10477           char *l = aopGet (right, offset++, FALSE, FALSE);
10478           MOVA (l);
10479           emitcode ("lcall", "__gptrput");
10480           if (size || pi)
10481             emitcode ("inc", "dptr");
10482         }
10483     }
10484
10485   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10486     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10487     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10488     pi->generated=1;
10489   }
10490   freeAsmop (result, NULL, ic, TRUE);
10491   freeAsmop (right, NULL, ic, TRUE);
10492 }
10493
10494 /*-----------------------------------------------------------------*/
10495 /* genPointerSet - stores the value into a pointer location        */
10496 /*-----------------------------------------------------------------*/
10497 static void
10498 genPointerSet (iCode * ic, iCode *pi)
10499 {
10500   operand *right, *result;
10501   sym_link *type, *etype;
10502   int p_type;
10503
10504   D(emitcode (";     genPointerSet",""));
10505
10506   right = IC_RIGHT (ic);
10507   result = IC_RESULT (ic);
10508
10509   /* depending on the type of pointer we need to
10510      move it to the correct pointer register */
10511   type = operandType (result);
10512   etype = getSpec (type);
10513   /* if left is of type of pointer then it is simple */
10514   if (IS_PTR (type) && !IS_FUNC (type->next))
10515     {
10516       p_type = DCL_TYPE (type);
10517     }
10518   else
10519     {
10520       /* we have to go by the storage class */
10521       p_type = PTR_TYPE (SPEC_OCLS (etype));
10522     }
10523
10524   /* special case when cast remat */
10525   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10526       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10527           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10528           type = operandType (result);
10529           p_type = DCL_TYPE (type);
10530   }
10531   /* now that we have the pointer type we assign
10532      the pointer values */
10533   switch (p_type)
10534     {
10535
10536     case POINTER:
10537     case IPOINTER:
10538       genNearPointerSet (right, result, ic, pi);
10539       break;
10540
10541     case PPOINTER:
10542       genPagedPointerSet (right, result, ic, pi);
10543       break;
10544
10545     case FPOINTER:
10546       genFarPointerSet (right, result, ic, pi);
10547       break;
10548
10549     case GPOINTER:
10550       genGenPointerSet (right, result, ic, pi);
10551       break;
10552
10553     default:
10554       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10555               "genPointerSet: illegal pointer type");
10556     }
10557
10558 }
10559
10560 /*-----------------------------------------------------------------*/
10561 /* genIfx - generate code for Ifx statement                        */
10562 /*-----------------------------------------------------------------*/
10563 static void
10564 genIfx (iCode * ic, iCode * popIc)
10565 {
10566   operand *cond = IC_COND (ic);
10567   int isbit = 0;
10568   char *dup = NULL;
10569
10570   D(emitcode (";     genIfx",""));
10571
10572   aopOp (cond, ic, FALSE);
10573
10574   /* get the value into acc */
10575   if (AOP_TYPE (cond) != AOP_CRY)
10576     toBoolean (cond);
10577   else
10578     {
10579       isbit = 1;
10580       if (AOP(cond)->aopu.aop_dir)
10581         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10582     }
10583   /* the result is now in the accumulator or a directly addressable bit */
10584   freeAsmop (cond, NULL, ic, TRUE);
10585
10586   /* if there was something to be popped then do it */
10587   if (popIc)
10588     genIpop (popIc);
10589
10590   /* if the condition is a bit variable */
10591   if (isbit && dup)
10592     genIfxJump(ic, dup, NULL, NULL, NULL);
10593   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10594     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10595   else if (isbit && !IS_ITEMP (cond))
10596     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10597   else
10598     genIfxJump (ic, "a", NULL, NULL, NULL);
10599
10600   ic->generated = 1;
10601 }
10602
10603 /*-----------------------------------------------------------------*/
10604 /* genAddrOf - generates code for address of                       */
10605 /*-----------------------------------------------------------------*/
10606 static void
10607 genAddrOf (iCode * ic)
10608 {
10609   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10610   int size, offset;
10611
10612   D(emitcode (";     genAddrOf",""));
10613
10614   aopOp (IC_RESULT (ic), ic, FALSE);
10615
10616   /* if the operand is on the stack then we
10617      need to get the stack offset of this
10618      variable */
10619   if (sym->onStack)
10620     {
10621       /* if it has an offset then we need to compute
10622          it */
10623       if (sym->stack)
10624         {
10625           emitcode ("mov", "a,%s", SYM_BP (sym));
10626           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10627                                          ((char) (sym->stack - _G.nRegsSaved)) :
10628                                          ((char) sym->stack)) & 0xff);
10629           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10630         }
10631       else
10632         {
10633           /* we can just move _bp */
10634           aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10635         }
10636       /* fill the result with zero */
10637       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10638
10639       offset = 1;
10640       while (size--)
10641         {
10642           aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10643         }
10644
10645       goto release;
10646     }
10647
10648   /* object not on stack then we need the name */
10649   size = AOP_SIZE (IC_RESULT (ic));
10650   offset = 0;
10651
10652   while (size--)
10653     {
10654       char s[SDCC_NAME_MAX];
10655       if (offset)
10656         sprintf (s, "#(%s >> %d)",
10657                  sym->rname,
10658                  offset * 8);
10659       else
10660         sprintf (s, "#%s", sym->rname);
10661       aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10662     }
10663
10664 release:
10665   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10666
10667 }
10668
10669 /*-----------------------------------------------------------------*/
10670 /* genFarFarAssign - assignment when both are in far space         */
10671 /*-----------------------------------------------------------------*/
10672 static void
10673 genFarFarAssign (operand * result, operand * right, iCode * ic)
10674 {
10675   int size = AOP_SIZE (right);
10676   int offset = 0;
10677   char *l;
10678
10679   D(emitcode (";     genFarFarAssign",""));
10680
10681   /* first push the right side on to the stack */
10682   while (size--)
10683     {
10684       l = aopGet (right, offset++, FALSE, FALSE);
10685       MOVA (l);
10686       emitcode ("push", "acc");
10687     }
10688
10689   freeAsmop (right, NULL, ic, FALSE);
10690   /* now assign DPTR to result */
10691   aopOp (result, ic, FALSE);
10692   size = AOP_SIZE (result);
10693   while (size--)
10694     {
10695       emitcode ("pop", "acc");
10696       aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10697     }
10698   freeAsmop (result, NULL, ic, FALSE);
10699 }
10700
10701 /*-----------------------------------------------------------------*/
10702 /* genAssign - generate code for assignment                        */
10703 /*-----------------------------------------------------------------*/
10704 static void
10705 genAssign (iCode * ic)
10706 {
10707   operand *result, *right;
10708   int size, offset;
10709   unsigned long lit = 0L;
10710
10711   D(emitcode(";     genAssign",""));
10712
10713   result = IC_RESULT (ic);
10714   right = IC_RIGHT (ic);
10715
10716   /* if they are the same */
10717   if (operandsEqu (result, right) &&
10718       !isOperandVolatile (result, FALSE) &&
10719       !isOperandVolatile (right, FALSE))
10720     return;
10721
10722   aopOp (right, ic, FALSE);
10723
10724   /* special case both in far space */
10725   if (AOP_TYPE (right) == AOP_DPTR &&
10726       IS_TRUE_SYMOP (result) &&
10727       isOperandInFarSpace (result))
10728     {
10729
10730       genFarFarAssign (result, right, ic);
10731       return;
10732     }
10733
10734   aopOp (result, ic, TRUE);
10735
10736   /* if they are the same registers */
10737   if (sameRegs (AOP (right), AOP (result)) &&
10738       !isOperandVolatile (result, FALSE) &&
10739       !isOperandVolatile (right, FALSE))
10740     goto release;
10741
10742   /* if the result is a bit */
10743   if (AOP_TYPE (result) == AOP_CRY)
10744     {
10745
10746       /* if the right size is a literal then
10747          we know what the value is */
10748       if (AOP_TYPE (right) == AOP_LIT)
10749         {
10750           if (((int) operandLitValue (right)))
10751             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10752           else
10753             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10754           goto release;
10755         }
10756
10757       /* the right is also a bit variable */
10758       if (AOP_TYPE (right) == AOP_CRY)
10759         {
10760           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10761           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10762           goto release;
10763         }
10764
10765       /* we need to or */
10766       toBoolean (right);
10767       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10768       goto release;
10769     }
10770
10771   /* bit variables done */
10772   /* general case */
10773   size = AOP_SIZE (result);
10774   offset = 0;
10775   if (AOP_TYPE (right) == AOP_LIT)
10776     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10777   if ((size > 1) &&
10778       (AOP_TYPE (result) != AOP_REG) &&
10779       (AOP_TYPE (right) == AOP_LIT) &&
10780       !IS_FLOAT (operandType (right)) &&
10781       (lit < 256L))
10782     {
10783       while ((size) && (lit))
10784         {
10785           aopPut (result,
10786                   aopGet (right, offset, FALSE, FALSE),
10787                   offset,
10788                   isOperandVolatile (result, FALSE));
10789           lit >>= 8;
10790           offset++;
10791           size--;
10792         }
10793       emitcode ("clr", "a");
10794       while (size--)
10795         {
10796           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10797           offset++;
10798         }
10799     }
10800   else
10801     {
10802       while (size--)
10803         {
10804           aopPut (result,
10805                   aopGet (right, offset, FALSE, FALSE),
10806                   offset,
10807                   isOperandVolatile (result, FALSE));
10808           offset++;
10809         }
10810     }
10811
10812 release:
10813   freeAsmop (result, NULL, ic, TRUE);
10814   freeAsmop (right, NULL, ic, TRUE);
10815 }
10816
10817 /*-----------------------------------------------------------------*/
10818 /* genJumpTab - generates code for jump table                      */
10819 /*-----------------------------------------------------------------*/
10820 static void
10821 genJumpTab (iCode * ic)
10822 {
10823   symbol *jtab,*jtablo,*jtabhi;
10824   char *l;
10825   unsigned int count;
10826
10827   D(emitcode (";     genJumpTab",""));
10828
10829   count = elementsInSet( IC_JTLABELS (ic) );
10830
10831   if( count <= 16 )
10832     {
10833       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10834          if the switch argument is in a register.
10835          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10836       /* (MB) What if peephole converts ljmp to sjmp or ret ???
10837          How will multiply by three be updated ???*/
10838       aopOp (IC_JTCOND (ic), ic, FALSE);
10839       /* get the condition into accumulator */
10840       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10841       MOVA (l);
10842       /* multiply by three */
10843       emitcode ("add", "a,acc");
10844       emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10845       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10846
10847       jtab = newiTempLabel (NULL);
10848       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10849       emitcode ("jmp", "@a+dptr");
10850       emitcode ("", "%05d$:", jtab->key + 100);
10851       /* now generate the jump labels */
10852       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10853            jtab = setNextItem (IC_JTLABELS (ic)))
10854         emitcode ("ljmp", "%05d$", jtab->key + 100);
10855     }
10856   else
10857     {
10858       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10859          if the switch argument is in a register.
10860          For n>6 this algorithm may be more compact */
10861       jtablo = newiTempLabel (NULL);
10862       jtabhi = newiTempLabel (NULL);
10863
10864       /* get the condition into accumulator.
10865          Using b as temporary storage, if register push/pop is needed */
10866       aopOp (IC_JTCOND (ic), ic, FALSE);
10867       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10868       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10869           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10870         {
10871           // (MB) what if B is in use???
10872           wassertl(!BINUSE, "B was in use");
10873           emitcode ("mov", "b,%s", l);
10874           l = "b";
10875         }
10876       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10877       MOVA (l);
10878       if( count <= 112 )
10879         {
10880           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10881           emitcode ("movc", "a,@a+pc");
10882           emitcode ("push", "acc");
10883
10884           MOVA (l);
10885           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10886           emitcode ("movc", "a,@a+pc");
10887           emitcode ("push", "acc");
10888         }
10889       else
10890         {
10891           /* this scales up to n<=255, but needs two more bytes
10892              and changes dptr */
10893           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10894           emitcode ("movc", "a,@a+dptr");
10895           emitcode ("push", "acc");
10896
10897           MOVA (l);
10898           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10899           emitcode ("movc", "a,@a+dptr");
10900           emitcode ("push", "acc");
10901         }
10902
10903       emitcode ("ret", "");
10904
10905       /* now generate jump table, LSB */
10906       emitcode ("", "%05d$:", jtablo->key + 100);
10907       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10908            jtab = setNextItem (IC_JTLABELS (ic)))
10909         emitcode (".db", "%05d$", jtab->key + 100);
10910
10911       /* now generate jump table, MSB */
10912       emitcode ("", "%05d$:", jtabhi->key + 100);
10913       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10914            jtab = setNextItem (IC_JTLABELS (ic)))
10915          emitcode (".db", "%05d$>>8", jtab->key + 100);
10916     }
10917 }
10918
10919 /*-----------------------------------------------------------------*/
10920 /* genCast - gen code for casting                                  */
10921 /*-----------------------------------------------------------------*/
10922 static void
10923 genCast (iCode * ic)
10924 {
10925   operand *result = IC_RESULT (ic);
10926   sym_link *ctype = operandType (IC_LEFT (ic));
10927   sym_link *rtype = operandType (IC_RIGHT (ic));
10928   operand *right = IC_RIGHT (ic);
10929   int size, offset;
10930
10931   D(emitcode(";     genCast",""));
10932
10933   /* if they are equivalent then do nothing */
10934   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10935     return;
10936
10937   aopOp (right, ic, FALSE);
10938   aopOp (result, ic, FALSE);
10939
10940   /* if the result is a bit (and not a bitfield) */
10941   // if (AOP_TYPE (result) == AOP_CRY)
10942   if (IS_BIT (OP_SYMBOL (result)->type))
10943     /* not for bitfields */
10944     {
10945       /* if the right size is a literal then
10946          we know what the value is */
10947       if (AOP_TYPE (right) == AOP_LIT)
10948         {
10949           if (((int) operandLitValue (right)))
10950             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10951           else
10952             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10953
10954           goto release;
10955         }
10956
10957       /* the right is also a bit variable */
10958       if (AOP_TYPE (right) == AOP_CRY)
10959         {
10960           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10961           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10962           goto release;
10963         }
10964
10965       /* we need to or */
10966       toBoolean (right);
10967       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10968       goto release;
10969     }
10970
10971
10972   /* if they are the same size : or less */
10973   if (AOP_SIZE (result) <= AOP_SIZE (right))
10974     {
10975
10976       /* if they are in the same place */
10977       if (sameRegs (AOP (right), AOP (result)))
10978         goto release;
10979
10980       /* if they in different places then copy */
10981       size = AOP_SIZE (result);
10982       offset = 0;
10983       while (size--)
10984         {
10985           aopPut (result,
10986                   aopGet (right, offset, FALSE, FALSE),
10987                   offset,
10988                   isOperandVolatile (result, FALSE));
10989           offset++;
10990         }
10991       goto release;
10992     }
10993
10994
10995   /* if the result is of type pointer */
10996   if (IS_PTR (ctype))
10997     {
10998
10999       int p_type;
11000       sym_link *type = operandType (right);
11001       sym_link *etype = getSpec (type);
11002
11003       /* pointer to generic pointer */
11004       if (IS_GENPTR (ctype))
11005         {
11006           if (IS_PTR (type))
11007             p_type = DCL_TYPE (type);
11008           else
11009             {
11010               if (SPEC_SCLS(etype)==S_REGISTER) {
11011                 // let's assume it is a generic pointer
11012                 p_type=GPOINTER;
11013               } else {
11014                 /* we have to go by the storage class */
11015                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11016               }
11017             }
11018
11019           /* the first two bytes are known */
11020           size = GPTRSIZE - 1;
11021           offset = 0;
11022           while (size--)
11023             {
11024               aopPut (result,
11025                       aopGet (right, offset, FALSE, FALSE),
11026                       offset,
11027                       isOperandVolatile (result, FALSE));
11028               offset++;
11029             }
11030           /* the last byte depending on type */
11031             {
11032                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11033                 char gpValStr[10];
11034
11035                 if (gpVal == -1)
11036                 {
11037                     // pointerTypeToGPByte will have bitched.
11038                     exit(1);
11039                 }
11040
11041                 sprintf(gpValStr, "#0x%x", gpVal);
11042                 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
11043             }
11044           goto release;
11045         }
11046
11047       /* just copy the pointers */
11048       size = AOP_SIZE (result);
11049       offset = 0;
11050       while (size--)
11051         {
11052           aopPut (result,
11053                   aopGet (right, offset, FALSE, FALSE),
11054                   offset,
11055                   isOperandVolatile (result, FALSE));
11056           offset++;
11057         }
11058       goto release;
11059     }
11060
11061   /* so we now know that the size of destination is greater
11062      than the size of the source */
11063   /* we move to result for the size of source */
11064   size = AOP_SIZE (right);
11065   offset = 0;
11066   while (size--)
11067     {
11068       aopPut (result,
11069               aopGet (right, offset, FALSE, FALSE),
11070               offset,
11071               isOperandVolatile (result, FALSE));
11072       offset++;
11073     }
11074
11075   /* now depending on the sign of the source && destination */
11076   size = AOP_SIZE (result) - AOP_SIZE (right);
11077   /* if unsigned or not an integral type */
11078   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11079     {
11080       while (size--)
11081         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11082     }
11083   else
11084     {
11085       /* we need to extend the sign :{ */
11086       char *l = aopGet (right, AOP_SIZE (right) - 1,
11087                         FALSE, FALSE);
11088       MOVA (l);
11089       emitcode ("rlc", "a");
11090       emitcode ("subb", "a,acc");
11091       while (size--)
11092         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11093     }
11094
11095   /* we are done hurray !!!! */
11096
11097 release:
11098   freeAsmop (result, NULL, ic, TRUE);
11099   freeAsmop (right, NULL, ic, TRUE);
11100 }
11101
11102 /*-----------------------------------------------------------------*/
11103 /* genDjnz - generate decrement & jump if not zero instrucion      */
11104 /*-----------------------------------------------------------------*/
11105 static int
11106 genDjnz (iCode * ic, iCode * ifx)
11107 {
11108   symbol *lbl, *lbl1;
11109   if (!ifx)
11110     return 0;
11111
11112   D(emitcode (";     genDjnz",""));
11113
11114   /* if the if condition has a false label
11115      then we cannot save */
11116   if (IC_FALSE (ifx))
11117     return 0;
11118
11119   /* if the minus is not of the form
11120      a = a - 1 */
11121   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11122       !IS_OP_LITERAL (IC_RIGHT (ic)))
11123     return 0;
11124
11125   if (operandLitValue (IC_RIGHT (ic)) != 1)
11126     return 0;
11127
11128   /* if the size of this greater than one then no
11129      saving */
11130   if (getSize (operandType (IC_RESULT (ic))) > 1)
11131     return 0;
11132
11133   /* otherwise we can save BIG */
11134   lbl = newiTempLabel (NULL);
11135   lbl1 = newiTempLabel (NULL);
11136
11137   aopOp (IC_RESULT (ic), ic, FALSE);
11138
11139   if (AOP_NEEDSACC(IC_RESULT(ic)))
11140   {
11141       /* If the result is accessed indirectly via
11142        * the accumulator, we must explicitly write
11143        * it back after the decrement.
11144        */
11145       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11146
11147       if (strcmp(rByte, "a"))
11148       {
11149            /* Something is hopelessly wrong */
11150            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11151                    __FILE__, __LINE__);
11152            /* We can just give up; the generated code will be inefficient,
11153             * but what the hey.
11154             */
11155            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11156            return 0;
11157       }
11158       emitcode ("dec", "%s", rByte);
11159       aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11160       emitcode ("jnz", "%05d$", lbl->key + 100);
11161   }
11162   else if (IS_AOP_PREG (IC_RESULT (ic)))
11163     {
11164       emitcode ("dec", "%s",
11165                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11166       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11167       emitcode ("jnz", "%05d$", lbl->key + 100);
11168     }
11169   else
11170     {
11171       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11172                 lbl->key + 100);
11173     }
11174   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11175   emitcode ("", "%05d$:", lbl->key + 100);
11176   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11177   emitcode ("", "%05d$:", lbl1->key + 100);
11178
11179   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11180   ifx->generated = 1;
11181   return 1;
11182 }
11183
11184 /*-----------------------------------------------------------------*/
11185 /* genReceive - generate code for a receive iCode                  */
11186 /*-----------------------------------------------------------------*/
11187 static void
11188 genReceive (iCode * ic)
11189 {
11190   int size = getSize (operandType (IC_RESULT (ic)));
11191   int offset = 0;
11192
11193   D(emitcode (";     genReceive",""));
11194
11195   if (ic->argreg == 1)
11196     { /* first parameter */
11197       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11198            isOperandInPagedSpace (IC_RESULT (ic))) &&
11199           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11200            IS_TRUE_SYMOP (IC_RESULT (ic))))
11201         {
11202           regs *tempRegs[4];
11203           int receivingA = 0;
11204           int roffset = 0;
11205
11206           for (offset = 0; offset<size; offset++)
11207             if (!strcmp (fReturn[offset], "a"))
11208               receivingA = 1;
11209
11210           if (!receivingA)
11211             {
11212               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11213                 {
11214                   for (offset = size-1; offset>0; offset--)
11215                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11216                   emitcode("mov","a,%s", fReturn[0]);
11217                   _G.accInUse++;
11218                   aopOp (IC_RESULT (ic), ic, FALSE);
11219                   _G.accInUse--;
11220                   aopPut (IC_RESULT (ic), "a", offset,
11221                           isOperandVolatile (IC_RESULT (ic), FALSE));
11222                   for (offset = 1; offset<size; offset++)
11223                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11224                             isOperandVolatile (IC_RESULT (ic), FALSE));
11225                   goto release;
11226                 }
11227             }
11228           else
11229             {
11230               if (getTempRegs(tempRegs, size, ic))
11231                 {
11232                   for (offset = 0; offset<size; offset++)
11233                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11234                   aopOp (IC_RESULT (ic), ic, FALSE);
11235                   for (offset = 0; offset<size; offset++)
11236                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11237                             isOperandVolatile (IC_RESULT (ic), FALSE));
11238                   goto release;
11239                 }
11240             }
11241
11242           offset = fReturnSizeMCS51 - size;
11243           while (size--)
11244             {
11245               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11246                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11247               offset++;
11248             }
11249           aopOp (IC_RESULT (ic), ic, FALSE);
11250           size = AOP_SIZE (IC_RESULT (ic));
11251           offset = 0;
11252           while (size--)
11253             {
11254               emitcode ("pop", "acc");
11255               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11256             }
11257         }
11258       else
11259         {
11260           _G.accInUse++;
11261           aopOp (IC_RESULT (ic), ic, FALSE);
11262           _G.accInUse--;
11263           assignResultValue (IC_RESULT (ic), NULL);
11264         }
11265     }
11266   else if (ic->argreg > 12)
11267     { /* bit parameters */
11268       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11269         {
11270           aopOp (IC_RESULT (ic), ic, FALSE);
11271           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11272           outBitC(IC_RESULT (ic));
11273         }
11274     }
11275   else
11276     { /* other parameters */
11277       int rb1off ;
11278       aopOp (IC_RESULT (ic), ic, FALSE);
11279       rb1off = ic->argreg;
11280       while (size--)
11281         {
11282           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11283         }
11284     }
11285
11286 release:
11287   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11288 }
11289
11290 /*-----------------------------------------------------------------*/
11291 /* genDummyRead - generate code for dummy read of volatiles        */
11292 /*-----------------------------------------------------------------*/
11293 static void
11294 genDummyRead (iCode * ic)
11295 {
11296   operand *op;
11297   int size, offset;
11298
11299   D(emitcode(";     genDummyRead",""));
11300
11301   op = IC_RIGHT (ic);
11302   if (op && IS_SYMOP (op))
11303     {
11304       aopOp (op, ic, FALSE);
11305
11306       /* if the result is a bit */
11307       if (AOP_TYPE (op) == AOP_CRY)
11308         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11309       else
11310         {
11311           /* bit variables done */
11312           /* general case */
11313           size = AOP_SIZE (op);
11314           offset = 0;
11315           while (size--)
11316           {
11317             MOVA (aopGet (op, offset, FALSE, FALSE));
11318             offset++;
11319           }
11320         }
11321
11322       freeAsmop (op, NULL, ic, TRUE);
11323     }
11324
11325   op = IC_LEFT (ic);
11326   if (op && IS_SYMOP (op))
11327     {
11328       aopOp (op, ic, FALSE);
11329
11330       /* if the result is a bit */
11331       if (AOP_TYPE (op) == AOP_CRY)
11332         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11333       else
11334         {
11335           /* bit variables done */
11336           /* general case */
11337           size = AOP_SIZE (op);
11338           offset = 0;
11339           while (size--)
11340           {
11341             MOVA (aopGet (op, offset, FALSE, FALSE));
11342             offset++;
11343           }
11344         }
11345
11346       freeAsmop (op, NULL, ic, TRUE);
11347     }
11348 }
11349
11350 /*-----------------------------------------------------------------*/
11351 /* genCritical - generate code for start of a critical sequence    */
11352 /*-----------------------------------------------------------------*/
11353 static void
11354 genCritical (iCode *ic)
11355 {
11356   symbol *tlbl = newiTempLabel (NULL);
11357
11358   D(emitcode(";     genCritical",""));
11359
11360   if (IC_RESULT (ic))
11361     {
11362       aopOp (IC_RESULT (ic), ic, TRUE);
11363       aopPut (IC_RESULT (ic), one, 0, 0);
11364       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11365       aopPut (IC_RESULT (ic), zero, 0, 0);
11366       emitcode ("", "%05d$:", (tlbl->key + 100));
11367       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11368     }
11369   else
11370     {
11371       emitcode ("setb", "c");
11372       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11373       emitcode ("clr", "c");
11374       emitcode ("", "%05d$:", (tlbl->key + 100));
11375       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11376     }
11377 }
11378
11379 /*-----------------------------------------------------------------*/
11380 /* genEndCritical - generate code for end of a critical sequence   */
11381 /*-----------------------------------------------------------------*/
11382 static void
11383 genEndCritical (iCode *ic)
11384 {
11385   D(emitcode(";     genEndCritical",""));
11386
11387   if (IC_RIGHT (ic))
11388     {
11389       aopOp (IC_RIGHT (ic), ic, FALSE);
11390       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11391         {
11392           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11393           emitcode ("mov", "ea,c");
11394         }
11395       else
11396         {
11397           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11398             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11399           emitcode ("rrc", "a");
11400           emitcode ("mov", "ea,c");
11401         }
11402       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11403     }
11404   else
11405     {
11406       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11407       emitcode ("mov", "ea,c");
11408     }
11409 }
11410
11411 /*-----------------------------------------------------------------*/
11412 /* gen51Code - generate code for 8051 based controllers            */
11413 /*-----------------------------------------------------------------*/
11414 void
11415 gen51Code (iCode * lic)
11416 {
11417   iCode *ic;
11418   int cln = 0;
11419   /* int cseq = 0; */
11420
11421   _G.currentFunc = NULL;
11422   lineHead = lineCurr = NULL;
11423
11424   /* print the allocation information */
11425   if (allocInfo && currFunc)
11426     printAllocInfo (currFunc, codeOutFile);
11427   /* if debug information required */
11428   if (options.debug && currFunc)
11429     {
11430       debugFile->writeFunction (currFunc, lic);
11431     }
11432   /* stack pointer name */
11433   if (options.useXstack)
11434     spname = "_spx";
11435   else
11436     spname = "sp";
11437
11438
11439   for (ic = lic; ic; ic = ic->next)
11440     {
11441       _G.current_iCode = ic;
11442
11443       if (ic->lineno && cln != ic->lineno)
11444         {
11445           if (options.debug)
11446             {
11447               debugFile->writeCLine (ic);
11448             }
11449           if (!options.noCcodeInAsm) {
11450             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11451                       printCLine(ic->filename, ic->lineno));
11452           }
11453           cln = ic->lineno;
11454         }
11455       #if 0
11456       if (ic->seqPoint && ic->seqPoint != cseq)
11457         {
11458           emitcode ("", "; sequence point %d", ic->seqPoint);
11459           cseq = ic->seqPoint;
11460         }
11461       #endif
11462       if (options.iCodeInAsm) {
11463         char regsInUse[80];
11464         int i;
11465
11466         #if 0
11467         for (i=0; i<8; i++) {
11468           sprintf (&regsInUse[i],
11469                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11470         regsInUse[i]=0;
11471         #else
11472         strcpy (regsInUse, "--------");
11473         for (i=0; i < 8; i++) {
11474           if (bitVectBitValue (ic->rMask, i))
11475             {
11476               int offset = regs8051[i].offset;
11477               regsInUse[offset] = offset + '0'; /* show rMask */
11478             }
11479         #endif
11480         }
11481         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11482       }
11483       /* if the result is marked as
11484          spilt and rematerializable or code for
11485          this has already been generated then
11486          do nothing */
11487       if (resultRemat (ic) || ic->generated)
11488         continue;
11489
11490       /* depending on the operation */
11491       switch (ic->op)
11492         {
11493         case '!':
11494           genNot (ic);
11495           break;
11496
11497         case '~':
11498           genCpl (ic);
11499           break;
11500
11501         case UNARYMINUS:
11502           genUminus (ic);
11503           break;
11504
11505         case IPUSH:
11506           genIpush (ic);
11507           break;
11508
11509         case IPOP:
11510           /* IPOP happens only when trying to restore a
11511              spilt live range, if there is an ifx statement
11512              following this pop then the if statement might
11513              be using some of the registers being popped which
11514              would destory the contents of the register so
11515              we need to check for this condition and handle it */
11516           if (ic->next &&
11517               ic->next->op == IFX &&
11518               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11519             genIfx (ic->next, ic);
11520           else
11521             genIpop (ic);
11522           break;
11523
11524         case CALL:
11525           genCall (ic);
11526           break;
11527
11528         case PCALL:
11529           genPcall (ic);
11530           break;
11531
11532         case FUNCTION:
11533           genFunction (ic);
11534           break;
11535
11536         case ENDFUNCTION:
11537           genEndFunction (ic);
11538           break;
11539
11540         case RETURN:
11541           genRet (ic);
11542           break;
11543
11544         case LABEL:
11545           genLabel (ic);
11546           break;
11547
11548         case GOTO:
11549           genGoto (ic);
11550           break;
11551
11552         case '+':
11553           genPlus (ic);
11554           break;
11555
11556         case '-':
11557           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11558             genMinus (ic);
11559           break;
11560
11561         case '*':
11562           genMult (ic);
11563           break;
11564
11565         case '/':
11566           genDiv (ic);
11567           break;
11568
11569         case '%':
11570           genMod (ic);
11571           break;
11572
11573         case '>':
11574           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11575           break;
11576
11577         case '<':
11578           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11579           break;
11580
11581         case LE_OP:
11582         case GE_OP:
11583         case NE_OP:
11584
11585           /* note these two are xlated by algebraic equivalence
11586              during parsing SDCC.y */
11587           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11588                   "got '>=' or '<=' shouldn't have come here");
11589           break;
11590
11591         case EQ_OP:
11592           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11593           break;
11594
11595         case AND_OP:
11596           genAndOp (ic);
11597           break;
11598
11599         case OR_OP:
11600           genOrOp (ic);
11601           break;
11602
11603         case '^':
11604           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11605           break;
11606
11607         case '|':
11608           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11609           break;
11610
11611         case BITWISEAND:
11612           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11613           break;
11614
11615         case INLINEASM:
11616           genInline (ic);
11617           break;
11618
11619         case RRC:
11620           genRRC (ic);
11621           break;
11622
11623         case RLC:
11624           genRLC (ic);
11625           break;
11626
11627         case GETHBIT:
11628           genGetHbit (ic);
11629           break;
11630
11631         case GETABIT:
11632           genGetAbit (ic);
11633           break;
11634
11635         case GETBYTE:
11636           genGetByte (ic);
11637           break;
11638
11639         case GETWORD:
11640           genGetWord (ic);
11641           break;
11642
11643         case LEFT_OP:
11644           genLeftShift (ic);
11645           break;
11646
11647         case RIGHT_OP:
11648           genRightShift (ic);
11649           break;
11650
11651         case GET_VALUE_AT_ADDRESS:
11652           genPointerGet (ic,
11653                          hasInc (IC_LEFT (ic), ic,
11654                                  getSize (operandType (IC_RESULT (ic)))),
11655                          ifxForOp (IC_RESULT (ic), ic) );
11656           break;
11657
11658         case '=':
11659           if (POINTER_SET (ic))
11660             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11661           else
11662             genAssign (ic);
11663           break;
11664
11665         case IFX:
11666           genIfx (ic, NULL);
11667           break;
11668
11669         case ADDRESS_OF:
11670           genAddrOf (ic);
11671           break;
11672
11673         case JUMPTABLE:
11674           genJumpTab (ic);
11675           break;
11676
11677         case CAST:
11678           genCast (ic);
11679           break;
11680
11681         case RECEIVE:
11682           genReceive (ic);
11683           break;
11684
11685         case SEND:
11686           addSet (&_G.sendSet, ic);
11687           break;
11688
11689         case DUMMY_READ_VOLATILE:
11690           genDummyRead (ic);
11691           break;
11692
11693         case CRITICAL:
11694           genCritical (ic);
11695           break;
11696
11697         case ENDCRITICAL:
11698           genEndCritical (ic);
11699           break;
11700
11701         case SWAP:
11702           genSwap (ic);
11703           break;
11704
11705         default:
11706           ic = ic;
11707         }
11708     }
11709
11710   _G.current_iCode = NULL;
11711
11712   /* now we are ready to call the
11713      peep hole optimizer */
11714   if (!options.nopeep)
11715     peepHole (&lineHead);
11716
11717   /* now do the actual printing */
11718   printLine (lineHead, codeOutFile);
11719   return;
11720 }