* src/mcs51/gen.c (genPlus, genMinus, genMult, genGetAbit, genGetByte,
[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   return aop;
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* pointerCode - returns the code for a pointer type               */
480 /*-----------------------------------------------------------------*/
481 static int
482 pointerCode (sym_link * etype)
483 {
484
485   return PTR_TYPE (SPEC_OCLS (etype));
486
487 }
488
489 /*-----------------------------------------------------------------*/
490 /* leftRightUseAcc - returns size of accumulator use by operands   */
491 /*-----------------------------------------------------------------*/
492 static int
493 leftRightUseAcc(iCode *ic)
494 {
495   operand *op;
496   int size;
497   int accuseSize = 0;
498   int accuse = 0;
499
500   if (!ic)
501     {
502       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
503               "null iCode pointer");
504       return 0;
505     }
506
507   if (ic->op == IFX)
508     {
509       op = IC_COND (ic);
510       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
511         {
512           accuse = 1;
513           size = getSize (OP_SYMBOL (op)->type);
514           if (size>accuseSize)
515             accuseSize = size;
516         }
517     }
518   else if (ic->op == JUMPTABLE)
519     {
520       op = IC_JTCOND (ic);
521       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
522         {
523           accuse = 1;
524           size = getSize (OP_SYMBOL (op)->type);
525           if (size>accuseSize)
526             accuseSize = size;
527         }
528     }
529   else
530     {
531       op = IC_LEFT (ic);
532       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
533         {
534           accuse = 1;
535           size = getSize (OP_SYMBOL (op)->type);
536           if (size>accuseSize)
537             accuseSize = size;
538         }
539       op = IC_RIGHT (ic);
540       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
541         {
542           accuse = 1;
543           size = getSize (OP_SYMBOL (op)->type);
544           if (size>accuseSize)
545             accuseSize = size;
546         }
547     }
548
549   if (accuseSize)
550     return accuseSize;
551   else
552     return accuse;
553 }
554
555 /*-----------------------------------------------------------------*/
556 /* aopForSym - for a true symbol                                   */
557 /*-----------------------------------------------------------------*/
558 static asmop *
559 aopForSym (iCode * ic, symbol * sym, bool result)
560 {
561   asmop *aop;
562   memmap *space;
563
564   wassertl (ic != NULL, "Got a null iCode");
565   wassertl (sym != NULL, "Got a null symbol");
566
567   space = SPEC_OCLS (sym->etype);
568
569   /* if already has one */
570   if (sym->aop)
571     return sym->aop;
572
573   /* assign depending on the storage class */
574   /* if it is on the stack or indirectly addressable */
575   /* space we need to assign either r0 or r1 to it   */
576   if (sym->onStack || sym->iaccess)
577     {
578       sym->aop = aop = newAsmop (0);
579       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
580       aop->size = getSize (sym->type);
581
582       /* now assign the address of the variable to
583          the pointer register */
584       if (aop->type != AOP_STK)
585         {
586
587           if (sym->onStack)
588             {
589               char offset = ((sym->stack < 0) ?
590                          ((char) (sym->stack - _G.nRegsSaved)) :
591                          ((char) sym->stack)) & 0xff;
592
593               if ((offset >= -3) && (offset <= 3))
594                 {
595                   emitcode ("mov", "%s,%s",
596                             aop->aopu.aop_ptr->name, SYM_BP (sym));
597                   while (offset < 0)
598                     {
599                       emitcode ("dec", aop->aopu.aop_ptr->name);
600                       offset++;
601                     }
602                   while (offset > 0)
603                     {
604                       emitcode ("inc", aop->aopu.aop_ptr->name);
605                       offset--;
606                     }
607                 }
608               else
609                 {
610                   if (_G.accInUse || leftRightUseAcc (ic))
611                     emitcode ("push", "acc");
612                   emitcode ("mov", "a,%s", SYM_BP (sym));
613                   emitcode ("add", "a,#0x%02x", offset);
614                   emitcode ("mov", "%s,a",
615                             aop->aopu.aop_ptr->name);
616                   if (_G.accInUse || leftRightUseAcc (ic))
617                     emitcode ("pop", "acc");
618                 }
619             }
620           else
621             emitcode ("mov", "%s,#%s",
622                       aop->aopu.aop_ptr->name,
623                       sym->rname);
624           aop->paged = space->paged;
625         }
626       else
627         aop->aopu.aop_stk = sym->stack;
628       return aop;
629     }
630
631   /* if in bit space */
632   if (IN_BITSPACE (space))
633     {
634       sym->aop = aop = newAsmop (AOP_CRY);
635       aop->aopu.aop_dir = sym->rname;
636       aop->size = getSize (sym->type);
637       return aop;
638     }
639   /* if it is in direct space */
640   if (IN_DIRSPACE (space))
641     {
642       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
643       //printTypeChainRaw(sym->type, NULL);
644       //printf("space = %s\n", space ? space->sname : "NULL");
645       sym->aop = aop = newAsmop (AOP_DIR);
646       aop->aopu.aop_dir = sym->rname;
647       aop->size = getSize (sym->type);
648       return aop;
649     }
650
651   /* special case for a function */
652   if (IS_FUNC (sym->type))
653     {
654       sym->aop = aop = newAsmop (AOP_IMMD);
655       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
656       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
657       aop->size = getSize (sym->type);
658       return aop;
659     }
660
661   /* only remaining is far space */
662   /* in which case DPTR gets the address */
663   sym->aop = aop = newAsmop (AOP_DPTR);
664   emitcode ("mov", "dptr,#%s", sym->rname);
665   aop->size = getSize (sym->type);
666
667   /* if it is in code space */
668   if (IN_CODESPACE (space))
669     aop->code = 1;
670
671   return aop;
672 }
673
674 /*-----------------------------------------------------------------*/
675 /* aopForRemat - rematerialzes an object                           */
676 /*-----------------------------------------------------------------*/
677 static asmop *
678 aopForRemat (symbol * sym)
679 {
680   iCode *ic = sym->rematiCode;
681   asmop *aop = newAsmop (AOP_IMMD);
682   int ptr_type = 0;
683   int val = 0;
684
685   for (;;)
686     {
687       if (ic->op == '+')
688         val += (int) operandLitValue (IC_RIGHT (ic));
689       else if (ic->op == '-')
690         val -= (int) operandLitValue (IC_RIGHT (ic));
691       else if (IS_CAST_ICODE(ic)) {
692               sym_link *from_type = operandType(IC_RIGHT(ic));
693               aop->aopu.aop_immd.from_cast_remat = 1;
694               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
695               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
696               continue;
697       } else break;
698
699       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
700     }
701
702   if (val)
703     sprintf (buffer, "(%s %c 0x%04x)",
704              OP_SYMBOL (IC_LEFT (ic))->rname,
705              val >= 0 ? '+' : '-',
706              abs (val) & 0xffff);
707   else
708     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
709
710   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
711   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
712   /* set immd2 field if required */
713   if (aop->aopu.aop_immd.from_cast_remat) {
714           sprintf(buffer,"#0x%02x",ptr_type);
715           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
716           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
717   }
718
719   return aop;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common       */
724 /*-----------------------------------------------------------------*/
725 static bool
726 regsInCommon (operand * op1, operand * op2)
727 {
728   symbol *sym1, *sym2;
729   int i;
730
731   /* if they have registers in common */
732   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
733     return FALSE;
734
735   sym1 = OP_SYMBOL (op1);
736   sym2 = OP_SYMBOL (op2);
737
738   if (sym1->nRegs == 0 || sym2->nRegs == 0)
739     return FALSE;
740
741   for (i = 0; i < sym1->nRegs; i++)
742     {
743       int j;
744       if (!sym1->regs[i])
745         continue;
746
747       for (j = 0; j < sym2->nRegs; j++)
748         {
749           if (!sym2->regs[j])
750             continue;
751
752           if (sym2->regs[j] == sym1->regs[i])
753             return TRUE;
754         }
755     }
756
757   return FALSE;
758 }
759
760 /*-----------------------------------------------------------------*/
761 /* operandsEqu - equivalent                                        */
762 /*-----------------------------------------------------------------*/
763 static bool
764 operandsEqu (operand * op1, operand * op2)
765 {
766   symbol *sym1, *sym2;
767
768   /* if they're not symbols */
769   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
770     return FALSE;
771
772   sym1 = OP_SYMBOL (op1);
773   sym2 = OP_SYMBOL (op2);
774
775   /* if both are itemps & one is spilt
776      and the other is not then false */
777   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
778       sym1->isspilt != sym2->isspilt)
779     return FALSE;
780
781   /* if they are the same */
782   if (sym1 == sym2)
783     return TRUE;
784
785   /* if they have the same rname */
786   if (sym1->rname[0] && sym2->rname[0] &&
787       strcmp (sym1->rname, sym2->rname) == 0 &&
788       !(IS_PARM (op2) && IS_ITEMP (op1)))
789     return TRUE;
790
791   /* if left is a tmp & right is not */
792   if (IS_ITEMP (op1) &&
793       !IS_ITEMP (op2) &&
794       sym1->isspilt &&
795       (sym1->usl.spillLoc == sym2))
796     return TRUE;
797
798   if (IS_ITEMP (op2) &&
799       !IS_ITEMP (op1) &&
800       sym2->isspilt &&
801       sym1->level > 0 &&
802       (sym2->usl.spillLoc == sym1))
803     return TRUE;
804
805   return FALSE;
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* sameRegs - two asmops have the same registers                   */
810 /*-----------------------------------------------------------------*/
811 static bool
812 sameRegs (asmop * aop1, asmop * aop2)
813 {
814   int i;
815
816   if (aop1 == aop2)
817     return TRUE;
818
819   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
820     return FALSE;
821
822   if (aop1->type != aop2->type)
823     return FALSE;
824
825   if (aop1->size != aop2->size)
826     return FALSE;
827
828   for (i = 0; i < aop1->size; i++)
829     if (aop1->aopu.aop_reg[i] !=
830         aop2->aopu.aop_reg[i])
831       return FALSE;
832
833   return TRUE;
834 }
835
836 /*-----------------------------------------------------------------*/
837 /* aopOp - allocates an asmop for an operand  :                    */
838 /*-----------------------------------------------------------------*/
839 static void
840 aopOp (operand * op, iCode * ic, bool result)
841 {
842   asmop *aop;
843   symbol *sym;
844   int i;
845
846   if (!op)
847     return;
848
849   /* if this a literal */
850   if (IS_OP_LITERAL (op))
851     {
852       op->aop = aop = newAsmop (AOP_LIT);
853       aop->aopu.aop_lit = op->operand.valOperand;
854       aop->size = getSize (operandType (op));
855       return;
856     }
857
858   /* if already has a asmop then continue */
859   if (op->aop )
860     return;
861
862   /* if the underlying symbol has a aop */
863   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
864     {
865       op->aop = OP_SYMBOL (op)->aop;
866       return;
867     }
868
869   /* if this is a true symbol */
870   if (IS_TRUE_SYMOP (op))
871     {
872       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
873       return;
874     }
875
876   /* this is a temporary : this has
877      only five choices :
878      a) register
879      b) spillocation
880      c) rematerialize
881      d) conditional
882      e) can be a return use only */
883
884   sym = OP_SYMBOL (op);
885
886   /* if the type is a conditional */
887   if (sym->regType == REG_CND)
888     {
889       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
890       aop->size = 0;
891       return;
892     }
893
894   /* if it is spilt then two situations
895      a) is rematerialize
896      b) has a spill location */
897   if (sym->isspilt || sym->nRegs == 0)
898     {
899
900       /* rematerialize it NOW */
901       if (sym->remat)
902         {
903           sym->aop = op->aop = aop =
904             aopForRemat (sym);
905           aop->size = getSize (sym->type);
906           return;
907         }
908
909       if (sym->accuse)
910         {
911           int i;
912           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
913           aop->size = getSize (sym->type);
914           for (i = 0; i < 2; i++)
915             aop->aopu.aop_str[i] = accUse[i];
916           return;
917         }
918
919       if (sym->ruonly)
920         {
921           unsigned i;
922
923           aop = op->aop = sym->aop = newAsmop (AOP_STR);
924           aop->size = getSize (sym->type);
925           for (i = 0; i < fReturnSizeMCS51; i++)
926             aop->aopu.aop_str[i] = fReturn[i];
927           return;
928         }
929
930       if (sym->usl.spillLoc)
931         {
932           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
933             {
934               /* force a new aop if sizes differ */
935               sym->usl.spillLoc->aop = NULL;
936             }
937           sym->aop = op->aop = aop =
938                      aopForSym (ic, sym->usl.spillLoc, result);
939           aop->size = getSize (sym->type);
940           return;
941         }
942
943       /* else must be a dummy iTemp */
944       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
945       aop->size = getSize (sym->type);
946       return;
947     }
948
949   /* if the type is a bit register */
950   if (sym->regType == REG_BIT)
951     {
952       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
953       aop->size = sym->nRegs;//1???
954       aop->aopu.aop_reg[0] = sym->regs[0];
955       aop->aopu.aop_dir = sym->regs[0]->name;
956       return;
957     }
958
959   /* must be in a register */
960   sym->aop = op->aop = aop = newAsmop (AOP_REG);
961   aop->size = sym->nRegs;
962   for (i = 0; i < sym->nRegs; i++)
963     aop->aopu.aop_reg[i] = sym->regs[i];
964 }
965
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand               */
968 /*----------------------------------------------------------------*/
969 static void
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
971 {
972   asmop *aop;
973
974   if (!op)
975     aop = aaop;
976   else
977     aop = op->aop;
978
979   if (!aop)
980     return;
981
982   if (aop->freed)
983     goto dealloc;
984
985   aop->freed = 1;
986
987   /* depending on the asmop type only three cases need work AOP_RO
988      , AOP_R1 && AOP_STK */
989   switch (aop->type)
990     {
991     case AOP_R0:
992       if (R0INB)
993         {
994           emitcode ("mov", "r0,b");
995           R0INB--;
996         }
997       else if (_G.r0Pushed)
998         {
999           if (pop)
1000             {
1001               emitcode ("pop", "ar0");
1002               _G.r0Pushed--;
1003             }
1004         }
1005       bitVectUnSetBit (ic->rUsed, R0_IDX);
1006       break;
1007
1008     case AOP_R1:
1009       if (R1INB)
1010         {
1011           emitcode ("mov", "r1,b");
1012           R1INB--;
1013         }
1014       if (_G.r1Pushed)
1015         {
1016           if (pop)
1017             {
1018               emitcode ("pop", "ar1");
1019               _G.r1Pushed--;
1020             }
1021         }
1022       bitVectUnSetBit (ic->rUsed, R1_IDX);
1023       break;
1024
1025     case AOP_STK:
1026       {
1027         int sz = aop->size;
1028         int stk = aop->aopu.aop_stk + aop->size - 1;
1029         bitVectUnSetBit (ic->rUsed, R0_IDX);
1030         bitVectUnSetBit (ic->rUsed, R1_IDX);
1031
1032         getFreePtr (ic, &aop, FALSE);
1033
1034         if (stk)
1035           {
1036             emitcode ("mov", "a,_bp");
1037             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1038             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1039           }
1040         else
1041           {
1042             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1043           }
1044
1045         while (sz--)
1046           {
1047             emitcode ("pop", "acc");
1048             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1049             if (!sz)
1050               break;
1051             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1052           }
1053         op->aop = aop;
1054         freeAsmop (op, NULL, ic, TRUE);
1055         if (_G.r1Pushed)
1056           {
1057             emitcode ("pop", "ar1");
1058             _G.r1Pushed--;
1059           }
1060
1061         if (_G.r0Pushed)
1062           {
1063             emitcode ("pop", "ar0");
1064             _G.r0Pushed--;
1065           }
1066       }
1067     }
1068
1069 dealloc:
1070   /* all other cases just dealloc */
1071   if (op)
1072     {
1073       op->aop = NULL;
1074       if (IS_SYMOP (op))
1075         {
1076           OP_SYMBOL (op)->aop = NULL;
1077           /* if the symbol has a spill */
1078           if (SPIL_LOC (op))
1079             SPIL_LOC (op)->aop = NULL;
1080         }
1081     }
1082 }
1083
1084 /*------------------------------------------------------------------*/
1085 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1086 /*                      pop r0 or r1 off stack if pushed            */
1087 /*------------------------------------------------------------------*/
1088 static void
1089 freeForBranchAsmop (operand * op)
1090 {
1091   asmop *aop;
1092
1093   if (!op)
1094     return;
1095
1096   aop = op->aop;
1097
1098   if (!aop)
1099     return;
1100
1101   if (aop->freed)
1102     return;
1103
1104   switch (aop->type)
1105     {
1106     case AOP_R0:
1107       if (R0INB)
1108         {
1109           emitcode ("mov", "r0,b");
1110         }
1111       else if (_G.r0Pushed)
1112         {
1113           emitcode ("pop", "ar0");
1114         }
1115       break;
1116
1117     case AOP_R1:
1118       if (R1INB)
1119         {
1120           emitcode ("mov", "r1,b");
1121         }
1122       else if (_G.r1Pushed)
1123         {
1124           emitcode ("pop", "ar1");
1125         }
1126       break;
1127
1128     case AOP_STK:
1129       {
1130         int sz = aop->size;
1131         int stk = aop->aopu.aop_stk + aop->size - 1;
1132
1133         emitcode ("mov", "b,r0");
1134         if (stk)
1135           {
1136             emitcode ("mov", "a,_bp");
1137             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1138             emitcode ("mov", "r0,a");
1139           }
1140         else
1141           {
1142             emitcode ("mov", "r0,_bp");
1143           }
1144
1145         while (sz--)
1146           {
1147             emitcode ("pop", "acc");
1148             emitcode ("mov", "@r0,a");
1149             if (!sz)
1150               break;
1151             emitcode ("dec", "r0");
1152           }
1153         emitcode ("mov", "r0,b");
1154       }
1155     }
1156
1157 }
1158
1159 /*-----------------------------------------------------------------*/
1160 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1161 /*                 clobber the accumulator                         */
1162 /*-----------------------------------------------------------------*/
1163 static bool
1164 aopGetUsesAcc (operand * oper, int offset)
1165 {
1166   asmop * aop = AOP (oper);
1167
1168   if (offset > (aop->size - 1))
1169     return FALSE;
1170
1171   switch (aop->type)
1172     {
1173
1174     case AOP_R0:
1175     case AOP_R1:
1176       if (aop->paged)
1177         return TRUE;
1178       return FALSE;
1179     case AOP_DPTR:
1180       return TRUE;
1181     case AOP_IMMD:
1182       return FALSE;
1183     case AOP_DIR:
1184       return FALSE;
1185     case AOP_REG:
1186       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1187       return FALSE;
1188     case AOP_CRY:
1189       return TRUE;
1190     case AOP_ACC:
1191       if (offset)
1192         return FALSE;
1193       return TRUE;
1194     case AOP_LIT:
1195       return FALSE;
1196     case AOP_STR:
1197       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1198         return TRUE;
1199       return FALSE;
1200     case AOP_DUMMY:
1201       return FALSE;
1202     default:
1203       /* Error case --- will have been caught already */
1204       wassert(0);
1205       return FALSE;
1206     }
1207 }
1208
1209 /*-----------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop                          */
1211 /*-----------------------------------------------------------------*/
1212 static char *
1213 aopGet (operand * oper, int offset, bool bit16, bool dname)
1214 {
1215   char *s = buffer;
1216   char *rs;
1217   asmop * aop = AOP (oper);
1218
1219   /* offset is greater than
1220      size then zero */
1221   if (offset > (aop->size - 1) &&
1222       aop->type != AOP_LIT)
1223     return zero;
1224
1225   /* depending on type */
1226   switch (aop->type)
1227     {
1228     case AOP_DUMMY:
1229       return zero;
1230
1231     case AOP_R0:
1232     case AOP_R1:
1233       /* if we need to increment it */
1234       while (offset > aop->coff)
1235         {
1236           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1237           aop->coff++;
1238         }
1239
1240       while (offset < aop->coff)
1241         {
1242           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1243           aop->coff--;
1244         }
1245
1246       aop->coff = offset;
1247       if (aop->paged)
1248         {
1249           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1250           return (dname ? "acc" : "a");
1251         }
1252       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1253       rs = Safe_calloc (1, strlen (s) + 1);
1254       strcpy (rs, s);
1255       return rs;
1256
1257     case AOP_DPTR:
1258       if (aop->code && aop->coff==0 && offset>=1) {
1259         emitcode ("mov", "a,#0x%02x", offset);
1260         emitcode ("movc", "a,@a+dptr");
1261         return (dname ? "acc" : "a");
1262       }
1263
1264       while (offset > aop->coff)
1265         {
1266           emitcode ("inc", "dptr");
1267           aop->coff++;
1268         }
1269
1270       while (offset < aop->coff)
1271         {
1272           emitcode ("lcall", "__decdptr");
1273           aop->coff--;
1274         }
1275
1276       aop->coff = offset;
1277       if (aop->code)
1278         {
1279           emitcode ("clr", "a");
1280           emitcode ("movc", "a,@a+dptr");
1281         }
1282       else
1283         {
1284           emitcode ("movx", "a,@dptr");
1285         }
1286       return (dname ? "acc" : "a");
1287
1288
1289     case AOP_IMMD:
1290       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1291               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1292       } else if (bit16)
1293         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1294       else if (offset)
1295         sprintf (s, "#(%s >> %d)",
1296                  aop->aopu.aop_immd.aop_immd1,
1297                  offset * 8);
1298       else
1299         sprintf (s, "#%s",
1300                  aop->aopu.aop_immd.aop_immd1);
1301       rs = Safe_calloc (1, strlen (s) + 1);
1302       strcpy (rs, s);
1303       return rs;
1304
1305     case AOP_DIR:
1306       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1307         sprintf (s, "(%s >> %d)",
1308                  aop->aopu.aop_dir, offset * 8);
1309       else if (offset)
1310         sprintf (s, "(%s + %d)",
1311                  aop->aopu.aop_dir,
1312                  offset);
1313       else
1314         sprintf (s, "%s", aop->aopu.aop_dir);
1315       rs = Safe_calloc (1, strlen (s) + 1);
1316       strcpy (rs, s);
1317       return rs;
1318
1319     case AOP_REG:
1320       if (dname)
1321         return aop->aopu.aop_reg[offset]->dname;
1322       else
1323         return aop->aopu.aop_reg[offset]->name;
1324
1325     case AOP_CRY:
1326       emitcode ("clr", "a");
1327       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1328       emitcode ("rlc", "a");
1329       return (dname ? "acc" : "a");
1330
1331     case AOP_ACC:
1332       if (!offset && dname)
1333         return "acc";
1334       return aop->aopu.aop_str[offset];
1335
1336     case AOP_LIT:
1337       return aopLiteral (aop->aopu.aop_lit, offset);
1338
1339     case AOP_STR:
1340       aop->coff = offset;
1341       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1342           dname)
1343         return "acc";
1344
1345       return aop->aopu.aop_str[offset];
1346
1347     }
1348
1349   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1350           "aopget got unsupported aop->type");
1351   exit (1);
1352 }
1353
1354 /*-----------------------------------------------------------------*/
1355 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1356 /*                 clobber the accumulator                         */
1357 /*-----------------------------------------------------------------*/
1358 static bool
1359 aopPutUsesAcc (operand * oper, const char *s, int offset)
1360 {
1361   asmop * aop = AOP (oper);
1362
1363   if (offset > (aop->size - 1))
1364     return FALSE;
1365
1366   switch (aop->type)
1367     {
1368     case AOP_DUMMY:
1369       return TRUE;
1370     case AOP_DIR:
1371       return FALSE;
1372     case AOP_REG:
1373       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1374       return FALSE;
1375     case AOP_DPTR:
1376       return TRUE;
1377     case AOP_R0:
1378     case AOP_R1:
1379       return ((aop->paged) || (*s == '@'));
1380     case AOP_STK:
1381       return (*s == '@');
1382     case AOP_CRY:
1383       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1384     case AOP_STR:
1385       return FALSE;
1386     case AOP_IMMD:
1387       return FALSE;
1388     case AOP_ACC:
1389       return FALSE;
1390     default:
1391       /* Error case --- will have been caught already */
1392       wassert(0);
1393       return FALSE;
1394     }
1395 }
1396
1397 /*-----------------------------------------------------------------*/
1398 /* aopPut - puts a string for a aop and indicates if acc is in use */
1399 /*-----------------------------------------------------------------*/
1400 static bool
1401 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1402 {
1403   char *d = buffer;
1404   bool accuse = FALSE;
1405   asmop * aop = AOP (result);
1406
1407   if (aop->size && offset > (aop->size - 1))
1408     {
1409       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1410               "aopPut got offset > aop->size");
1411       exit (1);
1412     }
1413
1414   /* will assign value to value */
1415   /* depending on where it is ofcourse */
1416   switch (aop->type)
1417     {
1418     case AOP_DUMMY:
1419       MOVA (s);         /* read s in case it was volatile */
1420       accuse = TRUE;
1421       break;
1422
1423     case AOP_DIR:
1424       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1425         sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1426       else if (offset)
1427         sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1428       else
1429         sprintf (d, "%s", aop->aopu.aop_dir);
1430
1431       if (strcmp (d, s) || bvolatile)
1432           emitcode ("mov", "%s,%s", d, s);
1433       if (!strcmp (d, "acc"))
1434           accuse = TRUE;
1435
1436       break;
1437
1438     case AOP_REG:
1439       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1440           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1441         {
1442           if (*s == '@' ||
1443               strcmp (s, "r0") == 0 ||
1444               strcmp (s, "r1") == 0 ||
1445               strcmp (s, "r2") == 0 ||
1446               strcmp (s, "r3") == 0 ||
1447               strcmp (s, "r4") == 0 ||
1448               strcmp (s, "r5") == 0 ||
1449               strcmp (s, "r6") == 0 ||
1450               strcmp (s, "r7") == 0)
1451             emitcode ("mov", "%s,%s",
1452                       aop->aopu.aop_reg[offset]->dname, s);
1453           else
1454             emitcode ("mov", "%s,%s",
1455                       aop->aopu.aop_reg[offset]->name, s);
1456         }
1457       break;
1458
1459     case AOP_DPTR:
1460       if (aop->code)
1461         {
1462           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1463                   "aopPut writing to code space");
1464           exit (1);
1465         }
1466
1467       while (offset > aop->coff)
1468         {
1469           aop->coff++;
1470           emitcode ("inc", "dptr");
1471         }
1472
1473       while (offset < aop->coff)
1474         {
1475           aop->coff--;
1476           emitcode ("lcall", "__decdptr");
1477         }
1478
1479       aop->coff = offset;
1480
1481       /* if not in accumulator */
1482       MOVA (s);
1483
1484       emitcode ("movx", "@dptr,a");
1485       break;
1486
1487     case AOP_R0:
1488     case AOP_R1:
1489       while (offset > aop->coff)
1490         {
1491           aop->coff++;
1492           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1493         }
1494       while (offset < aop->coff)
1495         {
1496           aop->coff--;
1497           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1498         }
1499       aop->coff = offset;
1500
1501       if (aop->paged)
1502         {
1503           MOVA (s);
1504           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1505         }
1506       else if (*s == '@')
1507         {
1508           MOVA (s);
1509           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1510         }
1511       else if (strcmp (s, "r0") == 0 ||
1512                strcmp (s, "r1") == 0 ||
1513                strcmp (s, "r2") == 0 ||
1514                strcmp (s, "r3") == 0 ||
1515                strcmp (s, "r4") == 0 ||
1516                strcmp (s, "r5") == 0 ||
1517                strcmp (s, "r6") == 0 ||
1518                strcmp (s, "r7") == 0)
1519         {
1520           char buffer[10];
1521           sprintf (buffer, "a%s", s);
1522           emitcode ("mov", "@%s,%s",
1523                     aop->aopu.aop_ptr->name, buffer);
1524         }
1525       else
1526         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1527
1528       break;
1529
1530     case AOP_STK:
1531       if (strcmp (s, "a") == 0)
1532         emitcode ("push", "acc");
1533       else
1534         if (*s=='@') {
1535           MOVA(s);
1536           emitcode ("push", "acc");
1537         } else {
1538           emitcode ("push", s);
1539         }
1540
1541       break;
1542
1543     case AOP_CRY:
1544       /* if not bit variable */
1545       if (!aop->aopu.aop_dir)
1546         {
1547           /* inefficient: move carry into A and use jz/jnz */
1548           emitcode ("clr", "a");
1549           emitcode ("rlc", "a");
1550           accuse = TRUE;
1551         }
1552       else
1553         {
1554           if (s == zero)
1555             emitcode ("clr", "%s", aop->aopu.aop_dir);
1556           else if (s == one)
1557             emitcode ("setb", "%s", aop->aopu.aop_dir);
1558           else if (!strcmp (s, "c"))
1559             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1560           else if (strcmp (s, aop->aopu.aop_dir))
1561             {
1562               MOVA (s);
1563               /* set C, if a >= 1 */
1564               emitcode ("add", "a,#0xff");
1565               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1566             }
1567         }
1568       break;
1569
1570     case AOP_STR:
1571       aop->coff = offset;
1572       if (strcmp (aop->aopu.aop_str[offset], s) ||
1573           bvolatile)
1574         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1575       break;
1576
1577     case AOP_ACC:
1578       accuse = TRUE;
1579       aop->coff = offset;
1580       if (!offset && (strcmp (s, "acc") == 0) &&
1581           !bvolatile)
1582         break;
1583
1584       if (strcmp (aop->aopu.aop_str[offset], s) &&
1585           !bvolatile)
1586         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1587       break;
1588
1589     default:
1590       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1591               "aopPut got unsupported aop->type");
1592       exit (1);
1593     }
1594
1595     return accuse;
1596 }
1597
1598
1599 #if 0
1600 /*-----------------------------------------------------------------*/
1601 /* pointToEnd :- points to the last byte of the operand            */
1602 /*-----------------------------------------------------------------*/
1603 static void
1604 pointToEnd (asmop * aop)
1605 {
1606   int count;
1607   if (!aop)
1608     return;
1609
1610   aop->coff = count = (aop->size - 1);
1611   switch (aop->type)
1612     {
1613     case AOP_R0:
1614     case AOP_R1:
1615       while (count--)
1616         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1617       break;
1618     case AOP_DPTR:
1619       while (count--)
1620         emitcode ("inc", "dptr");
1621       break;
1622     }
1623
1624 }
1625 #endif
1626
1627 /*-----------------------------------------------------------------*/
1628 /* reAdjustPreg - points a register back to where it should        */
1629 /*-----------------------------------------------------------------*/
1630 static void
1631 reAdjustPreg (asmop * aop)
1632 {
1633   if ((aop->coff==0) || aop->size <= 1)
1634     return;
1635
1636   switch (aop->type)
1637     {
1638     case AOP_R0:
1639     case AOP_R1:
1640       while (aop->coff--)
1641         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1642       break;
1643     case AOP_DPTR:
1644       while (aop->coff--)
1645         {
1646           emitcode ("lcall", "__decdptr");
1647         }
1648       break;
1649     }
1650   aop->coff = 0;
1651 }
1652
1653 /*-----------------------------------------------------------------*/
1654 /* opIsGptr: returns non-zero if the passed operand is       */
1655 /* a generic pointer type.             */
1656 /*-----------------------------------------------------------------*/
1657 static int
1658 opIsGptr (operand * op)
1659 {
1660   sym_link *type = operandType (op);
1661
1662   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1663     {
1664       return 1;
1665     }
1666   return 0;
1667 }
1668
1669 /*-----------------------------------------------------------------*/
1670 /* getDataSize - get the operand data size                         */
1671 /*-----------------------------------------------------------------*/
1672 static int
1673 getDataSize (operand * op)
1674 {
1675   int size;
1676   size = AOP_SIZE (op);
1677   if (size == GPTRSIZE)
1678     {
1679       sym_link *type = operandType (op);
1680       if (IS_GENPTR (type))
1681         {
1682           /* generic pointer; arithmetic operations
1683            * should ignore the high byte (pointer type).
1684            */
1685           size--;
1686         }
1687     }
1688   return size;
1689 }
1690
1691 /*-----------------------------------------------------------------*/
1692 /* outAcc - output Acc                                             */
1693 /*-----------------------------------------------------------------*/
1694 static void
1695 outAcc (operand * result)
1696 {
1697   int size, offset;
1698   size = getDataSize (result);
1699   if (size)
1700     {
1701       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1702       size--;
1703       offset = 1;
1704       /* unsigned or positive */
1705       while (size--)
1706         {
1707           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1708         }
1709     }
1710 }
1711
1712 /*-----------------------------------------------------------------*/
1713 /* outBitC - output a bit C                                        */
1714 /*-----------------------------------------------------------------*/
1715 static void
1716 outBitC (operand * result)
1717 {
1718   /* if the result is bit */
1719   if (AOP_TYPE (result) == AOP_CRY)
1720     aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1721   else
1722     {
1723       emitcode ("clr", "a");
1724       emitcode ("rlc", "a");
1725       outAcc (result);
1726     }
1727 }
1728
1729 /*-----------------------------------------------------------------*/
1730 /* toBoolean - emit code for orl a,operator(sizeop)                */
1731 /*-----------------------------------------------------------------*/
1732 static void
1733 toBoolean (operand * oper)
1734 {
1735   int size = AOP_SIZE (oper) - 1;
1736   int offset = 1;
1737   bool AccUsed = FALSE;
1738   bool pushedB;
1739
1740   while (!AccUsed && size--)
1741     {
1742       AccUsed |= aopGetUsesAcc(oper, offset++);
1743     }
1744
1745   size = AOP_SIZE (oper) - 1;
1746   offset = 1;
1747   MOVA (aopGet (oper, 0, FALSE, FALSE));
1748   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1749     {
1750       pushedB = pushB ();
1751       emitcode("mov", "b,a");
1752       while (--size)
1753         {
1754           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1755           emitcode ("orl", "b,a");
1756         }
1757       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1758       emitcode ("orl", "a,b");
1759       popB (pushedB);
1760     }
1761   else
1762     {
1763       while (size--)
1764         {
1765           emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1766         }
1767     }
1768 }
1769
1770
1771 /*-----------------------------------------------------------------*/
1772 /* genNot - generate code for ! operation                          */
1773 /*-----------------------------------------------------------------*/
1774 static void
1775 genNot (iCode * ic)
1776 {
1777   symbol *tlbl;
1778
1779   D(emitcode (";     genNot",""));
1780
1781   /* assign asmOps to operand & result */
1782   aopOp (IC_LEFT (ic), ic, FALSE);
1783   aopOp (IC_RESULT (ic), ic, TRUE);
1784
1785   /* if in bit space then a special case */
1786   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1787     {
1788       /* if left==result then cpl bit */
1789       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1790         {
1791           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1792         }
1793       else
1794         {
1795           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1796           emitcode ("cpl", "c");
1797           outBitC (IC_RESULT (ic));
1798         }
1799       goto release;
1800     }
1801
1802   toBoolean (IC_LEFT (ic));
1803
1804   /* set C, if a == 0 */
1805   tlbl = newiTempLabel (NULL);
1806   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1807   emitcode ("", "%05d$:", tlbl->key + 100);
1808   outBitC (IC_RESULT (ic));
1809
1810 release:
1811   /* release the aops */
1812   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1813   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1814 }
1815
1816
1817 /*-----------------------------------------------------------------*/
1818 /* genCpl - generate code for complement                           */
1819 /*-----------------------------------------------------------------*/
1820 static void
1821 genCpl (iCode * ic)
1822 {
1823   int offset = 0;
1824   int size;
1825   symbol *tlbl;
1826   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1827
1828   D(emitcode (";", "genCpl"));
1829
1830   /* assign asmOps to operand & result */
1831   aopOp (IC_LEFT (ic), ic, FALSE);
1832   aopOp (IC_RESULT (ic), ic, TRUE);
1833
1834   /* special case if in bit space */
1835   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1836     {
1837       char *l;
1838
1839       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1840           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1841         {
1842           /* promotion rules are responsible for this strange result:
1843              bit -> int -> ~int -> bit
1844              uchar -> int -> ~int -> bit
1845           */
1846           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1847           goto release;
1848         }
1849
1850       tlbl=newiTempLabel(NULL);
1851       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1852       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1853           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1854           IS_AOP_PREG (IC_LEFT (ic)))
1855         {
1856           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1857         }
1858       else
1859         {
1860           MOVA (l);
1861           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1862         }
1863       emitcode ("", "%05d$:", tlbl->key + 100);
1864       outBitC (IC_RESULT(ic));
1865       goto release;
1866     }
1867
1868   size = AOP_SIZE (IC_RESULT (ic));
1869   while (size--)
1870     {
1871       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1872       MOVA (l);
1873       emitcode ("cpl", "a");
1874       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1875     }
1876
1877
1878 release:
1879   /* release the aops */
1880   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1881   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1882 }
1883
1884 /*-----------------------------------------------------------------*/
1885 /* genUminusFloat - unary minus for floating points                */
1886 /*-----------------------------------------------------------------*/
1887 static void
1888 genUminusFloat (operand * op, operand * result)
1889 {
1890   int size, offset = 0;
1891   char *l;
1892
1893   D(emitcode (";     genUminusFloat",""));
1894
1895   /* for this we just copy and then flip the bit */
1896
1897   size = AOP_SIZE (op) - 1;
1898
1899   while (size--)
1900     {
1901       aopPut (result,
1902               aopGet (op, offset, FALSE, FALSE),
1903               offset,
1904               isOperandVolatile (result, FALSE));
1905       offset++;
1906     }
1907
1908   l = aopGet (op, offset, FALSE, FALSE);
1909
1910   MOVA (l);
1911
1912   emitcode ("cpl", "acc.7");
1913   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1914 }
1915
1916 /*-----------------------------------------------------------------*/
1917 /* genUminus - unary minus code generation                         */
1918 /*-----------------------------------------------------------------*/
1919 static void
1920 genUminus (iCode * ic)
1921 {
1922   int offset, size;
1923   sym_link *optype, *rtype;
1924
1925
1926   D(emitcode (";     genUminus",""));
1927
1928   /* assign asmops */
1929   aopOp (IC_LEFT (ic), ic, FALSE);
1930   aopOp (IC_RESULT (ic), ic, TRUE);
1931
1932   /* if both in bit space then special
1933      case */
1934   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1935       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1936     {
1937
1938       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1939       emitcode ("cpl", "c");
1940       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1941       goto release;
1942     }
1943
1944   optype = operandType (IC_LEFT (ic));
1945   rtype = operandType (IC_RESULT (ic));
1946
1947   /* if float then do float stuff */
1948   if (IS_FLOAT (optype))
1949     {
1950       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1951       goto release;
1952     }
1953
1954   /* otherwise subtract from zero */
1955   size = AOP_SIZE (IC_LEFT (ic));
1956   offset = 0;
1957   //CLRC ;
1958   while (size--)
1959     {
1960       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1961       if (!strcmp (l, "a"))
1962         {
1963           if (offset == 0)
1964             SETC;
1965           emitcode ("cpl", "a");
1966           emitcode ("addc", "a,#0");
1967         }
1968       else
1969         {
1970           if (offset == 0)
1971             CLRC;
1972           emitcode ("clr", "a");
1973           emitcode ("subb", "a,%s", l);
1974         }
1975       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1976     }
1977
1978   /* if any remaining bytes in the result */
1979   /* we just need to propagate the sign   */
1980   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1981     {
1982       emitcode ("rlc", "a");
1983       emitcode ("subb", "a,acc");
1984       while (size--)
1985         aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1986     }
1987
1988 release:
1989   /* release the aops */
1990   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1991   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1992 }
1993
1994 /*-----------------------------------------------------------------*/
1995 /* saveRegisters - will look for a call and save the registers     */
1996 /*-----------------------------------------------------------------*/
1997 static void
1998 saveRegisters (iCode * lic)
1999 {
2000   int i;
2001   iCode *ic;
2002   bitVect *rsave;
2003
2004   /* look for call */
2005   for (ic = lic; ic; ic = ic->next)
2006     if (ic->op == CALL || ic->op == PCALL)
2007       break;
2008
2009   if (!ic)
2010     {
2011       fprintf (stderr, "found parameter push with no function call\n");
2012       return;
2013     }
2014
2015   /* if the registers have been saved already or don't need to be then
2016      do nothing */
2017   if (ic->regsSaved)
2018     return;
2019   if (IS_SYMOP(IC_LEFT(ic)) &&
2020       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2021        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2022     return;
2023
2024   /* save the registers in use at this time but skip the
2025      ones for the result */
2026   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2027                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2028
2029   ic->regsSaved = 1;
2030   if (options.useXstack)
2031     {
2032       int count = bitVectnBitsOn (rsave);
2033
2034       if (count == 1)
2035         {
2036           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2037           if (reg->type == REG_BIT)
2038             {
2039               emitcode ("mov", "a,%s", reg->base);
2040             }
2041           else
2042             {
2043               emitcode ("mov", "a,%s", reg->name);
2044             }
2045           emitcode ("mov", "r0,%s", spname);
2046           emitcode ("inc", "%s", spname);// allocate before use
2047           emitcode ("movx", "@r0,a");
2048           if (bitVectBitValue (rsave, R0_IDX))
2049             emitcode ("mov", "r0,a");
2050         }
2051       else if (count != 0)
2052         {
2053           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2054           int nBits = bitVectnBitsOn (rsavebits);
2055
2056           if (nBits != 0)
2057             {
2058               count = count - nBits + 1;
2059               /* remove all but the first bits as they are pushed all at once */
2060               rsave = bitVectCplAnd (rsave, rsavebits);
2061               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2062             }
2063
2064           if (bitVectBitValue (rsave, R0_IDX))
2065             {
2066               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2067             }
2068           emitcode ("mov", "r0,%s", spname);
2069           MOVA ("r0");
2070           emitcode ("add", "a,#%d", count);
2071           emitcode ("mov", "%s,a", spname);
2072           for (i = 0; i < mcs51_nRegs; i++)
2073             {
2074               if (bitVectBitValue (rsave, i))
2075                 {
2076                   regs * reg = mcs51_regWithIdx (i);
2077                   if (i == R0_IDX)
2078                     {
2079                       emitcode ("pop", "acc");
2080                       emitcode ("push", "acc");
2081                     }
2082                   else if (reg->type == REG_BIT)
2083                     {
2084                       emitcode ("mov", "a,%s", reg->base);
2085                     }
2086                   else
2087                     {
2088                       emitcode ("mov", "a,%s", reg->name);
2089                     }
2090                   emitcode ("movx", "@r0,a");
2091                   if (--count)
2092                     {
2093                       emitcode ("inc", "r0");
2094                     }
2095                 }
2096             }
2097           if (bitVectBitValue (rsave, R0_IDX))
2098             {
2099               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2100             }
2101         }
2102     }
2103   else
2104     {
2105       bool bits_pushed = FALSE;
2106       for (i = 0; i < mcs51_nRegs; i++)
2107         {
2108           if (bitVectBitValue (rsave, i))
2109             {
2110               bits_pushed = pushReg (i, bits_pushed);
2111             }
2112         }
2113     }
2114 }
2115
2116 /*-----------------------------------------------------------------*/
2117 /* unsaveRegisters - pop the pushed registers                      */
2118 /*-----------------------------------------------------------------*/
2119 static void
2120 unsaveRegisters (iCode * ic)
2121 {
2122   int i;
2123   bitVect *rsave;
2124
2125   /* restore the registers in use at this time but skip the
2126      ones for the result */
2127   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2128                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2129
2130   if (options.useXstack)
2131     {
2132       int count = bitVectnBitsOn (rsave);
2133
2134       if (count == 1)
2135         {
2136           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2137           emitcode ("mov", "r0,%s", spname);
2138           emitcode ("dec", "r0");
2139           emitcode ("movx", "a,@r0");
2140           if (reg->type == REG_BIT)
2141             {
2142               emitcode ("mov", "%s,a", reg->base);
2143             }
2144           else
2145             {
2146               emitcode ("mov", "%s,a", reg->name);
2147             }
2148           emitcode ("dec", "%s", spname);
2149         }
2150       else if (count != 0)
2151         {
2152           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2153           int nBits = bitVectnBitsOn (rsavebits);
2154
2155           if (nBits != 0)
2156             {
2157               count = count - nBits + 1;
2158               /* remove all but the first bits as they are popped all at once */
2159               rsave = bitVectCplAnd (rsave, rsavebits);
2160               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2161             }
2162
2163           emitcode ("mov", "r0,%s", spname);
2164           for (i = mcs51_nRegs; i >= 0; i--)
2165             {
2166               if (bitVectBitValue (rsave, i))
2167                 {
2168                   regs * reg = mcs51_regWithIdx (i);
2169                   emitcode ("dec", "r0");
2170                   emitcode ("movx", "a,@r0");
2171                   if (i == R0_IDX)
2172                     {
2173                       emitcode ("push", "acc");
2174                     }
2175                   else if (reg->type == REG_BIT)
2176                     {
2177                       emitcode ("mov", "%s,a", reg->base);
2178                     }
2179                   else
2180                     {
2181                       emitcode ("mov", "%s,a", reg->name);
2182                     }
2183                 }
2184             }
2185           emitcode ("mov", "%s,r0", spname);
2186           if (bitVectBitValue (rsave, R0_IDX))
2187             {
2188               emitcode ("pop", "ar0");
2189             }
2190         }
2191     }
2192   else
2193     {
2194       bool bits_popped = FALSE;
2195       for (i = mcs51_nRegs; i >= 0; i--)
2196         {
2197           if (bitVectBitValue (rsave, i))
2198             {
2199               bits_popped = popReg (i, bits_popped);
2200             }
2201         }
2202     }
2203 }
2204
2205
2206 /*-----------------------------------------------------------------*/
2207 /* pushSide -                                                      */
2208 /*-----------------------------------------------------------------*/
2209 static void
2210 pushSide (operand * oper, int size)
2211 {
2212   int offset = 0;
2213   while (size--)
2214     {
2215       char *l = aopGet (oper, offset++, FALSE, TRUE);
2216       if (AOP_TYPE (oper) != AOP_REG &&
2217           AOP_TYPE (oper) != AOP_DIR &&
2218           strcmp (l, "a"))
2219         {
2220           MOVA (l);
2221           emitcode ("push", "acc");
2222         }
2223       else
2224         {
2225           emitcode ("push", "%s", l);
2226         }
2227     }
2228 }
2229
2230 /*-----------------------------------------------------------------*/
2231 /* assignResultValue - also indicates if acc is in use afterwards  */
2232 /*-----------------------------------------------------------------*/
2233 static bool
2234 assignResultValue (operand * oper, operand * func)
2235 {
2236   int offset = 0;
2237   int size = AOP_SIZE (oper);
2238   bool accuse = FALSE;
2239   bool pushedA = FALSE;
2240
2241   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2242     {
2243       outBitC (oper);
2244       return FALSE;
2245     }
2246
2247   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2248     {
2249       emitcode ("push", "acc");
2250       pushedA = TRUE;
2251     }
2252   while (size--)
2253     {
2254       if ((offset == 3) && pushedA)
2255         emitcode ("pop", "acc");
2256       accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2257       offset++;
2258     }
2259   return accuse;
2260 }
2261
2262
2263 /*-----------------------------------------------------------------*/
2264 /* genXpush - pushes onto the external stack                       */
2265 /*-----------------------------------------------------------------*/
2266 static void
2267 genXpush (iCode * ic)
2268 {
2269   asmop *aop = newAsmop (0);
2270   regs *r;
2271   int size, offset = 0;
2272
2273   D(emitcode (";     genXpush",""));
2274
2275   aopOp (IC_LEFT (ic), ic, FALSE);
2276   r = getFreePtr (ic, &aop, FALSE);
2277
2278   size = AOP_SIZE (IC_LEFT (ic));
2279
2280   if (size == 1)
2281     {
2282       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2283       emitcode ("mov", "%s,%s", r->name, spname);
2284       emitcode ("inc", "%s", spname); // allocate space first
2285       emitcode ("movx", "@%s,a", r->name);
2286     }
2287   else
2288     {
2289       // allocate space first
2290       emitcode ("mov", "%s,%s", r->name, spname);
2291       MOVA (r->name);
2292       emitcode ("add", "a,#%d", size);
2293       emitcode ("mov", "%s,a", spname);
2294
2295       while (size--)
2296         {
2297           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2298           emitcode ("movx", "@%s,a", r->name);
2299           emitcode ("inc", "%s", r->name);
2300         }
2301     }
2302
2303   freeAsmop (NULL, aop, ic, TRUE);
2304   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* genIpush - generate code for pushing this gets a little complex */
2309 /*-----------------------------------------------------------------*/
2310 static void
2311 genIpush (iCode * ic)
2312 {
2313   int size, offset = 0;
2314   char *l;
2315   char *prev = "";
2316
2317   D(emitcode (";     genIpush",""));
2318
2319   /* if this is not a parm push : ie. it is spill push
2320      and spill push is always done on the local stack */
2321   if (!ic->parmPush)
2322     {
2323
2324       /* and the item is spilt then do nothing */
2325       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2326         return;
2327
2328       aopOp (IC_LEFT (ic), ic, FALSE);
2329       size = AOP_SIZE (IC_LEFT (ic));
2330       /* push it on the stack */
2331       while (size--)
2332         {
2333           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2334           if (*l == '#')
2335             {
2336               MOVA (l);
2337               l = "acc";
2338             }
2339           emitcode ("push", "%s", l);
2340         }
2341       return;
2342     }
2343
2344   /* this is a parameter push: in this case we call
2345      the routine to find the call and save those
2346      registers that need to be saved */
2347   saveRegisters (ic);
2348
2349   /* if use external stack then call the external
2350      stack pushing routine */
2351   if (options.useXstack)
2352     {
2353       genXpush (ic);
2354       return;
2355     }
2356
2357   /* then do the push */
2358   aopOp (IC_LEFT (ic), ic, FALSE);
2359
2360   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2361   size = AOP_SIZE (IC_LEFT (ic));
2362
2363   while (size--)
2364     {
2365       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2366       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2367           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2368           strcmp (l, "a"))
2369         {
2370           if (strcmp (l, prev) || *l == '@')
2371             MOVA (l);
2372           emitcode ("push", "acc");
2373         }
2374       else
2375         {
2376           emitcode ("push", "%s", l);
2377         }
2378       prev = l;
2379     }
2380
2381   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2382 }
2383
2384 /*-----------------------------------------------------------------*/
2385 /* genIpop - recover the registers: can happen only for spilling   */
2386 /*-----------------------------------------------------------------*/
2387 static void
2388 genIpop (iCode * ic)
2389 {
2390   int size, offset;
2391
2392   D(emitcode (";     genIpop",""));
2393
2394   /* if the temp was not pushed then */
2395   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2396     return;
2397
2398   aopOp (IC_LEFT (ic), ic, FALSE);
2399   size = AOP_SIZE (IC_LEFT (ic));
2400   offset = (size - 1);
2401   while (size--)
2402     emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2403                                    FALSE, TRUE));
2404
2405   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2406 }
2407
2408 /*-----------------------------------------------------------------*/
2409 /* saveRBank - saves an entire register bank on the stack          */
2410 /*-----------------------------------------------------------------*/
2411 static void
2412 saveRBank (int bank, iCode * ic, bool pushPsw)
2413 {
2414   int i;
2415   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2416   asmop *aop = NULL;
2417   regs *r = NULL;
2418
2419   if (options.useXstack)
2420     {
2421       if (!ic)
2422       {
2423           /* Assume r0 is available for use. */
2424           r = mcs51_regWithIdx (R0_IDX);;
2425       }
2426       else
2427       {
2428           aop = newAsmop (0);
2429           r = getFreePtr (ic, &aop, FALSE);
2430       }
2431       // allocate space first
2432       emitcode ("mov", "%s,%s", r->name, spname);
2433       MOVA (r->name);
2434       emitcode ("add", "a,#%d", count);
2435       emitcode ("mov", "%s,a", spname);
2436     }
2437
2438   for (i = 0; i < 8; i++)
2439     {
2440       if (options.useXstack)
2441         {
2442           emitcode ("mov", "a,(%s+%d)",
2443                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2444           emitcode ("movx", "@%s,a", r->name);
2445           if (--count)
2446             emitcode ("inc", "%s", r->name);
2447         }
2448       else
2449         emitcode ("push", "(%s+%d)",
2450                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2451     }
2452
2453   if (mcs51_nRegs > 8)
2454     {
2455       if (options.useXstack)
2456         {
2457           emitcode ("mov", "a,bits");
2458           emitcode ("movx", "@%s,a", r->name);
2459           if (--count)
2460             emitcode ("inc", "%s", r->name);
2461         }
2462       else
2463         {
2464           emitcode ("push", "bits");
2465         }
2466       BitBankUsed = 1;
2467     }
2468
2469   if (pushPsw)
2470     {
2471       if (options.useXstack)
2472         {
2473           emitcode ("mov", "a,psw");
2474           emitcode ("movx", "@%s,a", r->name);
2475
2476         }
2477       else
2478         {
2479           emitcode ("push", "psw");
2480         }
2481
2482       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2483     }
2484
2485   if (aop)
2486     {
2487       freeAsmop (NULL, aop, ic, TRUE);
2488     }
2489
2490   if (ic)
2491   {
2492     ic->bankSaved = 1;
2493   }
2494 }
2495
2496 /*-----------------------------------------------------------------*/
2497 /* unsaveRBank - restores the register bank from stack             */
2498 /*-----------------------------------------------------------------*/
2499 static void
2500 unsaveRBank (int bank, iCode * ic, bool popPsw)
2501 {
2502   int i;
2503   asmop *aop = NULL;
2504   regs *r = NULL;
2505
2506   if (options.useXstack)
2507     {
2508       if (!ic)
2509         {
2510           /* Assume r0 is available for use. */
2511           r = mcs51_regWithIdx (R0_IDX);;
2512         }
2513       else
2514         {
2515           aop = newAsmop (0);
2516           r = getFreePtr (ic, &aop, FALSE);
2517         }
2518       emitcode ("mov", "%s,%s", r->name, spname);
2519     }
2520
2521   if (popPsw)
2522     {
2523       if (options.useXstack)
2524         {
2525           emitcode ("dec", "%s", r->name);
2526           emitcode ("movx", "a,@%s", r->name);
2527           emitcode ("mov", "psw,a");
2528         }
2529       else
2530         {
2531           emitcode ("pop", "psw");
2532         }
2533     }
2534
2535   if (mcs51_nRegs > 8)
2536     {
2537       if (options.useXstack)
2538         {
2539           emitcode ("dec", "%s", r->name);
2540           emitcode ("movx", "a,@%s", r->name);
2541           emitcode ("mov", "bits,a");
2542         }
2543       else
2544         {
2545           emitcode ("pop", "bits");
2546         }
2547     }
2548
2549   for (i = 7; i >= 0; i--)
2550     {
2551       if (options.useXstack)
2552         {
2553           emitcode ("dec", "%s", r->name);
2554           emitcode ("movx", "a,@%s", r->name);
2555           emitcode ("mov", "(%s+%d),a",
2556                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2557         }
2558       else
2559         {
2560           emitcode ("pop", "(%s+%d)",
2561                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2562         }
2563     }
2564
2565   if (options.useXstack)
2566     {
2567       emitcode ("mov", "%s,%s", spname, r->name);
2568     }
2569
2570   if (aop)
2571     {
2572       freeAsmop (NULL, aop, ic, TRUE);
2573     }
2574 }
2575
2576 /*-----------------------------------------------------------------*/
2577 /* genSend - gen code for SEND                                     */
2578 /*-----------------------------------------------------------------*/
2579 static void genSend(set *sendSet)
2580 {
2581   iCode *sic;
2582   int bit_count = 0;
2583
2584   /* first we do all bit parameters */
2585   for (sic = setFirstItem (sendSet); sic;
2586        sic = setNextItem (sendSet))
2587     {
2588       aopOp (IC_LEFT (sic), sic, FALSE);
2589
2590       if (sic->argreg > 12)
2591         {
2592           int bit = sic->argreg-13;
2593
2594           /* if left is a literal then
2595              we know what the value is */
2596           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2597             {
2598               if (((int) operandLitValue (IC_LEFT (sic))))
2599                   emitcode ("setb", "b[%d]", bit);
2600               else
2601                   emitcode ("clr", "b[%d]", bit);
2602             }
2603           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2604             {
2605               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2606                 if (strcmp (l, "c"))
2607                     emitcode ("mov", "c,%s", l);
2608                 emitcode ("mov", "b[%d],c", bit);
2609             }
2610           else
2611             {
2612               /* we need to or */
2613               toBoolean (IC_LEFT (sic));
2614               /* set C, if a >= 1 */
2615               emitcode ("add", "a,#0xff");
2616               emitcode ("mov", "b[%d],c", bit);
2617             }
2618           bit_count++;
2619           BitBankUsed = 1;
2620         }
2621       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2622     }
2623
2624   if (bit_count)
2625     {
2626       saveRegisters (setFirstItem (sendSet));
2627       emitcode ("mov", "bits,b");
2628     }
2629
2630   /* then we do all other parameters */
2631   for (sic = setFirstItem (sendSet); sic;
2632        sic = setNextItem (sendSet))
2633     {
2634       int size, offset = 0;
2635       aopOp (IC_LEFT (sic), sic, FALSE);
2636       size = AOP_SIZE (IC_LEFT (sic));
2637
2638       if (sic->argreg == 1)
2639         {
2640           while (size--)
2641             {
2642               char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2643               if (strcmp (l, fReturn[offset]))
2644                   emitcode ("mov", "%s,%s", fReturn[offset], l);
2645               offset++;
2646             }
2647         }
2648       else if (sic->argreg <= 12)
2649         {
2650           while (size--)
2651             {
2652               emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2653                         aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2654               offset++;
2655             }
2656         }
2657       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2658     }
2659 }
2660
2661 /*-----------------------------------------------------------------*/
2662 /* selectRegBank - emit code to select the register bank           */
2663 /*-----------------------------------------------------------------*/
2664 static void
2665 selectRegBank (short bank, bool keepFlags)
2666 {
2667   /* if f.e. result is in carry */
2668   if (keepFlags)
2669     {
2670       emitcode ("anl", "psw,#0xE7");
2671       if (bank)
2672         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2673     }
2674   else
2675     {
2676       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2677     }
2678 }
2679
2680 /*-----------------------------------------------------------------*/
2681 /* genCall - generates a call statement                            */
2682 /*-----------------------------------------------------------------*/
2683 static void
2684 genCall (iCode * ic)
2685 {
2686   sym_link *dtype;
2687   sym_link *etype;
2688 //  bool restoreBank = FALSE;
2689   bool swapBanks = FALSE;
2690   bool accuse = FALSE;
2691   bool accPushed = FALSE;
2692   bool resultInF0 = FALSE;
2693
2694   D(emitcode(";     genCall",""));
2695
2696   dtype = operandType (IC_LEFT (ic));
2697   etype = getSpec(dtype);
2698   /* if send set is not empty then assign */
2699   if (_G.sendSet)
2700     {
2701         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2702             genSend(reverseSet(_G.sendSet));
2703         } else {
2704             genSend(_G.sendSet);
2705         }
2706
2707       _G.sendSet = NULL;
2708     }
2709
2710   /* if we are calling a not _naked function that is not using
2711      the same register bank then we need to save the
2712      destination registers on the stack */
2713   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2714       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2715        !IFFUNC_ISISR (dtype))
2716     {
2717       swapBanks = TRUE;
2718     }
2719
2720   /* if caller saves & we have not saved then */
2721   if (!ic->regsSaved)
2722       saveRegisters (ic);
2723
2724   if (swapBanks)
2725     {
2726         emitcode ("mov", "psw,#0x%02x",
2727            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2728     }
2729
2730   /* make the call */
2731   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2732     {
2733       if (IFFUNC_CALLEESAVES(dtype))
2734         {
2735           werror (E_BANKED_WITH_CALLEESAVES);
2736         }
2737       else
2738         {
2739           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2740                      OP_SYMBOL (IC_LEFT (ic))->rname :
2741                      OP_SYMBOL (IC_LEFT (ic))->name);
2742
2743           emitcode ("mov", "r0,#%s", l);
2744           emitcode ("mov", "r1,#(%s >> 8)", l);
2745           emitcode ("mov", "r2,#(%s >> 16)", l);
2746           emitcode ("lcall", "__sdcc_banked_call");
2747         }
2748     }
2749   else
2750     {
2751       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2752                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2753                                 OP_SYMBOL (IC_LEFT (ic))->name));
2754     }
2755
2756   if (swapBanks)
2757     {
2758       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2759     }
2760
2761   /* if we need assign a result value */
2762   if ((IS_ITEMP (IC_RESULT (ic)) &&
2763        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2764        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2765         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2766         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2767       IS_TRUE_SYMOP (IC_RESULT (ic)))
2768     {
2769
2770       _G.accInUse++;
2771       aopOp (IC_RESULT (ic), ic, FALSE);
2772       _G.accInUse--;
2773
2774       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2775
2776       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2777     }
2778
2779   /* adjust the stack for parameters if required */
2780   if (ic->parmBytes)
2781     {
2782       int i;
2783       if (ic->parmBytes > 3)
2784         {
2785           if (accuse)
2786             {
2787               emitcode ("push", "acc");
2788               accPushed = TRUE;
2789             }
2790           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2791               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2792             {
2793               emitcode ("mov", "F0,c");
2794               resultInF0 = TRUE;
2795             }
2796
2797           emitcode ("mov", "a,%s", spname);
2798           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2799           emitcode ("mov", "%s,a", spname);
2800
2801           /* unsaveRegisters from xstack needs acc, but */
2802           /* unsaveRegisters from stack needs this popped */
2803           if (accPushed && !options.useXstack)
2804             {
2805               emitcode ("pop", "acc");
2806               accPushed = FALSE;
2807             }
2808         }
2809       else
2810         for (i = 0; i < ic->parmBytes; i++)
2811           emitcode ("dec", "%s", spname);
2812     }
2813
2814   /* if we had saved some registers then unsave them */
2815   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2816     {
2817       if (accuse && !accPushed && options.useXstack)
2818         {
2819           /* xstack needs acc, but doesn't touch normal stack */
2820           emitcode ("push", "acc");
2821           accPushed = TRUE;
2822         }
2823       unsaveRegisters (ic);
2824     }
2825
2826 //  /* if register bank was saved then pop them */
2827 //  if (restoreBank)
2828 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2829
2830   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2831     {
2832       if (resultInF0)
2833           emitcode ("mov", "c,F0");
2834
2835       aopOp (IC_RESULT (ic), ic, FALSE);
2836       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2837       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2838     }
2839
2840   if (accPushed)
2841     emitcode ("pop", "acc");
2842 }
2843
2844 /*-----------------------------------------------------------------*/
2845 /* -10l - generates a call by pointer statement                */
2846 /*-----------------------------------------------------------------*/
2847 static void
2848 genPcall (iCode * ic)
2849 {
2850   sym_link *dtype;
2851   sym_link *etype;
2852   symbol *rlbl = newiTempLabel (NULL);
2853 //  bool restoreBank=FALSE;
2854   bool swapBanks = FALSE;
2855   bool resultInF0 = FALSE;
2856
2857   D(emitcode(";     genPCall",""));
2858
2859   dtype = operandType (IC_LEFT (ic))->next;
2860   etype = getSpec(dtype);
2861   /* if caller saves & we have not saved then */
2862   if (!ic->regsSaved)
2863     saveRegisters (ic);
2864
2865   /* if we are calling a not _naked function that is not using
2866      the same register bank then we need to save the
2867      destination registers on the stack */
2868   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2869       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2870       !IFFUNC_ISISR (dtype))
2871     {
2872 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2873 //    restoreBank=TRUE;
2874       swapBanks = TRUE;
2875       // need caution message to user here
2876     }
2877
2878   if (IS_LITERAL(etype))
2879     {
2880       /* if send set is not empty then assign */
2881       if (_G.sendSet)
2882         {
2883           genSend(reverseSet(_G.sendSet));
2884           _G.sendSet = NULL;
2885         }
2886
2887       if (swapBanks)
2888         {
2889           emitcode ("mov", "psw,#0x%02x",
2890            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2891         }
2892
2893       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2894         {
2895           if (IFFUNC_CALLEESAVES(dtype))
2896             {
2897               werror (E_BANKED_WITH_CALLEESAVES);
2898             }
2899           else
2900             {
2901               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2902
2903               emitcode ("mov", "r0,#%s", l);
2904               emitcode ("mov", "r1,#(%s >> 8)", l);
2905               emitcode ("mov", "r2,#(%s >> 16)", l);
2906               emitcode ("lcall", "__sdcc_banked_call");
2907             }
2908         }
2909       else
2910         {
2911           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2912         }
2913     }
2914   else
2915     {
2916       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2917         {
2918           if (IFFUNC_CALLEESAVES(dtype))
2919             {
2920               werror (E_BANKED_WITH_CALLEESAVES);
2921             }
2922           else
2923             {
2924               aopOp (IC_LEFT (ic), ic, FALSE);
2925
2926               if (!swapBanks)
2927                 {
2928                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2929                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2930                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2931                 }
2932               else
2933                 {
2934                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2935                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2936                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2937                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2938                 }
2939
2940               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2941
2942               /* if send set is not empty then assign */
2943               if (_G.sendSet)
2944                 {
2945                   genSend(reverseSet(_G.sendSet));
2946                   _G.sendSet = NULL;
2947                 }
2948
2949               if (swapBanks)
2950                 {
2951                   emitcode ("mov", "psw,#0x%02x",
2952                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2953                 }
2954
2955               /* make the call */
2956               emitcode ("lcall", "__sdcc_banked_call");
2957             }
2958         }
2959       else
2960         {
2961           /* push the return address on to the stack */
2962           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2963           emitcode ("push", "acc");
2964           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2965           emitcode ("push", "acc");
2966
2967           /* now push the calling address */
2968           aopOp (IC_LEFT (ic), ic, FALSE);
2969
2970           pushSide (IC_LEFT (ic), FPTRSIZE);
2971
2972           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2973
2974           /* if send set is not empty the assign */
2975           if (_G.sendSet)
2976             {
2977               genSend(reverseSet(_G.sendSet));
2978               _G.sendSet = NULL;
2979             }
2980
2981           if (swapBanks)
2982             {
2983               emitcode ("mov", "psw,#0x%02x",
2984                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2985             }
2986
2987           /* make the call */
2988           emitcode ("ret", "");
2989           emitcode ("", "%05d$:", (rlbl->key + 100));
2990         }
2991     }
2992   if (swapBanks)
2993     {
2994       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2995     }
2996
2997   /* if we need assign a result value */
2998   if ((IS_ITEMP (IC_RESULT (ic)) &&
2999        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3000        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3001         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3002       IS_TRUE_SYMOP (IC_RESULT (ic)))
3003     {
3004
3005       _G.accInUse++;
3006       aopOp (IC_RESULT (ic), ic, FALSE);
3007       _G.accInUse--;
3008
3009       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3010
3011       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3012     }
3013
3014   /* adjust the stack for parameters if required */
3015   if (ic->parmBytes)
3016     {
3017       int i;
3018       if (ic->parmBytes > 3)
3019         {
3020           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3021               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3022             {
3023               emitcode ("mov", "F0,c");
3024               resultInF0 = TRUE;
3025             }
3026
3027           emitcode ("mov", "a,%s", spname);
3028           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3029           emitcode ("mov", "%s,a", spname);
3030         }
3031       else
3032         for (i = 0; i < ic->parmBytes; i++)
3033           emitcode ("dec", "%s", spname);
3034
3035     }
3036
3037 //  /* if register bank was saved then unsave them */
3038 //  if (restoreBank)
3039 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3040
3041   /* if we had saved some registers then unsave them */
3042   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3043     unsaveRegisters (ic);
3044
3045   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3046     {
3047       if (resultInF0)
3048           emitcode ("mov", "c,F0");
3049
3050       aopOp (IC_RESULT (ic), ic, FALSE);
3051       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3052       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3053     }
3054 }
3055
3056 /*-----------------------------------------------------------------*/
3057 /* resultRemat - result  is rematerializable                       */
3058 /*-----------------------------------------------------------------*/
3059 static int
3060 resultRemat (iCode * ic)
3061 {
3062   if (SKIP_IC (ic) || ic->op == IFX)
3063     return 0;
3064
3065   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3066     {
3067       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3068       if (sym->remat && !POINTER_SET (ic))
3069         return 1;
3070     }
3071
3072   return 0;
3073 }
3074
3075 #if defined(__BORLANDC__) || defined(_MSC_VER)
3076 #define STRCASECMP stricmp
3077 #else
3078 #define STRCASECMP strcasecmp
3079 #endif
3080
3081 /*-----------------------------------------------------------------*/
3082 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3083 /*-----------------------------------------------------------------*/
3084 static int
3085 regsCmp(void *p1, void *p2)
3086 {
3087   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3088 }
3089
3090 static bool
3091 inExcludeList (char *s)
3092 {
3093   const char *p = setFirstItem(options.excludeRegsSet);
3094
3095   if (p == NULL || STRCASECMP(p, "none") == 0)
3096     return FALSE;
3097
3098
3099   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3100 }
3101
3102 /*-----------------------------------------------------------------*/
3103 /* genFunction - generated code for function entry                 */
3104 /*-----------------------------------------------------------------*/
3105 static void
3106 genFunction (iCode * ic)
3107 {
3108   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3109   sym_link *ftype;
3110   bool     switchedPSW = FALSE;
3111   int      calleesaves_saved_register = -1;
3112   int      stackAdjust = sym->stack;
3113   int      accIsFree = sym->recvSize < 4;
3114   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3115   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3116
3117   _G.nRegsSaved = 0;
3118   /* create the function header */
3119   emitcode (";", "-----------------------------------------");
3120   emitcode (";", " function %s", sym->name);
3121   emitcode (";", "-----------------------------------------");
3122
3123   emitcode ("", "%s:", sym->rname);
3124   ftype = operandType (IC_LEFT (ic));
3125   _G.currentFunc = sym;
3126
3127   if (IFFUNC_ISNAKED(ftype))
3128   {
3129       emitcode(";", "naked function: no prologue.");
3130       return;
3131   }
3132
3133   /* here we need to generate the equates for the
3134      register bank if required */
3135   if (FUNC_REGBANK (ftype) != rbank)
3136     {
3137       int i;
3138
3139       rbank = FUNC_REGBANK (ftype);
3140       for (i = 0; i < mcs51_nRegs; i++)
3141         {
3142           if (regs8051[i].type != REG_BIT)
3143             {
3144               if (strcmp (regs8051[i].base, "0") == 0)
3145                 emitcode ("", "%s = 0x%02x",
3146                           regs8051[i].dname,
3147                           8 * rbank + regs8051[i].offset);
3148               else
3149                 emitcode ("", "%s = %s + 0x%02x",
3150                           regs8051[i].dname,
3151                           regs8051[i].base,
3152                           8 * rbank + regs8051[i].offset);
3153             }
3154         }
3155     }
3156
3157   /* if this is an interrupt service routine then
3158      save acc, b, dpl, dph  */
3159   if (IFFUNC_ISISR (sym->type))
3160     {
3161
3162       if (!inExcludeList ("acc"))
3163         emitcode ("push", "acc");
3164       if (!inExcludeList ("b"))
3165         emitcode ("push", "b");
3166       if (!inExcludeList ("dpl"))
3167         emitcode ("push", "dpl");
3168       if (!inExcludeList ("dph"))
3169         emitcode ("push", "dph");
3170       /* if this isr has no bank i.e. is going to
3171          run with bank 0 , then we need to save more
3172          registers :-) */
3173       if (!FUNC_REGBANK (sym->type))
3174         {
3175
3176           /* if this function does not call any other
3177              function then we can be economical and
3178              save only those registers that are used */
3179           if (!IFFUNC_HASFCALL(sym->type))
3180             {
3181               int i;
3182
3183               /* if any registers used */
3184               if (sym->regsUsed)
3185                 {
3186                   bool bits_pushed = FALSE;
3187                   /* save the registers used */
3188                   for (i = 0; i < sym->regsUsed->size; i++)
3189                     {
3190                       if (bitVectBitValue (sym->regsUsed, i))
3191                         bits_pushed = pushReg (i, bits_pushed);
3192                     }
3193                 }
3194             }
3195           else
3196             {
3197
3198               /* this function has a function call. We cannot
3199                  determines register usage so we will have to push the
3200                  entire bank */
3201                 saveRBank (0, ic, FALSE);
3202                 if (options.parms_in_bank1) {
3203                     int i;
3204                     for (i=0; i < 8 ; i++ ) {
3205                         emitcode ("push","%s",rb1regs[i]);
3206                     }
3207                 }
3208             }
3209         }
3210         else
3211         {
3212             /* This ISR uses a non-zero bank.
3213              *
3214              * We assume that the bank is available for our
3215              * exclusive use.
3216              *
3217              * However, if this ISR calls a function which uses some
3218              * other bank, we must save that bank entirely.
3219              */
3220             unsigned long banksToSave = 0;
3221
3222             if (IFFUNC_HASFCALL(sym->type))
3223             {
3224
3225 #define MAX_REGISTER_BANKS 4
3226
3227                 iCode *i;
3228                 int ix;
3229
3230                 for (i = ic; i; i = i->next)
3231                 {
3232                     if (i->op == ENDFUNCTION)
3233                     {
3234                         /* we got to the end OK. */
3235                         break;
3236                     }
3237
3238                     if (i->op == CALL)
3239                     {
3240                         sym_link *dtype;
3241
3242                         dtype = operandType (IC_LEFT(i));
3243                         if (dtype
3244                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3245                         {
3246                              /* Mark this bank for saving. */
3247                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3248                              {
3249                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3250                              }
3251                              else
3252                              {
3253                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3254                              }
3255
3256                              /* And note that we don't need to do it in
3257                               * genCall.
3258                               */
3259                              i->bankSaved = 1;
3260                         }
3261                     }
3262                     if (i->op == PCALL)
3263                     {
3264                         /* This is a mess; we have no idea what
3265                          * register bank the called function might
3266                          * use.
3267                          *
3268                          * The only thing I can think of to do is
3269                          * throw a warning and hope.
3270                          */
3271                         werror(W_FUNCPTR_IN_USING_ISR);
3272                     }
3273                 }
3274
3275                 if (banksToSave && options.useXstack)
3276                 {
3277                     /* Since we aren't passing it an ic,
3278                      * saveRBank will assume r0 is available to abuse.
3279                      *
3280                      * So switch to our (trashable) bank now, so
3281                      * the caller's R0 isn't trashed.
3282                      */
3283                     emitcode ("push", "psw");
3284                     emitcode ("mov", "psw,#0x%02x",
3285                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3286                     switchedPSW = TRUE;
3287                 }
3288
3289                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3290                 {
3291                      if (banksToSave & (1 << ix))
3292                      {
3293                          saveRBank(ix, NULL, FALSE);
3294                      }
3295                 }
3296             }
3297             // TODO: this needs a closer look
3298             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3299         }
3300
3301       /* Set the register bank to the desired value if nothing else */
3302       /* has done so yet. */
3303       if (!switchedPSW)
3304         {
3305           emitcode ("push", "psw");
3306           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3307         }
3308     }
3309   else
3310     {
3311       /* This is a non-ISR function. The caller has already switched register */
3312       /* banks, if necessary, so just handle the callee-saves option. */
3313
3314       /* if callee-save to be used for this function
3315          then save the registers being used in this function */
3316       if (IFFUNC_CALLEESAVES(sym->type))
3317         {
3318           int i;
3319
3320           /* if any registers used */
3321           if (sym->regsUsed)
3322             {
3323               bool bits_pushed = FALSE;
3324               /* save the registers used */
3325               for (i = 0; i < sym->regsUsed->size; i++)
3326                 {
3327                   if (bitVectBitValue (sym->regsUsed, i))
3328                     {
3329                       /* remember one saved register for later usage */
3330                       if (calleesaves_saved_register < 0)
3331                         calleesaves_saved_register = i;
3332                       bits_pushed = pushReg (i, bits_pushed);
3333                       _G.nRegsSaved++;
3334                     }
3335                 }
3336             }
3337         }
3338     }
3339
3340
3341   if (fReentrant)
3342     {
3343       if (options.useXstack)
3344         {
3345           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3346             {
3347               emitcode ("mov", "r0,%s", spname);
3348               emitcode ("inc", "%s", spname);
3349               emitcode ("xch", "a,_bpx");
3350               emitcode ("movx", "@r0,a");
3351               emitcode ("inc", "r0");
3352               emitcode ("mov", "a,r0");
3353               emitcode ("xch", "a,_bpx");
3354             }
3355           if (sym->stack)
3356             {
3357               emitcode ("push", "_bp");     /* save the callers stack  */
3358               emitcode ("mov", "_bp,sp");
3359             }
3360         }
3361       else
3362         {
3363           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3364             {
3365               /* set up the stack */
3366               emitcode ("push", "_bp");     /* save the callers stack  */
3367               emitcode ("mov", "_bp,sp");
3368             }
3369         }
3370     }
3371
3372   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3373   /* before setting up the stack frame completely. */
3374   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3375     {
3376       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3377
3378       if (rsym->isitmp)
3379         {
3380           if (rsym && rsym->regType == REG_CND)
3381             rsym = NULL;
3382           if (rsym && (rsym->accuse || rsym->ruonly))
3383             rsym = NULL;
3384           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3385             rsym = rsym->usl.spillLoc;
3386         }
3387
3388       /* If the RECEIVE operand immediately spills to the first entry on the */
3389       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3390       /* rather than the usual @r0/r1 machinations. */
3391       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3392         {
3393           int ofs;
3394
3395           _G.current_iCode = ric;
3396           D(emitcode (";     genReceive",""));
3397           for (ofs=0; ofs < sym->recvSize; ofs++)
3398             {
3399               if (!strcmp (fReturn[ofs], "a"))
3400                 emitcode ("push", "acc");
3401               else
3402                 emitcode ("push", fReturn[ofs]);
3403             }
3404           stackAdjust -= sym->recvSize;
3405           if (stackAdjust<0)
3406             {
3407               assert (stackAdjust>=0);
3408               stackAdjust = 0;
3409             }
3410           _G.current_iCode = ic;
3411           ric->generated = 1;
3412           accIsFree = 1;
3413         }
3414       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3415       /* to free up the accumulator. */
3416       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3417         {
3418           int ofs;
3419
3420           _G.current_iCode = ric;
3421           D(emitcode (";     genReceive",""));
3422           for (ofs=0; ofs < sym->recvSize; ofs++)
3423             {
3424               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3425             }
3426           _G.current_iCode = ic;
3427           ric->generated = 1;
3428           accIsFree = 1;
3429         }
3430     }
3431
3432   /* adjust the stack for the function */
3433   if (stackAdjust)
3434     {
3435       int i = stackAdjust;
3436       if (i > 256)
3437         werror (W_STACK_OVERFLOW, sym->name);
3438
3439       if (i > 3 && accIsFree)
3440         {
3441           emitcode ("mov", "a,sp");
3442           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3443           emitcode ("mov", "sp,a");
3444         }
3445       else if (i > 5)
3446         {
3447           /* The accumulator is not free, so we will need another register */
3448           /* to clobber. No need to worry about a possible conflict with */
3449           /* the above early RECEIVE optimizations since they would have */
3450           /* freed the accumulator if they were generated. */
3451
3452           if (IFFUNC_CALLEESAVES(sym->type))
3453             {
3454               /* if it's a callee-saves function we need a saved register */
3455               if (calleesaves_saved_register >= 0)
3456                 {
3457                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3458                   emitcode ("mov", "a,sp");
3459                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3460                   emitcode ("mov", "sp,a");
3461                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3462                 }
3463               else
3464                 /* do it the hard way */
3465                 while (i--)
3466                   emitcode ("inc", "sp");
3467             }
3468           else
3469             {
3470               /* not callee-saves, we can clobber r0 */
3471               emitcode ("mov", "r0,a");
3472               emitcode ("mov", "a,sp");
3473               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3474               emitcode ("mov", "sp,a");
3475               emitcode ("mov", "a,r0");
3476             }
3477         }
3478       else
3479         while (i--)
3480           emitcode ("inc", "sp");
3481     }
3482
3483   if (sym->xstack)
3484     {
3485       char i = ((char) sym->xstack & 0xff);
3486
3487       if (i > 3 && accIsFree)
3488         {
3489           emitcode ("mov", "a,_spx");
3490           emitcode ("add", "a,#0x%02x", i);
3491           emitcode ("mov", "_spx,a");
3492         }
3493       else if (i > 5)
3494         {
3495           emitcode ("push", "acc");
3496           emitcode ("mov", "a,_spx");
3497           emitcode ("add", "a,#0x%02x", i);
3498           emitcode ("mov", "_spx,a");
3499           emitcode ("pop", "acc");
3500         }
3501       else
3502         {
3503           while (i--)
3504             emitcode ("inc", "_spx");
3505         }
3506     }
3507
3508   /* if critical function then turn interrupts off */
3509   if (IFFUNC_ISCRITICAL (ftype))
3510     {
3511       symbol *tlbl = newiTempLabel (NULL);
3512       emitcode ("setb", "c");
3513       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3514       emitcode ("clr", "c");
3515       emitcode ("", "%05d$:", (tlbl->key + 100));
3516       emitcode ("push", "psw"); /* save old ea via c in psw */
3517     }
3518 }
3519
3520 /*-----------------------------------------------------------------*/
3521 /* genEndFunction - generates epilogue for functions               */
3522 /*-----------------------------------------------------------------*/
3523 static void
3524 genEndFunction (iCode * ic)
3525 {
3526   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3527   lineNode *lnp = lineCurr;
3528   bitVect  *regsUsed;
3529   bitVect  *regsUsedPrologue;
3530   bitVect  *regsUnneeded;
3531   int      idx;
3532
3533   _G.currentFunc = NULL;
3534   if (IFFUNC_ISNAKED(sym->type))
3535   {
3536       emitcode(";", "naked function: no epilogue.");
3537       if (options.debug && currFunc)
3538         debugFile->writeEndFunction (currFunc, ic, 0);
3539       return;
3540   }
3541
3542   if (IFFUNC_ISCRITICAL (sym->type))
3543     {
3544       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3545         {
3546           emitcode ("rlc", "a");   /* save c in a */
3547           emitcode ("pop", "psw"); /* restore ea via c in psw */
3548           emitcode ("mov", "ea,c");
3549           emitcode ("rrc", "a");   /* restore c from a */
3550         }
3551       else
3552         {
3553           emitcode ("pop", "psw"); /* restore ea via c in psw */
3554           emitcode ("mov", "ea,c");
3555         }
3556     }
3557
3558   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3559     {
3560       if (options.useXstack)
3561         {
3562           if (sym->stack)
3563             {
3564               emitcode ("mov", "sp,_bp");
3565               emitcode ("pop", "_bp");
3566             }
3567           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3568             {
3569               emitcode ("xch", "a,_bpx");
3570               emitcode ("mov", "r0,a");
3571               emitcode ("dec", "r0");
3572               emitcode ("movx", "a,@r0");
3573               emitcode ("xch", "a,_bpx");
3574               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3575             }
3576         }
3577       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3578         {
3579           emitcode ("mov", "sp,_bp");
3580           emitcode ("pop", "_bp");
3581         }
3582     }
3583
3584   /* restore the register bank  */
3585   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3586   {
3587     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3588      || !options.useXstack)
3589     {
3590         /* Special case of ISR using non-zero bank with useXstack
3591          * is handled below.
3592          */
3593         emitcode ("pop", "psw");
3594     }
3595   }
3596
3597   if (IFFUNC_ISISR (sym->type))
3598     {
3599
3600       /* now we need to restore the registers */
3601       /* if this isr has no bank i.e. is going to
3602          run with bank 0 , then we need to save more
3603          registers :-) */
3604       if (!FUNC_REGBANK (sym->type))
3605         {
3606           /* if this function does not call any other
3607              function then we can be economical and
3608              save only those registers that are used */
3609           if (!IFFUNC_HASFCALL(sym->type))
3610             {
3611               int i;
3612
3613               /* if any registers used */
3614               if (sym->regsUsed)
3615                 {
3616                   bool bits_popped = FALSE;
3617                   /* save the registers used */
3618                   for (i = sym->regsUsed->size; i >= 0; i--)
3619                     {
3620                       if (bitVectBitValue (sym->regsUsed, i))
3621                         bits_popped = popReg (i, bits_popped);
3622                     }
3623                 }
3624             }
3625           else
3626             {
3627               if (options.parms_in_bank1) {
3628                   int i;
3629                   for (i = 7 ; i >= 0 ; i-- ) {
3630                       emitcode ("pop","%s",rb1regs[i]);
3631                   }
3632               }
3633               /* this function has  a function call cannot
3634                  determines register usage so we will have to pop the
3635                  entire bank */
3636               unsaveRBank (0, ic, FALSE);
3637             }
3638         }
3639         else
3640         {
3641             /* This ISR uses a non-zero bank.
3642              *
3643              * Restore any register banks saved by genFunction
3644              * in reverse order.
3645              */
3646             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3647             int ix;
3648
3649             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3650             {
3651                 if (savedBanks & (1 << ix))
3652                 {
3653                     unsaveRBank(ix, NULL, FALSE);
3654                 }
3655             }
3656
3657             if (options.useXstack)
3658             {
3659                 /* Restore bank AFTER calling unsaveRBank,
3660                  * since it can trash r0.
3661                  */
3662                 emitcode ("pop", "psw");
3663             }
3664         }
3665
3666       if (!inExcludeList ("dph"))
3667         emitcode ("pop", "dph");
3668       if (!inExcludeList ("dpl"))
3669         emitcode ("pop", "dpl");
3670       if (!inExcludeList ("b"))
3671         emitcode ("pop", "b");
3672       if (!inExcludeList ("acc"))
3673         emitcode ("pop", "acc");
3674
3675       /* if debug then send end of function */
3676       if (options.debug && currFunc)
3677         {
3678           debugFile->writeEndFunction (currFunc, ic, 1);
3679         }
3680
3681       emitcode ("reti", "");
3682     }
3683   else
3684     {
3685       if (IFFUNC_CALLEESAVES(sym->type))
3686         {
3687           int i;
3688
3689           /* if any registers used */
3690           if (sym->regsUsed)
3691             {
3692               /* save the registers used */
3693               for (i = sym->regsUsed->size; i >= 0; i--)
3694                 {
3695                   if (bitVectBitValue (sym->regsUsed, i) ||
3696                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3697                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3698                 }
3699             }
3700           else if (mcs51_ptrRegReq)
3701             {
3702               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3703               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3704             }
3705
3706         }
3707
3708       /* if debug then send end of function */
3709       if (options.debug && currFunc)
3710         {
3711           debugFile->writeEndFunction (currFunc, ic, 1);
3712         }
3713
3714       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3715         {
3716           emitcode ("ljmp", "__sdcc_banked_ret");
3717         }
3718       else
3719         {
3720           emitcode ("ret", "");
3721         }
3722     }
3723
3724   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3725     return;
3726
3727   /* If this was an interrupt handler using bank 0 that called another */
3728   /* function, then all registers must be saved; nothing to optimized. */
3729   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3730       && !FUNC_REGBANK(sym->type))
3731     return;
3732
3733   /* There are no push/pops to optimize if not callee-saves or ISR */
3734   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3735     return;
3736
3737   /* If there were stack parameters, we cannot optimize without also    */
3738   /* fixing all of the stack offsets; this is too dificult to consider. */
3739   if (FUNC_HASSTACKPARM(sym->type))
3740     return;
3741
3742   /* Compute the registers actually used */
3743   regsUsed = newBitVect (mcs51_nRegs);
3744   regsUsedPrologue = newBitVect (mcs51_nRegs);
3745   while (lnp)
3746     {
3747       if (lnp->ic && lnp->ic->op == FUNCTION)
3748         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3749       else
3750         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3751
3752       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3753           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3754         break;
3755       if (!lnp->prev)
3756         break;
3757       lnp = lnp->prev;
3758     }
3759
3760   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3761       && !bitVectBitValue (regsUsed, CND_IDX))
3762     {
3763       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3764       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3765           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3766         bitVectUnSetBit (regsUsed, CND_IDX);
3767     }
3768   else
3769     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3770
3771   /* If this was an interrupt handler that called another function */
3772   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3773   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3774     {
3775       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3776       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3777       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3778       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3779       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3780     }
3781
3782   /* Remove the unneeded push/pops */
3783   regsUnneeded = newBitVect (mcs51_nRegs);
3784   while (lnp)
3785     {
3786       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3787         {
3788           if (!strncmp(lnp->line, "push", 4))
3789             {
3790               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3791               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3792                 {
3793                   connectLine (lnp->prev, lnp->next);
3794                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3795                 }
3796             }
3797           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3798             {
3799               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3800               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3801                 {
3802                   connectLine (lnp->prev, lnp->next);
3803                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3804                 }
3805             }
3806         }
3807       lnp = lnp->next;
3808     }
3809
3810   for (idx = 0; idx < regsUnneeded->size; idx++)
3811     if (bitVectBitValue (regsUnneeded, idx))
3812       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3813
3814   freeBitVect (regsUnneeded);
3815   freeBitVect (regsUsed);
3816   freeBitVect (regsUsedPrologue);
3817 }
3818
3819 /*-----------------------------------------------------------------*/
3820 /* genRet - generate code for return statement                     */
3821 /*-----------------------------------------------------------------*/
3822 static void
3823 genRet (iCode * ic)
3824 {
3825   int size, offset = 0, pushed = 0;
3826
3827   D(emitcode (";     genRet",""));
3828
3829   /* if we have no return value then
3830      just generate the "ret" */
3831   if (!IC_LEFT (ic))
3832     goto jumpret;
3833
3834   /* we have something to return then
3835      move the return value into place */
3836   aopOp (IC_LEFT (ic), ic, FALSE);
3837   size = AOP_SIZE (IC_LEFT (ic));
3838
3839
3840   if (IS_BIT(_G.currentFunc->etype))
3841     {
3842       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3843       size = 0;
3844     }
3845
3846   while (size--)
3847     {
3848       char *l;
3849       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3850         {
3851           /* #NOCHANGE */
3852           l = aopGet (IC_LEFT (ic), offset++,
3853                       FALSE, TRUE);
3854           emitcode ("push", "%s", l);
3855           pushed++;
3856         }
3857       else
3858         {
3859           l = aopGet (IC_LEFT (ic), offset,
3860                       FALSE, FALSE);
3861           if (strcmp (fReturn[offset], l))
3862             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3863         }
3864     }
3865
3866   while (pushed)
3867     {
3868       pushed--;
3869       if (strcmp (fReturn[pushed], "a"))
3870         emitcode ("pop", fReturn[pushed]);
3871       else
3872         emitcode ("pop", "acc");
3873     }
3874   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3875
3876 jumpret:
3877   /* generate a jump to the return label
3878      if the next is not the return statement */
3879   if (!(ic->next && ic->next->op == LABEL &&
3880         IC_LABEL (ic->next) == returnLabel))
3881
3882     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3883
3884 }
3885
3886 /*-----------------------------------------------------------------*/
3887 /* genLabel - generates a label                                    */
3888 /*-----------------------------------------------------------------*/
3889 static void
3890 genLabel (iCode * ic)
3891 {
3892   /* special case never generate */
3893   if (IC_LABEL (ic) == entryLabel)
3894     return;
3895
3896   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3897 }
3898
3899 /*-----------------------------------------------------------------*/
3900 /* genGoto - generates a ljmp                                      */
3901 /*-----------------------------------------------------------------*/
3902 static void
3903 genGoto (iCode * ic)
3904 {
3905   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3906 }
3907
3908 /*-----------------------------------------------------------------*/
3909 /* findLabelBackwards: walks back through the iCode chain looking  */
3910 /* for the given label. Returns number of iCode instructions     */
3911 /* between that label and given ic.          */
3912 /* Returns zero if label not found.          */
3913 /*-----------------------------------------------------------------*/
3914 static int
3915 findLabelBackwards (iCode * ic, int key)
3916 {
3917   int count = 0;
3918
3919   while (ic->prev)
3920     {
3921       ic = ic->prev;
3922       count++;
3923
3924       /* If we have any pushes or pops, we cannot predict the distance.
3925          I don't like this at all, this should be dealt with in the
3926          back-end */
3927       if (ic->op == IPUSH || ic->op == IPOP) {
3928         return 0;
3929       }
3930
3931       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3932         {
3933           return count;
3934         }
3935     }
3936
3937   return 0;
3938 }
3939
3940 /*-----------------------------------------------------------------*/
3941 /* genPlusIncr :- does addition with increment if possible         */
3942 /*-----------------------------------------------------------------*/
3943 static bool
3944 genPlusIncr (iCode * ic)
3945 {
3946   unsigned int icount;
3947   unsigned int size = getDataSize (IC_RESULT (ic));
3948
3949   /* will try to generate an increment */
3950   /* if the right side is not a literal
3951      we cannot */
3952   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3953     return FALSE;
3954
3955   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3956
3957   D(emitcode (";     genPlusIncr",""));
3958
3959   /* if increment >=16 bits in register or direct space */
3960   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3961       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3962       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3963       (size > 1) &&
3964       (icount == 1))
3965     {
3966       symbol *tlbl;
3967       int emitTlbl;
3968       int labelRange;
3969
3970       /* If the next instruction is a goto and the goto target
3971        * is < 10 instructions previous to this, we can generate
3972        * jumps straight to that target.
3973        */
3974       if (ic->next && ic->next->op == GOTO
3975           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3976           && labelRange <= 10)
3977         {
3978           emitcode (";", "tail increment optimized");
3979           tlbl = IC_LABEL (ic->next);
3980           emitTlbl = 0;
3981         }
3982       else
3983         {
3984           tlbl = newiTempLabel (NULL);
3985           emitTlbl = 1;
3986         }
3987       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3988       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3989           IS_AOP_PREG (IC_RESULT (ic)))
3990         emitcode ("cjne", "%s,#0x00,%05d$",
3991                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3992                   tlbl->key + 100);
3993       else
3994         {
3995           emitcode ("clr", "a");
3996           emitcode ("cjne", "a,%s,%05d$",
3997                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3998                     tlbl->key + 100);
3999         }
4000
4001       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4002       if (size > 2)
4003         {
4004           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4005               IS_AOP_PREG (IC_RESULT (ic)))
4006             emitcode ("cjne", "%s,#0x00,%05d$",
4007                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4008                       tlbl->key + 100);
4009           else
4010             emitcode ("cjne", "a,%s,%05d$",
4011                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4012                       tlbl->key + 100);
4013
4014           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4015         }
4016       if (size > 3)
4017         {
4018           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4019               IS_AOP_PREG (IC_RESULT (ic)))
4020             emitcode ("cjne", "%s,#0x00,%05d$",
4021                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4022                       tlbl->key + 100);
4023           else
4024             {
4025               emitcode ("cjne", "a,%s,%05d$",
4026                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4027                         tlbl->key + 100);
4028             }
4029           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4030         }
4031
4032       if (emitTlbl)
4033         {
4034           emitcode ("", "%05d$:", tlbl->key + 100);
4035         }
4036       return TRUE;
4037     }
4038
4039   /* if result is dptr */
4040   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4041       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4042       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4043       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4044     {
4045       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4046         return FALSE;
4047
4048       if (icount > 9)
4049         return FALSE;
4050
4051       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4052         return FALSE;
4053
4054       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4055       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4056       while (icount--)
4057         emitcode ("inc", "dptr");
4058
4059       return TRUE;
4060     }
4061
4062   /* if the literal value of the right hand side
4063      is greater than 4 then it is not worth it */
4064   if (icount > 4)
4065     return FALSE;
4066
4067   /* if the sizes are greater than 1 then we cannot */
4068   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4069       AOP_SIZE (IC_LEFT (ic)) > 1)
4070     return FALSE;
4071
4072   /* we can if the aops of the left & result match or
4073      if they are in registers and the registers are the
4074      same */
4075   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4076     {
4077
4078       if (icount > 3)
4079         {
4080           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4081           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4082           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4083         }
4084       else
4085         {
4086
4087           while (icount--)
4088             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4089         }
4090
4091       return TRUE;
4092     }
4093
4094   return FALSE;
4095 }
4096
4097 /*-----------------------------------------------------------------*/
4098 /* outBitAcc - output a bit in acc                                 */
4099 /*-----------------------------------------------------------------*/
4100 static void
4101 outBitAcc (operand * result)
4102 {
4103   symbol *tlbl = newiTempLabel (NULL);
4104   /* if the result is a bit */
4105   if (AOP_TYPE (result) == AOP_CRY)
4106     {
4107       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4108     }
4109   else
4110     {
4111       emitcode ("jz", "%05d$", tlbl->key + 100);
4112       emitcode ("mov", "a,%s", one);
4113       emitcode ("", "%05d$:", tlbl->key + 100);
4114       outAcc (result);
4115     }
4116 }
4117
4118 /*-----------------------------------------------------------------*/
4119 /* genPlusBits - generates code for addition of two bits           */
4120 /*-----------------------------------------------------------------*/
4121 static void
4122 genPlusBits (iCode * ic)
4123 {
4124   D(emitcode (";     genPlusBits",""));
4125
4126   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4127     {
4128       symbol *lbl = newiTempLabel (NULL);
4129       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4130       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4131       emitcode ("cpl", "c");
4132       emitcode ("", "%05d$:", (lbl->key + 100));
4133       outBitC (IC_RESULT (ic));
4134     }
4135   else
4136     {
4137       emitcode ("clr", "a");
4138       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4139       emitcode ("rlc", "a");
4140       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4141       emitcode ("addc", "a,#0x00");
4142       outAcc (IC_RESULT (ic));
4143     }
4144 }
4145
4146 #if 0
4147 /* This is the original version of this code.
4148
4149  * This is being kept around for reference,
4150  * because I am not entirely sure I got it right...
4151  */
4152 static void
4153 adjustArithmeticResult (iCode * ic)
4154 {
4155   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4156       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4157       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4158     aopPut (IC_RESULT (ic),
4159             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4160             2,
4161             isOperandVolatile (IC_RESULT (ic), FALSE));
4162
4163   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4164       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4165       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4166     aopPut (IC_RESULT (ic),
4167             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4168             2,
4169             isOperandVolatile (IC_RESULT (ic), FALSE));
4170
4171   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4172       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4173       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4174       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4175       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4176     {
4177       char buffer[5];
4178       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4179       aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4180     }
4181 }
4182 #else
4183 /* This is the pure and virtuous version of this code.
4184  * I'm pretty certain it's right, but not enough to toss the old
4185  * code just yet...
4186  */
4187 static void
4188 adjustArithmeticResult (iCode * ic)
4189 {
4190   if (opIsGptr (IC_RESULT (ic)) &&
4191       opIsGptr (IC_LEFT (ic)) &&
4192       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4193     {
4194       aopPut (IC_RESULT (ic),
4195               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4196               GPTRSIZE - 1,
4197               isOperandVolatile (IC_RESULT (ic), FALSE));
4198     }
4199
4200   if (opIsGptr (IC_RESULT (ic)) &&
4201       opIsGptr (IC_RIGHT (ic)) &&
4202       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4203     {
4204       aopPut (IC_RESULT (ic),
4205               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4206               GPTRSIZE - 1,
4207               isOperandVolatile (IC_RESULT (ic), FALSE));
4208     }
4209
4210   if (opIsGptr (IC_RESULT (ic)) &&
4211       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4212       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4213       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4214       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4215     {
4216       char buffer[5];
4217       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4218       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4219     }
4220 }
4221 #endif
4222
4223 /*-----------------------------------------------------------------*/
4224 /* genPlus - generates code for addition                           */
4225 /*-----------------------------------------------------------------*/
4226 static void
4227 genPlus (iCode * ic)
4228 {
4229   int size, offset = 0;
4230   int skip_bytes = 0;
4231   char *add = "add";
4232   operand *leftOp, *rightOp;
4233   operand * op;
4234
4235   /* special cases :- */
4236
4237   D(emitcode (";     genPlus",""));
4238
4239   aopOp (IC_LEFT (ic), ic, FALSE);
4240   aopOp (IC_RIGHT (ic), ic, FALSE);
4241   aopOp (IC_RESULT (ic), ic, TRUE);
4242
4243   /* if literal, literal on the right or
4244      if left requires ACC or right is already
4245      in ACC */
4246   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4247       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4248       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4249     {
4250       operand *t = IC_RIGHT (ic);
4251       IC_RIGHT (ic) = IC_LEFT (ic);
4252       IC_LEFT (ic) = t;
4253     }
4254
4255   /* if both left & right are in bit
4256      space */
4257   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4258       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4259     {
4260       genPlusBits (ic);
4261       goto release;
4262     }
4263
4264   /* if left in bit space & right literal */
4265   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4266       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4267     {
4268       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4269       /* if result in bit space */
4270       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4271         {
4272           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4273             emitcode ("cpl", "c");
4274           outBitC (IC_RESULT (ic));
4275         }
4276       else
4277         {
4278           size = getDataSize (IC_RESULT (ic));
4279           while (size--)
4280             {
4281               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4282               emitcode ("addc", "a,#00");
4283               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4284             }
4285         }
4286       goto release;
4287     }
4288
4289   /* if I can do an increment instead
4290      of add then GOOD for ME */
4291   if (genPlusIncr (ic) == TRUE)
4292     goto release;
4293
4294   size = getDataSize (IC_RESULT (ic));
4295   leftOp = IC_LEFT(ic);
4296   rightOp = IC_RIGHT(ic);
4297   op=IC_LEFT(ic);
4298
4299   /* if this is an add for an array access
4300      at a 256 byte boundary */
4301   if ( 2 == size
4302        && AOP_TYPE (op) == AOP_IMMD
4303        && IS_SYMOP (op)
4304        && IS_SPEC (OP_SYM_ETYPE (op))
4305        && SPEC_ABSA (OP_SYM_ETYPE (op))
4306        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4307      )
4308     {
4309       D(emitcode (";     genPlus aligned array",""));
4310       aopPut (IC_RESULT (ic),
4311               aopGet (rightOp, 0, FALSE, FALSE),
4312               0,
4313               isOperandVolatile (IC_RESULT (ic), FALSE));
4314
4315       if( 1 == getDataSize (IC_RIGHT (ic)) )
4316         {
4317           aopPut (IC_RESULT (ic),
4318                   aopGet (leftOp, 1, FALSE, FALSE),
4319                   1,
4320                   isOperandVolatile (IC_RESULT (ic), FALSE));
4321         }
4322       else
4323         {
4324           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4325           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4326           aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4327         }
4328       goto release;
4329     }
4330
4331   /* if the lower bytes of a literal are zero skip the addition */
4332   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4333     {
4334        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4335               (skip_bytes+1 < size))
4336          {
4337            skip_bytes++;
4338          }
4339        if (skip_bytes)
4340          D(emitcode (";     genPlus shortcut",""));
4341     }
4342
4343   while (size--)
4344     {
4345       if( offset >= skip_bytes )
4346         {
4347           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4348             {
4349               bool pushedB;
4350               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4351               pushedB = pushB ();
4352               emitcode("xch", "a,b");
4353               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4354               emitcode (add, "a,b");
4355               popB (pushedB);
4356             }
4357           else if (aopGetUsesAcc (leftOp, offset))
4358             {
4359               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4360               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4361             }
4362           else
4363             {
4364               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4365               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4366             }
4367           aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4368           add = "addc";  /* further adds must propagate carry */
4369         }
4370       else
4371         {
4372           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4373               isOperandVolatile (IC_RESULT (ic), FALSE))
4374             {
4375               /* just move */
4376               aopPut (IC_RESULT (ic),
4377                       aopGet (leftOp, offset, FALSE, FALSE),
4378                       offset,
4379                       isOperandVolatile (IC_RESULT (ic), FALSE));
4380             }
4381         }
4382       offset++;
4383     }
4384
4385   adjustArithmeticResult (ic);
4386
4387 release:
4388   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4390   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4391 }
4392
4393 /*-----------------------------------------------------------------*/
4394 /* genMinusDec :- does subtraction with decrement if possible      */
4395 /*-----------------------------------------------------------------*/
4396 static bool
4397 genMinusDec (iCode * ic)
4398 {
4399   unsigned int icount;
4400   unsigned int size = getDataSize (IC_RESULT (ic));
4401
4402   /* will try to generate an increment */
4403   /* if the right side is not a literal
4404      we cannot */
4405   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4406     return FALSE;
4407
4408   /* if the literal value of the right hand side
4409      is greater than 4 then it is not worth it */
4410   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4411     return FALSE;
4412
4413   D(emitcode (";     genMinusDec",""));
4414
4415   /* if decrement >=16 bits in register or direct space */
4416   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4417       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4418       (size > 1) &&
4419       (icount == 1))
4420     {
4421       symbol *tlbl;
4422       int emitTlbl;
4423       int labelRange;
4424
4425       /* If the next instruction is a goto and the goto target
4426        * is <= 10 instructions previous to this, we can generate
4427        * jumps straight to that target.
4428        */
4429       if (ic->next && ic->next->op == GOTO
4430           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4431           && labelRange <= 10)
4432         {
4433           emitcode (";", "tail decrement optimized");
4434           tlbl = IC_LABEL (ic->next);
4435           emitTlbl = 0;
4436         }
4437       else
4438         {
4439           tlbl = newiTempLabel (NULL);
4440           emitTlbl = 1;
4441         }
4442
4443       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4444       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4445           IS_AOP_PREG (IC_RESULT (ic)))
4446         emitcode ("cjne", "%s,#0xff,%05d$"
4447                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4448                   ,tlbl->key + 100);
4449       else
4450         {
4451           emitcode ("mov", "a,#0xff");
4452           emitcode ("cjne", "a,%s,%05d$"
4453                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4454                     ,tlbl->key + 100);
4455         }
4456       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4457       if (size > 2)
4458         {
4459           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4460               IS_AOP_PREG (IC_RESULT (ic)))
4461             emitcode ("cjne", "%s,#0xff,%05d$"
4462                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4463                       ,tlbl->key + 100);
4464           else
4465             {
4466               emitcode ("cjne", "a,%s,%05d$"
4467                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4468                         ,tlbl->key + 100);
4469             }
4470           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4471         }
4472       if (size > 3)
4473         {
4474           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4475               IS_AOP_PREG (IC_RESULT (ic)))
4476             emitcode ("cjne", "%s,#0xff,%05d$"
4477                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4478                       ,tlbl->key + 100);
4479           else
4480             {
4481               emitcode ("cjne", "a,%s,%05d$"
4482                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4483                         ,tlbl->key + 100);
4484             }
4485           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4486         }
4487       if (emitTlbl)
4488         {
4489           emitcode ("", "%05d$:", tlbl->key + 100);
4490         }
4491       return TRUE;
4492     }
4493
4494   /* if the sizes are greater than 1 then we cannot */
4495   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4496       AOP_SIZE (IC_LEFT (ic)) > 1)
4497     return FALSE;
4498
4499   /* we can if the aops of the left & result match or
4500      if they are in registers and the registers are the
4501      same */
4502   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4503     {
4504       char *l;
4505
4506       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4507         {
4508           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4509           l = "a";
4510         }
4511       else
4512         {
4513           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4514         }
4515
4516       while (icount--)
4517         emitcode ("dec", "%s", l);
4518
4519       if (AOP_NEEDSACC (IC_RESULT (ic)))
4520         aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4521
4522       return TRUE;
4523     }
4524
4525   return FALSE;
4526 }
4527
4528 /*-----------------------------------------------------------------*/
4529 /* addSign - complete with sign                                    */
4530 /*-----------------------------------------------------------------*/
4531 static void
4532 addSign (operand * result, int offset, int sign)
4533 {
4534   int size = (getDataSize (result) - offset);
4535   if (size > 0)
4536     {
4537       if (sign)
4538         {
4539           emitcode ("rlc", "a");
4540           emitcode ("subb", "a,acc");
4541           while (size--)
4542             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4543         }
4544       else
4545         while (size--)
4546           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4547     }
4548 }
4549
4550 /*-----------------------------------------------------------------*/
4551 /* genMinusBits - generates code for subtraction  of two bits      */
4552 /*-----------------------------------------------------------------*/
4553 static void
4554 genMinusBits (iCode * ic)
4555 {
4556   symbol *lbl = newiTempLabel (NULL);
4557
4558   D(emitcode (";     genMinusBits",""));
4559
4560   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4561     {
4562       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4563       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4564       emitcode ("cpl", "c");
4565       emitcode ("", "%05d$:", (lbl->key + 100));
4566       outBitC (IC_RESULT (ic));
4567     }
4568   else
4569     {
4570       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4571       emitcode ("subb", "a,acc");
4572       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4573       emitcode ("inc", "a");
4574       emitcode ("", "%05d$:", (lbl->key + 100));
4575       aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4576       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4577     }
4578 }
4579
4580 /*-----------------------------------------------------------------*/
4581 /* genMinus - generates code for subtraction                       */
4582 /*-----------------------------------------------------------------*/
4583 static void
4584 genMinus (iCode * ic)
4585 {
4586   int size, offset = 0;
4587
4588   D(emitcode (";     genMinus",""));
4589
4590   aopOp (IC_LEFT (ic), ic, FALSE);
4591   aopOp (IC_RIGHT (ic), ic, FALSE);
4592   aopOp (IC_RESULT (ic), ic, TRUE);
4593
4594   /* special cases :- */
4595   /* if both left & right are in bit space */
4596   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4597       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4598     {
4599       genMinusBits (ic);
4600       goto release;
4601     }
4602
4603   /* if I can do an decrement instead
4604      of subtract then GOOD for ME */
4605   if (genMinusDec (ic) == TRUE)
4606     goto release;
4607
4608   size = getDataSize (IC_RESULT (ic));
4609
4610   /* if literal, add a,#-lit, else normal subb */
4611   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4612     {
4613       unsigned long lit = 0L;
4614       bool useCarry = FALSE;
4615
4616       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4617       lit = -(long) lit;
4618
4619       while (size--)
4620         {
4621           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4622             {
4623             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4624               if (!offset && !size && lit== (unsigned long) -1)
4625                 {
4626                   emitcode ("dec", "a");
4627                 }
4628               else if (!useCarry)
4629                 {
4630                   /* first add without previous c */
4631                   emitcode ("add", "a,#0x%02x",
4632                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4633                   useCarry = TRUE;
4634                 }
4635               else
4636                 {
4637                   emitcode ("addc", "a,#0x%02x",
4638                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4639                 }
4640               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4641             }
4642           else
4643             {
4644               /* no need to add zeroes */
4645               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4646                 {
4647                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4648                           offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4649                 }
4650               offset++;
4651             }
4652         }
4653     }
4654   else
4655     {
4656       operand *leftOp, *rightOp;
4657
4658       leftOp = IC_LEFT(ic);
4659       rightOp = IC_RIGHT(ic);
4660
4661       while (size--)
4662         {
4663           if (aopGetUsesAcc(rightOp, offset)) {
4664             if (aopGetUsesAcc(leftOp, offset)) {
4665               bool pushedB;
4666
4667               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4668               pushedB = pushB ();
4669               emitcode ("mov", "b,a");
4670               if (offset == 0)
4671                 CLRC;
4672               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4673               emitcode ("subb", "a,b");
4674               popB (pushedB);
4675             } else {
4676               /* reverse subtraction with 2's complement */
4677               if (offset == 0)
4678                 emitcode( "setb", "c");
4679                else
4680                 emitcode( "cpl", "c");
4681               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4682               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4683               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4684               emitcode("cpl", "a");
4685               if (size) /* skip if last byte */
4686                 emitcode( "cpl", "c");
4687             }
4688           } else {
4689             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4690             if (offset == 0)
4691               CLRC;
4692             emitcode ("subb", "a,%s",
4693                       aopGet(rightOp, offset, FALSE, TRUE));
4694           }
4695
4696           aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4697         }
4698     }
4699
4700
4701   adjustArithmeticResult (ic);
4702
4703 release:
4704   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4707 }
4708
4709
4710 /*-----------------------------------------------------------------*/
4711 /* genMultbits :- multiplication of bits                           */
4712 /*-----------------------------------------------------------------*/
4713 static void
4714 genMultbits (operand * left,
4715              operand * right,
4716              operand * result)
4717 {
4718   D(emitcode (";     genMultbits",""));
4719
4720   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4721   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4722   outBitC (result);
4723 }
4724
4725 /*-----------------------------------------------------------------*/
4726 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4727 /*-----------------------------------------------------------------*/
4728 static void
4729 genMultOneByte (operand * left,
4730                 operand * right,
4731                 operand * result)
4732 {
4733   symbol *lbl;
4734   int size = AOP_SIZE (result);
4735   bool runtimeSign, compiletimeSign;
4736   bool lUnsigned, rUnsigned, pushedB;
4737
4738   D(emitcode (";     genMultOneByte",""));
4739
4740   if (size < 1 || size > 2)
4741     {
4742       /* this should never happen */
4743       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4744                AOP_SIZE(result), __FILE__, lineno);
4745       exit (1);
4746     }
4747
4748   /* (if two literals: the value is computed before) */
4749   /* if one literal, literal on the right */
4750   if (AOP_TYPE (left) == AOP_LIT)
4751     {
4752       operand *t = right;
4753       right = left;
4754       left = t;
4755       /* emitcode (";", "swapped left and right"); */
4756     }
4757   /* if no literal, unsigned on the right: shorter code */
4758   if (   AOP_TYPE (right) != AOP_LIT
4759       && SPEC_USIGN (getSpec (operandType (left))))
4760     {
4761       operand *t = right;
4762       right = left;
4763       left = t;
4764     }
4765
4766   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4767   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4768
4769   pushedB = pushB ();
4770
4771   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4772                    no need to take care about the signedness! */
4773       || (lUnsigned && rUnsigned))
4774     {
4775       /* just an unsigned 8 * 8 = 8 multiply
4776          or 8u * 8u = 16u */
4777       /* emitcode (";","unsigned"); */
4778       /* TODO: check for accumulator clash between left & right aops? */
4779
4780       if (AOP_TYPE (right) == AOP_LIT)
4781         {
4782           /* moving to accumulator first helps peepholes */
4783           MOVA (aopGet (left, 0, FALSE, FALSE));
4784           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4785         }
4786       else
4787         {
4788           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4789           MOVA (aopGet (left, 0, FALSE, FALSE));
4790         }
4791
4792       emitcode ("mul", "ab");
4793       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4794       if (size == 2)
4795         aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4796
4797       popB (pushedB);
4798       return;
4799     }
4800
4801   /* we have to do a signed multiply */
4802   /* emitcode (";", "signed"); */
4803
4804   /* now sign adjust for both left & right */
4805
4806   /* let's see what's needed: */
4807   /* apply negative sign during runtime */
4808   runtimeSign = FALSE;
4809   /* negative sign from literals */
4810   compiletimeSign = FALSE;
4811
4812   if (!lUnsigned)
4813     {
4814       if (AOP_TYPE(left) == AOP_LIT)
4815         {
4816           /* signed literal */
4817           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4818           if (val < 0)
4819             compiletimeSign = TRUE;
4820         }
4821       else
4822         /* signed but not literal */
4823         runtimeSign = TRUE;
4824     }
4825
4826   if (!rUnsigned)
4827     {
4828       if (AOP_TYPE(right) == AOP_LIT)
4829         {
4830           /* signed literal */
4831           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4832           if (val < 0)
4833             compiletimeSign ^= TRUE;
4834         }
4835       else
4836         /* signed but not literal */
4837         runtimeSign = TRUE;
4838     }
4839
4840   /* initialize F0, which stores the runtime sign */
4841   if (runtimeSign)
4842     {
4843       if (compiletimeSign)
4844         emitcode ("setb", "F0"); /* set sign flag */
4845       else
4846         emitcode ("clr", "F0"); /* reset sign flag */
4847     }
4848
4849   /* save the signs of the operands */
4850   if (AOP_TYPE(right) == AOP_LIT)
4851     {
4852       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4853
4854       if (!rUnsigned && val < 0)
4855         emitcode ("mov", "b,#0x%02x", -val);
4856       else
4857         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4858     }
4859   else /* ! literal */
4860     {
4861       if (rUnsigned)  /* emitcode (";", "signed"); */
4862
4863         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4864       else
4865         {
4866           MOVA (aopGet (right, 0, FALSE, FALSE));
4867           lbl = newiTempLabel (NULL);
4868           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4869           emitcode ("cpl", "F0"); /* complement sign flag */
4870           emitcode ("cpl", "a");  /* 2's complement */
4871           emitcode ("inc", "a");
4872           emitcode ("", "%05d$:", (lbl->key + 100));
4873           emitcode ("mov", "b,a");
4874         }
4875     }
4876
4877   if (AOP_TYPE(left) == AOP_LIT)
4878     {
4879       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4880
4881       if (!lUnsigned && val < 0)
4882         emitcode ("mov", "a,#0x%02x", -val);
4883       else
4884         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4885     }
4886   else /* ! literal */
4887     {
4888       MOVA (aopGet (left, 0, FALSE, FALSE));
4889
4890       if (!lUnsigned)
4891         {
4892           lbl = newiTempLabel (NULL);
4893           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4894           emitcode ("cpl", "F0"); /* complement sign flag */
4895           emitcode ("cpl", "a"); /* 2's complement */
4896           emitcode ("inc", "a");
4897           emitcode ("", "%05d$:", (lbl->key + 100));
4898         }
4899     }
4900
4901   /* now the multiplication */
4902   emitcode ("mul", "ab");
4903   if (runtimeSign || compiletimeSign)
4904     {
4905       lbl = newiTempLabel (NULL);
4906       if (runtimeSign)
4907         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4908       emitcode ("cpl", "a"); /* lsb 2's complement */
4909       if (size != 2)
4910         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4911       else
4912         {
4913           emitcode ("add", "a,#1"); /* this sets carry flag */
4914           emitcode ("xch", "a,b");
4915           emitcode ("cpl", "a"); /* msb 2's complement */
4916           emitcode ("addc", "a,#0");
4917           emitcode ("xch", "a,b");
4918         }
4919       emitcode ("", "%05d$:", (lbl->key + 100));
4920     }
4921   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4922   if (size == 2)
4923     aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4924
4925   popB (pushedB);
4926 }
4927
4928 /*-----------------------------------------------------------------*/
4929 /* genMult - generates code for multiplication                     */
4930 /*-----------------------------------------------------------------*/
4931 static void
4932 genMult (iCode * ic)
4933 {
4934   operand *left = IC_LEFT (ic);
4935   operand *right = IC_RIGHT (ic);
4936   operand *result = IC_RESULT (ic);
4937
4938   D(emitcode (";     genMult",""));
4939
4940   /* assign the asmops */
4941   aopOp (left, ic, FALSE);
4942   aopOp (right, ic, FALSE);
4943   aopOp (result, ic, TRUE);
4944
4945   /* special cases first */
4946   /* both are bits */
4947   if (AOP_TYPE (left) == AOP_CRY &&
4948       AOP_TYPE (right) == AOP_CRY)
4949     {
4950       genMultbits (left, right, result);
4951       goto release;
4952     }
4953
4954   /* if both are of size == 1 */
4955 #if 0 // one of them can be a sloc shared with the result
4956     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4957 #else
4958   if (getSize(operandType(left)) == 1 &&
4959       getSize(operandType(right)) == 1)
4960 #endif
4961     {
4962       genMultOneByte (left, right, result);
4963       goto release;
4964     }
4965
4966   /* should have been converted to function call */
4967     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4968              getSize(OP_SYMBOL(right)->type));
4969   assert (0);
4970
4971 release:
4972   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4973   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4974   freeAsmop (result, NULL, ic, TRUE);
4975 }
4976
4977 /*-----------------------------------------------------------------*/
4978 /* genDivbits :- division of bits                                  */
4979 /*-----------------------------------------------------------------*/
4980 static void
4981 genDivbits (operand * left,
4982             operand * right,
4983             operand * result)
4984 {
4985   char *l;
4986   bool pushedB;
4987
4988   D(emitcode (";     genDivbits",""));
4989
4990   pushedB = pushB ();
4991
4992   /* the result must be bit */
4993   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4994   l = aopGet (left, 0, FALSE, FALSE);
4995
4996   MOVA (l);
4997
4998   emitcode ("div", "ab");
4999   emitcode ("rrc", "a");
5000
5001   popB (pushedB);
5002
5003   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5004 }
5005
5006 /*-----------------------------------------------------------------*/
5007 /* genDivOneByte : 8 bit division                                  */
5008 /*-----------------------------------------------------------------*/
5009 static void
5010 genDivOneByte (operand * left,
5011                operand * right,
5012                operand * result)
5013 {
5014   bool lUnsigned, rUnsigned, pushedB;
5015   bool runtimeSign, compiletimeSign;
5016   bool accuse = FALSE;
5017   bool pushedA = FALSE;
5018   symbol *lbl;
5019   int size, offset;
5020
5021   D(emitcode (";     genDivOneByte",""));
5022
5023   /* Why is it necessary that genDivOneByte() can return an int result?
5024      Have a look at:
5025
5026         volatile unsigned char uc;
5027         volatile signed char sc1, sc2;
5028         volatile int i;
5029
5030         uc  = 255;
5031         sc1 = -1;
5032         i = uc / sc1;
5033
5034      Or:
5035
5036         sc1 = -128;
5037         sc2 = -1;
5038         i = sc1 / sc2;
5039
5040      In all cases a one byte result would overflow, the following cast to int
5041      would return the wrong result.
5042
5043      Two possible solution:
5044         a) cast operands to int, if ((unsigned) / (signed)) or
5045            ((signed) / (signed))
5046         b) return an 16 bit signed int; this is what we're doing here!
5047   */
5048
5049   size = AOP_SIZE (result) - 1;
5050   offset = 1;
5051   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5052   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5053
5054   pushedB = pushB ();
5055
5056   /* signed or unsigned */
5057   if (lUnsigned && rUnsigned)
5058     {
5059       /* unsigned is easy */
5060       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5061       MOVA (aopGet (left, 0, FALSE, FALSE));
5062       emitcode ("div", "ab");
5063       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5064       while (size--)
5065         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5066
5067       popB (pushedB);
5068       return;
5069     }
5070
5071   /* signed is a little bit more difficult */
5072
5073   /* now sign adjust for both left & right */
5074
5075   /* let's see what's needed: */
5076   /* apply negative sign during runtime */
5077   runtimeSign = FALSE;
5078   /* negative sign from literals */
5079   compiletimeSign = FALSE;
5080
5081   if (!lUnsigned)
5082     {
5083       if (AOP_TYPE(left) == AOP_LIT)
5084         {
5085           /* signed literal */
5086           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5087           if (val < 0)
5088             compiletimeSign = TRUE;
5089         }
5090       else
5091         /* signed but not literal */
5092         runtimeSign = TRUE;
5093     }
5094
5095   if (!rUnsigned)
5096     {
5097       if (AOP_TYPE(right) == AOP_LIT)
5098         {
5099           /* signed literal */
5100           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5101           if (val < 0)
5102             compiletimeSign ^= TRUE;
5103         }
5104       else
5105         /* signed but not literal */
5106         runtimeSign = TRUE;
5107     }
5108
5109   /* initialize F0, which stores the runtime sign */
5110   if (runtimeSign)
5111     {
5112       if (compiletimeSign)
5113         emitcode ("setb", "F0"); /* set sign flag */
5114       else
5115         emitcode ("clr", "F0"); /* reset sign flag */
5116     }
5117
5118   /* save the signs of the operands */
5119   if (AOP_TYPE(right) == AOP_LIT)
5120     {
5121       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5122
5123       if (!rUnsigned && val < 0)
5124         emitcode ("mov", "b,#0x%02x", -val);
5125       else
5126         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5127     }
5128   else /* ! literal */
5129     {
5130       if (rUnsigned)
5131         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5132       else
5133         {
5134           MOVA (aopGet (right, 0, FALSE, FALSE));
5135           lbl = newiTempLabel (NULL);
5136           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5137           emitcode ("cpl", "F0"); /* complement sign flag */
5138           emitcode ("cpl", "a");  /* 2's complement */
5139           emitcode ("inc", "a");
5140           emitcode ("", "%05d$:", (lbl->key + 100));
5141           emitcode ("mov", "b,a");
5142         }
5143     }
5144
5145   if (AOP_TYPE(left) == AOP_LIT)
5146     {
5147       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5148
5149       if (!lUnsigned && val < 0)
5150         emitcode ("mov", "a,#0x%02x", -val);
5151       else
5152         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5153     }
5154   else /* ! literal */
5155     {
5156       MOVA (aopGet (left, 0, FALSE, FALSE));
5157
5158       if (!lUnsigned)
5159         {
5160           lbl = newiTempLabel (NULL);
5161           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5162           emitcode ("cpl", "F0"); /* complement sign flag */
5163           emitcode ("cpl", "a");  /* 2's complement */
5164           emitcode ("inc", "a");
5165           emitcode ("", "%05d$:", (lbl->key + 100));
5166         }
5167     }
5168
5169   /* now the division */
5170   emitcode ("div", "ab");
5171
5172   if (runtimeSign || compiletimeSign)
5173     {
5174       lbl = newiTempLabel (NULL);
5175       if (runtimeSign)
5176         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5177       emitcode ("cpl", "a"); /* lsb 2's complement */
5178       emitcode ("inc", "a");
5179       emitcode ("", "%05d$:", (lbl->key + 100));
5180
5181       accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5182       if (size > 0)
5183         {
5184           /* msb is 0x00 or 0xff depending on the sign */
5185           if (runtimeSign)
5186             {
5187               if (accuse)
5188                 {
5189                   emitcode ("push", "acc");
5190                   pushedA = TRUE;
5191                 }
5192               emitcode ("mov", "c,F0");
5193               emitcode ("subb", "a,acc");
5194               while (size--)
5195                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5196             }
5197           else /* compiletimeSign */
5198             {
5199               if (aopPutUsesAcc (result, "#0xFF", offset))
5200                 {
5201                   emitcode ("push", "acc");
5202                   pushedA = TRUE;
5203                 }
5204               while (size--)
5205                 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5206             }
5207         }
5208     }
5209   else
5210     {
5211       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5212       while (size--)
5213         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5214     }
5215
5216   if (pushedA)
5217     emitcode ("pop", "acc");
5218   popB (pushedB);
5219 }
5220
5221 /*-----------------------------------------------------------------*/
5222 /* genDiv - generates code for division                            */
5223 /*-----------------------------------------------------------------*/
5224 static void
5225 genDiv (iCode * ic)
5226 {
5227   operand *left = IC_LEFT (ic);
5228   operand *right = IC_RIGHT (ic);
5229   operand *result = IC_RESULT (ic);
5230
5231   D(emitcode (";     genDiv",""));
5232
5233   /* assign the amsops */
5234   aopOp (left, ic, FALSE);
5235   aopOp (right, ic, FALSE);
5236   aopOp (result, ic, TRUE);
5237
5238   /* special cases first */
5239   /* both are bits */
5240   if (AOP_TYPE (left) == AOP_CRY &&
5241       AOP_TYPE (right) == AOP_CRY)
5242     {
5243       genDivbits (left, right, result);
5244       goto release;
5245     }
5246
5247   /* if both are of size == 1 */
5248   if (AOP_SIZE (left) == 1 &&
5249       AOP_SIZE (right) == 1)
5250     {
5251       genDivOneByte (left, right, result);
5252       goto release;
5253     }
5254
5255   /* should have been converted to function call */
5256   assert (0);
5257 release:
5258   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5259   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5260   freeAsmop (result, NULL, ic, TRUE);
5261 }
5262
5263 /*-----------------------------------------------------------------*/
5264 /* genModbits :- modulus of bits                                   */
5265 /*-----------------------------------------------------------------*/
5266 static void
5267 genModbits (operand * left,
5268             operand * right,
5269             operand * result)
5270 {
5271   char *l;
5272   bool pushedB;
5273
5274   D(emitcode (";     genModbits",""));
5275
5276   pushedB = pushB ();
5277
5278   /* the result must be bit */
5279   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5280   l = aopGet (left, 0, FALSE, FALSE);
5281
5282   MOVA (l);
5283
5284   emitcode ("div", "ab");
5285   emitcode ("mov", "a,b");
5286   emitcode ("rrc", "a");
5287
5288   popB (pushedB);
5289
5290   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5291 }
5292
5293 /*-----------------------------------------------------------------*/
5294 /* genModOneByte : 8 bit modulus                                   */
5295 /*-----------------------------------------------------------------*/
5296 static void
5297 genModOneByte (operand * left,
5298                operand * right,
5299                operand * result)
5300 {
5301   bool lUnsigned, rUnsigned, pushedB;
5302   bool runtimeSign, compiletimeSign;
5303   symbol *lbl;
5304   int size, offset;
5305
5306   D(emitcode (";     genModOneByte",""));
5307
5308   size = AOP_SIZE (result) - 1;
5309   offset = 1;
5310   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5311   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5312
5313   /* if right is a literal, check it for 2^n */
5314   if (AOP_TYPE(right) == AOP_LIT)
5315     {
5316       unsigned char val = abs((int) operandLitValue(right));
5317       symbol *lbl2 = NULL;
5318
5319       switch (val)
5320         {
5321           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5322           case 2:
5323           case 4:
5324           case 8:
5325           case 16:
5326           case 32:
5327           case 64:
5328           case 128:
5329             if (lUnsigned)
5330               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5331                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5332               /* because iCode should have been changed to genAnd  */
5333               /* see file "SDCCopt.c", function "convertToFcall()" */
5334
5335             MOVA (aopGet (left, 0, FALSE, FALSE));
5336             emitcode ("mov", "c,acc.7");
5337             emitcode ("anl", "a,#0x%02x", val - 1);
5338             lbl = newiTempLabel (NULL);
5339             emitcode ("jz", "%05d$", (lbl->key + 100));
5340             emitcode ("jnc", "%05d$", (lbl->key + 100));
5341             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5342             if (size)
5343               {
5344                 int size2 = size;
5345                 int offs2 = offset;
5346
5347                 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5348                 while (size2--)
5349                   aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5350                 lbl2 = newiTempLabel (NULL);
5351                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5352               }
5353             emitcode ("", "%05d$:", (lbl->key + 100));
5354             aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5355             while (size--)
5356               aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5357             if (lbl2)
5358               {
5359                 emitcode ("", "%05d$:", (lbl2->key + 100));
5360               }
5361             return;
5362
5363           default:
5364             break;
5365         }
5366     }
5367
5368   pushedB = pushB ();
5369
5370   /* signed or unsigned */
5371   if (lUnsigned && rUnsigned)
5372     {
5373       /* unsigned is easy */
5374       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5375       MOVA (aopGet (left, 0, FALSE, FALSE));
5376       emitcode ("div", "ab");
5377       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5378       while (size--)
5379         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5380
5381       popB (pushedB);
5382       return;
5383     }
5384
5385   /* signed is a little bit more difficult */
5386
5387   /* now sign adjust for both left & right */
5388
5389   /* modulus: sign of the right operand has no influence on the result! */
5390   if (AOP_TYPE(right) == AOP_LIT)
5391     {
5392       signed char val = (char) operandLitValue(right);
5393
5394       if (!rUnsigned && val < 0)
5395         emitcode ("mov", "b,#0x%02x", -val);
5396       else
5397         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5398     }
5399   else /* not literal */
5400     {
5401       if (rUnsigned)
5402         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5403       else
5404         {
5405           MOVA (aopGet (right, 0, FALSE, FALSE));
5406           lbl = newiTempLabel (NULL);
5407           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5408           emitcode ("cpl", "a"); /* 2's complement */
5409           emitcode ("inc", "a");
5410           emitcode ("", "%05d$:", (lbl->key + 100));
5411           emitcode ("mov", "b,a");
5412         }
5413     }
5414
5415   /* let's see what's needed: */
5416   /* apply negative sign during runtime */
5417   runtimeSign = FALSE;
5418   /* negative sign from literals */
5419   compiletimeSign = FALSE;
5420
5421   /* sign adjust left side */
5422   if (AOP_TYPE(left) == AOP_LIT)
5423     {
5424       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5425
5426       if (!lUnsigned && val < 0)
5427         {
5428           compiletimeSign = TRUE; /* set sign flag */
5429           emitcode ("mov", "a,#0x%02x", -val);
5430         }
5431       else
5432         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5433     }
5434   else /* ! literal */
5435     {
5436       MOVA (aopGet (left, 0, FALSE, FALSE));
5437
5438       if (!lUnsigned)
5439         {
5440           runtimeSign = TRUE;
5441           emitcode ("clr", "F0"); /* clear sign flag */
5442
5443           lbl = newiTempLabel (NULL);
5444           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5445           emitcode ("setb", "F0"); /* set sign flag */
5446           emitcode ("cpl", "a");   /* 2's complement */
5447           emitcode ("inc", "a");
5448           emitcode ("", "%05d$:", (lbl->key + 100));
5449         }
5450     }
5451
5452   /* now the modulus */
5453   emitcode ("div", "ab");
5454
5455   if (runtimeSign || compiletimeSign)
5456     {
5457       emitcode ("mov", "a,b");
5458       lbl = newiTempLabel (NULL);
5459       if (runtimeSign)
5460         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5461       emitcode ("cpl", "a"); /* 2's complement */
5462       emitcode ("inc", "a");
5463       emitcode ("", "%05d$:", (lbl->key + 100));
5464
5465       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5466       if (size > 0)
5467         {
5468           /* msb is 0x00 or 0xff depending on the sign */
5469           if (runtimeSign)
5470             {
5471               emitcode ("mov", "c,F0");
5472               emitcode ("subb", "a,acc");
5473               while (size--)
5474                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5475             }
5476           else /* compiletimeSign */
5477             while (size--)
5478               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5479         }
5480     }
5481   else
5482     {
5483       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5484       while (size--)
5485         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5486     }
5487
5488   popB (pushedB);
5489 }
5490
5491 /*-----------------------------------------------------------------*/
5492 /* genMod - generates code for division                            */
5493 /*-----------------------------------------------------------------*/
5494 static void
5495 genMod (iCode * ic)
5496 {
5497   operand *left = IC_LEFT (ic);
5498   operand *right = IC_RIGHT (ic);
5499   operand *result = IC_RESULT (ic);
5500
5501   D(emitcode (";     genMod",""));
5502
5503   /* assign the asmops */
5504   aopOp (left, ic, FALSE);
5505   aopOp (right, ic, FALSE);
5506   aopOp (result, ic, TRUE);
5507
5508   /* special cases first */
5509   /* both are bits */
5510   if (AOP_TYPE (left) == AOP_CRY &&
5511       AOP_TYPE (right) == AOP_CRY)
5512     {
5513       genModbits (left, right, result);
5514       goto release;
5515     }
5516
5517   /* if both are of size == 1 */
5518   if (AOP_SIZE (left) == 1 &&
5519       AOP_SIZE (right) == 1)
5520     {
5521       genModOneByte (left, right, result);
5522       goto release;
5523     }
5524
5525   /* should have been converted to function call */
5526   assert (0);
5527
5528 release:
5529   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5530   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5531   freeAsmop (result, NULL, ic, TRUE);
5532 }
5533
5534 /*-----------------------------------------------------------------*/
5535 /* genIfxJump :- will create a jump depending on the ifx           */
5536 /*-----------------------------------------------------------------*/
5537 static void
5538 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5539 {
5540   symbol *jlbl;
5541   symbol *tlbl = newiTempLabel (NULL);
5542   char *inst;
5543
5544   D(emitcode (";     genIfxJump",""));
5545
5546   /* if true label then we jump if condition
5547      supplied is true */
5548   if (IC_TRUE (ic))
5549     {
5550       jlbl = IC_TRUE (ic);
5551       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5552                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5553     }
5554   else
5555     {
5556       /* false label is present */
5557       jlbl = IC_FALSE (ic);
5558       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5559                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5560     }
5561   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5562     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5563   else
5564     emitcode (inst, "%05d$", tlbl->key + 100);
5565   freeForBranchAsmop (result);
5566   freeForBranchAsmop (right);
5567   freeForBranchAsmop (left);
5568   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5569   emitcode ("", "%05d$:", tlbl->key + 100);
5570
5571   /* mark the icode as generated */
5572   ic->generated = 1;
5573 }
5574
5575 /*-----------------------------------------------------------------*/
5576 /* genCmp :- greater or less than comparison                       */
5577 /*-----------------------------------------------------------------*/
5578 static void
5579 genCmp (operand * left, operand * right,
5580         operand * result, iCode * ifx, int sign, iCode *ic)
5581 {
5582   int size, offset = 0;
5583   unsigned long lit = 0L;
5584   bool rightInB;
5585
5586   D(emitcode (";     genCmp",""));
5587
5588   /* if left & right are bit variables */
5589   if (AOP_TYPE (left) == AOP_CRY &&
5590       AOP_TYPE (right) == AOP_CRY)
5591     {
5592       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5593       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5594     }
5595   else
5596     {
5597       /* subtract right from left if at the
5598          end the carry flag is set then we know that
5599          left is greater than right */
5600       size = max (AOP_SIZE (left), AOP_SIZE (right));
5601
5602       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5603       if ((size == 1) && !sign &&
5604           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5605         {
5606           symbol *lbl = newiTempLabel (NULL);
5607           emitcode ("cjne", "%s,%s,%05d$",
5608                     aopGet (left, offset, FALSE, FALSE),
5609                     aopGet (right, offset, FALSE, FALSE),
5610                     lbl->key + 100);
5611           emitcode ("", "%05d$:", lbl->key + 100);
5612         }
5613       else
5614         {
5615           if (AOP_TYPE (right) == AOP_LIT)
5616             {
5617               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5618               /* optimize if(x < 0) or if(x >= 0) */
5619               if (lit == 0L)
5620                 {
5621                   if (!sign)
5622                     {
5623                       CLRC;
5624                     }
5625                   else
5626                     {
5627                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5628                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5629                         {
5630                           genIfxJump (ifx, "acc.7", left, right, result);
5631                           freeAsmop (right, NULL, ic, TRUE);
5632                           freeAsmop (left, NULL, ic, TRUE);
5633
5634                           return;
5635                         }
5636                       else
5637                         emitcode ("rlc", "a");
5638                     }
5639                   goto release;
5640                 }
5641             }
5642           CLRC;
5643           while (size--)
5644             {
5645               bool pushedB = FALSE;
5646               rightInB = aopGetUsesAcc(right, offset);
5647               if (rightInB)
5648                 {
5649                   pushedB = pushB ();
5650                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5651                 }
5652               MOVA (aopGet (left, offset, FALSE, FALSE));
5653               if (sign && size == 0)
5654                 {
5655                   emitcode ("xrl", "a,#0x80");
5656                   if (AOP_TYPE (right) == AOP_LIT)
5657                     {
5658                       unsigned long lit = (unsigned long)
5659                       floatFromVal (AOP (right)->aopu.aop_lit);
5660                       emitcode ("subb", "a,#0x%02x",
5661                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5662                     }
5663                   else
5664                     {
5665                       if (!rightInB)
5666                         {
5667                           pushedB = pushB ();
5668                           rightInB++;
5669                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5670                         }
5671                       emitcode ("xrl", "b,#0x80");
5672                       emitcode ("subb", "a,b");
5673                     }
5674                 }
5675               else
5676                 {
5677                   if (rightInB)
5678                     emitcode ("subb", "a,b");
5679                   else
5680                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5681                 }
5682               if (rightInB)
5683                 popB (pushedB);
5684               offset++;
5685             }
5686         }
5687     }
5688
5689 release:
5690   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5691   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5692   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5693     {
5694       outBitC (result);
5695     }
5696   else
5697     {
5698       /* if the result is used in the next
5699          ifx conditional branch then generate
5700          code a little differently */
5701       if (ifx)
5702         genIfxJump (ifx, "c", NULL, NULL, result);
5703       else
5704         outBitC (result);
5705       /* leave the result in acc */
5706     }
5707 }
5708
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpGt :- greater than comparison                             */
5711 /*-----------------------------------------------------------------*/
5712 static void
5713 genCmpGt (iCode * ic, iCode * ifx)
5714 {
5715   operand *left, *right, *result;
5716   sym_link *letype, *retype;
5717   int sign;
5718
5719   D(emitcode (";     genCmpGt",""));
5720
5721   left = IC_LEFT (ic);
5722   right = IC_RIGHT (ic);
5723   result = IC_RESULT (ic);
5724
5725   letype = getSpec (operandType (left));
5726   retype = getSpec (operandType (right));
5727   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5728            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5729   /* assign the amsops */
5730   aopOp (left, ic, FALSE);
5731   aopOp (right, ic, FALSE);
5732   aopOp (result, ic, TRUE);
5733
5734   genCmp (right, left, result, ifx, sign, ic);
5735
5736   freeAsmop (result, NULL, ic, TRUE);
5737 }
5738
5739 /*-----------------------------------------------------------------*/
5740 /* genCmpLt - less than comparisons                                */
5741 /*-----------------------------------------------------------------*/
5742 static void
5743 genCmpLt (iCode * ic, iCode * ifx)
5744 {
5745   operand *left, *right, *result;
5746   sym_link *letype, *retype;
5747   int sign;
5748
5749   D(emitcode (";     genCmpLt",""));
5750
5751   left = IC_LEFT (ic);
5752   right = IC_RIGHT (ic);
5753   result = IC_RESULT (ic);
5754
5755   letype = getSpec (operandType (left));
5756   retype = getSpec (operandType (right));
5757   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5758            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5759   /* assign the amsops */
5760   aopOp (left, ic, FALSE);
5761   aopOp (right, ic, FALSE);
5762   aopOp (result, ic, TRUE);
5763
5764   genCmp (left, right, result, ifx, sign, ic);
5765
5766   freeAsmop (result, NULL, ic, TRUE);
5767 }
5768
5769 /*-----------------------------------------------------------------*/
5770 /* gencjneshort - compare and jump if not equal                    */
5771 /*-----------------------------------------------------------------*/
5772 static void
5773 gencjneshort (operand * left, operand * right, symbol * lbl)
5774 {
5775   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5776   int offset = 0;
5777   unsigned long lit = 0L;
5778
5779   /* if the left side is a literal or
5780      if the right is in a pointer register and left
5781      is not */
5782   if ((AOP_TYPE (left) == AOP_LIT) ||
5783       (AOP_TYPE (left) == AOP_IMMD) ||
5784       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5785     {
5786       operand *t = right;
5787       right = left;
5788       left = t;
5789     }
5790
5791   if (AOP_TYPE (right) == AOP_LIT)
5792     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5793
5794   /* if the right side is a literal then anything goes */
5795   if (AOP_TYPE (right) == AOP_LIT &&
5796       AOP_TYPE (left) != AOP_DIR  &&
5797       AOP_TYPE (left) != AOP_IMMD)
5798     {
5799       while (size--)
5800         {
5801           emitcode ("cjne", "%s,%s,%05d$",
5802                     aopGet (left, offset, FALSE, FALSE),
5803                     aopGet (right, offset, FALSE, FALSE),
5804                     lbl->key + 100);
5805           offset++;
5806         }
5807     }
5808
5809   /* if the right side is in a register or in direct space or
5810      if the left is a pointer register & right is not */
5811   else if (AOP_TYPE (right) == AOP_REG ||
5812            AOP_TYPE (right) == AOP_DIR ||
5813            AOP_TYPE (right) == AOP_LIT ||
5814            AOP_TYPE (right) == AOP_IMMD ||
5815            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5816            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5817     {
5818       while (size--)
5819         {
5820           MOVA (aopGet (left, offset, FALSE, FALSE));
5821           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5822               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5823             emitcode ("jnz", "%05d$", lbl->key + 100);
5824           else
5825             emitcode ("cjne", "a,%s,%05d$",
5826                       aopGet (right, offset, FALSE, TRUE),
5827                       lbl->key + 100);
5828           offset++;
5829         }
5830     }
5831   else
5832     {
5833       /* right is a pointer reg need both a & b */
5834       while (size--)
5835         {
5836           char *l;
5837           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5838           wassertl(!BINUSE, "B was in use");
5839           l = aopGet (left, offset, FALSE, FALSE);
5840           if (strcmp (l, "b"))
5841             emitcode ("mov", "b,%s", l);
5842           MOVA (aopGet (right, offset, FALSE, FALSE));
5843           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5844           offset++;
5845         }
5846     }
5847 }
5848
5849 /*-----------------------------------------------------------------*/
5850 /* gencjne - compare and jump if not equal                         */
5851 /*-----------------------------------------------------------------*/
5852 static void
5853 gencjne (operand * left, operand * right, symbol * lbl)
5854 {
5855   symbol *tlbl = newiTempLabel (NULL);
5856
5857   gencjneshort (left, right, lbl);
5858
5859   emitcode ("mov", "a,%s", one);
5860   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5861   emitcode ("", "%05d$:", lbl->key + 100);
5862   emitcode ("clr", "a");
5863   emitcode ("", "%05d$:", tlbl->key + 100);
5864 }
5865
5866 /*-----------------------------------------------------------------*/
5867 /* genCmpEq - generates code for equal to                          */
5868 /*-----------------------------------------------------------------*/
5869 static void
5870 genCmpEq (iCode * ic, iCode * ifx)
5871 {
5872   operand *left, *right, *result;
5873
5874   D(emitcode (";     genCmpEq",""));
5875
5876   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5877   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5878   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5879
5880   /* if literal, literal on the right or
5881      if the right is in a pointer register and left
5882      is not */
5883   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5884       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5885     {
5886       operand *t = IC_RIGHT (ic);
5887       IC_RIGHT (ic) = IC_LEFT (ic);
5888       IC_LEFT (ic) = t;
5889     }
5890
5891   if (ifx && !AOP_SIZE (result))
5892     {
5893       symbol *tlbl;
5894       /* if they are both bit variables */
5895       if (AOP_TYPE (left) == AOP_CRY &&
5896           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5897         {
5898           if (AOP_TYPE (right) == AOP_LIT)
5899             {
5900               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5901               if (lit == 0L)
5902                 {
5903                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5904                   emitcode ("cpl", "c");
5905                 }
5906               else if (lit == 1L)
5907                 {
5908                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5909                 }
5910               else
5911                 {
5912                   emitcode ("clr", "c");
5913                 }
5914               /* AOP_TYPE(right) == AOP_CRY */
5915             }
5916           else
5917             {
5918               symbol *lbl = newiTempLabel (NULL);
5919               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5920               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5921               emitcode ("cpl", "c");
5922               emitcode ("", "%05d$:", (lbl->key + 100));
5923             }
5924           /* if true label then we jump if condition
5925              supplied is true */
5926           tlbl = newiTempLabel (NULL);
5927           if (IC_TRUE (ifx))
5928             {
5929               emitcode ("jnc", "%05d$", tlbl->key + 100);
5930               freeForBranchAsmop (result);
5931               freeForBranchAsmop (right);
5932               freeForBranchAsmop (left);
5933               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5934             }
5935           else
5936             {
5937               emitcode ("jc", "%05d$", tlbl->key + 100);
5938               freeForBranchAsmop (result);
5939               freeForBranchAsmop (right);
5940               freeForBranchAsmop (left);
5941               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5942             }
5943           emitcode ("", "%05d$:", tlbl->key + 100);
5944         }
5945       else
5946         {
5947           tlbl = newiTempLabel (NULL);
5948           gencjneshort (left, right, tlbl);
5949           if (IC_TRUE (ifx))
5950             {
5951               freeForBranchAsmop (result);
5952               freeForBranchAsmop (right);
5953               freeForBranchAsmop (left);
5954               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5955               emitcode ("", "%05d$:", tlbl->key + 100);
5956             }
5957           else
5958             {
5959               symbol *lbl = newiTempLabel (NULL);
5960               emitcode ("sjmp", "%05d$", lbl->key + 100);
5961               emitcode ("", "%05d$:", tlbl->key + 100);
5962               freeForBranchAsmop (result);
5963               freeForBranchAsmop (right);
5964               freeForBranchAsmop (left);
5965               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5966               emitcode ("", "%05d$:", lbl->key + 100);
5967             }
5968         }
5969       /* mark the icode as generated */
5970       ifx->generated = 1;
5971       goto release;
5972     }
5973
5974   /* if they are both bit variables */
5975   if (AOP_TYPE (left) == AOP_CRY &&
5976       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5977     {
5978       if (AOP_TYPE (right) == AOP_LIT)
5979         {
5980           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5981           if (lit == 0L)
5982             {
5983               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5984               emitcode ("cpl", "c");
5985             }
5986           else if (lit == 1L)
5987             {
5988               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5989             }
5990           else
5991             {
5992               emitcode ("clr", "c");
5993             }
5994           /* AOP_TYPE(right) == AOP_CRY */
5995         }
5996       else
5997         {
5998           symbol *lbl = newiTempLabel (NULL);
5999           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6000           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6001           emitcode ("cpl", "c");
6002           emitcode ("", "%05d$:", (lbl->key + 100));
6003         }
6004       /* c = 1 if egal */
6005       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6006         {
6007           outBitC (result);
6008           goto release;
6009         }
6010       if (ifx)
6011         {
6012           genIfxJump (ifx, "c", left, right, result);
6013           goto release;
6014         }
6015       /* if the result is used in an arithmetic operation
6016          then put the result in place */
6017       outBitC (result);
6018     }
6019   else
6020     {
6021       gencjne (left, right, newiTempLabel (NULL));
6022       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6023         {
6024           aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6025           goto release;
6026         }
6027       if (ifx)
6028         {
6029           genIfxJump (ifx, "a", left, right, result);
6030           goto release;
6031         }
6032       /* if the result is used in an arithmetic operation
6033          then put the result in place */
6034       if (AOP_TYPE (result) != AOP_CRY)
6035         outAcc (result);
6036       /* leave the result in acc */
6037     }
6038
6039 release:
6040   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6041   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6042   freeAsmop (result, NULL, ic, TRUE);
6043 }
6044
6045 /*-----------------------------------------------------------------*/
6046 /* ifxForOp - returns the icode containing the ifx for operand     */
6047 /*-----------------------------------------------------------------*/
6048 static iCode *
6049 ifxForOp (operand * op, iCode * ic)
6050 {
6051   /* if true symbol then needs to be assigned */
6052   if (IS_TRUE_SYMOP (op))
6053     return NULL;
6054
6055   /* if this has register type condition and
6056      the next instruction is ifx with the same operand
6057      and live to of the operand is upto the ifx only then */
6058   if (ic->next &&
6059       ic->next->op == IFX &&
6060       IC_COND (ic->next)->key == op->key &&
6061       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6062     return ic->next;
6063
6064   return NULL;
6065 }
6066
6067 /*-----------------------------------------------------------------*/
6068 /* hasInc - operand is incremented before any other use            */
6069 /*-----------------------------------------------------------------*/
6070 static iCode *
6071 hasInc (operand *op, iCode *ic,int osize)
6072 {
6073   sym_link *type = operandType(op);
6074   sym_link *retype = getSpec (type);
6075   iCode *lic = ic->next;
6076   int isize ;
6077
6078   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6079   if (!IS_SYMOP(op)) return NULL;
6080
6081   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6082   if (IS_AGGREGATE(type->next)) return NULL;
6083   if (osize != (isize = getSize(type->next))) return NULL;
6084
6085   while (lic) {
6086     /* if operand of the form op = op + <sizeof *op> */
6087     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6088         isOperandEqual(IC_RESULT(lic),op) &&
6089         isOperandLiteral(IC_RIGHT(lic)) &&
6090         operandLitValue(IC_RIGHT(lic)) == isize) {
6091       return lic;
6092     }
6093     /* if the operand used or deffed */
6094     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6095       return NULL;
6096     }
6097     /* if GOTO or IFX */
6098     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6099     lic = lic->next;
6100   }
6101   return NULL;
6102 }
6103
6104 /*-----------------------------------------------------------------*/
6105 /* genAndOp - for && operation                                     */
6106 /*-----------------------------------------------------------------*/
6107 static void
6108 genAndOp (iCode * ic)
6109 {
6110   operand *left, *right, *result;
6111   symbol *tlbl;
6112
6113   D(emitcode (";     genAndOp",""));
6114
6115   /* note here that && operations that are in an
6116      if statement are taken away by backPatchLabels
6117      only those used in arthmetic operations remain */
6118   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6119   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6120   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6121
6122   /* if both are bit variables */
6123   if (AOP_TYPE (left) == AOP_CRY &&
6124       AOP_TYPE (right) == AOP_CRY)
6125     {
6126       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6127       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6128       outBitC (result);
6129     }
6130   else
6131     {
6132       tlbl = newiTempLabel (NULL);
6133       toBoolean (left);
6134       emitcode ("jz", "%05d$", tlbl->key + 100);
6135       toBoolean (right);
6136       emitcode ("", "%05d$:", tlbl->key + 100);
6137       outBitAcc (result);
6138     }
6139
6140   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6141   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6142   freeAsmop (result, NULL, ic, TRUE);
6143 }
6144
6145
6146 /*-----------------------------------------------------------------*/
6147 /* genOrOp - for || operation                                      */
6148 /*-----------------------------------------------------------------*/
6149 static void
6150 genOrOp (iCode * ic)
6151 {
6152   operand *left, *right, *result;
6153   symbol *tlbl;
6154
6155   D(emitcode (";     genOrOp",""));
6156
6157   /* note here that || operations that are in an
6158      if statement are taken away by backPatchLabels
6159      only those used in arthmetic operations remain */
6160   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6161   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6162   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6163
6164   /* if both are bit variables */
6165   if (AOP_TYPE (left) == AOP_CRY &&
6166       AOP_TYPE (right) == AOP_CRY)
6167     {
6168       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6169       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6170       outBitC (result);
6171     }
6172   else
6173     {
6174       tlbl = newiTempLabel (NULL);
6175       toBoolean (left);
6176       emitcode ("jnz", "%05d$", tlbl->key + 100);
6177       toBoolean (right);
6178       emitcode ("", "%05d$:", tlbl->key + 100);
6179       outBitAcc (result);
6180     }
6181
6182   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6183   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6184   freeAsmop (result, NULL, ic, TRUE);
6185 }
6186
6187 /*-----------------------------------------------------------------*/
6188 /* isLiteralBit - test if lit == 2^n                               */
6189 /*-----------------------------------------------------------------*/
6190 static int
6191 isLiteralBit (unsigned long lit)
6192 {
6193   unsigned long pw[32] =
6194   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6195    0x100L, 0x200L, 0x400L, 0x800L,
6196    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6197    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6198    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6199    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6200    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6201   int idx;
6202
6203   for (idx = 0; idx < 32; idx++)
6204     if (lit == pw[idx])
6205       return idx + 1;
6206   return 0;
6207 }
6208
6209 /*-----------------------------------------------------------------*/
6210 /* continueIfTrue -                                                */
6211 /*-----------------------------------------------------------------*/
6212 static void
6213 continueIfTrue (iCode * ic)
6214 {
6215   if (IC_TRUE (ic))
6216     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6217   ic->generated = 1;
6218 }
6219
6220 /*-----------------------------------------------------------------*/
6221 /* jmpIfTrue -                                                     */
6222 /*-----------------------------------------------------------------*/
6223 static void
6224 jumpIfTrue (iCode * ic)
6225 {
6226   if (!IC_TRUE (ic))
6227     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6228   ic->generated = 1;
6229 }
6230
6231 /*-----------------------------------------------------------------*/
6232 /* jmpTrueOrFalse -                                                */
6233 /*-----------------------------------------------------------------*/
6234 static void
6235 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6236 {
6237   // ugly but optimized by peephole
6238   if (IC_TRUE (ic))
6239     {
6240       symbol *nlbl = newiTempLabel (NULL);
6241       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6242       emitcode ("", "%05d$:", tlbl->key + 100);
6243       freeForBranchAsmop (result);
6244       freeForBranchAsmop (right);
6245       freeForBranchAsmop (left);
6246       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6247       emitcode ("", "%05d$:", nlbl->key + 100);
6248     }
6249   else
6250     {
6251       freeForBranchAsmop (result);
6252       freeForBranchAsmop (right);
6253       freeForBranchAsmop (left);
6254       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6255       emitcode ("", "%05d$:", tlbl->key + 100);
6256     }
6257   ic->generated = 1;
6258 }
6259
6260 /*-----------------------------------------------------------------*/
6261 /* genAnd  - code for and                                          */
6262 /*-----------------------------------------------------------------*/
6263 static void
6264 genAnd (iCode * ic, iCode * ifx)
6265 {
6266   operand *left, *right, *result;
6267   int size, offset = 0;
6268   unsigned long lit = 0L;
6269   int bytelit = 0;
6270   char buffer[10];
6271
6272   D(emitcode (";     genAnd",""));
6273
6274   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6275   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6276   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6277
6278 #ifdef DEBUG_TYPE
6279   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6280             AOP_TYPE (result),
6281             AOP_TYPE (left), AOP_TYPE (right));
6282   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6283             AOP_SIZE (result),
6284             AOP_SIZE (left), AOP_SIZE (right));
6285 #endif
6286
6287   /* if left is a literal & right is not then exchange them */
6288   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6289       AOP_NEEDSACC (left))
6290     {
6291       operand *tmp = right;
6292       right = left;
6293       left = tmp;
6294     }
6295
6296   /* if result = right then exchange left and right */
6297   if (sameRegs (AOP (result), AOP (right)))
6298     {
6299       operand *tmp = right;
6300       right = left;
6301       left = tmp;
6302     }
6303
6304   /* if right is bit then exchange them */
6305   if (AOP_TYPE (right) == AOP_CRY &&
6306       AOP_TYPE (left) != AOP_CRY)
6307     {
6308       operand *tmp = right;
6309       right = left;
6310       left = tmp;
6311     }
6312   if (AOP_TYPE (right) == AOP_LIT)
6313     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6314
6315   size = AOP_SIZE (result);
6316
6317   // if(bit & yy)
6318   // result = bit & yy;
6319   if (AOP_TYPE (left) == AOP_CRY)
6320     {
6321       // c = bit & literal;
6322       if (AOP_TYPE (right) == AOP_LIT)
6323         {
6324           if (lit & 1)
6325             {
6326               if (size && sameRegs (AOP (result), AOP (left)))
6327                 // no change
6328                 goto release;
6329               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6330             }
6331           else
6332             {
6333               // bit(result) = 0;
6334               if (size && (AOP_TYPE (result) == AOP_CRY))
6335                 {
6336                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6337                   goto release;
6338                 }
6339               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6340                 {
6341                   jumpIfTrue (ifx);
6342                   goto release;
6343                 }
6344               emitcode ("clr", "c");
6345             }
6346         }
6347       else
6348         {
6349           if (AOP_TYPE (right) == AOP_CRY)
6350             {
6351               // c = bit & bit;
6352               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6353               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6354             }
6355           else
6356             {
6357               // c = bit & val;
6358               MOVA (aopGet (right, 0, FALSE, FALSE));
6359               // c = lsb
6360               emitcode ("rrc", "a");
6361               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6362             }
6363         }
6364       // bit = c
6365       // val = c
6366       if (size)
6367         outBitC (result);
6368       // if(bit & ...)
6369       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6370         genIfxJump (ifx, "c", left, right, result);
6371       goto release;
6372     }
6373
6374   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6375   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6376   if ((AOP_TYPE (right) == AOP_LIT) &&
6377       (AOP_TYPE (result) == AOP_CRY) &&
6378       (AOP_TYPE (left) != AOP_CRY))
6379     {
6380       int posbit = isLiteralBit (lit);
6381       /* left &  2^n */
6382       if (posbit)
6383         {
6384           posbit--;
6385           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6386           // bit = left & 2^n
6387           if (size)
6388             {
6389               switch (posbit & 0x07)
6390                 {
6391                   case 0: emitcode ("rrc", "a");
6392                           break;
6393                   case 7: emitcode ("rlc", "a");
6394                           break;
6395                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6396                           break;
6397                 }
6398             }
6399           // if(left &  2^n)
6400           else
6401             {
6402               if (ifx)
6403                 {
6404                   SNPRINTF (buffer, sizeof(buffer),
6405                             "acc.%d", posbit & 0x07);
6406                   genIfxJump (ifx, buffer, left, right, result);
6407                 }
6408               else
6409                 {// what is this case? just found it in ds390/gen.c
6410                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6411                 }
6412               goto release;
6413             }
6414         }
6415       else
6416         {
6417           symbol *tlbl = newiTempLabel (NULL);
6418           int sizel = AOP_SIZE (left);
6419           if (size)
6420             emitcode ("setb", "c");
6421           while (sizel--)
6422             {
6423               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6424                 {
6425                   MOVA (aopGet (left, offset, FALSE, FALSE));
6426                   // byte ==  2^n ?
6427                   if ((posbit = isLiteralBit (bytelit)) != 0)
6428                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6429                   else
6430                     {
6431                       if (bytelit != 0x0FFL)
6432                         emitcode ("anl", "a,%s",
6433                                   aopGet (right, offset, FALSE, TRUE));
6434                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6435                     }
6436                 }
6437               offset++;
6438             }
6439           // bit = left & literal
6440           if (size)
6441             {
6442               emitcode ("clr", "c");
6443               emitcode ("", "%05d$:", tlbl->key + 100);
6444             }
6445           // if(left & literal)
6446           else
6447             {
6448               if (ifx)
6449                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6450               else
6451                 emitcode ("", "%05d$:", tlbl->key + 100);
6452               goto release;
6453             }
6454         }
6455       outBitC (result);
6456       goto release;
6457     }
6458
6459   /* if left is same as result */
6460   if (sameRegs (AOP (result), AOP (left)))
6461     {
6462       for (; size--; offset++)
6463         {
6464           if (AOP_TYPE (right) == AOP_LIT)
6465             {
6466               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6467               if (bytelit == 0x0FF)
6468                 {
6469                   /* dummy read of volatile operand */
6470                   if (isOperandVolatile (left, FALSE))
6471                     MOVA (aopGet (left, offset, FALSE, FALSE));
6472                   else
6473                     continue;
6474                 }
6475               else if (bytelit == 0)
6476                 {
6477                   aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6478                 }
6479               else if (IS_AOP_PREG (result))
6480                 {
6481                   MOVA (aopGet (left, offset, FALSE, TRUE));
6482                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6483                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6484                 }
6485               else
6486                 emitcode ("anl", "%s,%s",
6487                           aopGet (left, offset, FALSE, TRUE),
6488                           aopGet (right, offset, FALSE, FALSE));
6489             }
6490           else
6491             {
6492               if (AOP_TYPE (left) == AOP_ACC)
6493                 {
6494                   if (offset)
6495                     emitcode("mov", "a,b");
6496                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6497                 }
6498               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6499                 {
6500                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6501                   MOVA (aopGet (right, offset, FALSE, FALSE));
6502                   emitcode ("anl", "a,b");
6503                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6504                 }
6505               else if (aopGetUsesAcc (left, offset))
6506                 {
6507                   MOVA (aopGet (left, offset, FALSE, FALSE));
6508                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6509                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6510                 }
6511               else
6512                 {
6513                   MOVA (aopGet (right, offset, FALSE, FALSE));
6514                   if (IS_AOP_PREG (result))
6515                     {
6516                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6517                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6518                     }
6519                   else
6520                     emitcode ("anl", "%s,a",
6521                               aopGet (left, offset, FALSE, TRUE));
6522                 }
6523             }
6524         }
6525     }
6526   else
6527     {
6528       // left & result in different registers
6529       if (AOP_TYPE (result) == AOP_CRY)
6530         {
6531           // result = bit
6532           // if(size), result in bit
6533           // if(!size && ifx), conditional oper: if(left & right)
6534           symbol *tlbl = newiTempLabel (NULL);
6535           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6536           if (size)
6537             emitcode ("setb", "c");
6538           while (sizer--)
6539             {
6540               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6541                   && AOP_TYPE(left)==AOP_ACC)
6542                 {
6543                   if (offset)
6544                     emitcode("mov", "a,b");
6545                   emitcode ("anl", "a,%s",
6546                             aopGet (right, offset, FALSE, FALSE));
6547                 } else {
6548                   if (AOP_TYPE(left)==AOP_ACC)
6549                     {
6550                       if (!offset)
6551                         {
6552                           bool pushedB = pushB ();
6553                           emitcode("mov", "b,a");
6554                           MOVA (aopGet (right, offset, FALSE, FALSE));
6555                           emitcode("anl", "a,b");
6556                           popB (pushedB);
6557                         }
6558                       else
6559                         {
6560                           MOVA (aopGet (right, offset, FALSE, FALSE));
6561                           emitcode("anl", "a,b");
6562                         }
6563                     } else {
6564                       MOVA (aopGet (right, offset, FALSE, FALSE));
6565                       emitcode ("anl", "a,%s",
6566                                 aopGet (left, offset, FALSE, FALSE));
6567                     }
6568                 }
6569               emitcode ("jnz", "%05d$", tlbl->key + 100);
6570               offset++;
6571             }
6572           if (size)
6573             {
6574               CLRC;
6575               emitcode ("", "%05d$:", tlbl->key + 100);
6576               outBitC (result);
6577             }
6578           else if (ifx)
6579             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6580           else
6581             emitcode ("", "%05d$:", tlbl->key + 100);
6582         }
6583       else
6584         {
6585           for (; (size--); offset++)
6586             {
6587               // normal case
6588               // result = left & right
6589               if (AOP_TYPE (right) == AOP_LIT)
6590                 {
6591                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6592                   if (bytelit == 0x0FF)
6593                     {
6594                       aopPut (result,
6595                               aopGet (left, offset, FALSE, FALSE),
6596                               offset,
6597                               isOperandVolatile (result, FALSE));
6598                       continue;
6599                     }
6600                   else if (bytelit == 0)
6601                     {
6602                       /* dummy read of volatile operand */
6603                       if (isOperandVolatile (left, FALSE))
6604                         MOVA (aopGet (left, offset, FALSE, FALSE));
6605                       aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6606                       continue;
6607                     }
6608                   else if (AOP_TYPE (left) == AOP_ACC)
6609                     {
6610                       if (!offset)
6611                         {
6612                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6613                           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6614                           continue;
6615                         }
6616                       else
6617                         {
6618                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6619                           aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6620                           continue;
6621                         }
6622                     }
6623                 }
6624               // faster than result <- left, anl result,right
6625               // and better if result is SFR
6626               if (AOP_TYPE (left) == AOP_ACC)
6627                 {
6628                   if (offset)
6629                     emitcode("mov", "a,b");
6630                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6631                 }
6632               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6633                 {
6634                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6635                   MOVA (aopGet (right, offset, FALSE, FALSE));
6636                   emitcode ("anl", "a,b");
6637                 }
6638               else if (aopGetUsesAcc (left, offset))
6639                 {
6640                   MOVA (aopGet (left, offset, FALSE, FALSE));
6641                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6642                 }
6643               else
6644                 {
6645                   MOVA (aopGet (right, offset, FALSE, FALSE));
6646                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6647                 }
6648               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6649             }
6650         }
6651     }
6652
6653 release:
6654   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6655   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6656   freeAsmop (result, NULL, ic, TRUE);
6657 }
6658
6659 /*-----------------------------------------------------------------*/
6660 /* genOr  - code for or                                            */
6661 /*-----------------------------------------------------------------*/
6662 static void
6663 genOr (iCode * ic, iCode * ifx)
6664 {
6665   operand *left, *right, *result;
6666   int size, offset = 0;
6667   unsigned long lit = 0L;
6668   int bytelit = 0;
6669
6670   D(emitcode (";     genOr",""));
6671
6672   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6673   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6674   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6675
6676 #ifdef DEBUG_TYPE
6677   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6678             AOP_TYPE (result),
6679             AOP_TYPE (left), AOP_TYPE (right));
6680   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6681             AOP_SIZE (result),
6682             AOP_SIZE (left), AOP_SIZE (right));
6683 #endif
6684
6685   /* if left is a literal & right is not then exchange them */
6686   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6687       AOP_NEEDSACC (left))
6688     {
6689       operand *tmp = right;
6690       right = left;
6691       left = tmp;
6692     }
6693
6694   /* if result = right then exchange them */
6695   if (sameRegs (AOP (result), AOP (right)))
6696     {
6697       operand *tmp = right;
6698       right = left;
6699       left = tmp;
6700     }
6701
6702   /* if right is bit then exchange them */
6703   if (AOP_TYPE (right) == AOP_CRY &&
6704       AOP_TYPE (left) != AOP_CRY)
6705     {
6706       operand *tmp = right;
6707       right = left;
6708       left = tmp;
6709     }
6710   if (AOP_TYPE (right) == AOP_LIT)
6711     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6712
6713   size = AOP_SIZE (result);
6714
6715   // if(bit | yy)
6716   // xx = bit | yy;
6717   if (AOP_TYPE (left) == AOP_CRY)
6718     {
6719       if (AOP_TYPE (right) == AOP_LIT)
6720         {
6721           // c = bit | literal;
6722           if (lit)
6723             {
6724               // lit != 0 => result = 1
6725               if (AOP_TYPE (result) == AOP_CRY)
6726                 {
6727                   if (size)
6728                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6729                   else if (ifx)
6730                     continueIfTrue (ifx);
6731                   goto release;
6732                 }
6733               emitcode ("setb", "c");
6734             }
6735           else
6736             {
6737               // lit == 0 => result = left
6738               if (size && sameRegs (AOP (result), AOP (left)))
6739                 goto release;
6740               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6741             }
6742         }
6743       else
6744         {
6745           if (AOP_TYPE (right) == AOP_CRY)
6746             {
6747               // c = bit | bit;
6748               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6749               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6750             }
6751           else
6752             {
6753               // c = bit | val;
6754               symbol *tlbl = newiTempLabel (NULL);
6755               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6756                 emitcode ("setb", "c");
6757               emitcode ("jb", "%s,%05d$",
6758                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6759               toBoolean (right);
6760               emitcode ("jnz", "%05d$", tlbl->key + 100);
6761               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6762                 {
6763                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6764                   goto release;
6765                 }
6766               else
6767                 {
6768                   CLRC;
6769                   emitcode ("", "%05d$:", tlbl->key + 100);
6770                 }
6771             }
6772         }
6773       // bit = c
6774       // val = c
6775       if (size)
6776         outBitC (result);
6777       // if(bit | ...)
6778       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6779         genIfxJump (ifx, "c", left, right, result);
6780       goto release;
6781     }
6782
6783   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6784   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6785   if ((AOP_TYPE (right) == AOP_LIT) &&
6786       (AOP_TYPE (result) == AOP_CRY) &&
6787       (AOP_TYPE (left) != AOP_CRY))
6788     {
6789       if (lit)
6790         {
6791           // result = 1
6792           if (size)
6793             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6794           else
6795             continueIfTrue (ifx);
6796           goto release;
6797         }
6798       else
6799         {
6800           // lit = 0, result = boolean(left)
6801           if (size)
6802             emitcode ("setb", "c");
6803           toBoolean (right);
6804           if (size)
6805             {
6806               symbol *tlbl = newiTempLabel (NULL);
6807               emitcode ("jnz", "%05d$", tlbl->key + 100);
6808               CLRC;
6809               emitcode ("", "%05d$:", tlbl->key + 100);
6810             }
6811           else
6812             {
6813               genIfxJump (ifx, "a", left, right, result);
6814               goto release;
6815             }
6816         }
6817       outBitC (result);
6818       goto release;
6819     }
6820
6821   /* if left is same as result */
6822   if (sameRegs (AOP (result), AOP (left)))
6823     {
6824       for (; size--; offset++)
6825         {
6826           if (AOP_TYPE (right) == AOP_LIT)
6827             {
6828               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6829               if (bytelit == 0)
6830                 {
6831                   /* dummy read of volatile operand */
6832                   if (isOperandVolatile (left, FALSE))
6833                     MOVA (aopGet (left, offset, FALSE, FALSE));
6834                   else
6835                     continue;
6836                 }
6837               else if (bytelit == 0x0FF)
6838                 {
6839                   aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6840                 }
6841               else if (IS_AOP_PREG (left))
6842                 {
6843                   MOVA (aopGet (left, offset, FALSE, TRUE));
6844                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6845                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6846                 }
6847               else
6848                 {
6849                   emitcode ("orl", "%s,%s",
6850                             aopGet (left, offset, FALSE, TRUE),
6851                             aopGet (right, offset, FALSE, FALSE));
6852                 }
6853             }
6854           else
6855             {
6856               if (AOP_TYPE (left) == AOP_ACC)
6857                 {
6858                   if (offset)
6859                     emitcode("mov", "a,b");
6860                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6861                 }
6862               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6863                 {
6864                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6865                   MOVA (aopGet (right, offset, FALSE, FALSE));
6866                   emitcode ("orl", "a,b");
6867                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6868                 }
6869               else if (aopGetUsesAcc (left, offset))
6870                 {
6871                   MOVA (aopGet (left, offset, FALSE, FALSE));
6872                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6873                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6874                 }
6875               else
6876                 {
6877                   MOVA (aopGet (right, offset, FALSE, FALSE));
6878                   if (IS_AOP_PREG (left))
6879                     {
6880                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6881                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6882                     }
6883                   else
6884                     {
6885                       emitcode ("orl", "%s,a",
6886                                 aopGet (left, offset, FALSE, TRUE));
6887                     }
6888                 }
6889             }
6890         }
6891     }
6892   else
6893     {
6894       // left & result in different registers
6895       if (AOP_TYPE (result) == AOP_CRY)
6896         {
6897           // result = bit
6898           // if(size), result in bit
6899           // if(!size && ifx), conditional oper: if(left | right)
6900           symbol *tlbl = newiTempLabel (NULL);
6901           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6902           if (size)
6903             emitcode ("setb", "c");
6904           while (sizer--)
6905             {
6906               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6907                 if (offset)
6908                   emitcode("mov", "a,b");
6909                 emitcode ("orl", "a,%s",
6910                           aopGet (right, offset, FALSE, FALSE));
6911               } else {
6912                 MOVA (aopGet (right, offset, FALSE, FALSE));
6913                 emitcode ("orl", "a,%s",
6914                           aopGet (left, offset, FALSE, FALSE));
6915               }
6916               emitcode ("jnz", "%05d$", tlbl->key + 100);
6917               offset++;
6918             }
6919           if (size)
6920             {
6921               CLRC;
6922               emitcode ("", "%05d$:", tlbl->key + 100);
6923               outBitC (result);
6924             }
6925           else if (ifx)
6926             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6927           else
6928             emitcode ("", "%05d$:", tlbl->key + 100);
6929         }
6930       else
6931         {
6932           for (; (size--); offset++)
6933             {
6934               // normal case
6935               // result = left | right
6936               if (AOP_TYPE (right) == AOP_LIT)
6937                 {
6938                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6939                   if (bytelit == 0)
6940                     {
6941                       aopPut (result,
6942                               aopGet (left, offset, FALSE, FALSE),
6943                               offset,
6944                               isOperandVolatile (result, FALSE));
6945                       continue;
6946                     }
6947                   else if (bytelit == 0x0FF)
6948                     {
6949                       /* dummy read of volatile operand */
6950                       if (isOperandVolatile (left, FALSE))
6951                         MOVA (aopGet (left, offset, FALSE, FALSE));
6952                       aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6953                       continue;
6954                     }
6955                 }
6956               // faster than result <- left, anl result,right
6957               // and better if result is SFR
6958               if (AOP_TYPE (left) == AOP_ACC)
6959                 {
6960                   if (offset)
6961                     emitcode("mov", "a,b");
6962                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6963                 }
6964               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6965                 {
6966                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6967                   MOVA (aopGet (right, offset, FALSE, FALSE));
6968                   emitcode ("orl", "a,b");
6969                 }
6970               else if (aopGetUsesAcc (left, offset))
6971                 {
6972                   MOVA (aopGet (left, offset, FALSE, FALSE));
6973                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6974                 }
6975               else
6976                 {
6977                   MOVA (aopGet (right, offset, FALSE, FALSE));
6978                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6979                 }
6980               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6981             }
6982         }
6983     }
6984
6985 release:
6986   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6987   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6988   freeAsmop (result, NULL, ic, TRUE);
6989 }
6990
6991 /*-----------------------------------------------------------------*/
6992 /* genXor - code for xclusive or                                   */
6993 /*-----------------------------------------------------------------*/
6994 static void
6995 genXor (iCode * ic, iCode * ifx)
6996 {
6997   operand *left, *right, *result;
6998   int size, offset = 0;
6999   unsigned long lit = 0L;
7000   int bytelit = 0;
7001
7002   D(emitcode (";     genXor",""));
7003
7004   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7005   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7006   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7007
7008 #ifdef DEBUG_TYPE
7009   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7010             AOP_TYPE (result),
7011             AOP_TYPE (left), AOP_TYPE (right));
7012   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7013             AOP_SIZE (result),
7014             AOP_SIZE (left), AOP_SIZE (right));
7015 #endif
7016
7017   /* if left is a literal & right is not ||
7018      if left needs acc & right does not */
7019   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7020       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7021     {
7022       operand *tmp = right;
7023       right = left;
7024       left = tmp;
7025     }
7026
7027   /* if result = right then exchange them */
7028   if (sameRegs (AOP (result), AOP (right)))
7029     {
7030       operand *tmp = right;
7031       right = left;
7032       left = tmp;
7033     }
7034
7035   /* if right is bit then exchange them */
7036   if (AOP_TYPE (right) == AOP_CRY &&
7037       AOP_TYPE (left) != AOP_CRY)
7038     {
7039       operand *tmp = right;
7040       right = left;
7041       left = tmp;
7042     }
7043   if (AOP_TYPE (right) == AOP_LIT)
7044     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7045
7046   size = AOP_SIZE (result);
7047
7048   // if(bit ^ yy)
7049   // xx = bit ^ yy;
7050   if (AOP_TYPE (left) == AOP_CRY)
7051     {
7052       if (AOP_TYPE (right) == AOP_LIT)
7053         {
7054           // c = bit & literal;
7055           if (lit >> 1)
7056             {
7057               // lit>>1  != 0 => result = 1
7058               if (AOP_TYPE (result) == AOP_CRY)
7059                 {
7060                   if (size)
7061                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7062                   else if (ifx)
7063                     continueIfTrue (ifx);
7064                   goto release;
7065                 }
7066               emitcode ("setb", "c");
7067             }
7068           else
7069             {
7070               // lit == (0 or 1)
7071               if (lit == 0)
7072                 {
7073                   // lit == 0, result = left
7074                   if (size && sameRegs (AOP (result), AOP (left)))
7075                     goto release;
7076                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7077                 }
7078               else
7079                 {
7080                   // lit == 1, result = not(left)
7081                   if (size && sameRegs (AOP (result), AOP (left)))
7082                     {
7083                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7084                       goto release;
7085                     }
7086                   else
7087                     {
7088                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7089                       emitcode ("cpl", "c");
7090                     }
7091                 }
7092             }
7093
7094         }
7095       else
7096         {
7097           // right != literal
7098           symbol *tlbl = newiTempLabel (NULL);
7099           if (AOP_TYPE (right) == AOP_CRY)
7100             {
7101               // c = bit ^ bit;
7102               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7103             }
7104           else
7105             {
7106               int sizer = AOP_SIZE (right);
7107               // c = bit ^ val
7108               // if val>>1 != 0, result = 1
7109               emitcode ("setb", "c");
7110               while (sizer)
7111                 {
7112                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7113                   if (sizer == 1)
7114                     // test the msb of the lsb
7115                     emitcode ("anl", "a,#0xfe");
7116                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7117                   sizer--;
7118                 }
7119               // val = (0,1)
7120               emitcode ("rrc", "a");
7121             }
7122           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7123           emitcode ("cpl", "c");
7124           emitcode ("", "%05d$:", (tlbl->key + 100));
7125         }
7126       // bit = c
7127       // val = c
7128       if (size)
7129         outBitC (result);
7130       // if(bit | ...)
7131       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7132         genIfxJump (ifx, "c", left, right, result);
7133       goto release;
7134     }
7135
7136   /* if left is same as result */
7137   if (sameRegs (AOP (result), AOP (left)))
7138     {
7139       for (; size--; offset++)
7140         {
7141           if (AOP_TYPE (right) == AOP_LIT)
7142             {
7143               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7144               if (bytelit == 0)
7145                 {
7146                   /* dummy read of volatile operand */
7147                   if (isOperandVolatile (left, FALSE))
7148                     MOVA (aopGet (left, offset, FALSE, FALSE));
7149                   else
7150                     continue;
7151                 }
7152               else if (IS_AOP_PREG (left))
7153                 {
7154                   MOVA (aopGet (left, offset, FALSE, TRUE));
7155                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7156                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7157                 }
7158               else
7159                 {
7160                   emitcode ("xrl", "%s,%s",
7161                             aopGet (left, offset, FALSE, TRUE),
7162                             aopGet (right, offset, FALSE, FALSE));
7163                 }
7164             }
7165           else
7166             {
7167               if (AOP_TYPE (left) == AOP_ACC)
7168                 {
7169                   if (offset)
7170                     emitcode("mov", "a,b");
7171                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7172                 }
7173               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7174                 {
7175                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7176                   MOVA (aopGet (right, offset, FALSE, FALSE));
7177                   emitcode ("xrl", "a,b");
7178                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7179                 }
7180               else if (aopGetUsesAcc (left, offset))
7181                 {
7182                   MOVA (aopGet (left, offset, FALSE, FALSE));
7183                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7184                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7185                 }
7186               else
7187                 {
7188                   MOVA (aopGet (right, offset, FALSE, FALSE));
7189                   if (IS_AOP_PREG (left))
7190                     {
7191                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7192                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7193                     }
7194                   else
7195                     emitcode ("xrl", "%s,a",
7196                               aopGet (left, offset, FALSE, TRUE));
7197                 }
7198             }
7199         }
7200     }
7201   else
7202     {
7203       // left & result in different registers
7204       if (AOP_TYPE (result) == AOP_CRY)
7205         {
7206           // result = bit
7207           // if(size), result in bit
7208           // if(!size && ifx), conditional oper: if(left ^ right)
7209           symbol *tlbl = newiTempLabel (NULL);
7210           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7211           if (size)
7212             emitcode ("setb", "c");
7213           while (sizer--)
7214             {
7215               if ((AOP_TYPE (right) == AOP_LIT) &&
7216                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7217                 {
7218                   MOVA (aopGet (left, offset, FALSE, FALSE));
7219                 }
7220               else
7221                 {
7222                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7223                     if (offset)
7224                       emitcode("mov", "a,b");
7225                     emitcode ("xrl", "a,%s",
7226                               aopGet (right, offset, FALSE, FALSE));
7227                   } else {
7228                     MOVA (aopGet (right, offset, FALSE, FALSE));
7229                     emitcode ("xrl", "a,%s",
7230                               aopGet (left, offset, FALSE, FALSE));
7231                   }
7232                 }
7233               emitcode ("jnz", "%05d$", tlbl->key + 100);
7234               offset++;
7235             }
7236           if (size)
7237             {
7238               CLRC;
7239               emitcode ("", "%05d$:", tlbl->key + 100);
7240               outBitC (result);
7241             }
7242           else if (ifx)
7243             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7244         }
7245       else
7246         {
7247           for (; (size--); offset++)
7248             {
7249               // normal case
7250               // result = left & right
7251               if (AOP_TYPE (right) == AOP_LIT)
7252                 {
7253                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7254                   if (bytelit == 0)
7255                     {
7256                       aopPut (result,
7257                               aopGet (left, offset, FALSE, FALSE),
7258                               offset,
7259                               isOperandVolatile (result, FALSE));
7260                       continue;
7261                     }
7262                 }
7263               // faster than result <- left, anl result,right
7264               // and better if result is SFR
7265               if (AOP_TYPE (left) == AOP_ACC)
7266                 {
7267                   if (offset)
7268                     emitcode("mov", "a,b");
7269                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7270                 }
7271               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7272                 {
7273                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7274                   MOVA (aopGet (right, offset, FALSE, FALSE));
7275                   emitcode ("xrl", "a,b");
7276                 }
7277               else if (aopGetUsesAcc (left, offset))
7278                 {
7279                   MOVA (aopGet (left, offset, FALSE, FALSE));
7280                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281                 }
7282               else
7283                 {
7284                   MOVA (aopGet (right, offset, FALSE, FALSE));
7285                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7286                 }
7287               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7288             }
7289         }
7290     }
7291
7292 release:
7293   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7294   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7295   freeAsmop (result, NULL, ic, TRUE);
7296 }
7297
7298 /*-----------------------------------------------------------------*/
7299 /* genInline - write the inline code out                           */
7300 /*-----------------------------------------------------------------*/
7301 static void
7302 genInline (iCode * ic)
7303 {
7304   char *buffer, *bp, *bp1;
7305
7306   D(emitcode (";     genInline",""));
7307
7308   _G.inLine += (!options.asmpeep);
7309
7310   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7311   strcpy (buffer, IC_INLINE (ic));
7312
7313   /* emit each line as a code */
7314   while (*bp)
7315     {
7316       if (*bp == '\n')
7317         {
7318           *bp++ = '\0';
7319           emitcode (bp1, "");
7320           bp1 = bp;
7321         }
7322       else
7323         {
7324           /* Add \n for labels, not dirs such as c:\mydir */
7325           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7326             {
7327               bp++;
7328               *bp = '\0';
7329               bp++;
7330               emitcode (bp1, "");
7331               bp1 = bp;
7332             }
7333           else
7334             bp++;
7335         }
7336     }
7337   if (bp1 != bp)
7338     emitcode (bp1, "");
7339   /*     emitcode("",buffer); */
7340   _G.inLine -= (!options.asmpeep);
7341 }
7342
7343 /*-----------------------------------------------------------------*/
7344 /* genRRC - rotate right with carry                                */
7345 /*-----------------------------------------------------------------*/
7346 static void
7347 genRRC (iCode * ic)
7348 {
7349   operand *left, *result;
7350   int size, offset = 0;
7351   char *l;
7352
7353   D(emitcode (";     genRRC",""));
7354
7355   /* rotate right with carry */
7356   left = IC_LEFT (ic);
7357   result = IC_RESULT (ic);
7358   aopOp (left, ic, FALSE);
7359   aopOp (result, ic, FALSE);
7360
7361   /* move it to the result */
7362   size = AOP_SIZE (result);
7363   offset = size - 1;
7364   if (size == 1) { /* special case for 1 byte */
7365       l = aopGet (left, offset, FALSE, FALSE);
7366       MOVA (l);
7367       emitcode ("rr", "a");
7368       goto release;
7369   }
7370   /* no need to clear carry, bit7 will be written later */
7371   while (size--)
7372     {
7373       l = aopGet (left, offset, FALSE, FALSE);
7374       MOVA (l);
7375       emitcode ("rrc", "a");
7376       if (AOP_SIZE (result) > 1)
7377         aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7378     }
7379   /* now we need to put the carry into the
7380      highest order byte of the result */
7381   if (AOP_SIZE (result) > 1)
7382     {
7383       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7384       MOVA (l);
7385     }
7386   emitcode ("mov", "acc.7,c");
7387  release:
7388   aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7389   freeAsmop (left, NULL, ic, TRUE);
7390   freeAsmop (result, NULL, ic, TRUE);
7391 }
7392
7393 /*-----------------------------------------------------------------*/
7394 /* genRLC - generate code for rotate left with carry               */
7395 /*-----------------------------------------------------------------*/
7396 static void
7397 genRLC (iCode * ic)
7398 {
7399   operand *left, *result;
7400   int size, offset = 0;
7401   char *l;
7402
7403   D(emitcode (";     genRLC",""));
7404
7405   /* rotate right with carry */
7406   left = IC_LEFT (ic);
7407   result = IC_RESULT (ic);
7408   aopOp (left, ic, FALSE);
7409   aopOp (result, ic, FALSE);
7410
7411   /* move it to the result */
7412   size = AOP_SIZE (result);
7413   offset = 0;
7414   if (size--)
7415     {
7416       l = aopGet (left, offset, FALSE, FALSE);
7417       MOVA (l);
7418       if (size == 0) { /* special case for 1 byte */
7419               emitcode("rl","a");
7420               goto release;
7421       }
7422       emitcode("rlc","a"); /* bit0 will be written later */
7423       if (AOP_SIZE (result) > 1)
7424         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7425       while (size--)
7426         {
7427           l = aopGet (left, offset, FALSE, FALSE);
7428           MOVA (l);
7429           emitcode ("rlc", "a");
7430           if (AOP_SIZE (result) > 1)
7431             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7432         }
7433     }
7434   /* now we need to put the carry into the
7435      highest order byte of the result */
7436   if (AOP_SIZE (result) > 1)
7437     {
7438       l = aopGet (result, 0, FALSE, FALSE);
7439       MOVA (l);
7440     }
7441   emitcode ("mov", "acc.0,c");
7442  release:
7443   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7444   freeAsmop (left, NULL, ic, TRUE);
7445   freeAsmop (result, NULL, ic, TRUE);
7446 }
7447
7448 /*-----------------------------------------------------------------*/
7449 /* genGetHbit - generates code get highest order bit               */
7450 /*-----------------------------------------------------------------*/
7451 static void
7452 genGetHbit (iCode * ic)
7453 {
7454   operand *left, *result;
7455
7456   D(emitcode (";     genGetHbit",""));
7457
7458   left = IC_LEFT (ic);
7459   result = IC_RESULT (ic);
7460   aopOp (left, ic, FALSE);
7461   aopOp (result, ic, FALSE);
7462
7463   /* get the highest order byte into a */
7464   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7465   if (AOP_TYPE (result) == AOP_CRY)
7466     {
7467       emitcode ("rlc", "a");
7468       outBitC (result);
7469     }
7470   else
7471     {
7472       emitcode ("rl", "a");
7473       emitcode ("anl", "a,#0x01");
7474       outAcc (result);
7475     }
7476
7477   freeAsmop (left, NULL, ic, TRUE);
7478   freeAsmop (result, NULL, ic, TRUE);
7479 }
7480
7481 /*-----------------------------------------------------------------*/
7482 /* genGetAbit - generates code get a single bit                    */
7483 /*-----------------------------------------------------------------*/
7484 static void
7485 genGetAbit (iCode * ic)
7486 {
7487   operand *left, *right, *result;
7488   int shCount;
7489
7490   D(emitcode (";     genGetAbit",""));
7491
7492   left = IC_LEFT (ic);
7493   right = IC_RIGHT (ic);
7494   result = IC_RESULT (ic);
7495   aopOp (left, ic, FALSE);
7496   aopOp (right, ic, FALSE);
7497   aopOp (result, ic, FALSE);
7498
7499   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7500
7501   /* get the needed byte into a */
7502   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7503   shCount %= 8;
7504   if (AOP_TYPE (result) == AOP_CRY)
7505     {
7506       if ((shCount) == 7)
7507           emitcode ("rlc", "a");
7508       else if ((shCount) == 0)
7509           emitcode ("rrc", "a");
7510       else
7511           emitcode ("mov", "c,acc[%d]", shCount);
7512       outBitC (result);
7513     }
7514   else
7515     {
7516       switch (shCount)
7517         {
7518         case 2:
7519           emitcode ("rr", "a");
7520           //fallthrough
7521         case 1:
7522           emitcode ("rr", "a");
7523           //fallthrough
7524         case 0:
7525           emitcode ("anl", "a,#0x01");
7526           break;
7527         case 3:
7528         case 5:
7529           emitcode ("mov", "c,acc[%d]", shCount);
7530           emitcode ("clr", "a");
7531           emitcode ("rlc", "a");
7532           break;
7533         case 4:
7534           emitcode ("swap", "a");
7535           emitcode ("anl", "a,#0x01");
7536           break;
7537         case 6:
7538           emitcode ("rl", "a");
7539           //fallthrough
7540         case 7:
7541           emitcode ("rl", "a");
7542           emitcode ("anl", "a,#0x01");
7543           break;
7544         }
7545       outAcc (result);
7546     }
7547
7548   freeAsmop (right, NULL, ic, TRUE);
7549   freeAsmop (left, NULL, ic, TRUE);
7550   freeAsmop (result, NULL, ic, TRUE);
7551 }
7552
7553 /*-----------------------------------------------------------------*/
7554 /* genGetByte - generates code get a single byte                   */
7555 /*-----------------------------------------------------------------*/
7556 static void
7557 genGetByte (iCode * ic)
7558 {
7559   operand *left, *right, *result;
7560   int offset;
7561
7562   D(emitcode (";     genGetByte",""));
7563
7564   left = IC_LEFT (ic);
7565   right = IC_RIGHT (ic);
7566   result = IC_RESULT (ic);
7567   aopOp (left, ic, FALSE);
7568   aopOp (right, ic, FALSE);
7569   aopOp (result, ic, FALSE);
7570
7571   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7572   aopPut (result,
7573           aopGet (left, offset, FALSE, FALSE),
7574           0,
7575           isOperandVolatile (result, FALSE));
7576
7577   freeAsmop (right, NULL, ic, TRUE);
7578   freeAsmop (left, NULL, ic, TRUE);
7579   freeAsmop (result, NULL, ic, TRUE);
7580 }
7581
7582 /*-----------------------------------------------------------------*/
7583 /* genGetWord - generates code get two bytes                       */
7584 /*-----------------------------------------------------------------*/
7585 static void
7586 genGetWord (iCode * ic)
7587 {
7588   operand *left, *right, *result;
7589   int offset;
7590
7591   D(emitcode (";     genGetWord",""));
7592
7593   left = IC_LEFT (ic);
7594   right = IC_RIGHT (ic);
7595   result = IC_RESULT (ic);
7596   aopOp (left, ic, FALSE);
7597   aopOp (right, ic, FALSE);
7598   aopOp (result, ic, FALSE);
7599
7600   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7601   aopPut (result,
7602           aopGet (left, offset, FALSE, FALSE),
7603           0,
7604           isOperandVolatile (result, FALSE));
7605   aopPut (result,
7606           aopGet (left, offset+1, FALSE, FALSE),
7607           1,
7608           isOperandVolatile (result, FALSE));
7609
7610   freeAsmop (right, NULL, ic, TRUE);
7611   freeAsmop (left, NULL, ic, TRUE);
7612   freeAsmop (result, NULL, ic, TRUE);
7613 }
7614
7615 /*-----------------------------------------------------------------*/
7616 /* genSwap - generates code to swap nibbles or bytes               */
7617 /*-----------------------------------------------------------------*/
7618 static void
7619 genSwap (iCode * ic)
7620 {
7621   operand *left, *result;
7622
7623   D(emitcode (";     genSwap",""));
7624
7625   left = IC_LEFT (ic);
7626   result = IC_RESULT (ic);
7627   aopOp (left, ic, FALSE);
7628   aopOp (result, ic, FALSE);
7629
7630   switch (AOP_SIZE (left))
7631     {
7632     case 1: /* swap nibbles in byte */
7633       MOVA (aopGet (left, 0, FALSE, FALSE));
7634       emitcode ("swap", "a");
7635       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7636       break;
7637     case 2: /* swap bytes in word */
7638       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7639         {
7640           MOVA (aopGet (left, 0, FALSE, FALSE));
7641           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7642                   0, isOperandVolatile (result, FALSE));
7643           aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7644         }
7645       else if (operandsEqu (left, result))
7646         {
7647           char * reg = "a";
7648           bool pushedB = FALSE, leftInB = FALSE;
7649
7650           MOVA (aopGet (left, 0, FALSE, FALSE));
7651           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7652             {
7653               pushedB = pushB ();
7654               emitcode ("mov", "b,a");
7655               reg = "b";
7656               leftInB = TRUE;
7657             }
7658           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7659                   0, isOperandVolatile (result, FALSE));
7660           aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7661
7662           if (leftInB)
7663             popB (pushedB);
7664         }
7665       else
7666         {
7667           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7668                   0, isOperandVolatile (result, FALSE));
7669           aopPut (result, aopGet (left, 0, FALSE, FALSE),
7670                   1, isOperandVolatile (result, FALSE));
7671         }
7672       break;
7673     default:
7674       wassertl(FALSE, "unsupported SWAP operand size");
7675     }
7676
7677   freeAsmop (left, NULL, ic, TRUE);
7678   freeAsmop (result, NULL, ic, TRUE);
7679 }
7680
7681
7682 /*-----------------------------------------------------------------*/
7683 /* AccRol - rotate left accumulator by known count                 */
7684 /*-----------------------------------------------------------------*/
7685 static void
7686 AccRol (int shCount)
7687 {
7688   shCount &= 0x0007;            // shCount : 0..7
7689
7690   switch (shCount)
7691     {
7692     case 0:
7693       break;
7694     case 1:
7695       emitcode ("rl", "a");
7696       break;
7697     case 2:
7698       emitcode ("rl", "a");
7699       emitcode ("rl", "a");
7700       break;
7701     case 3:
7702       emitcode ("swap", "a");
7703       emitcode ("rr", "a");
7704       break;
7705     case 4:
7706       emitcode ("swap", "a");
7707       break;
7708     case 5:
7709       emitcode ("swap", "a");
7710       emitcode ("rl", "a");
7711       break;
7712     case 6:
7713       emitcode ("rr", "a");
7714       emitcode ("rr", "a");
7715       break;
7716     case 7:
7717       emitcode ("rr", "a");
7718       break;
7719     }
7720 }
7721
7722 /*-----------------------------------------------------------------*/
7723 /* AccLsh - left shift accumulator by known count                  */
7724 /*-----------------------------------------------------------------*/
7725 static void
7726 AccLsh (int shCount)
7727 {
7728   if (shCount != 0)
7729     {
7730       if (shCount == 1)
7731         emitcode ("add", "a,acc");
7732       else if (shCount == 2)
7733         {
7734           emitcode ("add", "a,acc");
7735           emitcode ("add", "a,acc");
7736         }
7737       else
7738         {
7739           /* rotate left accumulator */
7740           AccRol (shCount);
7741           /* and kill the lower order bits */
7742           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7743         }
7744     }
7745 }
7746
7747 /*-----------------------------------------------------------------*/
7748 /* AccRsh - right shift accumulator by known count                 */
7749 /*-----------------------------------------------------------------*/
7750 static void
7751 AccRsh (int shCount)
7752 {
7753   if (shCount != 0)
7754     {
7755       if (shCount == 1)
7756         {
7757           CLRC;
7758           emitcode ("rrc", "a");
7759         }
7760       else
7761         {
7762           /* rotate right accumulator */
7763           AccRol (8 - shCount);
7764           /* and kill the higher order bits */
7765           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7766         }
7767     }
7768 }
7769
7770 /*-----------------------------------------------------------------*/
7771 /* AccSRsh - signed right shift accumulator by known count                 */
7772 /*-----------------------------------------------------------------*/
7773 static void
7774 AccSRsh (int shCount)
7775 {
7776   symbol *tlbl;
7777   if (shCount != 0)
7778     {
7779       if (shCount == 1)
7780         {
7781           emitcode ("mov", "c,acc.7");
7782           emitcode ("rrc", "a");
7783         }
7784       else if (shCount == 2)
7785         {
7786           emitcode ("mov", "c,acc.7");
7787           emitcode ("rrc", "a");
7788           emitcode ("mov", "c,acc.7");
7789           emitcode ("rrc", "a");
7790         }
7791       else
7792         {
7793           tlbl = newiTempLabel (NULL);
7794           /* rotate right accumulator */
7795           AccRol (8 - shCount);
7796           /* and kill the higher order bits */
7797           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7798           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7799           emitcode ("orl", "a,#0x%02x",
7800                     (unsigned char) ~SRMask[shCount]);
7801           emitcode ("", "%05d$:", tlbl->key + 100);
7802         }
7803     }
7804 }
7805
7806 /*-----------------------------------------------------------------*/
7807 /* shiftR1Left2Result - shift right one byte from left to result   */
7808 /*-----------------------------------------------------------------*/
7809 static void
7810 shiftR1Left2Result (operand * left, int offl,
7811                     operand * result, int offr,
7812                     int shCount, int sign)
7813 {
7814   MOVA (aopGet (left, offl, FALSE, FALSE));
7815   /* shift right accumulator */
7816   if (sign)
7817     AccSRsh (shCount);
7818   else
7819     AccRsh (shCount);
7820   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7821 }
7822
7823 /*-----------------------------------------------------------------*/
7824 /* shiftL1Left2Result - shift left one byte from left to result    */
7825 /*-----------------------------------------------------------------*/
7826 static void
7827 shiftL1Left2Result (operand * left, int offl,
7828                     operand * result, int offr, int shCount)
7829 {
7830   char *l;
7831   l = aopGet (left, offl, FALSE, FALSE);
7832   MOVA (l);
7833   /* shift left accumulator */
7834   AccLsh (shCount);
7835   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7836 }
7837
7838 /*-----------------------------------------------------------------*/
7839 /* movLeft2Result - move byte from left to result                  */
7840 /*-----------------------------------------------------------------*/
7841 static void
7842 movLeft2Result (operand * left, int offl,
7843                 operand * result, int offr, int sign)
7844 {
7845   char *l;
7846   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7847     {
7848       l = aopGet (left, offl, FALSE, FALSE);
7849
7850       if (*l == '@' && (IS_AOP_PREG (result)))
7851         {
7852           emitcode ("mov", "a,%s", l);
7853           aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7854         }
7855       else
7856         {
7857           if (!sign)
7858             aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7859           else
7860             {
7861               /* MSB sign in acc.7 ! */
7862               if (getDataSize (left) == offl + 1)
7863                 {
7864                   MOVA (l);
7865                   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7866                 }
7867             }
7868         }
7869     }
7870 }
7871
7872 /*-----------------------------------------------------------------*/
7873 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7874 /*-----------------------------------------------------------------*/
7875 static void
7876 AccAXRrl1 (char *x)
7877 {
7878   emitcode ("rrc", "a");
7879   emitcode ("xch", "a,%s", x);
7880   emitcode ("rrc", "a");
7881   emitcode ("xch", "a,%s", x);
7882 }
7883
7884 /*-----------------------------------------------------------------*/
7885 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7886 /*-----------------------------------------------------------------*/
7887 static void
7888 AccAXLrl1 (char *x)
7889 {
7890   emitcode ("xch", "a,%s", x);
7891   emitcode ("rlc", "a");
7892   emitcode ("xch", "a,%s", x);
7893   emitcode ("rlc", "a");
7894 }
7895
7896 /*-----------------------------------------------------------------*/
7897 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7898 /*-----------------------------------------------------------------*/
7899 static void
7900 AccAXLsh1 (char *x)
7901 {
7902   emitcode ("xch", "a,%s", x);
7903   emitcode ("add", "a,acc");
7904   emitcode ("xch", "a,%s", x);
7905   emitcode ("rlc", "a");
7906 }
7907
7908 /*-----------------------------------------------------------------*/
7909 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7910 /*-----------------------------------------------------------------*/
7911 static void
7912 AccAXLsh (char *x, int shCount)
7913 {
7914   switch (shCount)
7915     {
7916     case 0:
7917       break;
7918     case 1:
7919       AccAXLsh1 (x);
7920       break;
7921     case 2:
7922       AccAXLsh1 (x);
7923       AccAXLsh1 (x);
7924       break;
7925     case 3:
7926     case 4:
7927     case 5:                     // AAAAABBB:CCCCCDDD
7928
7929       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7930
7931       emitcode ("anl", "a,#0x%02x",
7932                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7933
7934       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7935
7936       AccRol (shCount);         // DDDCCCCC:BBB00000
7937
7938       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7939
7940       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7941
7942       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7943
7944       emitcode ("anl", "a,#0x%02x",
7945                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7946
7947       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7948
7949       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7950
7951       break;
7952     case 6:                     // AAAAAABB:CCCCCCDD
7953       emitcode ("anl", "a,#0x%02x",
7954                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7955       emitcode ("mov", "c,acc.0");      // c = B
7956       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7957 #if 0 // REMOVE ME
7958       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7959       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7960 #else
7961       emitcode("rrc","a");
7962       emitcode("xch","a,%s", x);
7963       emitcode("rrc","a");
7964       emitcode("mov","c,acc.0"); //<< get correct bit
7965       emitcode("xch","a,%s", x);
7966
7967       emitcode("rrc","a");
7968       emitcode("xch","a,%s", x);
7969       emitcode("rrc","a");
7970       emitcode("xch","a,%s", x);
7971 #endif
7972       break;
7973     case 7:                     // a:x <<= 7
7974
7975       emitcode ("anl", "a,#0x%02x",
7976                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7977
7978       emitcode ("mov", "c,acc.0");      // c = B
7979
7980       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7981
7982       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7983
7984       break;
7985     default:
7986       break;
7987     }
7988 }
7989
7990 /*-----------------------------------------------------------------*/
7991 /* AccAXRsh - right shift a:x known count (0..7)                   */
7992 /*-----------------------------------------------------------------*/
7993 static void
7994 AccAXRsh (char *x, int shCount)
7995 {
7996   switch (shCount)
7997     {
7998     case 0:
7999       break;
8000     case 1:
8001       CLRC;
8002       AccAXRrl1 (x);            // 0->a:x
8003
8004       break;
8005     case 2:
8006       CLRC;
8007       AccAXRrl1 (x);            // 0->a:x
8008
8009       CLRC;
8010       AccAXRrl1 (x);            // 0->a:x
8011
8012       break;
8013     case 3:
8014     case 4:
8015     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8016
8017       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8018
8019       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8020
8021       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8022
8023       emitcode ("anl", "a,#0x%02x",
8024                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8025
8026       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8027
8028       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8029
8030       emitcode ("anl", "a,#0x%02x",
8031                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8032
8033       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8034
8035       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8036
8037       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8038
8039       break;
8040     case 6:                     // AABBBBBB:CCDDDDDD
8041
8042       emitcode ("mov", "c,acc.7");
8043       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8044
8045       emitcode ("mov", "c,acc.7");
8046       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8047
8048       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8049
8050       emitcode ("anl", "a,#0x%02x",
8051                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8052
8053       break;
8054     case 7:                     // ABBBBBBB:CDDDDDDD
8055
8056       emitcode ("mov", "c,acc.7");      // c = A
8057
8058       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8059
8060       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8061
8062       emitcode ("anl", "a,#0x%02x",
8063                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8064
8065       break;
8066     default:
8067       break;
8068     }
8069 }
8070
8071 /*-----------------------------------------------------------------*/
8072 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8073 /*-----------------------------------------------------------------*/
8074 static void
8075 AccAXRshS (char *x, int shCount)
8076 {
8077   symbol *tlbl;
8078   switch (shCount)
8079     {
8080     case 0:
8081       break;
8082     case 1:
8083       emitcode ("mov", "c,acc.7");
8084       AccAXRrl1 (x);            // s->a:x
8085
8086       break;
8087     case 2:
8088       emitcode ("mov", "c,acc.7");
8089       AccAXRrl1 (x);            // s->a:x
8090
8091       emitcode ("mov", "c,acc.7");
8092       AccAXRrl1 (x);            // s->a:x
8093
8094       break;
8095     case 3:
8096     case 4:
8097     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8098
8099       tlbl = newiTempLabel (NULL);
8100       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8101
8102       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8103
8104       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8105
8106       emitcode ("anl", "a,#0x%02x",
8107                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8108
8109       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8110
8111       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8112
8113       emitcode ("anl", "a,#0x%02x",
8114                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8115
8116       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8117
8118       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8119
8120       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8121
8122       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8123       emitcode ("orl", "a,#0x%02x",
8124                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8125
8126       emitcode ("", "%05d$:", tlbl->key + 100);
8127       break;                    // SSSSAAAA:BBBCCCCC
8128
8129     case 6:                     // AABBBBBB:CCDDDDDD
8130
8131       tlbl = newiTempLabel (NULL);
8132       emitcode ("mov", "c,acc.7");
8133       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8134
8135       emitcode ("mov", "c,acc.7");
8136       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8137
8138       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8139
8140       emitcode ("anl", "a,#0x%02x",
8141                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8142
8143       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8144       emitcode ("orl", "a,#0x%02x",
8145                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8146
8147       emitcode ("", "%05d$:", tlbl->key + 100);
8148       break;
8149     case 7:                     // ABBBBBBB:CDDDDDDD
8150
8151       tlbl = newiTempLabel (NULL);
8152       emitcode ("mov", "c,acc.7");      // c = A
8153
8154       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8155
8156       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8157
8158       emitcode ("anl", "a,#0x%02x",
8159                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8160
8161       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8162       emitcode ("orl", "a,#0x%02x",
8163                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8164
8165       emitcode ("", "%05d$:", tlbl->key + 100);
8166       break;
8167     default:
8168       break;
8169     }
8170 }
8171
8172 /*-----------------------------------------------------------------*/
8173 /* shiftL2Left2Result - shift left two bytes from left to result   */
8174 /*-----------------------------------------------------------------*/
8175 static void
8176 shiftL2Left2Result (operand * left, int offl,
8177                     operand * result, int offr, int shCount)
8178 {
8179   char * x;
8180   bool pushedB = FALSE;
8181   bool usedB = FALSE;
8182
8183   if (sameRegs (AOP (result), AOP (left)) &&
8184       ((offl + MSB16) == offr))
8185     {
8186       /* don't crash result[offr] */
8187       MOVA (aopGet (left, offl, FALSE, FALSE));
8188       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8189       x = aopGet (result, offr, FALSE, FALSE);
8190     }
8191   else if (aopGetUsesAcc (result, offr))
8192     {
8193       movLeft2Result (left, offl, result, offr, 0);
8194       pushedB = pushB ();
8195       usedB = TRUE;
8196       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8197       MOVA (aopGet (result, offr, FALSE, FALSE));
8198       emitcode ("xch", "a,b");
8199       x = "b";
8200     }
8201   else
8202     {
8203       movLeft2Result (left, offl, result, offr, 0);
8204       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8205       x = aopGet (result, offr, FALSE, FALSE);
8206     }
8207   /* ax << shCount (x = lsb(result)) */
8208   AccAXLsh (x, shCount);
8209   if (usedB)
8210     {
8211       emitcode ("xch", "a,b");
8212       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8213       aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8214       popB (pushedB);
8215     }
8216   else
8217     {
8218       aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8219     }
8220 }
8221
8222
8223 /*-----------------------------------------------------------------*/
8224 /* shiftR2Left2Result - shift right two bytes from left to result  */
8225 /*-----------------------------------------------------------------*/
8226 static void
8227 shiftR2Left2Result (operand * left, int offl,
8228                     operand * result, int offr,
8229                     int shCount, int sign)
8230 {
8231   char * x;
8232   bool pushedB = FALSE;
8233   bool usedB = FALSE;
8234
8235   if (sameRegs (AOP (result), AOP (left)) &&
8236       ((offl + MSB16) == offr))
8237     {
8238       /* don't crash result[offr] */
8239       MOVA (aopGet (left, offl, FALSE, FALSE));
8240       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8241       x = aopGet (result, offr, FALSE, FALSE);
8242     }
8243   else if (aopGetUsesAcc (result, offr))
8244     {
8245       movLeft2Result (left, offl, result, offr, 0);
8246       pushedB = pushB ();
8247       usedB = TRUE;
8248       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8249       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8250       x = "b";
8251     }
8252   else
8253     {
8254       movLeft2Result (left, offl, result, offr, 0);
8255       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8256       x = aopGet (result, offr, FALSE, FALSE);
8257     }
8258   /* a:x >> shCount (x = lsb(result)) */
8259   if (sign)
8260     AccAXRshS (x, shCount);
8261   else
8262     AccAXRsh (x, shCount);
8263   if (usedB)
8264     {
8265       emitcode ("xch", "a,b");
8266       aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8267       emitcode ("xch", "a,b");
8268       popB (pushedB);
8269     }
8270   if (getDataSize (result) > 1)
8271     aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8272 }
8273
8274 /*-----------------------------------------------------------------*/
8275 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8276 /*-----------------------------------------------------------------*/
8277 static void
8278 shiftLLeftOrResult (operand * left, int offl,
8279                     operand * result, int offr, int shCount)
8280 {
8281   MOVA (aopGet (left, offl, FALSE, FALSE));
8282   /* shift left accumulator */
8283   AccLsh (shCount);
8284   /* or with result */
8285   if (aopGetUsesAcc (result, offr))
8286     {
8287       emitcode ("xch", "a,b");
8288       MOVA (aopGet (result, offr, FALSE, FALSE));
8289       emitcode ("orl", "a,b");
8290     }
8291   else
8292     {
8293       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8294     }
8295   /* back to result */
8296   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8297 }
8298
8299 /*-----------------------------------------------------------------*/
8300 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8301 /*-----------------------------------------------------------------*/
8302 static void
8303 shiftRLeftOrResult (operand * left, int offl,
8304                     operand * result, int offr, int shCount)
8305 {
8306   MOVA (aopGet (left, offl, FALSE, FALSE));
8307   /* shift right accumulator */
8308   AccRsh (shCount);
8309   /* or with result */
8310   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8311   /* back to result */
8312   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8313 }
8314
8315 /*-----------------------------------------------------------------*/
8316 /* genlshOne - left shift a one byte quantity by known count       */
8317 /*-----------------------------------------------------------------*/
8318 static void
8319 genlshOne (operand * result, operand * left, int shCount)
8320 {
8321   D(emitcode (";     genlshOne",""));
8322
8323   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8324 }
8325
8326 /*-----------------------------------------------------------------*/
8327 /* genlshTwo - left shift two bytes by known amount != 0           */
8328 /*-----------------------------------------------------------------*/
8329 static void
8330 genlshTwo (operand * result, operand * left, int shCount)
8331 {
8332   int size;
8333
8334   D(emitcode (";     genlshTwo",""));
8335
8336   size = getDataSize (result);
8337
8338   /* if shCount >= 8 */
8339   if (shCount >= 8)
8340     {
8341       shCount -= 8;
8342
8343       if (size > 1)
8344         {
8345           if (shCount)
8346             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8347           else
8348             movLeft2Result (left, LSB, result, MSB16, 0);
8349         }
8350       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8351     }
8352
8353   /*  1 <= shCount <= 7 */
8354   else
8355     {
8356       if (size == 1)
8357         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8358       else
8359         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8360     }
8361 }
8362
8363 /*-----------------------------------------------------------------*/
8364 /* shiftLLong - shift left one long from left to result            */
8365 /* offl = LSB or MSB16                                             */
8366 /*-----------------------------------------------------------------*/
8367 static void
8368 shiftLLong (operand * left, operand * result, int offr)
8369 {
8370   char *l;
8371   int size = AOP_SIZE (result);
8372
8373   if (size >= LSB + offr)
8374     {
8375       l = aopGet (left, LSB, FALSE, FALSE);
8376       MOVA (l);
8377       emitcode ("add", "a,acc");
8378       if (sameRegs (AOP (left), AOP (result)) &&
8379           size >= MSB16 + offr && offr != LSB)
8380         emitcode ("xch", "a,%s",
8381                   aopGet (left, LSB + offr, FALSE, FALSE));
8382       else
8383         aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8384     }
8385
8386   if (size >= MSB16 + offr)
8387     {
8388       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8389         {
8390           l = aopGet (left, MSB16, FALSE, FALSE);
8391           MOVA (l);
8392         }
8393       emitcode ("rlc", "a");
8394       if (sameRegs (AOP (left), AOP (result)) &&
8395           size >= MSB24 + offr && offr != LSB)
8396         emitcode ("xch", "a,%s",
8397                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8398       else
8399         aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8400     }
8401
8402   if (size >= MSB24 + offr)
8403     {
8404       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8405         {
8406           l = aopGet (left, MSB24, FALSE, FALSE);
8407           MOVA (l);
8408         }
8409       emitcode ("rlc", "a");
8410       if (sameRegs (AOP (left), AOP (result)) &&
8411           size >= MSB32 + offr && offr != LSB)
8412         emitcode ("xch", "a,%s",
8413                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8414       else
8415         aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8416     }
8417
8418   if (size > MSB32 + offr)
8419     {
8420       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8421         {
8422           l = aopGet (left, MSB32, FALSE, FALSE);
8423           MOVA (l);
8424         }
8425       emitcode ("rlc", "a");
8426       aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8427     }
8428   if (offr != LSB)
8429     aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8430 }
8431
8432 /*-----------------------------------------------------------------*/
8433 /* genlshFour - shift four byte by a known amount != 0             */
8434 /*-----------------------------------------------------------------*/
8435 static void
8436 genlshFour (operand * result, operand * left, int shCount)
8437 {
8438   int size;
8439
8440   D(emitcode (";     genlshFour",""));
8441
8442   size = AOP_SIZE (result);
8443
8444   /* if shifting more that 3 bytes */
8445   if (shCount >= 24)
8446     {
8447       shCount -= 24;
8448       if (shCount)
8449         /* lowest order of left goes to the highest
8450            order of the destination */
8451         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8452       else
8453         movLeft2Result (left, LSB, result, MSB32, 0);
8454       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8455       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8456       aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8457       return;
8458     }
8459
8460   /* more than two bytes */
8461   else if (shCount >= 16)
8462     {
8463       /* lower order two bytes goes to higher order two bytes */
8464       shCount -= 16;
8465       /* if some more remaining */
8466       if (shCount)
8467         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8468       else
8469         {
8470           movLeft2Result (left, MSB16, result, MSB32, 0);
8471           movLeft2Result (left, LSB, result, MSB24, 0);
8472         }
8473       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8474       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8475       return;
8476     }
8477
8478   /* if more than 1 byte */
8479   else if (shCount >= 8)
8480     {
8481       /* lower order three bytes goes to higher order  three bytes */
8482       shCount -= 8;
8483       if (size == 2)
8484         {
8485           if (shCount)
8486             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8487           else
8488             movLeft2Result (left, LSB, result, MSB16, 0);
8489         }
8490       else
8491         {                       /* size = 4 */
8492           if (shCount == 0)
8493             {
8494               movLeft2Result (left, MSB24, result, MSB32, 0);
8495               movLeft2Result (left, MSB16, result, MSB24, 0);
8496               movLeft2Result (left, LSB, result, MSB16, 0);
8497               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8498             }
8499           else if (shCount == 1)
8500             shiftLLong (left, result, MSB16);
8501           else
8502             {
8503               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8504               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8505               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8506               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8507             }
8508         }
8509     }
8510
8511   /* 1 <= shCount <= 7 */
8512   else if (shCount <= 2)
8513     {
8514       shiftLLong (left, result, LSB);
8515       if (shCount == 2)
8516         shiftLLong (result, result, LSB);
8517     }
8518   /* 3 <= shCount <= 7, optimize */
8519   else
8520     {
8521       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8522       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8523       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8524     }
8525 }
8526
8527 /*-----------------------------------------------------------------*/
8528 /* genLeftShiftLiteral - left shifting by known count              */
8529 /*-----------------------------------------------------------------*/
8530 static void
8531 genLeftShiftLiteral (operand * left,
8532                      operand * right,
8533                      operand * result,
8534                      iCode * ic)
8535 {
8536   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8537   int size;
8538
8539   D(emitcode (";     genLeftShiftLiteral",""));
8540
8541   freeAsmop (right, NULL, ic, TRUE);
8542
8543   aopOp (left, ic, FALSE);
8544   aopOp (result, ic, FALSE);
8545
8546   size = getSize (operandType (result));
8547
8548 #if VIEW_SIZE
8549   emitcode ("; shift left ", "result %d, left %d", size,
8550             AOP_SIZE (left));
8551 #endif
8552
8553   /* I suppose that the left size >= result size */
8554   if (shCount == 0)
8555     {
8556       while (size--)
8557         {
8558           movLeft2Result (left, size, result, size, 0);
8559         }
8560     }
8561
8562   else if (shCount >= (size * 8))
8563     while (size--)
8564       aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8565   else
8566     {
8567       switch (size)
8568         {
8569         case 1:
8570           genlshOne (result, left, shCount);
8571           break;
8572
8573         case 2:
8574           genlshTwo (result, left, shCount);
8575           break;
8576
8577         case 4:
8578           genlshFour (result, left, shCount);
8579           break;
8580         default:
8581           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8582                   "*** ack! mystery literal shift!\n");
8583           break;
8584         }
8585     }
8586   freeAsmop (left, NULL, ic, TRUE);
8587   freeAsmop (result, NULL, ic, TRUE);
8588 }
8589
8590 /*-----------------------------------------------------------------*/
8591 /* genLeftShift - generates code for left shifting                 */
8592 /*-----------------------------------------------------------------*/
8593 static void
8594 genLeftShift (iCode * ic)
8595 {
8596   operand *left, *right, *result;
8597   int size, offset;
8598   char *l;
8599   symbol *tlbl, *tlbl1;
8600   bool pushedB;
8601
8602   D(emitcode (";     genLeftShift",""));
8603
8604   right = IC_RIGHT (ic);
8605   left = IC_LEFT (ic);
8606   result = IC_RESULT (ic);
8607
8608   aopOp (right, ic, FALSE);
8609
8610   /* if the shift count is known then do it
8611      as efficiently as possible */
8612   if (AOP_TYPE (right) == AOP_LIT)
8613     {
8614       genLeftShiftLiteral (left, right, result, ic);
8615       return;
8616     }
8617
8618   /* shift count is unknown then we have to form
8619      a loop get the loop count in B : Note: we take
8620      only the lower order byte since shifting
8621      more that 32 bits make no sense anyway, ( the
8622      largest size of an object can be only 32 bits ) */
8623
8624   pushedB = pushB ();
8625   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8626   emitcode ("inc", "b");
8627   freeAsmop (right, NULL, ic, TRUE);
8628   aopOp (left, ic, FALSE);
8629   aopOp (result, ic, FALSE);
8630
8631   /* now move the left to the result if they are not the same */
8632   if (!sameRegs (AOP (left), AOP (result)) &&
8633       AOP_SIZE (result) > 1)
8634     {
8635
8636       size = AOP_SIZE (result);
8637       offset = 0;
8638       while (size--)
8639         {
8640           l = aopGet (left, offset, FALSE, TRUE);
8641           if (*l == '@' && (IS_AOP_PREG (result)))
8642             {
8643
8644               emitcode ("mov", "a,%s", l);
8645               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8646             }
8647           else
8648             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8649           offset++;
8650         }
8651     }
8652
8653   tlbl = newiTempLabel (NULL);
8654   size = AOP_SIZE (result);
8655   offset = 0;
8656   tlbl1 = newiTempLabel (NULL);
8657
8658   /* if it is only one byte then */
8659   if (size == 1)
8660     {
8661       symbol *tlbl1 = newiTempLabel (NULL);
8662
8663       l = aopGet (left, 0, FALSE, FALSE);
8664       MOVA (l);
8665       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8666       emitcode ("", "%05d$:", tlbl->key + 100);
8667       emitcode ("add", "a,acc");
8668       emitcode ("", "%05d$:", tlbl1->key + 100);
8669       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8670       popB (pushedB);
8671       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8672       goto release;
8673     }
8674
8675   reAdjustPreg (AOP (result));
8676
8677   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8678   emitcode ("", "%05d$:", tlbl->key + 100);
8679   l = aopGet (result, offset, FALSE, FALSE);
8680   MOVA (l);
8681   emitcode ("add", "a,acc");
8682   aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8683   while (--size)
8684     {
8685       l = aopGet (result, offset, FALSE, FALSE);
8686       MOVA (l);
8687       emitcode ("rlc", "a");
8688       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8689     }
8690   reAdjustPreg (AOP (result));
8691
8692   emitcode ("", "%05d$:", tlbl1->key + 100);
8693   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8694   popB (pushedB);
8695 release:
8696   freeAsmop (left, NULL, ic, TRUE);
8697   freeAsmop (result, NULL, ic, TRUE);
8698 }
8699
8700 /*-----------------------------------------------------------------*/
8701 /* genrshOne - right shift a one byte quantity by known count      */
8702 /*-----------------------------------------------------------------*/
8703 static void
8704 genrshOne (operand * result, operand * left,
8705            int shCount, int sign)
8706 {
8707   D(emitcode (";     genrshOne",""));
8708
8709   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8710 }
8711
8712 /*-----------------------------------------------------------------*/
8713 /* genrshTwo - right shift two bytes by known amount != 0          */
8714 /*-----------------------------------------------------------------*/
8715 static void
8716 genrshTwo (operand * result, operand * left,
8717            int shCount, int sign)
8718 {
8719   D(emitcode (";     genrshTwo",""));
8720
8721   /* if shCount >= 8 */
8722   if (shCount >= 8)
8723     {
8724       shCount -= 8;
8725       if (shCount)
8726         shiftR1Left2Result (left, MSB16, result, LSB,
8727                             shCount, sign);
8728       else
8729         movLeft2Result (left, MSB16, result, LSB, sign);
8730       addSign (result, MSB16, sign);
8731     }
8732
8733   /*  1 <= shCount <= 7 */
8734   else
8735     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8736 }
8737
8738 /*-----------------------------------------------------------------*/
8739 /* shiftRLong - shift right one long from left to result           */
8740 /* offl = LSB or MSB16                                             */
8741 /*-----------------------------------------------------------------*/
8742 static void
8743 shiftRLong (operand * left, int offl,
8744             operand * result, int sign)
8745 {
8746   int isSameRegs = sameRegs (AOP (left), AOP (result));
8747
8748   if (isSameRegs && offl>1) {
8749     // we are in big trouble, but this shouldn't happen
8750     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8751   }
8752
8753   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8754
8755   if (offl==MSB16) {
8756     // shift is > 8
8757     if (sign) {
8758       emitcode ("rlc", "a");
8759       emitcode ("subb", "a,acc");
8760       if (isSameRegs)
8761         emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8762       else {
8763         aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8764         MOVA (aopGet (left, MSB32, FALSE, FALSE));
8765       }
8766     } else {
8767       aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8768     }
8769   }
8770
8771   if (!sign) {
8772     emitcode ("clr", "c");
8773   } else {
8774     emitcode ("mov", "c,acc.7");
8775   }
8776
8777   emitcode ("rrc", "a");
8778
8779   if (isSameRegs && offl==MSB16) {
8780     emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8781   } else {
8782     aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8783     MOVA (aopGet (left, MSB24, FALSE, FALSE));
8784   }
8785
8786   emitcode ("rrc", "a");
8787   if (isSameRegs && offl==1) {
8788     emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8789   } else {
8790     aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8791     MOVA (aopGet (left, MSB16, FALSE, FALSE));
8792   }
8793   emitcode ("rrc", "a");
8794   aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8795
8796   if (offl == LSB)
8797     {
8798       MOVA (aopGet (left, LSB, FALSE, FALSE));
8799       emitcode ("rrc", "a");
8800       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8801     }
8802 }
8803
8804 /*-----------------------------------------------------------------*/
8805 /* genrshFour - shift four byte by a known amount != 0             */
8806 /*-----------------------------------------------------------------*/
8807 static void
8808 genrshFour (operand * result, operand * left,
8809             int shCount, int sign)
8810 {
8811   D(emitcode (";     genrshFour",""));
8812
8813   /* if shifting more that 3 bytes */
8814   if (shCount >= 24)
8815     {
8816       shCount -= 24;
8817       if (shCount)
8818         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8819       else
8820         movLeft2Result (left, MSB32, result, LSB, sign);
8821       addSign (result, MSB16, sign);
8822     }
8823   else if (shCount >= 16)
8824     {
8825       shCount -= 16;
8826       if (shCount)
8827         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8828       else
8829         {
8830           movLeft2Result (left, MSB24, result, LSB, 0);
8831           movLeft2Result (left, MSB32, result, MSB16, sign);
8832         }
8833       addSign (result, MSB24, sign);
8834     }
8835   else if (shCount >= 8)
8836     {
8837       shCount -= 8;
8838       if (shCount == 1)
8839         shiftRLong (left, MSB16, result, sign);
8840       else if (shCount == 0)
8841         {
8842           movLeft2Result (left, MSB16, result, LSB, 0);
8843           movLeft2Result (left, MSB24, result, MSB16, 0);
8844           movLeft2Result (left, MSB32, result, MSB24, sign);
8845           addSign (result, MSB32, sign);
8846         }
8847       else
8848         {
8849           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8850           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8851           /* the last shift is signed */
8852           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8853           addSign (result, MSB32, sign);
8854         }
8855     }
8856   else
8857     {                           /* 1 <= shCount <= 7 */
8858       if (shCount <= 2)
8859         {
8860           shiftRLong (left, LSB, result, sign);
8861           if (shCount == 2)
8862             shiftRLong (result, LSB, result, sign);
8863         }
8864       else
8865         {
8866           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8867           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8868           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8869         }
8870     }
8871 }
8872
8873 /*-----------------------------------------------------------------*/
8874 /* genRightShiftLiteral - right shifting by known count            */
8875 /*-----------------------------------------------------------------*/
8876 static void
8877 genRightShiftLiteral (operand * left,
8878                       operand * right,
8879                       operand * result,
8880                       iCode * ic,
8881                       int sign)
8882 {
8883   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8884   int size;
8885
8886   D(emitcode (";     genRightShiftLiteral",""));
8887
8888   freeAsmop (right, NULL, ic, TRUE);
8889
8890   aopOp (left, ic, FALSE);
8891   aopOp (result, ic, FALSE);
8892
8893 #if VIEW_SIZE
8894   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8895             AOP_SIZE (left));
8896 #endif
8897
8898   size = getDataSize (left);
8899   /* test the LEFT size !!! */
8900
8901   /* I suppose that the left size >= result size */
8902   if (shCount == 0)
8903     {
8904       size = getDataSize (result);
8905       while (size--)
8906         movLeft2Result (left, size, result, size, 0);
8907     }
8908
8909   else if (shCount >= (size * 8))
8910     {
8911       if (sign) {
8912         /* get sign in acc.7 */
8913         MOVA (aopGet (left, size - 1, FALSE, FALSE));
8914       }
8915       addSign (result, LSB, sign);
8916     }
8917   else
8918     {
8919       switch (size)
8920         {
8921         case 1:
8922           genrshOne (result, left, shCount, sign);
8923           break;
8924
8925         case 2:
8926           genrshTwo (result, left, shCount, sign);
8927           break;
8928
8929         case 4:
8930           genrshFour (result, left, shCount, sign);
8931           break;
8932         default:
8933           break;
8934         }
8935     }
8936   freeAsmop (left, NULL, ic, TRUE);
8937   freeAsmop (result, NULL, ic, TRUE);
8938 }
8939
8940 /*-----------------------------------------------------------------*/
8941 /* genSignedRightShift - right shift of signed number              */
8942 /*-----------------------------------------------------------------*/
8943 static void
8944 genSignedRightShift (iCode * ic)
8945 {
8946   operand *right, *left, *result;
8947   int size, offset;
8948   char *l;
8949   symbol *tlbl, *tlbl1;
8950   bool pushedB;
8951
8952   D(emitcode (";     genSignedRightShift",""));
8953
8954   /* we do it the hard way put the shift count in b
8955      and loop thru preserving the sign */
8956
8957   right = IC_RIGHT (ic);
8958   left = IC_LEFT (ic);
8959   result = IC_RESULT (ic);
8960
8961   aopOp (right, ic, FALSE);
8962
8963
8964   if (AOP_TYPE (right) == AOP_LIT)
8965     {
8966       genRightShiftLiteral (left, right, result, ic, 1);
8967       return;
8968     }
8969   /* shift count is unknown then we have to form
8970      a loop get the loop count in B : Note: we take
8971      only the lower order byte since shifting
8972      more that 32 bits make no sense anyway, ( the
8973      largest size of an object can be only 32 bits ) */
8974
8975   pushedB = pushB ();
8976   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8977   emitcode ("inc", "b");
8978   freeAsmop (right, NULL, ic, TRUE);
8979   aopOp (left, ic, FALSE);
8980   aopOp (result, ic, FALSE);
8981
8982   /* now move the left to the result if they are not the
8983      same */
8984   if (!sameRegs (AOP (left), AOP (result)) &&
8985       AOP_SIZE (result) > 1)
8986     {
8987
8988       size = AOP_SIZE (result);
8989       offset = 0;
8990       while (size--)
8991         {
8992           l = aopGet (left, offset, FALSE, TRUE);
8993           if (*l == '@' && IS_AOP_PREG (result))
8994             {
8995
8996               emitcode ("mov", "a,%s", l);
8997               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8998             }
8999           else
9000             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9001           offset++;
9002         }
9003     }
9004
9005   /* mov the highest order bit to OVR */
9006   tlbl = newiTempLabel (NULL);
9007   tlbl1 = newiTempLabel (NULL);
9008
9009   size = AOP_SIZE (result);
9010   offset = size - 1;
9011   MOVA (aopGet (left, offset, FALSE, FALSE));
9012   emitcode ("rlc", "a");
9013   emitcode ("mov", "ov,c");
9014   /* if it is only one byte then */
9015   if (size == 1)
9016     {
9017       l = aopGet (left, 0, FALSE, FALSE);
9018       MOVA (l);
9019       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9020       emitcode ("", "%05d$:", tlbl->key + 100);
9021       emitcode ("mov", "c,ov");
9022       emitcode ("rrc", "a");
9023       emitcode ("", "%05d$:", tlbl1->key + 100);
9024       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9025       popB (pushedB);
9026       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9027       goto release;
9028     }
9029
9030   reAdjustPreg (AOP (result));
9031   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9032   emitcode ("", "%05d$:", tlbl->key + 100);
9033   emitcode ("mov", "c,ov");
9034   while (size--)
9035     {
9036       l = aopGet (result, offset, FALSE, FALSE);
9037       MOVA (l);
9038       emitcode ("rrc", "a");
9039       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9040     }
9041   reAdjustPreg (AOP (result));
9042   emitcode ("", "%05d$:", tlbl1->key + 100);
9043   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9044   popB (pushedB);
9045
9046 release:
9047   freeAsmop (left, NULL, ic, TRUE);
9048   freeAsmop (result, NULL, ic, TRUE);
9049 }
9050
9051 /*-----------------------------------------------------------------*/
9052 /* genRightShift - generate code for right shifting                */
9053 /*-----------------------------------------------------------------*/
9054 static void
9055 genRightShift (iCode * ic)
9056 {
9057   operand *right, *left, *result;
9058   sym_link *letype;
9059   int size, offset;
9060   char *l;
9061   symbol *tlbl, *tlbl1;
9062   bool pushedB;
9063
9064   D(emitcode (";     genRightShift",""));
9065
9066   /* if signed then we do it the hard way preserve the
9067      sign bit moving it inwards */
9068   letype = getSpec (operandType (IC_LEFT (ic)));
9069
9070   if (!SPEC_USIGN (letype))
9071     {
9072       genSignedRightShift (ic);
9073       return;
9074     }
9075
9076   /* signed & unsigned types are treated the same : i.e. the
9077      signed is NOT propagated inwards : quoting from the
9078      ANSI - standard : "for E1 >> E2, is equivalent to division
9079      by 2**E2 if unsigned or if it has a non-negative value,
9080      otherwise the result is implementation defined ", MY definition
9081      is that the sign does not get propagated */
9082
9083   right = IC_RIGHT (ic);
9084   left = IC_LEFT (ic);
9085   result = IC_RESULT (ic);
9086
9087   aopOp (right, ic, FALSE);
9088
9089   /* if the shift count is known then do it
9090      as efficiently as possible */
9091   if (AOP_TYPE (right) == AOP_LIT)
9092     {
9093       genRightShiftLiteral (left, right, result, ic, 0);
9094       return;
9095     }
9096
9097   /* shift count is unknown then we have to form
9098      a loop get the loop count in B : Note: we take
9099      only the lower order byte since shifting
9100      more that 32 bits make no sense anyway, ( the
9101      largest size of an object can be only 32 bits ) */
9102
9103   pushedB = pushB ();
9104   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9105   emitcode ("inc", "b");
9106   freeAsmop (right, NULL, ic, TRUE);
9107   aopOp (left, ic, FALSE);
9108   aopOp (result, ic, FALSE);
9109
9110   /* now move the left to the result if they are not the
9111      same */
9112   if (!sameRegs (AOP (left), AOP (result)) &&
9113       AOP_SIZE (result) > 1)
9114     {
9115
9116       size = AOP_SIZE (result);
9117       offset = 0;
9118       while (size--)
9119         {
9120           l = aopGet (left, offset, FALSE, TRUE);
9121           if (*l == '@' && IS_AOP_PREG (result))
9122             {
9123
9124               emitcode ("mov", "a,%s", l);
9125               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9126             }
9127           else
9128             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9129           offset++;
9130         }
9131     }
9132
9133   tlbl = newiTempLabel (NULL);
9134   tlbl1 = newiTempLabel (NULL);
9135   size = AOP_SIZE (result);
9136   offset = size - 1;
9137
9138   /* if it is only one byte then */
9139   if (size == 1)
9140     {
9141       l = aopGet (left, 0, FALSE, FALSE);
9142       MOVA (l);
9143       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9144       emitcode ("", "%05d$:", tlbl->key + 100);
9145       CLRC;
9146       emitcode ("rrc", "a");
9147       emitcode ("", "%05d$:", tlbl1->key + 100);
9148       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9149       popB (pushedB);
9150       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9151       goto release;
9152     }
9153
9154   reAdjustPreg (AOP (result));
9155   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9156   emitcode ("", "%05d$:", tlbl->key + 100);
9157   CLRC;
9158   while (size--)
9159     {
9160       l = aopGet (result, offset, FALSE, FALSE);
9161       MOVA (l);
9162       emitcode ("rrc", "a");
9163       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9164     }
9165   reAdjustPreg (AOP (result));
9166
9167   emitcode ("", "%05d$:", tlbl1->key + 100);
9168   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9169   popB (pushedB);
9170
9171 release:
9172   freeAsmop (left, NULL, ic, TRUE);
9173   freeAsmop (result, NULL, ic, TRUE);
9174 }
9175
9176 /*-----------------------------------------------------------------*/
9177 /* emitPtrByteGet - emits code to get a byte into A through a      */
9178 /*                  pointer register (R0, R1, or DPTR). The        */
9179 /*                  original value of A can be preserved in B.     */
9180 /*-----------------------------------------------------------------*/
9181 static void
9182 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9183 {
9184   switch (p_type)
9185     {
9186     case IPOINTER:
9187     case POINTER:
9188       if (preserveAinB)
9189         emitcode ("mov", "b,a");
9190       emitcode ("mov", "a,@%s", rname);
9191       break;
9192
9193     case PPOINTER:
9194       if (preserveAinB)
9195         emitcode ("mov", "b,a");
9196       emitcode ("movx", "a,@%s", rname);
9197       break;
9198
9199     case FPOINTER:
9200       if (preserveAinB)
9201         emitcode ("mov", "b,a");
9202       emitcode ("movx", "a,@dptr");
9203       break;
9204
9205     case CPOINTER:
9206       if (preserveAinB)
9207         emitcode ("mov", "b,a");
9208       emitcode ("clr", "a");
9209       emitcode ("movc", "a,@a+dptr");
9210       break;
9211
9212     case GPOINTER:
9213       if (preserveAinB)
9214         {
9215           emitcode ("push", "b");
9216           emitcode ("push", "acc");
9217         }
9218       emitcode ("lcall", "__gptrget");
9219       if (preserveAinB)
9220         emitcode ("pop", "b");
9221       break;
9222     }
9223 }
9224
9225 /*-----------------------------------------------------------------*/
9226 /* emitPtrByteSet - emits code to set a byte from src through a    */
9227 /*                  pointer register (R0, R1, or DPTR).            */
9228 /*-----------------------------------------------------------------*/
9229 static void
9230 emitPtrByteSet (char *rname, int p_type, char *src)
9231 {
9232   switch (p_type)
9233     {
9234     case IPOINTER:
9235     case POINTER:
9236       if (*src=='@')
9237         {
9238           MOVA (src);
9239           emitcode ("mov", "@%s,a", rname);
9240         }
9241       else
9242         emitcode ("mov", "@%s,%s", rname, src);
9243       break;
9244
9245     case PPOINTER:
9246       MOVA (src);
9247       emitcode ("movx", "@%s,a", rname);
9248       break;
9249
9250     case FPOINTER:
9251       MOVA (src);
9252       emitcode ("movx", "@dptr,a");
9253       break;
9254
9255     case GPOINTER:
9256       MOVA (src);
9257       emitcode ("lcall", "__gptrput");
9258       break;
9259     }
9260 }
9261
9262 /*-----------------------------------------------------------------*/
9263 /* genUnpackBits - generates code for unpacking bits               */
9264 /*-----------------------------------------------------------------*/
9265 static void
9266 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9267 {
9268   int offset = 0;       /* result byte offset */
9269   int rsize;            /* result size */
9270   int rlen = 0;         /* remaining bitfield length */
9271   sym_link *etype;      /* bitfield type information */
9272   int blen;             /* bitfield length */
9273   int bstr;             /* bitfield starting bit within byte */
9274   char buffer[10];
9275
9276   D(emitcode (";     genUnpackBits",""));
9277
9278   etype = getSpec (operandType (result));
9279   rsize = getSize (operandType (result));
9280   blen = SPEC_BLEN (etype);
9281   bstr = SPEC_BSTR (etype);
9282
9283   if (ifx && blen <= 8)
9284     {
9285       emitPtrByteGet (rname, ptype, FALSE);
9286       if (blen == 1)
9287         {
9288           SNPRINTF (buffer, sizeof(buffer),
9289                     "acc.%d", bstr);
9290           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9291         }
9292       else
9293         {
9294           if (blen < 8)
9295             emitcode ("anl", "a,#0x%02x",
9296                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9297           genIfxJump (ifx, "a", NULL, NULL, NULL);
9298         }
9299       return;
9300     }
9301   wassert (!ifx);
9302
9303   /* If the bitfield length is less than a byte */
9304   if (blen < 8)
9305     {
9306       emitPtrByteGet (rname, ptype, FALSE);
9307       AccRol (8 - bstr);
9308       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9309       if (!SPEC_USIGN (etype))
9310         {
9311           /* signed bitfield */
9312           symbol *tlbl = newiTempLabel (NULL);
9313
9314           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9315           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9316           emitcode ("", "%05d$:", tlbl->key + 100);
9317         }
9318       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9319       goto finish;
9320     }
9321
9322   /* Bit field did not fit in a byte. Copy all
9323      but the partial byte at the end.  */
9324   for (rlen=blen;rlen>=8;rlen-=8)
9325     {
9326       emitPtrByteGet (rname, ptype, FALSE);
9327       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9328       if (rlen>8)
9329         emitcode ("inc", "%s", rname);
9330     }
9331
9332   /* Handle the partial byte at the end */
9333   if (rlen)
9334     {
9335       emitPtrByteGet (rname, ptype, FALSE);
9336       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9337       if (!SPEC_USIGN (etype))
9338         {
9339           /* signed bitfield */
9340           symbol *tlbl = newiTempLabel (NULL);
9341
9342           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9343           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9344           emitcode ("", "%05d$:", tlbl->key + 100);
9345         }
9346       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9347     }
9348
9349 finish:
9350   if (offset < rsize)
9351     {
9352       char *source;
9353
9354       if (SPEC_USIGN (etype))
9355         source = zero;
9356       else
9357         {
9358           /* signed bitfield: sign extension with 0x00 or 0xff */
9359           emitcode ("rlc", "a");
9360           emitcode ("subb", "a,acc");
9361
9362           source = "a";
9363         }
9364       rsize -= offset;
9365       while (rsize--)
9366         aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9367     }
9368 }
9369
9370
9371 /*-----------------------------------------------------------------*/
9372 /* genDataPointerGet - generates code when ptr offset is known     */
9373 /*-----------------------------------------------------------------*/
9374 static void
9375 genDataPointerGet (operand * left,
9376                    operand * result,
9377                    iCode * ic)
9378 {
9379   char *l;
9380   char buffer[256];
9381   int size, offset = 0;
9382
9383   D(emitcode (";     genDataPointerGet",""));
9384
9385   aopOp (result, ic, TRUE);
9386
9387   /* get the string representation of the name */
9388   l = aopGet (left, 0, FALSE, TRUE);
9389   size = AOP_SIZE (result);
9390   while (size--)
9391     {
9392       if (offset)
9393         sprintf (buffer, "(%s + %d)", l + 1, offset);
9394       else
9395         sprintf (buffer, "%s", l + 1);
9396       aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9397     }
9398
9399   freeAsmop (left, NULL, ic, TRUE);
9400   freeAsmop (result, NULL, ic, TRUE);
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* genNearPointerGet - emitcode for near pointer fetch             */
9405 /*-----------------------------------------------------------------*/
9406 static void
9407 genNearPointerGet (operand * left,
9408                    operand * result,
9409                    iCode * ic,
9410                    iCode * pi,
9411                    iCode * ifx)
9412 {
9413   asmop *aop = NULL;
9414   regs *preg = NULL;
9415   char *rname;
9416   sym_link *rtype, *retype;
9417   sym_link *ltype = operandType (left);
9418   char buffer[80];
9419
9420   D(emitcode (";     genNearPointerGet",""));
9421
9422   rtype = operandType (result);
9423   retype = getSpec (rtype);
9424
9425   aopOp (left, ic, FALSE);
9426
9427   /* if left is rematerialisable and
9428      result is not bitfield variable type and
9429      the left is pointer to data space i.e
9430      lower 128 bytes of space */
9431   if (AOP_TYPE (left) == AOP_IMMD &&
9432       !IS_BITFIELD (retype) &&
9433       DCL_TYPE (ltype) == POINTER)
9434     {
9435       genDataPointerGet (left, result, ic);
9436       return;
9437     }
9438
9439  /* if the value is already in a pointer register
9440      then don't need anything more */
9441   if (!AOP_INPREG (AOP (left)))
9442     {
9443       if (IS_AOP_PREG (left))
9444         {
9445           // Aha, it is a pointer, just in disguise.
9446           rname = aopGet (left, 0, FALSE, FALSE);
9447           if (*rname != '@')
9448             {
9449               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9450                       __FILE__, __LINE__);
9451             }
9452           else
9453             {
9454               // Expected case.
9455               emitcode ("mov", "a%s,%s", rname + 1, rname);
9456               rname++;  // skip the '@'.
9457             }
9458         }
9459       else
9460         {
9461           /* otherwise get a free pointer register */
9462           aop = newAsmop (0);
9463           preg = getFreePtr (ic, &aop, FALSE);
9464           emitcode ("mov", "%s,%s",
9465                     preg->name,
9466                     aopGet (left, 0, FALSE, TRUE));
9467           rname = preg->name;
9468         }
9469     }
9470   else
9471     rname = aopGet (left, 0, FALSE, FALSE);
9472
9473   //aopOp (result, ic, FALSE);
9474   aopOp (result, ic, result?TRUE:FALSE);
9475
9476   /* if bitfield then unpack the bits */
9477   if (IS_BITFIELD (retype))
9478     genUnpackBits (result, rname, POINTER, ifx);
9479   else
9480     {
9481       /* we have can just get the values */
9482       int size = AOP_SIZE (result);
9483       int offset = 0;
9484
9485       while (size--)
9486         {
9487           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9488             {
9489
9490               emitcode ("mov", "a,@%s", rname);
9491               if (!ifx)
9492               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9493             }
9494           else
9495             {
9496               sprintf (buffer, "@%s", rname);
9497               aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9498             }
9499           offset++;
9500           if (size || pi)
9501             emitcode ("inc", "%s", rname);
9502         }
9503     }
9504
9505   /* now some housekeeping stuff */
9506   if (aop)       /* we had to allocate for this iCode */
9507     {
9508       if (pi) { /* post increment present */
9509         aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9510       }
9511       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9512     }
9513   else
9514     {
9515       /* we did not allocate which means left
9516          already in a pointer register, then
9517          if size > 0 && this could be used again
9518          we have to point it back to where it
9519          belongs */
9520       if ((AOP_SIZE (result) > 1 &&
9521            !OP_SYMBOL (left)->remat &&
9522            (OP_SYMBOL (left)->liveTo > ic->seq ||
9523             ic->depth)) &&
9524           !pi)
9525         {
9526           int size = AOP_SIZE (result) - 1;
9527           while (size--)
9528             emitcode ("dec", "%s", rname);
9529         }
9530     }
9531
9532   if (ifx && !ifx->generated)
9533     {
9534       genIfxJump (ifx, "a", left, NULL, result);
9535     }
9536
9537   /* done */
9538   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9539   freeAsmop (left, NULL, ic, TRUE);
9540   if (pi) pi->generated = 1;
9541 }
9542
9543 /*-----------------------------------------------------------------*/
9544 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9545 /*-----------------------------------------------------------------*/
9546 static void
9547 genPagedPointerGet (operand * left,
9548                     operand * result,
9549                     iCode * ic,
9550                     iCode *pi,
9551                     iCode *ifx)
9552 {
9553   asmop *aop = NULL;
9554   regs *preg = NULL;
9555   char *rname;
9556   sym_link *rtype, *retype;
9557
9558   D(emitcode (";     genPagedPointerGet",""));
9559
9560   rtype = operandType (result);
9561   retype = getSpec (rtype);
9562
9563   aopOp (left, ic, FALSE);
9564
9565   /* if the value is already in a pointer register
9566      then don't need anything more */
9567   if (!AOP_INPREG (AOP (left)))
9568     {
9569       /* otherwise get a free pointer register */
9570       aop = newAsmop (0);
9571       preg = getFreePtr (ic, &aop, FALSE);
9572       emitcode ("mov", "%s,%s",
9573                 preg->name,
9574                 aopGet (left, 0, FALSE, TRUE));
9575       rname = preg->name;
9576     }
9577   else
9578     rname = aopGet (left, 0, FALSE, FALSE);
9579
9580   aopOp (result, ic, FALSE);
9581
9582   /* if bitfield then unpack the bits */
9583   if (IS_BITFIELD (retype))
9584     genUnpackBits (result, rname, PPOINTER, ifx);
9585   else
9586     {
9587       /* we have can just get the values */
9588       int size = AOP_SIZE (result);
9589       int offset = 0;
9590
9591       while (size--)
9592         {
9593
9594           emitcode ("movx", "a,@%s", rname);
9595           if (!ifx)
9596           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9597
9598           offset++;
9599
9600           if (size || pi)
9601             emitcode ("inc", "%s", rname);
9602         }
9603     }
9604
9605   /* now some housekeeping stuff */
9606   if (aop) /* we had to allocate for this iCode */
9607     {
9608       if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9609       freeAsmop (NULL, aop, ic, TRUE);
9610     }
9611   else
9612     {
9613       /* we did not allocate which means left
9614          already in a pointer register, then
9615          if size > 0 && this could be used again
9616          we have to point it back to where it
9617          belongs */
9618       if ((AOP_SIZE (result) > 1 &&
9619            !OP_SYMBOL (left)->remat &&
9620            (OP_SYMBOL (left)->liveTo > ic->seq ||
9621             ic->depth)) &&
9622           !pi)
9623         {
9624           int size = AOP_SIZE (result) - 1;
9625           while (size--)
9626             emitcode ("dec", "%s", rname);
9627         }
9628     }
9629
9630   if (ifx && !ifx->generated)
9631     {
9632       genIfxJump (ifx, "a", left, NULL, result);
9633     }
9634
9635   /* done */
9636   freeAsmop (left, NULL, ic, TRUE);
9637   freeAsmop (result, NULL, ic, TRUE);
9638   if (pi) pi->generated = 1;
9639
9640 }
9641
9642 /*--------------------------------------------------------------------*/
9643 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9644 /*--------------------------------------------------------------------*/
9645 static void
9646 loadDptrFromOperand (operand *op, bool loadBToo)
9647 {
9648   if (AOP_TYPE (op) != AOP_STR)
9649     {
9650       /* if this is rematerializable */
9651       if (AOP_TYPE (op) == AOP_IMMD)
9652         {
9653           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9654           if (loadBToo)
9655             {
9656               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9657                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9658               else
9659                 {
9660                   wassertl(FALSE, "need pointerCode");
9661                   emitcode ("", "; mov b,???");
9662                   /* genPointerGet and genPointerSet originally did different
9663                   ** things for this case. Both seem wrong.
9664                   ** from genPointerGet:
9665                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9666                   ** from genPointerSet:
9667                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9668                   */
9669                 }
9670             }
9671         }
9672       else if (AOP_TYPE (op) == AOP_DPTR)
9673         {
9674           if (loadBToo)
9675             {
9676               MOVA (aopGet (op, 0, FALSE, FALSE));
9677               emitcode ("push", "acc");
9678               MOVA (aopGet (op, 1, FALSE, FALSE));
9679               emitcode ("push", "acc");
9680               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9681               emitcode ("pop", "dph");
9682               emitcode ("pop", "dpl");
9683             }
9684           else
9685             {
9686               MOVA (aopGet (op, 0, FALSE, FALSE));
9687               emitcode ("push", "acc");
9688               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9689               emitcode ("pop", "dpl");
9690             }
9691         }
9692       else
9693         {                       /* we need to get it byte by byte */
9694           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9695           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9696           if (loadBToo)
9697             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9698         }
9699     }
9700 }
9701
9702 /*-----------------------------------------------------------------*/
9703 /* genFarPointerGet - gget value from far space                    */
9704 /*-----------------------------------------------------------------*/
9705 static void
9706 genFarPointerGet (operand * left,
9707                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9708 {
9709   int size, offset;
9710   sym_link *retype = getSpec (operandType (result));
9711
9712   D(emitcode (";     genFarPointerGet",""));
9713
9714   aopOp (left, ic, FALSE);
9715   loadDptrFromOperand (left, FALSE);
9716
9717   /* so dptr now contains the address */
9718   aopOp (result, ic, FALSE);
9719
9720   /* if bit then unpack */
9721   if (IS_BITFIELD (retype))
9722     genUnpackBits (result, "dptr", FPOINTER, ifx);
9723   else
9724     {
9725       size = AOP_SIZE (result);
9726       offset = 0;
9727
9728       while (size--)
9729         {
9730           emitcode ("movx", "a,@dptr");
9731           if (!ifx)
9732             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9733           if (size || pi)
9734             emitcode ("inc", "dptr");
9735         }
9736     }
9737
9738   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9739     {
9740     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9741     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9742     pi->generated = 1;
9743   }
9744
9745   if (ifx && !ifx->generated)
9746     {
9747       genIfxJump (ifx, "a", left, NULL, result);
9748     }
9749
9750   freeAsmop (left, NULL, ic, TRUE);
9751   freeAsmop (result, NULL, ic, TRUE);
9752 }
9753
9754 /*-----------------------------------------------------------------*/
9755 /* genCodePointerGet - gget value from code space                  */
9756 /*-----------------------------------------------------------------*/
9757 static void
9758 genCodePointerGet (operand * left,
9759                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9760 {
9761   int size, offset;
9762   sym_link *retype = getSpec (operandType (result));
9763
9764   D(emitcode (";     genCodePointerGet",""));
9765
9766   aopOp (left, ic, FALSE);
9767   loadDptrFromOperand (left, FALSE);
9768
9769   /* so dptr now contains the address */
9770   aopOp (result, ic, FALSE);
9771
9772   /* if bit then unpack */
9773   if (IS_BITFIELD (retype))
9774     genUnpackBits (result, "dptr", CPOINTER, ifx);
9775   else
9776     {
9777       size = AOP_SIZE (result);
9778       offset = 0;
9779
9780       while (size--)
9781         {
9782           if (pi)
9783             {
9784               emitcode ("clr", "a");
9785               emitcode ("movc", "a,@a+dptr");
9786               if (!ifx)
9787               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9788               emitcode ("inc", "dptr");
9789             }
9790           else
9791             {
9792               emitcode ("mov", "a,#0x%02x", offset);
9793               emitcode ("movc", "a,@a+dptr");
9794               if (!ifx)
9795               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9796             }
9797         }
9798     }
9799
9800   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9801     {
9802     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9803     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9804     pi->generated = 1;
9805   }
9806
9807   if (ifx && !ifx->generated)
9808     {
9809       genIfxJump (ifx, "a", left, NULL, result);
9810     }
9811
9812   freeAsmop (left, NULL, ic, TRUE);
9813   freeAsmop (result, NULL, ic, TRUE);
9814 }
9815
9816 /*-----------------------------------------------------------------*/
9817 /* genGenPointerGet - gget value from generic pointer space        */
9818 /*-----------------------------------------------------------------*/
9819 static void
9820 genGenPointerGet (operand * left,
9821                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9822 {
9823   int size, offset;
9824   sym_link *retype = getSpec (operandType (result));
9825
9826   D(emitcode (";     genGenPointerGet",""));
9827
9828   aopOp (left, ic, FALSE);
9829   loadDptrFromOperand (left, TRUE);
9830
9831   /* so dptr know contains the address */
9832   aopOp (result, ic, FALSE);
9833
9834   /* if bit then unpack */
9835   if (IS_BITFIELD (retype))
9836     genUnpackBits (result, "dptr", GPOINTER, ifx);
9837   else
9838     {
9839       size = AOP_SIZE (result);
9840       offset = 0;
9841
9842       while (size--)
9843         {
9844           emitcode ("lcall", "__gptrget");
9845           if (!ifx)
9846           aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9847           if (size || pi)
9848             emitcode ("inc", "dptr");
9849         }
9850     }
9851
9852   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9853     {
9854     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9855     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9856     pi->generated = 1;
9857   }
9858
9859   if (ifx && !ifx->generated)
9860     {
9861       genIfxJump (ifx, "a", left, NULL, result);
9862     }
9863
9864
9865   freeAsmop (left, NULL, ic, TRUE);
9866   freeAsmop (result, NULL, ic, TRUE);
9867 }
9868
9869 /*-----------------------------------------------------------------*/
9870 /* genPointerGet - generate code for pointer get                   */
9871 /*-----------------------------------------------------------------*/
9872 static void
9873 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9874 {
9875   operand *left, *result;
9876   sym_link *type, *etype;
9877   int p_type;
9878
9879   D(emitcode (";     genPointerGet",""));
9880
9881   left = IC_LEFT (ic);
9882   result = IC_RESULT (ic);
9883
9884   if (getSize (operandType (result))>1)
9885     ifx = NULL;
9886
9887   /* depending on the type of pointer we need to
9888      move it to the correct pointer register */
9889   type = operandType (left);
9890   etype = getSpec (type);
9891   /* if left is of type of pointer then it is simple */
9892   if (IS_PTR (type) && !IS_FUNC (type->next))
9893     p_type = DCL_TYPE (type);
9894   else
9895     {
9896       /* we have to go by the storage class */
9897       p_type = PTR_TYPE (SPEC_OCLS (etype));
9898     }
9899
9900   /* special case when cast remat */
9901   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9902       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9903           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9904           type = operandType (left);
9905           p_type = DCL_TYPE (type);
9906   }
9907   /* now that we have the pointer type we assign
9908      the pointer values */
9909   switch (p_type)
9910     {
9911
9912     case POINTER:
9913     case IPOINTER:
9914       genNearPointerGet (left, result, ic, pi, ifx);
9915       break;
9916
9917     case PPOINTER:
9918       genPagedPointerGet (left, result, ic, pi, ifx);
9919       break;
9920
9921     case FPOINTER:
9922       genFarPointerGet (left, result, ic, pi, ifx);
9923       break;
9924
9925     case CPOINTER:
9926       genCodePointerGet (left, result, ic, pi, ifx);
9927       break;
9928
9929     case GPOINTER:
9930       genGenPointerGet (left, result, ic, pi, ifx);
9931       break;
9932     }
9933
9934 }
9935
9936
9937
9938 /*-----------------------------------------------------------------*/
9939 /* genPackBits - generates code for packed bit storage             */
9940 /*-----------------------------------------------------------------*/
9941 static void
9942 genPackBits (sym_link * etype,
9943              operand * right,
9944              char *rname, int p_type)
9945 {
9946   int offset = 0;       /* source byte offset */
9947   int rlen = 0;         /* remaining bitfield length */
9948   int blen;             /* bitfield length */
9949   int bstr;             /* bitfield starting bit within byte */
9950   int litval;           /* source literal value (if AOP_LIT) */
9951   unsigned char mask;   /* bitmask within current byte */
9952
9953   D(emitcode (";     genPackBits",""));
9954
9955   blen = SPEC_BLEN (etype);
9956   bstr = SPEC_BSTR (etype);
9957
9958   /* If the bitfield length is less than a byte */
9959   if (blen < 8)
9960     {
9961       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9962               (unsigned char) (0xFF >> (8 - bstr)));
9963
9964       if (AOP_TYPE (right) == AOP_LIT)
9965         {
9966           /* Case with a bitfield length <8 and literal source
9967           */
9968           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9969           litval <<= bstr;
9970           litval &= (~mask) & 0xff;
9971           emitPtrByteGet (rname, p_type, FALSE);
9972           if ((mask|litval)!=0xff)
9973             emitcode ("anl","a,#0x%02x", mask);
9974           if (litval)
9975             emitcode ("orl","a,#0x%02x", litval);
9976         }
9977       else
9978         {
9979           if ((blen==1) && (p_type!=GPOINTER))
9980             {
9981               /* Case with a bitfield length == 1 and no generic pointer
9982               */
9983               if (AOP_TYPE (right) == AOP_CRY)
9984                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9985               else
9986                 {
9987                   MOVA (aopGet (right, 0, FALSE, FALSE));
9988                   emitcode ("rrc","a");
9989                 }
9990               emitPtrByteGet (rname, p_type, FALSE);
9991               emitcode ("mov","acc.%d,c",bstr);
9992             }
9993           else
9994             {
9995               bool pushedB;
9996               /* Case with a bitfield length < 8 and arbitrary source
9997               */
9998               MOVA (aopGet (right, 0, FALSE, FALSE));
9999               /* shift and mask source value */
10000               AccLsh (bstr);
10001               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10002
10003               pushedB = pushB ();
10004               /* transfer A to B and get next byte */
10005               emitPtrByteGet (rname, p_type, TRUE);
10006
10007               emitcode ("anl", "a,#0x%02x", mask);
10008               emitcode ("orl", "a,b");
10009               if (p_type == GPOINTER)
10010                 emitcode ("pop", "b");
10011
10012               popB (pushedB);
10013            }
10014         }
10015
10016       emitPtrByteSet (rname, p_type, "a");
10017       return;
10018     }
10019
10020   /* Bit length is greater than 7 bits. In this case, copy  */
10021   /* all except the partial byte at the end                 */
10022   for (rlen=blen;rlen>=8;rlen-=8)
10023     {
10024       emitPtrByteSet (rname, p_type,
10025                       aopGet (right, offset++, FALSE, TRUE) );
10026       if (rlen>8)
10027         emitcode ("inc", "%s", rname);
10028     }
10029
10030   /* If there was a partial byte at the end */
10031   if (rlen)
10032     {
10033       mask = (((unsigned char) -1 << rlen) & 0xff);
10034
10035       if (AOP_TYPE (right) == AOP_LIT)
10036         {
10037           /* Case with partial byte and literal source
10038           */
10039           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10040           litval >>= (blen-rlen);
10041           litval &= (~mask) & 0xff;
10042           emitPtrByteGet (rname, p_type, FALSE);
10043           if ((mask|litval)!=0xff)
10044             emitcode ("anl","a,#0x%02x", mask);
10045           if (litval)
10046             emitcode ("orl","a,#0x%02x", litval);
10047         }
10048       else
10049         {
10050           bool pushedB;
10051           /* Case with partial byte and arbitrary source
10052           */
10053           MOVA (aopGet (right, offset++, FALSE, FALSE));
10054           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10055
10056           pushedB = pushB ();
10057           /* transfer A to B and get next byte */
10058           emitPtrByteGet (rname, p_type, TRUE);
10059
10060           emitcode ("anl", "a,#0x%02x", mask);
10061           emitcode ("orl", "a,b");
10062           if (p_type == GPOINTER)
10063             emitcode ("pop", "b");
10064
10065           popB (pushedB);
10066         }
10067       emitPtrByteSet (rname, p_type, "a");
10068     }
10069
10070 }
10071
10072
10073 /*-----------------------------------------------------------------*/
10074 /* genDataPointerSet - remat pointer to data space                 */
10075 /*-----------------------------------------------------------------*/
10076 static void
10077 genDataPointerSet (operand * right,
10078                    operand * result,
10079                    iCode * ic)
10080 {
10081   int size, offset = 0;
10082   char *l, buffer[256];
10083
10084   D(emitcode (";     genDataPointerSet",""));
10085
10086   aopOp (right, ic, FALSE);
10087
10088   l = aopGet (result, 0, FALSE, TRUE);
10089   size = AOP_SIZE (right);
10090   while (size--)
10091     {
10092       if (offset)
10093         sprintf (buffer, "(%s + %d)", l + 1, offset);
10094       else
10095         sprintf (buffer, "%s", l + 1);
10096       emitcode ("mov", "%s,%s", buffer,
10097                 aopGet (right, offset++, FALSE, FALSE));
10098     }
10099
10100   freeAsmop (right, NULL, ic, TRUE);
10101   freeAsmop (result, NULL, ic, TRUE);
10102 }
10103
10104 /*-----------------------------------------------------------------*/
10105 /* genNearPointerSet - emitcode for near pointer put                */
10106 /*-----------------------------------------------------------------*/
10107 static void
10108 genNearPointerSet (operand * right,
10109                    operand * result,
10110                    iCode * ic,
10111                    iCode * pi)
10112 {
10113   asmop *aop = NULL;
10114   regs *preg = NULL;
10115   char *rname, *l;
10116   sym_link *retype, *letype;
10117   sym_link *ptype = operandType (result);
10118
10119   D(emitcode (";     genNearPointerSet",""));
10120
10121   retype = getSpec (operandType (right));
10122   letype = getSpec (ptype);
10123   aopOp (result, ic, FALSE);
10124
10125   /* if the result is rematerializable &
10126      in data space & not a bit variable */
10127   if (AOP_TYPE (result) == AOP_IMMD &&
10128       DCL_TYPE (ptype) == POINTER &&
10129       !IS_BITVAR (retype) &&
10130       !IS_BITVAR (letype))
10131     {
10132       genDataPointerSet (right, result, ic);
10133       return;
10134     }
10135
10136   /* if the value is already in a pointer register
10137      then don't need anything more */
10138   if (!AOP_INPREG (AOP (result)))
10139     {
10140         if (
10141             //AOP_TYPE (result) == AOP_STK
10142             IS_AOP_PREG(result)
10143             )
10144         {
10145             // Aha, it is a pointer, just in disguise.
10146             rname = aopGet (result, 0, FALSE, FALSE);
10147             if (*rname != '@')
10148             {
10149                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10150                         __FILE__, __LINE__);
10151             }
10152             else
10153             {
10154                 // Expected case.
10155                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10156                 rname++;  // skip the '@'.
10157             }
10158         }
10159         else
10160         {
10161             /* otherwise get a free pointer register */
10162             aop = newAsmop (0);
10163             preg = getFreePtr (ic, &aop, FALSE);
10164             emitcode ("mov", "%s,%s",
10165                       preg->name,
10166                       aopGet (result, 0, FALSE, TRUE));
10167             rname = preg->name;
10168         }
10169     }
10170     else
10171     {
10172         rname = aopGet (result, 0, FALSE, FALSE);
10173     }
10174
10175   aopOp (right, ic, FALSE);
10176
10177   /* if bitfield then unpack the bits */
10178   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10179     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10180   else
10181     {
10182       /* we have can just get the values */
10183       int size = AOP_SIZE (right);
10184       int offset = 0;
10185
10186       while (size--)
10187         {
10188           l = aopGet (right, offset, FALSE, TRUE);
10189           if (*l == '@')
10190             {
10191               MOVA (l);
10192               emitcode ("mov", "@%s,a", rname);
10193             }
10194           else
10195             emitcode ("mov", "@%s,%s", rname, l);
10196           if (size || pi)
10197             emitcode ("inc", "%s", rname);
10198           offset++;
10199         }
10200     }
10201
10202   /* now some housekeeping stuff */
10203   if (aop) /* we had to allocate for this iCode */
10204     {
10205       if (pi)
10206         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10207       freeAsmop (NULL, aop, ic, TRUE);
10208     }
10209   else
10210     {
10211       /* we did not allocate which means left
10212          already in a pointer register, then
10213          if size > 0 && this could be used again
10214          we have to point it back to where it
10215          belongs */
10216       if ((AOP_SIZE (right) > 1 &&
10217            !OP_SYMBOL (result)->remat &&
10218            (OP_SYMBOL (result)->liveTo > ic->seq ||
10219             ic->depth)) &&
10220           !pi)
10221         {
10222           int size = AOP_SIZE (right) - 1;
10223           while (size--)
10224             emitcode ("dec", "%s", rname);
10225         }
10226     }
10227
10228   /* done */
10229   if (pi) pi->generated = 1;
10230   freeAsmop (result, NULL, ic, TRUE);
10231   freeAsmop (right, NULL, ic, TRUE);
10232 }
10233
10234 /*-----------------------------------------------------------------*/
10235 /* genPagedPointerSet - emitcode for Paged pointer put             */
10236 /*-----------------------------------------------------------------*/
10237 static void
10238 genPagedPointerSet (operand * right,
10239                     operand * result,
10240                     iCode * ic,
10241                     iCode * pi)
10242 {
10243   asmop *aop = NULL;
10244   regs *preg = NULL;
10245   char *rname, *l;
10246   sym_link *retype, *letype;
10247
10248   D(emitcode (";     genPagedPointerSet",""));
10249
10250   retype = getSpec (operandType (right));
10251   letype = getSpec (operandType (result));
10252
10253   aopOp (result, ic, FALSE);
10254
10255   /* if the value is already in a pointer register
10256      then don't need anything more */
10257   if (!AOP_INPREG (AOP (result)))
10258     {
10259       /* otherwise get a free pointer register */
10260       aop = newAsmop (0);
10261       preg = getFreePtr (ic, &aop, FALSE);
10262       emitcode ("mov", "%s,%s",
10263                 preg->name,
10264                 aopGet (result, 0, FALSE, TRUE));
10265       rname = preg->name;
10266     }
10267   else
10268     rname = aopGet (result, 0, FALSE, FALSE);
10269
10270   aopOp (right, ic, FALSE);
10271
10272   /* if bitfield then unpack the bits */
10273   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10274     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10275   else
10276     {
10277       /* we have can just get the values */
10278       int size = AOP_SIZE (right);
10279       int offset = 0;
10280
10281       while (size--)
10282         {
10283           l = aopGet (right, offset, FALSE, TRUE);
10284
10285           MOVA (l);
10286           emitcode ("movx", "@%s,a", rname);
10287
10288           if (size || pi)
10289             emitcode ("inc", "%s", rname);
10290
10291           offset++;
10292         }
10293     }
10294
10295   /* now some housekeeping stuff */
10296   if (aop) /* we had to allocate for this iCode */
10297     {
10298       if (pi)
10299         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10300       freeAsmop (NULL, aop, ic, TRUE);
10301     }
10302   else
10303     {
10304       /* we did not allocate which means left
10305          already in a pointer register, then
10306          if size > 0 && this could be used again
10307          we have to point it back to where it
10308          belongs */
10309       if (AOP_SIZE (right) > 1 &&
10310           !OP_SYMBOL (result)->remat &&
10311           (OP_SYMBOL (result)->liveTo > ic->seq ||
10312            ic->depth))
10313         {
10314           int size = AOP_SIZE (right) - 1;
10315           while (size--)
10316             emitcode ("dec", "%s", rname);
10317         }
10318     }
10319
10320   /* done */
10321   if (pi) pi->generated = 1;
10322   freeAsmop (result, NULL, ic, TRUE);
10323   freeAsmop (right, NULL, ic, TRUE);
10324
10325
10326 }
10327
10328 /*-----------------------------------------------------------------*/
10329 /* genFarPointerSet - set value from far space                     */
10330 /*-----------------------------------------------------------------*/
10331 static void
10332 genFarPointerSet (operand * right,
10333                   operand * result, iCode * ic, iCode * pi)
10334 {
10335   int size, offset;
10336   sym_link *retype = getSpec (operandType (right));
10337   sym_link *letype = getSpec (operandType (result));
10338
10339   D(emitcode (";     genFarPointerSet",""));
10340
10341   aopOp (result, ic, FALSE);
10342   loadDptrFromOperand (result, FALSE);
10343
10344   /* so dptr know contains the address */
10345   aopOp (right, ic, FALSE);
10346
10347   /* if bit then unpack */
10348   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10349     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10350   else
10351     {
10352       size = AOP_SIZE (right);
10353       offset = 0;
10354
10355       while (size--)
10356         {
10357           char *l = aopGet (right, offset++, FALSE, FALSE);
10358           MOVA (l);
10359           emitcode ("movx", "@dptr,a");
10360           if (size || pi)
10361             emitcode ("inc", "dptr");
10362         }
10363     }
10364   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10365     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10366     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10367     pi->generated=1;
10368   }
10369   freeAsmop (result, NULL, ic, TRUE);
10370   freeAsmop (right, NULL, ic, TRUE);
10371 }
10372
10373 /*-----------------------------------------------------------------*/
10374 /* genGenPointerSet - set value from generic pointer space         */
10375 /*-----------------------------------------------------------------*/
10376 static void
10377 genGenPointerSet (operand * right,
10378                   operand * result, iCode * ic, iCode * pi)
10379 {
10380   int size, offset;
10381   sym_link *retype = getSpec (operandType (right));
10382   sym_link *letype = getSpec (operandType (result));
10383
10384   D(emitcode (";     genGenPointerSet",""));
10385
10386   aopOp (result, ic, FALSE);
10387   loadDptrFromOperand (result, TRUE);
10388
10389   /* so dptr know contains the address */
10390   aopOp (right, ic, FALSE);
10391
10392   /* if bit then unpack */
10393   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10394     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10395   else
10396     {
10397       size = AOP_SIZE (right);
10398       offset = 0;
10399
10400       while (size--)
10401         {
10402           char *l = aopGet (right, offset++, FALSE, FALSE);
10403           MOVA (l);
10404           emitcode ("lcall", "__gptrput");
10405           if (size || pi)
10406             emitcode ("inc", "dptr");
10407         }
10408     }
10409
10410   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10411     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10412     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10413     pi->generated=1;
10414   }
10415   freeAsmop (result, NULL, ic, TRUE);
10416   freeAsmop (right, NULL, ic, TRUE);
10417 }
10418
10419 /*-----------------------------------------------------------------*/
10420 /* genPointerSet - stores the value into a pointer location        */
10421 /*-----------------------------------------------------------------*/
10422 static void
10423 genPointerSet (iCode * ic, iCode *pi)
10424 {
10425   operand *right, *result;
10426   sym_link *type, *etype;
10427   int p_type;
10428
10429   D(emitcode (";     genPointerSet",""));
10430
10431   right = IC_RIGHT (ic);
10432   result = IC_RESULT (ic);
10433
10434   /* depending on the type of pointer we need to
10435      move it to the correct pointer register */
10436   type = operandType (result);
10437   etype = getSpec (type);
10438   /* if left is of type of pointer then it is simple */
10439   if (IS_PTR (type) && !IS_FUNC (type->next))
10440     {
10441       p_type = DCL_TYPE (type);
10442     }
10443   else
10444     {
10445       /* we have to go by the storage class */
10446       p_type = PTR_TYPE (SPEC_OCLS (etype));
10447     }
10448
10449   /* special case when cast remat */
10450   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10451       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10452           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10453           type = operandType (result);
10454           p_type = DCL_TYPE (type);
10455   }
10456   /* now that we have the pointer type we assign
10457      the pointer values */
10458   switch (p_type)
10459     {
10460
10461     case POINTER:
10462     case IPOINTER:
10463       genNearPointerSet (right, result, ic, pi);
10464       break;
10465
10466     case PPOINTER:
10467       genPagedPointerSet (right, result, ic, pi);
10468       break;
10469
10470     case FPOINTER:
10471       genFarPointerSet (right, result, ic, pi);
10472       break;
10473
10474     case GPOINTER:
10475       genGenPointerSet (right, result, ic, pi);
10476       break;
10477
10478     default:
10479       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10480               "genPointerSet: illegal pointer type");
10481     }
10482
10483 }
10484
10485 /*-----------------------------------------------------------------*/
10486 /* genIfx - generate code for Ifx statement                        */
10487 /*-----------------------------------------------------------------*/
10488 static void
10489 genIfx (iCode * ic, iCode * popIc)
10490 {
10491   operand *cond = IC_COND (ic);
10492   int isbit = 0;
10493   char *dup = NULL;
10494
10495   D(emitcode (";     genIfx",""));
10496
10497   aopOp (cond, ic, FALSE);
10498
10499   /* get the value into acc */
10500   if (AOP_TYPE (cond) != AOP_CRY)
10501     toBoolean (cond);
10502   else
10503     {
10504       isbit = 1;
10505       if (AOP(cond)->aopu.aop_dir)
10506         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10507     }
10508   /* the result is now in the accumulator or a directly addressable bit */
10509   freeAsmop (cond, NULL, ic, TRUE);
10510
10511   /* if there was something to be popped then do it */
10512   if (popIc)
10513     genIpop (popIc);
10514
10515   /* if the condition is a bit variable */
10516   if (isbit && dup)
10517     genIfxJump(ic, dup, NULL, NULL, NULL);
10518   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10519     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10520   else if (isbit && !IS_ITEMP (cond))
10521     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10522   else
10523     genIfxJump (ic, "a", NULL, NULL, NULL);
10524
10525   ic->generated = 1;
10526 }
10527
10528 /*-----------------------------------------------------------------*/
10529 /* genAddrOf - generates code for address of                       */
10530 /*-----------------------------------------------------------------*/
10531 static void
10532 genAddrOf (iCode * ic)
10533 {
10534   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10535   int size, offset;
10536
10537   D(emitcode (";     genAddrOf",""));
10538
10539   aopOp (IC_RESULT (ic), ic, FALSE);
10540
10541   /* if the operand is on the stack then we
10542      need to get the stack offset of this
10543      variable */
10544   if (sym->onStack)
10545     {
10546       /* if it has an offset then we need to compute
10547          it */
10548       if (sym->stack)
10549         {
10550           emitcode ("mov", "a,%s", SYM_BP (sym));
10551           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10552                                          ((char) (sym->stack - _G.nRegsSaved)) :
10553                                          ((char) sym->stack)) & 0xff);
10554           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10555         }
10556       else
10557         {
10558           /* we can just move _bp */
10559           aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10560         }
10561       /* fill the result with zero */
10562       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10563
10564       offset = 1;
10565       while (size--)
10566         {
10567           aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10568         }
10569
10570       goto release;
10571     }
10572
10573   /* object not on stack then we need the name */
10574   size = AOP_SIZE (IC_RESULT (ic));
10575   offset = 0;
10576
10577   while (size--)
10578     {
10579       char s[SDCC_NAME_MAX];
10580       if (offset)
10581         sprintf (s, "#(%s >> %d)",
10582                  sym->rname,
10583                  offset * 8);
10584       else
10585         sprintf (s, "#%s", sym->rname);
10586       aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10587     }
10588
10589 release:
10590   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10591
10592 }
10593
10594 /*-----------------------------------------------------------------*/
10595 /* genFarFarAssign - assignment when both are in far space         */
10596 /*-----------------------------------------------------------------*/
10597 static void
10598 genFarFarAssign (operand * result, operand * right, iCode * ic)
10599 {
10600   int size = AOP_SIZE (right);
10601   int offset = 0;
10602   char *l;
10603
10604   D(emitcode (";     genFarFarAssign",""));
10605
10606   /* first push the right side on to the stack */
10607   while (size--)
10608     {
10609       l = aopGet (right, offset++, FALSE, FALSE);
10610       MOVA (l);
10611       emitcode ("push", "acc");
10612     }
10613
10614   freeAsmop (right, NULL, ic, FALSE);
10615   /* now assign DPTR to result */
10616   aopOp (result, ic, FALSE);
10617   size = AOP_SIZE (result);
10618   while (size--)
10619     {
10620       emitcode ("pop", "acc");
10621       aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10622     }
10623   freeAsmop (result, NULL, ic, FALSE);
10624
10625 }
10626
10627 /*-----------------------------------------------------------------*/
10628 /* genAssign - generate code for assignment                        */
10629 /*-----------------------------------------------------------------*/
10630 static void
10631 genAssign (iCode * ic)
10632 {
10633   operand *result, *right;
10634   int size, offset;
10635   unsigned long lit = 0L;
10636
10637   D(emitcode(";     genAssign",""));
10638
10639   result = IC_RESULT (ic);
10640   right = IC_RIGHT (ic);
10641
10642   /* if they are the same */
10643   if (operandsEqu (result, right) &&
10644       !isOperandVolatile (result, FALSE) &&
10645       !isOperandVolatile (right, FALSE))
10646     return;
10647
10648   aopOp (right, ic, FALSE);
10649
10650   /* special case both in far space */
10651   if (AOP_TYPE (right) == AOP_DPTR &&
10652       IS_TRUE_SYMOP (result) &&
10653       isOperandInFarSpace (result))
10654     {
10655
10656       genFarFarAssign (result, right, ic);
10657       return;
10658     }
10659
10660   aopOp (result, ic, TRUE);
10661
10662   /* if they are the same registers */
10663   if (sameRegs (AOP (right), AOP (result)) &&
10664       !isOperandVolatile (result, FALSE) &&
10665       !isOperandVolatile (right, FALSE))
10666     goto release;
10667
10668   /* if the result is a bit */
10669   if (AOP_TYPE (result) == AOP_CRY)
10670     {
10671
10672       /* if the right size is a literal then
10673          we know what the value is */
10674       if (AOP_TYPE (right) == AOP_LIT)
10675         {
10676           if (((int) operandLitValue (right)))
10677             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10678           else
10679             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10680           goto release;
10681         }
10682
10683       /* the right is also a bit variable */
10684       if (AOP_TYPE (right) == AOP_CRY)
10685         {
10686           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10687           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10688           goto release;
10689         }
10690
10691       /* we need to or */
10692       toBoolean (right);
10693       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10694       goto release;
10695     }
10696
10697   /* bit variables done */
10698   /* general case */
10699   size = AOP_SIZE (result);
10700   offset = 0;
10701   if (AOP_TYPE (right) == AOP_LIT)
10702     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10703   if ((size > 1) &&
10704       (AOP_TYPE (result) != AOP_REG) &&
10705       (AOP_TYPE (right) == AOP_LIT) &&
10706       !IS_FLOAT (operandType (right)) &&
10707       (lit < 256L))
10708     {
10709       while ((size) && (lit))
10710         {
10711           aopPut (result,
10712                   aopGet (right, offset, FALSE, FALSE),
10713                   offset,
10714                   isOperandVolatile (result, FALSE));
10715           lit >>= 8;
10716           offset++;
10717           size--;
10718         }
10719       emitcode ("clr", "a");
10720       while (size--)
10721         {
10722           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10723           offset++;
10724         }
10725     }
10726   else
10727     {
10728       while (size--)
10729         {
10730           aopPut (result,
10731                   aopGet (right, offset, FALSE, FALSE),
10732                   offset,
10733                   isOperandVolatile (result, FALSE));
10734           offset++;
10735         }
10736     }
10737
10738 release:
10739   freeAsmop (right, NULL, ic, TRUE);
10740   freeAsmop (result, NULL, ic, TRUE);
10741 }
10742
10743 /*-----------------------------------------------------------------*/
10744 /* genJumpTab - generates code for jump table                      */
10745 /*-----------------------------------------------------------------*/
10746 static void
10747 genJumpTab (iCode * ic)
10748 {
10749   symbol *jtab,*jtablo,*jtabhi;
10750   char *l;
10751   unsigned int count;
10752
10753   D(emitcode (";     genJumpTab",""));
10754
10755   count = elementsInSet( IC_JTLABELS (ic) );
10756
10757   if( count <= 16 )
10758     {
10759       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10760          if the switch argument is in a register.
10761          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10762       /* (MB) What if peephole converts ljmp to sjmp or ret ???
10763          How will multiply by three be updated ???*/
10764       aopOp (IC_JTCOND (ic), ic, FALSE);
10765       /* get the condition into accumulator */
10766       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10767       MOVA (l);
10768       /* multiply by three */
10769       emitcode ("add", "a,acc");
10770       emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10771       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10772
10773       jtab = newiTempLabel (NULL);
10774       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10775       emitcode ("jmp", "@a+dptr");
10776       emitcode ("", "%05d$:", jtab->key + 100);
10777       /* now generate the jump labels */
10778       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10779            jtab = setNextItem (IC_JTLABELS (ic)))
10780         emitcode ("ljmp", "%05d$", jtab->key + 100);
10781     }
10782   else
10783     {
10784       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10785          if the switch argument is in a register.
10786          For n>6 this algorithm may be more compact */
10787       jtablo = newiTempLabel (NULL);
10788       jtabhi = newiTempLabel (NULL);
10789
10790       /* get the condition into accumulator.
10791          Using b as temporary storage, if register push/pop is needed */
10792       aopOp (IC_JTCOND (ic), ic, FALSE);
10793       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10794       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10795           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10796         {
10797           // (MB) what if B is in use???
10798           wassertl(!BINUSE, "B was in use");
10799           emitcode ("mov", "b,%s", l);
10800           l = "b";
10801         }
10802       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10803       MOVA (l);
10804       if( count <= 112 )
10805         {
10806           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10807           emitcode ("movc", "a,@a+pc");
10808           emitcode ("push", "acc");
10809
10810           MOVA (l);
10811           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10812           emitcode ("movc", "a,@a+pc");
10813           emitcode ("push", "acc");
10814         }
10815       else
10816         {
10817           /* this scales up to n<=255, but needs two more bytes
10818              and changes dptr */
10819           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10820           emitcode ("movc", "a,@a+dptr");
10821           emitcode ("push", "acc");
10822
10823           MOVA (l);
10824           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10825           emitcode ("movc", "a,@a+dptr");
10826           emitcode ("push", "acc");
10827         }
10828
10829       emitcode ("ret", "");
10830
10831       /* now generate jump table, LSB */
10832       emitcode ("", "%05d$:", jtablo->key + 100);
10833       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10834            jtab = setNextItem (IC_JTLABELS (ic)))
10835         emitcode (".db", "%05d$", jtab->key + 100);
10836
10837       /* now generate jump table, MSB */
10838       emitcode ("", "%05d$:", jtabhi->key + 100);
10839       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10840            jtab = setNextItem (IC_JTLABELS (ic)))
10841          emitcode (".db", "%05d$>>8", jtab->key + 100);
10842     }
10843 }
10844
10845 /*-----------------------------------------------------------------*/
10846 /* genCast - gen code for casting                                  */
10847 /*-----------------------------------------------------------------*/
10848 static void
10849 genCast (iCode * ic)
10850 {
10851   operand *result = IC_RESULT (ic);
10852   sym_link *ctype = operandType (IC_LEFT (ic));
10853   sym_link *rtype = operandType (IC_RIGHT (ic));
10854   operand *right = IC_RIGHT (ic);
10855   int size, offset;
10856
10857   D(emitcode(";     genCast",""));
10858
10859   /* if they are equivalent then do nothing */
10860   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10861     return;
10862
10863   aopOp (right, ic, FALSE);
10864   aopOp (result, ic, FALSE);
10865
10866   /* if the result is a bit (and not a bitfield) */
10867   // if (AOP_TYPE (result) == AOP_CRY)
10868   if (IS_BIT (OP_SYMBOL (result)->type))
10869     /* not for bitfields */
10870     {
10871       /* if the right size is a literal then
10872          we know what the value is */
10873       if (AOP_TYPE (right) == AOP_LIT)
10874         {
10875           if (((int) operandLitValue (right)))
10876             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10877           else
10878             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10879
10880           goto release;
10881         }
10882
10883       /* the right is also a bit variable */
10884       if (AOP_TYPE (right) == AOP_CRY)
10885         {
10886           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10887           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10888           goto release;
10889         }
10890
10891       /* we need to or */
10892       toBoolean (right);
10893       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10894       goto release;
10895     }
10896
10897
10898   /* if they are the same size : or less */
10899   if (AOP_SIZE (result) <= AOP_SIZE (right))
10900     {
10901
10902       /* if they are in the same place */
10903       if (sameRegs (AOP (right), AOP (result)))
10904         goto release;
10905
10906       /* if they in different places then copy */
10907       size = AOP_SIZE (result);
10908       offset = 0;
10909       while (size--)
10910         {
10911           aopPut (result,
10912                   aopGet (right, offset, FALSE, FALSE),
10913                   offset,
10914                   isOperandVolatile (result, FALSE));
10915           offset++;
10916         }
10917       goto release;
10918     }
10919
10920
10921   /* if the result is of type pointer */
10922   if (IS_PTR (ctype))
10923     {
10924
10925       int p_type;
10926       sym_link *type = operandType (right);
10927       sym_link *etype = getSpec (type);
10928
10929       /* pointer to generic pointer */
10930       if (IS_GENPTR (ctype))
10931         {
10932           if (IS_PTR (type))
10933             p_type = DCL_TYPE (type);
10934           else
10935             {
10936               if (SPEC_SCLS(etype)==S_REGISTER) {
10937                 // let's assume it is a generic pointer
10938                 p_type=GPOINTER;
10939               } else {
10940                 /* we have to go by the storage class */
10941                 p_type = PTR_TYPE (SPEC_OCLS (etype));
10942               }
10943             }
10944
10945           /* the first two bytes are known */
10946           size = GPTRSIZE - 1;
10947           offset = 0;
10948           while (size--)
10949             {
10950               aopPut (result,
10951                       aopGet (right, offset, FALSE, FALSE),
10952                       offset,
10953                       isOperandVolatile (result, FALSE));
10954               offset++;
10955             }
10956           /* the last byte depending on type */
10957             {
10958                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10959                 char gpValStr[10];
10960
10961                 if (gpVal == -1)
10962                 {
10963                     // pointerTypeToGPByte will have bitched.
10964                     exit(1);
10965                 }
10966
10967                 sprintf(gpValStr, "#0x%x", gpVal);
10968                 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10969             }
10970           goto release;
10971         }
10972
10973       /* just copy the pointers */
10974       size = AOP_SIZE (result);
10975       offset = 0;
10976       while (size--)
10977         {
10978           aopPut (result,
10979                   aopGet (right, offset, FALSE, FALSE),
10980                   offset,
10981                   isOperandVolatile (result, FALSE));
10982           offset++;
10983         }
10984       goto release;
10985     }
10986
10987   /* so we now know that the size of destination is greater
10988      than the size of the source */
10989   /* we move to result for the size of source */
10990   size = AOP_SIZE (right);
10991   offset = 0;
10992   while (size--)
10993     {
10994       aopPut (result,
10995               aopGet (right, offset, FALSE, FALSE),
10996               offset,
10997               isOperandVolatile (result, FALSE));
10998       offset++;
10999     }
11000
11001   /* now depending on the sign of the source && destination */
11002   size = AOP_SIZE (result) - AOP_SIZE (right);
11003   /* if unsigned or not an integral type */
11004   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11005     {
11006       while (size--)
11007         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11008     }
11009   else
11010     {
11011       /* we need to extend the sign :{ */
11012       char *l = aopGet (right, AOP_SIZE (right) - 1,
11013                         FALSE, FALSE);
11014       MOVA (l);
11015       emitcode ("rlc", "a");
11016       emitcode ("subb", "a,acc");
11017       while (size--)
11018         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11019     }
11020
11021   /* we are done hurray !!!! */
11022
11023 release:
11024   freeAsmop (right, NULL, ic, TRUE);
11025   freeAsmop (result, NULL, ic, TRUE);
11026
11027 }
11028
11029 /*-----------------------------------------------------------------*/
11030 /* genDjnz - generate decrement & jump if not zero instrucion      */
11031 /*-----------------------------------------------------------------*/
11032 static int
11033 genDjnz (iCode * ic, iCode * ifx)
11034 {
11035   symbol *lbl, *lbl1;
11036   if (!ifx)
11037     return 0;
11038
11039   D(emitcode (";     genDjnz",""));
11040
11041   /* if the if condition has a false label
11042      then we cannot save */
11043   if (IC_FALSE (ifx))
11044     return 0;
11045
11046   /* if the minus is not of the form
11047      a = a - 1 */
11048   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11049       !IS_OP_LITERAL (IC_RIGHT (ic)))
11050     return 0;
11051
11052   if (operandLitValue (IC_RIGHT (ic)) != 1)
11053     return 0;
11054
11055   /* if the size of this greater than one then no
11056      saving */
11057   if (getSize (operandType (IC_RESULT (ic))) > 1)
11058     return 0;
11059
11060   /* otherwise we can save BIG */
11061   lbl = newiTempLabel (NULL);
11062   lbl1 = newiTempLabel (NULL);
11063
11064   aopOp (IC_RESULT (ic), ic, FALSE);
11065
11066   if (AOP_NEEDSACC(IC_RESULT(ic)))
11067   {
11068       /* If the result is accessed indirectly via
11069        * the accumulator, we must explicitly write
11070        * it back after the decrement.
11071        */
11072       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11073
11074       if (strcmp(rByte, "a"))
11075       {
11076            /* Something is hopelessly wrong */
11077            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11078                    __FILE__, __LINE__);
11079            /* We can just give up; the generated code will be inefficient,
11080             * but what the hey.
11081             */
11082            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11083            return 0;
11084       }
11085       emitcode ("dec", "%s", rByte);
11086       aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11087       emitcode ("jnz", "%05d$", lbl->key + 100);
11088   }
11089   else if (IS_AOP_PREG (IC_RESULT (ic)))
11090     {
11091       emitcode ("dec", "%s",
11092                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11093       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11094       emitcode ("jnz", "%05d$", lbl->key + 100);
11095     }
11096   else
11097     {
11098       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11099                 lbl->key + 100);
11100     }
11101   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11102   emitcode ("", "%05d$:", lbl->key + 100);
11103   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11104   emitcode ("", "%05d$:", lbl1->key + 100);
11105
11106   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11107   ifx->generated = 1;
11108   return 1;
11109 }
11110
11111 /*-----------------------------------------------------------------*/
11112 /* genReceive - generate code for a receive iCode                  */
11113 /*-----------------------------------------------------------------*/
11114 static void
11115 genReceive (iCode * ic)
11116 {
11117   int size = getSize (operandType (IC_RESULT (ic)));
11118   int offset = 0;
11119
11120   D(emitcode (";     genReceive",""));
11121
11122   if (ic->argreg == 1)
11123     { /* first parameter */
11124       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11125            isOperandInPagedSpace (IC_RESULT (ic))) &&
11126           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11127            IS_TRUE_SYMOP (IC_RESULT (ic))))
11128         {
11129           regs *tempRegs[4];
11130           int receivingA = 0;
11131           int roffset = 0;
11132
11133           for (offset = 0; offset<size; offset++)
11134             if (!strcmp (fReturn[offset], "a"))
11135               receivingA = 1;
11136
11137           if (!receivingA)
11138             {
11139               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11140                 {
11141                   for (offset = size-1; offset>0; offset--)
11142                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11143                   emitcode("mov","a,%s", fReturn[0]);
11144                   _G.accInUse++;
11145                   aopOp (IC_RESULT (ic), ic, FALSE);
11146                   _G.accInUse--;
11147                   aopPut (IC_RESULT (ic), "a", offset,
11148                           isOperandVolatile (IC_RESULT (ic), FALSE));
11149                   for (offset = 1; offset<size; offset++)
11150                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11151                             isOperandVolatile (IC_RESULT (ic), FALSE));
11152                   goto release;
11153                 }
11154             }
11155           else
11156             {
11157               if (getTempRegs(tempRegs, size, ic))
11158                 {
11159                   for (offset = 0; offset<size; offset++)
11160                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11161                   aopOp (IC_RESULT (ic), ic, FALSE);
11162                   for (offset = 0; offset<size; offset++)
11163                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11164                             isOperandVolatile (IC_RESULT (ic), FALSE));
11165                   goto release;
11166                 }
11167             }
11168
11169           offset = fReturnSizeMCS51 - size;
11170           while (size--)
11171             {
11172               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11173                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11174               offset++;
11175             }
11176           aopOp (IC_RESULT (ic), ic, FALSE);
11177           size = AOP_SIZE (IC_RESULT (ic));
11178           offset = 0;
11179           while (size--)
11180             {
11181               emitcode ("pop", "acc");
11182               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11183             }
11184         }
11185       else
11186         {
11187           _G.accInUse++;
11188           aopOp (IC_RESULT (ic), ic, FALSE);
11189           _G.accInUse--;
11190           assignResultValue (IC_RESULT (ic), NULL);
11191         }
11192     }
11193   else if (ic->argreg > 12)
11194     { /* bit parameters */
11195       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11196         {
11197           aopOp (IC_RESULT (ic), ic, FALSE);
11198           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11199           outBitC(IC_RESULT (ic));
11200         }
11201     }
11202   else
11203     { /* other parameters */
11204       int rb1off ;
11205       aopOp (IC_RESULT (ic), ic, FALSE);
11206       rb1off = ic->argreg;
11207       while (size--)
11208         {
11209           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11210         }
11211     }
11212
11213 release:
11214   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11215 }
11216
11217 /*-----------------------------------------------------------------*/
11218 /* genDummyRead - generate code for dummy read of volatiles        */
11219 /*-----------------------------------------------------------------*/
11220 static void
11221 genDummyRead (iCode * ic)
11222 {
11223   operand *op;
11224   int size, offset;
11225
11226   D(emitcode(";     genDummyRead",""));
11227
11228   op = IC_RIGHT (ic);
11229   if (op && IS_SYMOP (op))
11230     {
11231       aopOp (op, ic, FALSE);
11232
11233       /* if the result is a bit */
11234       if (AOP_TYPE (op) == AOP_CRY)
11235         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11236       else
11237         {
11238           /* bit variables done */
11239           /* general case */
11240           size = AOP_SIZE (op);
11241           offset = 0;
11242           while (size--)
11243           {
11244             MOVA (aopGet (op, offset, FALSE, FALSE));
11245             offset++;
11246           }
11247         }
11248
11249       freeAsmop (op, NULL, ic, TRUE);
11250     }
11251
11252   op = IC_LEFT (ic);
11253   if (op && IS_SYMOP (op))
11254     {
11255       aopOp (op, ic, FALSE);
11256
11257       /* if the result is a bit */
11258       if (AOP_TYPE (op) == AOP_CRY)
11259         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11260       else
11261         {
11262           /* bit variables done */
11263           /* general case */
11264           size = AOP_SIZE (op);
11265           offset = 0;
11266           while (size--)
11267           {
11268             MOVA (aopGet (op, offset, FALSE, FALSE));
11269             offset++;
11270           }
11271         }
11272
11273       freeAsmop (op, NULL, ic, TRUE);
11274     }
11275 }
11276
11277 /*-----------------------------------------------------------------*/
11278 /* genCritical - generate code for start of a critical sequence    */
11279 /*-----------------------------------------------------------------*/
11280 static void
11281 genCritical (iCode *ic)
11282 {
11283   symbol *tlbl = newiTempLabel (NULL);
11284
11285   D(emitcode(";     genCritical",""));
11286
11287   if (IC_RESULT (ic))
11288     {
11289       aopOp (IC_RESULT (ic), ic, TRUE);
11290       aopPut (IC_RESULT (ic), one, 0, 0);
11291       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11292       aopPut (IC_RESULT (ic), zero, 0, 0);
11293       emitcode ("", "%05d$:", (tlbl->key + 100));
11294       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11295     }
11296   else
11297     {
11298       emitcode ("setb", "c");
11299       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11300       emitcode ("clr", "c");
11301       emitcode ("", "%05d$:", (tlbl->key + 100));
11302       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11303     }
11304 }
11305
11306 /*-----------------------------------------------------------------*/
11307 /* genEndCritical - generate code for end of a critical sequence   */
11308 /*-----------------------------------------------------------------*/
11309 static void
11310 genEndCritical (iCode *ic)
11311 {
11312   D(emitcode(";     genEndCritical",""));
11313
11314   if (IC_RIGHT (ic))
11315     {
11316       aopOp (IC_RIGHT (ic), ic, FALSE);
11317       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11318         {
11319           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11320           emitcode ("mov", "ea,c");
11321         }
11322       else
11323         {
11324           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11325             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11326           emitcode ("rrc", "a");
11327           emitcode ("mov", "ea,c");
11328         }
11329       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11330     }
11331   else
11332     {
11333       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11334       emitcode ("mov", "ea,c");
11335     }
11336 }
11337
11338 /*-----------------------------------------------------------------*/
11339 /* gen51Code - generate code for 8051 based controllers            */
11340 /*-----------------------------------------------------------------*/
11341 void
11342 gen51Code (iCode * lic)
11343 {
11344   iCode *ic;
11345   int cln = 0;
11346   /* int cseq = 0; */
11347
11348   _G.currentFunc = NULL;
11349   lineHead = lineCurr = NULL;
11350
11351   /* print the allocation information */
11352   if (allocInfo && currFunc)
11353     printAllocInfo (currFunc, codeOutFile);
11354   /* if debug information required */
11355   if (options.debug && currFunc)
11356     {
11357       debugFile->writeFunction (currFunc, lic);
11358     }
11359   /* stack pointer name */
11360   if (options.useXstack)
11361     spname = "_spx";
11362   else
11363     spname = "sp";
11364
11365
11366   for (ic = lic; ic; ic = ic->next)
11367     {
11368       _G.current_iCode = ic;
11369
11370       if (ic->lineno && cln != ic->lineno)
11371         {
11372           if (options.debug)
11373             {
11374               debugFile->writeCLine (ic);
11375             }
11376           if (!options.noCcodeInAsm) {
11377             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11378                       printCLine(ic->filename, ic->lineno));
11379           }
11380           cln = ic->lineno;
11381         }
11382       #if 0
11383       if (ic->seqPoint && ic->seqPoint != cseq)
11384         {
11385           emitcode ("", "; sequence point %d", ic->seqPoint);
11386           cseq = ic->seqPoint;
11387         }
11388       #endif
11389       if (options.iCodeInAsm) {
11390         char regsInUse[80];
11391         int i;
11392
11393         #if 0
11394         for (i=0; i<8; i++) {
11395           sprintf (&regsInUse[i],
11396                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11397         regsInUse[i]=0;
11398         #else
11399         strcpy (regsInUse, "--------");
11400         for (i=0; i < 8; i++) {
11401           if (bitVectBitValue (ic->rMask, i))
11402             {
11403               int offset = regs8051[i].offset;
11404               regsInUse[offset] = offset + '0'; /* show rMask */
11405             }
11406         #endif
11407         }
11408         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11409       }
11410       /* if the result is marked as
11411          spilt and rematerializable or code for
11412          this has already been generated then
11413          do nothing */
11414       if (resultRemat (ic) || ic->generated)
11415         continue;
11416
11417       /* depending on the operation */
11418       switch (ic->op)
11419         {
11420         case '!':
11421           genNot (ic);
11422           break;
11423
11424         case '~':
11425           genCpl (ic);
11426           break;
11427
11428         case UNARYMINUS:
11429           genUminus (ic);
11430           break;
11431
11432         case IPUSH:
11433           genIpush (ic);
11434           break;
11435
11436         case IPOP:
11437           /* IPOP happens only when trying to restore a
11438              spilt live range, if there is an ifx statement
11439              following this pop then the if statement might
11440              be using some of the registers being popped which
11441              would destory the contents of the register so
11442              we need to check for this condition and handle it */
11443           if (ic->next &&
11444               ic->next->op == IFX &&
11445               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11446             genIfx (ic->next, ic);
11447           else
11448             genIpop (ic);
11449           break;
11450
11451         case CALL:
11452           genCall (ic);
11453           break;
11454
11455         case PCALL:
11456           genPcall (ic);
11457           break;
11458
11459         case FUNCTION:
11460           genFunction (ic);
11461           break;
11462
11463         case ENDFUNCTION:
11464           genEndFunction (ic);
11465           break;
11466
11467         case RETURN:
11468           genRet (ic);
11469           break;
11470
11471         case LABEL:
11472           genLabel (ic);
11473           break;
11474
11475         case GOTO:
11476           genGoto (ic);
11477           break;
11478
11479         case '+':
11480           genPlus (ic);
11481           break;
11482
11483         case '-':
11484           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11485             genMinus (ic);
11486           break;
11487
11488         case '*':
11489           genMult (ic);
11490           break;
11491
11492         case '/':
11493           genDiv (ic);
11494           break;
11495
11496         case '%':
11497           genMod (ic);
11498           break;
11499
11500         case '>':
11501           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11502           break;
11503
11504         case '<':
11505           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11506           break;
11507
11508         case LE_OP:
11509         case GE_OP:
11510         case NE_OP:
11511
11512           /* note these two are xlated by algebraic equivalence
11513              during parsing SDCC.y */
11514           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11515                   "got '>=' or '<=' shouldn't have come here");
11516           break;
11517
11518         case EQ_OP:
11519           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11520           break;
11521
11522         case AND_OP:
11523           genAndOp (ic);
11524           break;
11525
11526         case OR_OP:
11527           genOrOp (ic);
11528           break;
11529
11530         case '^':
11531           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11532           break;
11533
11534         case '|':
11535           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11536           break;
11537
11538         case BITWISEAND:
11539           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11540           break;
11541
11542         case INLINEASM:
11543           genInline (ic);
11544           break;
11545
11546         case RRC:
11547           genRRC (ic);
11548           break;
11549
11550         case RLC:
11551           genRLC (ic);
11552           break;
11553
11554         case GETHBIT:
11555           genGetHbit (ic);
11556           break;
11557
11558         case GETABIT:
11559           genGetAbit (ic);
11560           break;
11561
11562         case GETBYTE:
11563           genGetByte (ic);
11564           break;
11565
11566         case GETWORD:
11567           genGetWord (ic);
11568           break;
11569
11570         case LEFT_OP:
11571           genLeftShift (ic);
11572           break;
11573
11574         case RIGHT_OP:
11575           genRightShift (ic);
11576           break;
11577
11578         case GET_VALUE_AT_ADDRESS:
11579           genPointerGet (ic,
11580                          hasInc (IC_LEFT (ic), ic,
11581                                  getSize (operandType (IC_RESULT (ic)))),
11582                          ifxForOp (IC_RESULT (ic), ic) );
11583           break;
11584
11585         case '=':
11586           if (POINTER_SET (ic))
11587             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11588           else
11589             genAssign (ic);
11590           break;
11591
11592         case IFX:
11593           genIfx (ic, NULL);
11594           break;
11595
11596         case ADDRESS_OF:
11597           genAddrOf (ic);
11598           break;
11599
11600         case JUMPTABLE:
11601           genJumpTab (ic);
11602           break;
11603
11604         case CAST:
11605           genCast (ic);
11606           break;
11607
11608         case RECEIVE:
11609           genReceive (ic);
11610           break;
11611
11612         case SEND:
11613           addSet (&_G.sendSet, ic);
11614           break;
11615
11616         case DUMMY_READ_VOLATILE:
11617           genDummyRead (ic);
11618           break;
11619
11620         case CRITICAL:
11621           genCritical (ic);
11622           break;
11623
11624         case ENDCRITICAL:
11625           genEndCritical (ic);
11626           break;
11627
11628         case SWAP:
11629           genSwap (ic);
11630           break;
11631
11632         default:
11633           ic = ic;
11634         }
11635     }
11636
11637   _G.current_iCode = NULL;
11638
11639   /* now we are ready to call the
11640      peep hole optimizer */
11641   if (!options.nopeep)
11642     peepHole (&lineHead);
11643
11644   /* now do the actual printing */
11645   printLine (lineHead, codeOutFile);
11646   return;
11647 }