* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.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 #include "dbuf_string.h"
46
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
49 extern int allocInfo;
50
51 /* this is the down and dirty file with all kinds of
52    kludgy & hacky stuff. This is what it is all about
53    CODE GENERATION for a specific MCU . some of the
54    routines may be reusable, will have to see */
55
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
58 static char *spname;
59
60 char *fReturn8051[] =
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
65 {"a", "b"};
66
67 static unsigned short rbank = -1;
68
69 #define REG_WITH_INDEX   mcs51_regWithIdx
70
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75                         AOP_TYPE(x) == AOP_R0))
76
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
78                          AOP_TYPE(x) == AOP_DPTR || \
79                          AOP(x)->paged))
80
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
82                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84
85 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86
87 #define R0INB   _G.bu.bs.r0InB
88 #define R1INB   _G.bu.bs.r1InB
89 #define OPINB   _G.bu.bs.OpInB
90 #define BINUSE  _G.bu.BInUse
91
92 static struct
93   {
94     short r0Pushed;
95     short r1Pushed;
96     union
97       {
98         struct
99           {
100             short r0InB : 2;//2 so we can see it overflow
101             short r1InB : 2;//2 so we can see it overflow
102             short OpInB : 2;//2 so we can see it overflow
103           } bs;
104         short BInUse;
105       } bu;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111     iCode *current_iCode;
112     symbol *currentFunc;
113   }
114 _G;
115
116 static char *rb1regs[] = {
117     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
119 };
120
121 extern struct dbuf_s *codeOutBuf;
122 static void saveRBank (int, iCode *, bool);
123
124 #define RESULTONSTACK(x) \
125                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
126                          IC_RESULT(x)->aop->type == AOP_STK )
127
128 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
129 #define MOVB(x)  movb(x)
130
131 #define CLRC     emitcode("clr","c")
132 #define SETC     emitcode("setb","c")
133
134 static lineNode *lineHead = NULL;
135 static lineNode *lineCurr = NULL;
136
137 static unsigned char SLMask[] =
138 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
139  0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char SRMask[] =
141 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142  0x07, 0x03, 0x01, 0x00};
143
144 #define LSB     0
145 #define MSB16   1
146 #define MSB24   2
147 #define MSB32   3
148
149 /*-----------------------------------------------------------------*/
150 /* emitcode - writes the code into a file : for now it is simple    */
151 /*-----------------------------------------------------------------*/
152 static void
153 emitcode (const char *inst, const char *fmt,...)
154 {
155   va_list ap;
156   struct dbuf_s dbuf;
157   const char *lbp, *lb;
158
159   dbuf_init (&dbuf, INITIAL_INLINEASM);
160
161   va_start (ap, fmt);
162
163   if (inst && *inst)
164     {
165       dbuf_append_str (&dbuf, inst);
166
167       if (fmt && *fmt)
168         {
169           dbuf_append_char (&dbuf, '\t');
170           dbuf_tvprintf (&dbuf, fmt, ap);
171         }
172     }
173   else
174     {
175       dbuf_tvprintf (&dbuf, fmt, ap);
176     }
177
178   lbp = lb = dbuf_c_str(&dbuf);
179
180   while (isspace ((unsigned char)*lbp))
181     {
182       lbp++;
183     }
184
185   if (lbp && *lbp)
186     {
187       lineCurr = (lineCurr ?
188                   connectLine (lineCurr, newLineNode (lb)) :
189                   (lineHead = newLineNode (lb)));
190     }
191
192   lineCurr->isInline = _G.inLine;
193   lineCurr->isDebug = _G.debugLine;
194   lineCurr->ic = _G.current_iCode;
195   lineCurr->isComment = (*lbp==';');
196   va_end (ap);
197
198   dbuf_destroy(&dbuf);
199 }
200
201 static void
202 emitLabel (symbol *tlbl)
203 {
204   emitcode ("", "%05d$:", tlbl->key + 100);
205   lineCurr->isLabel = 1;
206 }
207
208 /*-----------------------------------------------------------------*/
209 /* mcs51_emitDebuggerSymbol - associate the current code location  */
210 /*   with a debugger symbol                                        */
211 /*-----------------------------------------------------------------*/
212 void
213 mcs51_emitDebuggerSymbol (char * debugSym)
214 {
215   _G.debugLine = 1;
216   emitcode ("", "%s ==.", debugSym);
217   _G.debugLine = 0;
218 }
219
220 /*-----------------------------------------------------------------*/
221 /* mova - moves specified value into accumulator                   */
222 /*-----------------------------------------------------------------*/
223 static void
224 mova (const char *x)
225 {
226   /* do some early peephole optimization */
227   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
228     return;
229
230   emitcode("mov", "a,%s", x);
231 }
232
233 /*-----------------------------------------------------------------*/
234 /* movb - moves specified value into register b                    */
235 /*-----------------------------------------------------------------*/
236 static void
237 movb (const char *x)
238 {
239   /* do some early peephole optimization */
240   if (!strncmp(x, "b", 2))
241     return;
242
243   emitcode("mov","b,%s", x);
244 }
245
246 /*-----------------------------------------------------------------*/
247 /* movc - moves specified value into the carry                     */
248 /*-----------------------------------------------------------------*/
249 static void
250 movc (const char *s)
251 {
252   if (!strcmp (s, zero))
253     CLRC;
254   else if (!strcmp (s, one))
255     SETC;
256   else if (strcmp (s, "c"))
257     {/* it's not in carry already */
258       MOVA (s);
259       /* set C, if a >= 1 */
260       emitcode ("add", "a,#0xff");
261     }
262 }
263
264 /*-----------------------------------------------------------------*/
265 /* pushB - saves register B if necessary                           */
266 /*-----------------------------------------------------------------*/
267 static bool
268 pushB (void)
269 {
270   bool pushedB = FALSE;
271
272   if (BINUSE)
273     {
274       emitcode ("push", "b");
275 //    printf("B was in use !\n");
276       pushedB = TRUE;
277     }
278   else
279     {
280       OPINB++;
281     }
282   return pushedB;
283 }
284
285 /*-----------------------------------------------------------------*/
286 /* popB - restores value of register B if necessary                */
287 /*-----------------------------------------------------------------*/
288 static void
289 popB (bool pushedB)
290 {
291   if (pushedB)
292     {
293       emitcode ("pop", "b");
294     }
295   else
296     {
297       OPINB--;
298     }
299 }
300
301 /*-----------------------------------------------------------------*/
302 /* pushReg - saves register                                        */
303 /*-----------------------------------------------------------------*/
304 static bool
305 pushReg (int index, bool bits_pushed)
306 {
307   regs * reg = REG_WITH_INDEX (index);
308   if (reg->type == REG_BIT)
309     {
310       if (!bits_pushed)
311         emitcode ("push", "%s", reg->base);
312       return TRUE;
313     }
314   else
315     emitcode ("push", "%s", reg->dname);
316   return bits_pushed;
317 }
318
319 /*-----------------------------------------------------------------*/
320 /* popReg - restores register                                      */
321 /*-----------------------------------------------------------------*/
322 static bool
323 popReg (int index, bool bits_popped)
324 {
325   regs * reg = REG_WITH_INDEX (index);
326   if (reg->type == REG_BIT)
327     {
328       if (!bits_popped)
329         emitcode ("pop", "%s", reg->base);
330       return TRUE;
331     }
332   else
333     emitcode ("pop", "%s", reg->dname);
334   return bits_popped;
335 }
336
337 /*-----------------------------------------------------------------*/
338 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
339 /*-----------------------------------------------------------------*/
340 static regs *
341 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 {
343   bool r0iu, r1iu;
344   bool r0ou, r1ou;
345
346   /* the logic: if r0 & r1 used in the instruction
347      then we are in trouble otherwise */
348
349   /* first check if r0 & r1 are used by this
350      instruction, in which case we are in trouble */
351   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
352   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353   if (r0iu && r1iu) {
354       goto endOfWorld;
355     }
356
357   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
358   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
359
360   /* if no usage of r0 then return it */
361   if (!r0iu && !r0ou)
362     {
363       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
364       (*aopp)->type = AOP_R0;
365
366       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
367     }
368
369   /* if no usage of r1 then return it */
370   if (!r1iu && !r1ou)
371     {
372       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
373       (*aopp)->type = AOP_R1;
374
375       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
376     }
377
378   /* now we know they both have usage */
379   /* if r0 not used in this instruction */
380   if (!r0iu)
381     {
382       /* push it if not already pushed */
383       if (ic->op == IPUSH)
384         {
385           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
386           R0INB++;
387         }
388       else if (!_G.r0Pushed)
389         {
390           emitcode ("push", "%s",
391                     REG_WITH_INDEX (R0_IDX)->dname);
392           _G.r0Pushed++;
393         }
394
395       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
396       (*aopp)->type = AOP_R0;
397
398       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
399     }
400
401   /* if r1 not used then */
402
403   if (!r1iu)
404     {
405       /* push it if not already pushed */
406       if (ic->op == IPUSH)
407         {
408           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
409           R1INB++;
410         }
411       else if (!_G.r1Pushed)
412         {
413           emitcode ("push", "%s",
414                     REG_WITH_INDEX (R1_IDX)->dname);
415           _G.r1Pushed++;
416         }
417
418       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
419       (*aopp)->type = AOP_R1;
420       return REG_WITH_INDEX (R1_IDX);
421     }
422
423 endOfWorld:
424   /* I said end of world, but not quite end of world yet */
425   /* if this is a result then we can push it on the stack */
426   if (result)
427     {
428       (*aopp)->type = AOP_STK;
429       return NULL;
430     }
431   /* in the case that result AND left AND right needs a pointer reg
432      we can safely use the result's */
433   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
434     {
435       (*aopp)->type = AOP_R0;
436       return REG_WITH_INDEX (R0_IDX);
437     }
438   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
439     {
440       (*aopp)->type = AOP_R1;
441       return REG_WITH_INDEX (R1_IDX);
442     }
443
444   /* now this is REALLY the end of the world */
445   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
446           "getFreePtr should never reach here");
447   exit (1);
448 }
449
450
451 /*-----------------------------------------------------------------*/
452 /* getTempRegs - initialize an array of pointers to GPR registers */
453 /*               that are not in use. Returns 1 if the requested   */
454 /*               number of registers were available, 0 otherwise.  */
455 /*-----------------------------------------------------------------*/
456 int
457 getTempRegs(regs **tempRegs, int size, iCode *ic)
458 {
459   bitVect * freeRegs;
460   int i;
461   int offset;
462
463   if (!ic)
464     ic = _G.current_iCode;
465   if (!ic)
466     return 0;
467   if (!_G.currentFunc)
468     return 0;
469
470   freeRegs = newBitVect(8);
471   bitVectSetBit (freeRegs, R2_IDX);
472   bitVectSetBit (freeRegs, R3_IDX);
473   bitVectSetBit (freeRegs, R4_IDX);
474   bitVectSetBit (freeRegs, R5_IDX);
475   bitVectSetBit (freeRegs, R6_IDX);
476   bitVectSetBit (freeRegs, R7_IDX);
477
478   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
479     {
480       bitVect * newfreeRegs;
481       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
482       freeBitVect(freeRegs);
483       freeRegs = newfreeRegs;
484     }
485   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
486
487   offset = 0;
488   for (i=0; i<freeRegs->size; i++)
489     {
490       if (bitVectBitValue(freeRegs,i))
491         tempRegs[offset++] = REG_WITH_INDEX(i);
492       if (offset>=size)
493         {
494           freeBitVect(freeRegs);
495           return 1;
496         }
497     }
498
499   freeBitVect(freeRegs);
500   return 0;
501 }
502
503
504 /*-----------------------------------------------------------------*/
505 /* newAsmop - creates a new asmOp                                  */
506 /*-----------------------------------------------------------------*/
507 static asmop *
508 newAsmop (short type)
509 {
510   asmop *aop;
511
512   aop = Safe_calloc (1, sizeof (asmop));
513   aop->type = type;
514   aop->allocated = 1;
515   return aop;
516 }
517
518 /*-----------------------------------------------------------------*/
519 /* pointerCode - returns the code for a pointer type               */
520 /*-----------------------------------------------------------------*/
521 static int
522 pointerCode (sym_link * etype)
523 {
524
525   return PTR_TYPE (SPEC_OCLS (etype));
526
527 }
528
529 /*-----------------------------------------------------------------*/
530 /* leftRightUseAcc - returns size of accumulator use by operands   */
531 /*-----------------------------------------------------------------*/
532 static int
533 leftRightUseAcc(iCode *ic)
534 {
535   operand *op;
536   int size;
537   int accuseSize = 0;
538   int accuse = 0;
539
540   if (!ic)
541     {
542       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
543               "null iCode pointer");
544       return 0;
545     }
546
547   if (ic->op == IFX)
548     {
549       op = IC_COND (ic);
550       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
551         {
552           accuse = 1;
553           size = getSize (OP_SYMBOL (op)->type);
554           if (size>accuseSize)
555             accuseSize = size;
556         }
557     }
558   else if (ic->op == JUMPTABLE)
559     {
560       op = IC_JTCOND (ic);
561       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
562         {
563           accuse = 1;
564           size = getSize (OP_SYMBOL (op)->type);
565           if (size>accuseSize)
566             accuseSize = size;
567         }
568     }
569   else
570     {
571       op = IC_LEFT (ic);
572       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
573         {
574           accuse = 1;
575           size = getSize (OP_SYMBOL (op)->type);
576           if (size>accuseSize)
577             accuseSize = size;
578         }
579       op = IC_RIGHT (ic);
580       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
581         {
582           accuse = 1;
583           size = getSize (OP_SYMBOL (op)->type);
584           if (size>accuseSize)
585             accuseSize = size;
586         }
587     }
588
589   if (accuseSize)
590     return accuseSize;
591   else
592     return accuse;
593 }
594
595 /*-----------------------------------------------------------------*/
596 /* aopForSym - for a true symbol                                   */
597 /*-----------------------------------------------------------------*/
598 static asmop *
599 aopForSym (iCode * ic, symbol * sym, bool result)
600 {
601   asmop *aop;
602   memmap *space;
603   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
604
605   wassertl (ic != NULL, "Got a null iCode");
606   wassertl (sym != NULL, "Got a null symbol");
607
608   space = SPEC_OCLS (sym->etype);
609
610   /* if already has one */
611   if (sym->aop)
612     {
613       sym->aop->allocated++;
614       return sym->aop;
615     }
616
617   /* assign depending on the storage class */
618   /* if it is on the stack or indirectly addressable */
619   /* space we need to assign either r0 or r1 to it   */
620   if (sym->onStack || sym->iaccess)
621     {
622       sym->aop = aop = newAsmop (0);
623       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
624       aop->size = getSize (sym->type);
625
626       /* now assign the address of the variable to
627          the pointer register */
628       if (aop->type != AOP_STK)
629         {
630           if (sym->onStack)
631             {
632               signed char offset = ((sym->stack < 0) ?
633                          ((signed char) (sym->stack - _G.nRegsSaved)) :
634                          ((signed char) sym->stack)) & 0xff;
635
636               if ((abs(offset) <= 3) ||
637                   (accuse && (abs(offset) <= 7)))
638                 {
639                   emitcode ("mov", "%s,%s",
640                             aop->aopu.aop_ptr->name, SYM_BP (sym));
641                   while (offset < 0)
642                     {
643                       emitcode ("dec", aop->aopu.aop_ptr->name);
644                       offset++;
645                     }
646                   while (offset > 0)
647                     {
648                       emitcode ("inc", aop->aopu.aop_ptr->name);
649                       offset--;
650                     }
651                 }
652               else
653                 {
654                   if (accuse)
655                     emitcode ("push", "acc");
656                   emitcode ("mov", "a,%s", SYM_BP (sym));
657                   emitcode ("add", "a,#0x%02x", offset & 0xff);
658                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
659                   if (accuse)
660                     emitcode ("pop", "acc");
661                 }
662             }
663           else
664             {
665               emitcode ("mov", "%s,#%s",
666                         aop->aopu.aop_ptr->name,
667                         sym->rname);
668             }
669           aop->paged = space->paged;
670         }
671       else
672         aop->aopu.aop_stk = sym->stack;
673       return aop;
674     }
675
676   /* if in bit space */
677   if (IN_BITSPACE (space))
678     {
679       sym->aop = aop = newAsmop (AOP_CRY);
680       aop->aopu.aop_dir = sym->rname;
681       aop->size = getSize (sym->type);
682       return aop;
683     }
684   /* if it is in direct space */
685   if (IN_DIRSPACE (space))
686     {
687       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
688       //printTypeChainRaw(sym->type, NULL);
689       //printf("space = %s\n", space ? space->sname : "NULL");
690       sym->aop = aop = newAsmop (AOP_DIR);
691       aop->aopu.aop_dir = sym->rname;
692       aop->size = getSize (sym->type);
693       return aop;
694     }
695
696   /* special case for a function */
697   if (IS_FUNC (sym->type))
698     {
699       sym->aop = aop = newAsmop (AOP_IMMD);
700       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
701       aop->size = getSize (sym->type);
702       return aop;
703     }
704
705   /* only remaining is far space */
706   /* in which case DPTR gets the address */
707   sym->aop = aop = newAsmop (AOP_DPTR);
708   emitcode ("mov", "dptr,#%s", sym->rname);
709   aop->size = getSize (sym->type);
710
711   /* if it is in code space */
712   if (IN_CODESPACE (space))
713     aop->code = 1;
714
715   return aop;
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* aopForRemat - rematerialzes an object                           */
720 /*-----------------------------------------------------------------*/
721 static asmop *
722 aopForRemat (symbol * sym)
723 {
724   iCode *ic = sym->rematiCode;
725   asmop *aop = newAsmop (AOP_IMMD);
726   int ptr_type = 0;
727   int val = 0;
728
729   for (;;)
730     {
731       if (ic->op == '+')
732         val += (int) operandLitValue (IC_RIGHT (ic));
733       else if (ic->op == '-')
734         val -= (int) operandLitValue (IC_RIGHT (ic));
735       else if (IS_CAST_ICODE(ic)) {
736               sym_link *from_type = operandType(IC_RIGHT(ic));
737               aop->aopu.aop_immd.from_cast_remat = 1;
738               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
739               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
740               continue;
741       } else break;
742
743       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
744     }
745
746   if (val)
747     {
748       SNPRINTF (buffer, sizeof(buffer),
749                 "(%s %c 0x%04x)",
750                 OP_SYMBOL (IC_LEFT (ic))->rname,
751                 val >= 0 ? '+' : '-',
752                 abs (val) & 0xffff);
753     }
754   else
755     {
756       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
757     }
758
759   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
760   /* set immd2 field if required */
761   if (aop->aopu.aop_immd.from_cast_remat)
762     {
763       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
764       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
765     }
766
767   return aop;
768 }
769
770 /*-----------------------------------------------------------------*/
771 /* regsInCommon - two operands have some registers in common       */
772 /*-----------------------------------------------------------------*/
773 static bool
774 regsInCommon (operand * op1, operand * op2)
775 {
776   symbol *sym1, *sym2;
777   int i;
778
779   /* if they have registers in common */
780   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
781     return FALSE;
782
783   sym1 = OP_SYMBOL (op1);
784   sym2 = OP_SYMBOL (op2);
785
786   if (sym1->nRegs == 0 || sym2->nRegs == 0)
787     return FALSE;
788
789   for (i = 0; i < sym1->nRegs; i++)
790     {
791       int j;
792       if (!sym1->regs[i])
793         continue;
794
795       for (j = 0; j < sym2->nRegs; j++)
796         {
797           if (!sym2->regs[j])
798             continue;
799
800           if (sym2->regs[j] == sym1->regs[i])
801             return TRUE;
802         }
803     }
804
805   return FALSE;
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* operandsEqu - equivalent                                        */
810 /*-----------------------------------------------------------------*/
811 static bool
812 operandsEqu (operand * op1, operand * op2)
813 {
814   symbol *sym1, *sym2;
815
816   /* if they're not symbols */
817   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
818     return FALSE;
819
820   sym1 = OP_SYMBOL (op1);
821   sym2 = OP_SYMBOL (op2);
822
823   /* if both are itemps & one is spilt
824      and the other is not then false */
825   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
826       sym1->isspilt != sym2->isspilt)
827     return FALSE;
828
829   /* if they are the same */
830   if (sym1 == sym2)
831     return TRUE;
832
833   /* if they have the same rname */
834   if (sym1->rname[0] && sym2->rname[0] &&
835       strcmp (sym1->rname, sym2->rname) == 0 &&
836       !(IS_PARM (op2) && IS_ITEMP (op1)))
837     return TRUE;
838
839   /* if left is a tmp & right is not */
840   if (IS_ITEMP (op1) &&
841       !IS_ITEMP (op2) &&
842       sym1->isspilt &&
843       (sym1->usl.spillLoc == sym2))
844     return TRUE;
845
846   if (IS_ITEMP (op2) &&
847       !IS_ITEMP (op1) &&
848       sym2->isspilt &&
849       sym1->level > 0 &&
850       (sym2->usl.spillLoc == sym1))
851     return TRUE;
852
853   return FALSE;
854 }
855
856 /*-----------------------------------------------------------------*/
857 /* sameByte - two asmops have the same address at given offsets    */
858 /*-----------------------------------------------------------------*/
859 static bool
860 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
861 {
862   if (aop1 == aop2 && off1 == off2)
863     return TRUE;
864
865   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
866     return FALSE;
867
868   if (aop1->type != aop2->type)
869     return FALSE;
870
871   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
872     return FALSE;
873
874   return TRUE;
875 }
876
877 /*-----------------------------------------------------------------*/
878 /* sameRegs - two asmops have the same registers                   */
879 /*-----------------------------------------------------------------*/
880 static bool
881 sameRegs (asmop * aop1, asmop * aop2)
882 {
883   int i;
884
885   if (aop1 == aop2)
886     return TRUE;
887
888   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
889     return FALSE;
890
891   if (aop1->type != aop2->type)
892     return FALSE;
893
894   if (aop1->size != aop2->size)
895     return FALSE;
896
897   for (i = 0; i < aop1->size; i++)
898     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
899       return FALSE;
900
901   return TRUE;
902 }
903
904 /*-----------------------------------------------------------------*/
905 /* aopOp - allocates an asmop for an operand  :                    */
906 /*-----------------------------------------------------------------*/
907 static void
908 aopOp (operand * op, iCode * ic, bool result)
909 {
910   asmop *aop;
911   symbol *sym;
912   int i;
913
914   if (!op)
915     return;
916
917   /* if this a literal */
918   if (IS_OP_LITERAL (op))
919     {
920       op->aop = aop = newAsmop (AOP_LIT);
921       aop->aopu.aop_lit = op->operand.valOperand;
922       aop->size = getSize (operandType (op));
923       return;
924     }
925
926   /* if already has a asmop then continue */
927   if (op->aop)
928     {
929       op->aop->allocated++;
930       return;
931     }
932
933   /* if the underlying symbol has a aop */
934   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
935     {
936       op->aop = OP_SYMBOL (op)->aop;
937       op->aop->allocated++;
938       return;
939     }
940
941   /* if this is a true symbol */
942   if (IS_TRUE_SYMOP (op))
943     {
944       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
945       return;
946     }
947
948   /* this is a temporary : this has
949      only five choices :
950      a) register
951      b) spillocation
952      c) rematerialize
953      d) conditional
954      e) can be a return use only */
955
956   sym = OP_SYMBOL (op);
957
958   /* if the type is a conditional */
959   if (sym->regType == REG_CND)
960     {
961       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
962       aop->size = 0;
963       return;
964     }
965
966   /* if it is spilt then two situations
967      a) is rematerialize
968      b) has a spill location */
969   if (sym->isspilt || sym->nRegs == 0)
970     {
971
972       /* rematerialize it NOW */
973       if (sym->remat)
974         {
975           sym->aop = op->aop = aop = aopForRemat (sym);
976           aop->size = getSize (sym->type);
977           return;
978         }
979
980       if (sym->accuse)
981         {
982           int i;
983           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
984           aop->size = getSize (sym->type);
985           for (i = 0; i < 2; i++)
986             aop->aopu.aop_str[i] = accUse[i];
987           return;
988         }
989
990       if (sym->ruonly)
991         {
992           unsigned i;
993
994           aop = op->aop = sym->aop = newAsmop (AOP_STR);
995           aop->size = getSize (sym->type);
996           for (i = 0; i < fReturnSizeMCS51; i++)
997             aop->aopu.aop_str[i] = fReturn[i];
998           return;
999         }
1000
1001       if (sym->usl.spillLoc)
1002         {
1003           asmop *oldAsmOp = NULL;
1004
1005           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1006             {
1007               /* force a new aop if sizes differ */
1008               oldAsmOp = sym->usl.spillLoc->aop;
1009               sym->usl.spillLoc->aop = NULL;
1010             }
1011           sym->aop = op->aop = aop =
1012                      aopForSym (ic, sym->usl.spillLoc, result);
1013           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1014             {
1015               /* Don't reuse the new aop, go with the last one */
1016               sym->usl.spillLoc->aop = oldAsmOp;
1017             }
1018           aop->size = getSize (sym->type);
1019           return;
1020         }
1021
1022       /* else must be a dummy iTemp */
1023       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1024       aop->size = getSize (sym->type);
1025       return;
1026     }
1027
1028   /* if the type is a bit register */
1029   if (sym->regType == REG_BIT)
1030     {
1031       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1032       aop->size = sym->nRegs;//1???
1033       aop->aopu.aop_reg[0] = sym->regs[0];
1034       aop->aopu.aop_dir = sym->regs[0]->name;
1035       return;
1036     }
1037
1038   /* must be in a register */
1039   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1040   aop->size = sym->nRegs;
1041   for (i = 0; i < sym->nRegs; i++)
1042     aop->aopu.aop_reg[i] = sym->regs[i];
1043 }
1044
1045 /*-----------------------------------------------------------------*/
1046 /* freeAsmop - free up the asmop given to an operand               */
1047 /*----------------------------------------------------------------*/
1048 static void
1049 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1050 {
1051   asmop *aop;
1052
1053   if (!op)
1054     aop = aaop;
1055   else
1056     aop = op->aop;
1057
1058   if (!aop)
1059     return;
1060
1061   aop->allocated--;
1062
1063   if (aop->allocated)
1064     goto dealloc;
1065
1066   /* depending on the asmop type only three cases need work
1067      AOP_R0, AOP_R1 & AOP_STK */
1068   switch (aop->type)
1069     {
1070     case AOP_R0:
1071       if (R0INB)
1072         {
1073           emitcode ("mov", "r0,b");
1074           R0INB--;
1075         }
1076       else if (_G.r0Pushed)
1077         {
1078           if (pop)
1079             {
1080               emitcode ("pop", "ar0");
1081               _G.r0Pushed--;
1082             }
1083         }
1084       bitVectUnSetBit (ic->rUsed, R0_IDX);
1085       break;
1086
1087     case AOP_R1:
1088       if (R1INB)
1089         {
1090           emitcode ("mov", "r1,b");
1091           R1INB--;
1092         }
1093       else if (_G.r1Pushed)
1094         {
1095           if (pop)
1096             {
1097               emitcode ("pop", "ar1");
1098               _G.r1Pushed--;
1099             }
1100         }
1101       bitVectUnSetBit (ic->rUsed, R1_IDX);
1102       break;
1103
1104     case AOP_STK:
1105       {
1106         int sz = aop->size;
1107         int stk = aop->aopu.aop_stk + aop->size - 1;
1108         bitVectUnSetBit (ic->rUsed, R0_IDX);
1109         bitVectUnSetBit (ic->rUsed, R1_IDX);
1110
1111         getFreePtr (ic, &aop, FALSE);
1112
1113         if (stk)
1114           {
1115             emitcode ("mov", "a,_bp");
1116             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1117             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1118           }
1119         else
1120           {
1121             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1122           }
1123
1124         while (sz--)
1125           {
1126             emitcode ("pop", "acc");
1127             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1128             if (!sz)
1129               break;
1130             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131           }
1132         op->aop = aop;
1133         freeAsmop (op, NULL, ic, TRUE);
1134         if (_G.r1Pushed)
1135           {
1136             emitcode ("pop", "ar1");
1137             _G.r1Pushed--;
1138           }
1139         if (_G.r0Pushed)
1140           {
1141             emitcode ("pop", "ar0");
1142             _G.r0Pushed--;
1143           }
1144       }
1145       break;
1146     }
1147
1148 dealloc:
1149   /* all other cases just dealloc */
1150   if (op)
1151     {
1152       op->aop = NULL;
1153       if (IS_SYMOP (op))
1154         {
1155           OP_SYMBOL (op)->aop = NULL;
1156           /* if the symbol has a spill */
1157           if (SPIL_LOC (op))
1158             SPIL_LOC (op)->aop = NULL;
1159         }
1160     }
1161 }
1162
1163 /*------------------------------------------------------------------*/
1164 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1165 /*                      pop r0 or r1 off stack if pushed            */
1166 /*------------------------------------------------------------------*/
1167 static void
1168 freeForBranchAsmop (operand * op)
1169 {
1170   asmop *aop;
1171
1172   if (!op)
1173     return;
1174
1175   aop = op->aop;
1176
1177   if (!aop)
1178     return;
1179
1180   if (!aop->allocated)
1181     return;
1182
1183   switch (aop->type)
1184     {
1185     case AOP_R0:
1186       if (R0INB)
1187         {
1188           emitcode ("mov", "r0,b");
1189         }
1190       else if (_G.r0Pushed)
1191         {
1192           emitcode ("pop", "ar0");
1193         }
1194       break;
1195
1196     case AOP_R1:
1197       if (R1INB)
1198         {
1199           emitcode ("mov", "r1,b");
1200         }
1201       else if (_G.r1Pushed)
1202         {
1203           emitcode ("pop", "ar1");
1204         }
1205       break;
1206
1207     case AOP_STK:
1208       {
1209         int sz = aop->size;
1210         int stk = aop->aopu.aop_stk + aop->size - 1;
1211
1212         emitcode ("mov", "b,r0");
1213         if (stk)
1214           {
1215             emitcode ("mov", "a,_bp");
1216             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1217             emitcode ("mov", "r0,a");
1218           }
1219         else
1220           {
1221             emitcode ("mov", "r0,_bp");
1222           }
1223
1224         while (sz--)
1225           {
1226             emitcode ("pop", "acc");
1227             emitcode ("mov", "@r0,a");
1228             if (!sz)
1229               break;
1230             emitcode ("dec", "r0");
1231           }
1232         emitcode ("mov", "r0,b");
1233       }
1234     }
1235
1236 }
1237
1238 /*-----------------------------------------------------------------*/
1239 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1240 /*                 clobber the accumulator                         */
1241 /*-----------------------------------------------------------------*/
1242 static bool
1243 aopGetUsesAcc (operand * oper, int offset)
1244 {
1245   asmop * aop = AOP (oper);
1246
1247   if (offset > (aop->size - 1))
1248     return FALSE;
1249
1250   switch (aop->type)
1251     {
1252
1253     case AOP_R0:
1254     case AOP_R1:
1255       if (aop->paged)
1256         return TRUE;
1257       return FALSE;
1258     case AOP_DPTR:
1259       return TRUE;
1260     case AOP_IMMD:
1261       return FALSE;
1262     case AOP_DIR:
1263       return FALSE;
1264     case AOP_REG:
1265       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1266       return FALSE;
1267     case AOP_CRY:
1268       return TRUE;
1269     case AOP_ACC:
1270       if (offset)
1271         return FALSE;
1272       return TRUE;
1273     case AOP_LIT:
1274       return FALSE;
1275     case AOP_STR:
1276       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1277         return TRUE;
1278       return FALSE;
1279     case AOP_DUMMY:
1280       return FALSE;
1281     default:
1282       /* Error case --- will have been caught already */
1283       wassert(0);
1284       return FALSE;
1285     }
1286 }
1287
1288 /*-------------------------------------------------------------------*/
1289 /* aopGet - for fetching value of the aop                            */
1290 /*-------------------------------------------------------------------*/
1291 static char *
1292 aopGet (operand * oper, int offset, bool bit16, bool dname)
1293 {
1294   asmop * aop = AOP (oper);
1295
1296   /* offset is greater than
1297      size then zero */
1298   if (offset > (aop->size - 1) &&
1299       aop->type != AOP_LIT)
1300     return zero;
1301
1302   /* depending on type */
1303   switch (aop->type)
1304     {
1305     case AOP_DUMMY:
1306       return zero;
1307
1308     case AOP_R0:
1309     case AOP_R1:
1310       /* if we need to increment it */
1311       while (offset > aop->coff)
1312         {
1313           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314           aop->coff++;
1315         }
1316
1317       while (offset < aop->coff)
1318         {
1319           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1320           aop->coff--;
1321         }
1322
1323       aop->coff = offset;
1324       if (aop->paged)
1325         {
1326           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1327           return (dname ? "acc" : "a");
1328         }
1329       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1330       return Safe_strdup(buffer);
1331
1332     case AOP_DPTR:
1333       if (aop->code && aop->coff==0 && offset>=1) {
1334         emitcode ("mov", "a,#0x%02x", offset);
1335         emitcode ("movc", "a,@a+dptr");
1336         return (dname ? "acc" : "a");
1337       }
1338
1339       while (offset > aop->coff)
1340         {
1341           emitcode ("inc", "dptr");
1342           aop->coff++;
1343         }
1344
1345       while (offset < aop->coff)
1346         {
1347           emitcode ("lcall", "__decdptr");
1348           aop->coff--;
1349         }
1350
1351       aop->coff = offset;
1352       if (aop->code)
1353         {
1354           emitcode ("clr", "a");
1355           emitcode ("movc", "a,@a+dptr");
1356         }
1357       else
1358         {
1359           emitcode ("movx", "a,@dptr");
1360         }
1361       return (dname ? "acc" : "a");
1362
1363     case AOP_IMMD:
1364       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1365         {
1366           SNPRINTF(buffer, sizeof(buffer),
1367                    "%s",aop->aopu.aop_immd.aop_immd2);
1368         }
1369       else if (bit16)
1370         {
1371           SNPRINTF(buffer, sizeof(buffer),
1372                    "#%s", aop->aopu.aop_immd.aop_immd1);
1373         }
1374       else if (offset)
1375         {
1376           SNPRINTF (buffer, sizeof(buffer),
1377                     "#(%s >> %d)",
1378                     aop->aopu.aop_immd.aop_immd1,
1379                     offset * 8);
1380         }
1381       else
1382         {
1383           SNPRINTF (buffer, sizeof(buffer),
1384                     "#%s",
1385                     aop->aopu.aop_immd.aop_immd1);
1386         }
1387       return Safe_strdup(buffer);
1388
1389     case AOP_DIR:
1390       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1391         {
1392           SNPRINTF (buffer, sizeof(buffer),
1393                     "(%s >> %d)",
1394                     aop->aopu.aop_dir, offset * 8);
1395         }
1396       else if (offset)
1397         {
1398           SNPRINTF (buffer, sizeof(buffer),
1399                     "(%s + %d)",
1400                     aop->aopu.aop_dir,
1401                     offset);
1402         }
1403       else
1404         {
1405           SNPRINTF (buffer, sizeof(buffer),
1406                     "%s",
1407                     aop->aopu.aop_dir);
1408         }
1409
1410       return Safe_strdup(buffer);
1411
1412     case AOP_REG:
1413       if (dname)
1414         return aop->aopu.aop_reg[offset]->dname;
1415       else
1416         return aop->aopu.aop_reg[offset]->name;
1417
1418     case AOP_CRY:
1419       emitcode ("clr", "a");
1420       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1421       emitcode ("rlc", "a");
1422       return (dname ? "acc" : "a");
1423
1424     case AOP_ACC:
1425       if (!offset && dname)
1426         return "acc";
1427       return aop->aopu.aop_str[offset];
1428
1429     case AOP_LIT:
1430       return aopLiteral (aop->aopu.aop_lit, offset);
1431
1432     case AOP_STR:
1433       aop->coff = offset;
1434       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1435           dname)
1436         return "acc";
1437
1438       return aop->aopu.aop_str[offset];
1439
1440     }
1441
1442   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1443           "aopget got unsupported aop->type");
1444   exit (1);
1445 }
1446
1447 /*-----------------------------------------------------------------*/
1448 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1449 /*                 clobber the accumulator                         */
1450 /*-----------------------------------------------------------------*/
1451 static bool
1452 aopPutUsesAcc (operand * oper, const char *s, int offset)
1453 {
1454   asmop * aop = AOP (oper);
1455
1456   if (offset > (aop->size - 1))
1457     return FALSE;
1458
1459   switch (aop->type)
1460     {
1461     case AOP_DUMMY:
1462       return TRUE;
1463     case AOP_DIR:
1464       return FALSE;
1465     case AOP_REG:
1466       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1467       return FALSE;
1468     case AOP_DPTR:
1469       return TRUE;
1470     case AOP_R0:
1471     case AOP_R1:
1472       return ((aop->paged) || (*s == '@'));
1473     case AOP_STK:
1474       return (*s == '@');
1475     case AOP_CRY:
1476       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1477     case AOP_STR:
1478       return FALSE;
1479     case AOP_IMMD:
1480       return FALSE;
1481     case AOP_ACC:
1482       return FALSE;
1483     default:
1484       /* Error case --- will have been caught already */
1485       wassert(0);
1486       return FALSE;
1487     }
1488 }
1489
1490 /*-----------------------------------------------------------------*/
1491 /* aopPut - puts a string for a aop and indicates if acc is in use */
1492 /*-----------------------------------------------------------------*/
1493 static bool
1494 aopPut (operand * result, const char *s, int offset)
1495 {
1496   bool bvolatile = isOperandVolatile (result, FALSE);
1497   bool accuse = FALSE;
1498   asmop * aop = AOP (result);
1499
1500   if (aop->size && offset > (aop->size - 1))
1501     {
1502       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1503               "aopPut got offset > aop->size");
1504       exit (1);
1505     }
1506
1507   /* will assign value to value */
1508   /* depending on where it is ofcourse */
1509   switch (aop->type)
1510     {
1511     case AOP_DUMMY:
1512       MOVA (s);         /* read s in case it was volatile */
1513       accuse = TRUE;
1514       break;
1515
1516     case AOP_DIR:
1517       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1518         {
1519           SNPRINTF (buffer, sizeof(buffer),
1520                     "(%s >> %d)",
1521                     aop->aopu.aop_dir, offset * 8);
1522         }
1523       else if (offset)
1524         {
1525           SNPRINTF (buffer, sizeof(buffer),
1526                     "(%s + %d)",
1527                     aop->aopu.aop_dir, offset);
1528         }
1529       else
1530         {
1531           SNPRINTF (buffer, sizeof(buffer),
1532                     "%s",
1533                     aop->aopu.aop_dir);
1534         }
1535
1536       if (strcmp (buffer, s) || bvolatile)
1537         {
1538           emitcode ("mov", "%s,%s", buffer, s);
1539         }
1540       if (!strcmp (buffer, "acc"))
1541         {
1542           accuse = TRUE;
1543         }
1544       break;
1545
1546     case AOP_REG:
1547       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1548           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1549         {
1550           if (*s == '@' ||
1551               strcmp (s, "r0") == 0 ||
1552               strcmp (s, "r1") == 0 ||
1553               strcmp (s, "r2") == 0 ||
1554               strcmp (s, "r3") == 0 ||
1555               strcmp (s, "r4") == 0 ||
1556               strcmp (s, "r5") == 0 ||
1557               strcmp (s, "r6") == 0 ||
1558               strcmp (s, "r7") == 0)
1559             {
1560               emitcode ("mov", "%s,%s",
1561                         aop->aopu.aop_reg[offset]->dname, s);
1562             }
1563           else
1564             {
1565               emitcode ("mov", "%s,%s",
1566                         aop->aopu.aop_reg[offset]->name, s);
1567             }
1568         }
1569       break;
1570
1571     case AOP_DPTR:
1572       if (aop->code)
1573         {
1574           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1575                   "aopPut writing to code space");
1576           exit (1);
1577         }
1578
1579       while (offset > aop->coff)
1580         {
1581           aop->coff++;
1582           emitcode ("inc", "dptr");
1583         }
1584
1585       while (offset < aop->coff)
1586         {
1587           aop->coff--;
1588           emitcode ("lcall", "__decdptr");
1589         }
1590
1591       aop->coff = offset;
1592
1593       /* if not in accumulator */
1594       MOVA (s);
1595
1596       emitcode ("movx", "@dptr,a");
1597       break;
1598
1599     case AOP_R0:
1600     case AOP_R1:
1601       while (offset > aop->coff)
1602         {
1603           aop->coff++;
1604           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1605         }
1606       while (offset < aop->coff)
1607         {
1608           aop->coff--;
1609           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1610         }
1611       aop->coff = offset;
1612
1613       if (aop->paged)
1614         {
1615           MOVA (s);
1616           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1617         }
1618       else if (*s == '@')
1619         {
1620           MOVA (s);
1621           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1622         }
1623       else if (strcmp (s, "r0") == 0 ||
1624                strcmp (s, "r1") == 0 ||
1625                strcmp (s, "r2") == 0 ||
1626                strcmp (s, "r3") == 0 ||
1627                strcmp (s, "r4") == 0 ||
1628                strcmp (s, "r5") == 0 ||
1629                strcmp (s, "r6") == 0 ||
1630                strcmp (s, "r7") == 0)
1631         {
1632           char buffer[10];
1633           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1634           emitcode ("mov", "@%s,%s",
1635                     aop->aopu.aop_ptr->name, buffer);
1636         }
1637       else
1638         {
1639           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1640         }
1641       break;
1642
1643     case AOP_STK:
1644       if (strcmp (s, "a") == 0)
1645         emitcode ("push", "acc");
1646       else
1647         if (*s=='@') {
1648           MOVA(s);
1649           emitcode ("push", "acc");
1650         } else {
1651           emitcode ("push", s);
1652         }
1653
1654       break;
1655
1656     case AOP_CRY:
1657       /* if not bit variable */
1658       if (!aop->aopu.aop_dir)
1659         {
1660           /* inefficient: move carry into A and use jz/jnz */
1661           emitcode ("clr", "a");
1662           emitcode ("rlc", "a");
1663           accuse = TRUE;
1664         }
1665       else
1666         {
1667           if (s == zero)
1668             emitcode ("clr", "%s", aop->aopu.aop_dir);
1669           else if (s == one)
1670             emitcode ("setb", "%s", aop->aopu.aop_dir);
1671           else if (!strcmp (s, "c"))
1672             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1673           else if (strcmp (s, aop->aopu.aop_dir))
1674             {
1675               MOVA (s);
1676               /* set C, if a >= 1 */
1677               emitcode ("add", "a,#0xff");
1678               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1679             }
1680         }
1681       break;
1682
1683     case AOP_STR:
1684       aop->coff = offset;
1685       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1686         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1687       break;
1688
1689     case AOP_ACC:
1690       accuse = TRUE;
1691       aop->coff = offset;
1692       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1693         break;
1694
1695       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1696         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1697       break;
1698
1699     default:
1700       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1701               "aopPut got unsupported aop->type");
1702       exit (1);
1703     }
1704
1705     return accuse;
1706 }
1707
1708
1709 #if 0
1710 /*-----------------------------------------------------------------*/
1711 /* pointToEnd :- points to the last byte of the operand            */
1712 /*-----------------------------------------------------------------*/
1713 static void
1714 pointToEnd (asmop * aop)
1715 {
1716   int count;
1717   if (!aop)
1718     return;
1719
1720   aop->coff = count = (aop->size - 1);
1721   switch (aop->type)
1722     {
1723     case AOP_R0:
1724     case AOP_R1:
1725       while (count--)
1726         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1727       break;
1728     case AOP_DPTR:
1729       while (count--)
1730         emitcode ("inc", "dptr");
1731       break;
1732     }
1733
1734 }
1735 #endif
1736
1737 /*-----------------------------------------------------------------*/
1738 /* reAdjustPreg - points a register back to where it should        */
1739 /*-----------------------------------------------------------------*/
1740 static void
1741 reAdjustPreg (asmop * aop)
1742 {
1743   if ((aop->coff==0) || (aop->size <= 1))
1744     return;
1745
1746   switch (aop->type)
1747     {
1748     case AOP_R0:
1749     case AOP_R1:
1750       while (aop->coff--)
1751         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1752       break;
1753     case AOP_DPTR:
1754       while (aop->coff--)
1755         {
1756           emitcode ("lcall", "__decdptr");
1757         }
1758       break;
1759     }
1760   aop->coff = 0;
1761 }
1762
1763 /*-----------------------------------------------------------------*/
1764 /* opIsGptr: returns non-zero if the passed operand is       */
1765 /* a generic pointer type.             */
1766 /*-----------------------------------------------------------------*/
1767 static int
1768 opIsGptr (operand * op)
1769 {
1770   sym_link *type = operandType (op);
1771
1772   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1773     {
1774       return 1;
1775     }
1776   return 0;
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* getDataSize - get the operand data size                         */
1781 /*-----------------------------------------------------------------*/
1782 static int
1783 getDataSize (operand * op)
1784 {
1785   int size;
1786   size = AOP_SIZE (op);
1787   if (size == GPTRSIZE)
1788     {
1789       sym_link *type = operandType (op);
1790       if (IS_GENPTR (type))
1791         {
1792           /* generic pointer; arithmetic operations
1793            * should ignore the high byte (pointer type).
1794            */
1795           size--;
1796         }
1797     }
1798   return size;
1799 }
1800
1801 /*-----------------------------------------------------------------*/
1802 /* outAcc - output Acc                                             */
1803 /*-----------------------------------------------------------------*/
1804 static void
1805 outAcc (operand * result)
1806 {
1807   int size, offset;
1808   size = getDataSize (result);
1809   if (size)
1810     {
1811       aopPut (result, "a", 0);
1812       size--;
1813       offset = 1;
1814       /* unsigned or positive */
1815       while (size--)
1816         {
1817           aopPut (result, zero, offset++);
1818         }
1819     }
1820 }
1821
1822 /*-----------------------------------------------------------------*/
1823 /* outBitC - output a bit C                                        */
1824 /*-----------------------------------------------------------------*/
1825 static void
1826 outBitC (operand * result)
1827 {
1828   /* if the result is bit */
1829   if (AOP_TYPE (result) == AOP_CRY)
1830     {
1831       aopPut (result, "c", 0);
1832     }
1833   else
1834     {
1835       emitcode ("clr", "a");
1836       emitcode ("rlc", "a");
1837       outAcc (result);
1838     }
1839 }
1840
1841 /*-----------------------------------------------------------------*/
1842 /* toBoolean - emit code for orl a,operator(sizeop)                */
1843 /*-----------------------------------------------------------------*/
1844 static void
1845 toBoolean (operand * oper)
1846 {
1847   int size = AOP_SIZE (oper) - 1;
1848   int offset = 1;
1849   bool AccUsed = FALSE;
1850   bool pushedB;
1851
1852   while (!AccUsed && size--)
1853     {
1854       AccUsed |= aopGetUsesAcc(oper, offset++);
1855     }
1856
1857   size = AOP_SIZE (oper) - 1;
1858   offset = 1;
1859   MOVA (aopGet (oper, 0, FALSE, FALSE));
1860   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1861     {
1862       pushedB = pushB ();
1863       emitcode("mov", "b,a");
1864       while (--size)
1865         {
1866           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1867           emitcode ("orl", "b,a");
1868         }
1869       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1870       emitcode ("orl", "a,b");
1871       popB (pushedB);
1872     }
1873   else
1874     {
1875       while (size--)
1876         {
1877           emitcode ("orl", "a,%s",
1878                     aopGet (oper, offset++, FALSE, FALSE));
1879         }
1880     }
1881 }
1882
1883
1884 /*-------------------------------------------------------------------*/
1885 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1886 /*-------------------------------------------------------------------*/
1887 static char *
1888 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1889 {
1890   char * l;
1891
1892   if (aopGetUsesAcc (oper, offset))
1893     {
1894       emitcode("mov", "b,a");
1895       MOVA (aopGet (oper, offset, bit16, dname));
1896       emitcode("xch", "a,b");
1897       aopPut (oper, "a", offset);
1898       emitcode("xch", "a,b");
1899       l = "b";
1900     }
1901   else
1902     {
1903       l = aopGet (oper, offset, bit16, dname);
1904       emitcode("xch", "a,%s", l);
1905     }
1906   return l;
1907 }
1908
1909
1910 /*-----------------------------------------------------------------*/
1911 /* genNot - generate code for ! operation                          */
1912 /*-----------------------------------------------------------------*/
1913 static void
1914 genNot (iCode * ic)
1915 {
1916   symbol *tlbl;
1917
1918   D (emitcode (";", "genNot"));
1919
1920   /* assign asmOps to operand & result */
1921   aopOp (IC_LEFT (ic), ic, FALSE);
1922   aopOp (IC_RESULT (ic), ic, TRUE);
1923
1924   /* if in bit space then a special case */
1925   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1926     {
1927       /* if left==result then cpl bit */
1928       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1929         {
1930           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931         }
1932       else
1933         {
1934           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1935           emitcode ("cpl", "c");
1936           outBitC (IC_RESULT (ic));
1937         }
1938       goto release;
1939     }
1940
1941   toBoolean (IC_LEFT (ic));
1942
1943   /* set C, if a == 0 */
1944   tlbl = newiTempLabel (NULL);
1945   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1946   emitLabel (tlbl);
1947   outBitC (IC_RESULT (ic));
1948
1949 release:
1950   /* release the aops */
1951   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1952   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1953 }
1954
1955
1956 /*-----------------------------------------------------------------*/
1957 /* genCpl - generate code for complement                           */
1958 /*-----------------------------------------------------------------*/
1959 static void
1960 genCpl (iCode * ic)
1961 {
1962   int offset = 0;
1963   int size;
1964   symbol *tlbl;
1965   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1966
1967   D(emitcode (";", "genCpl"));
1968
1969   /* assign asmOps to operand & result */
1970   aopOp (IC_LEFT (ic), ic, FALSE);
1971   aopOp (IC_RESULT (ic), ic, TRUE);
1972
1973   /* special case if in bit space */
1974   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1975     {
1976       char *l;
1977
1978       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1979           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1980         {
1981           /* promotion rules are responsible for this strange result:
1982              bit -> int -> ~int -> bit
1983              uchar -> int -> ~int -> bit
1984           */
1985           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1986           goto release;
1987         }
1988
1989       tlbl=newiTempLabel(NULL);
1990       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1991       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1992           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1993           IS_AOP_PREG (IC_LEFT (ic)))
1994         {
1995           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1996         }
1997       else
1998         {
1999           MOVA (l);
2000           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2001         }
2002       emitLabel (tlbl);
2003       outBitC (IC_RESULT(ic));
2004       goto release;
2005     }
2006
2007   size = AOP_SIZE (IC_RESULT (ic));
2008   while (size--)
2009     {
2010       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2011       MOVA (l);
2012       emitcode ("cpl", "a");
2013       aopPut (IC_RESULT (ic), "a", offset++);
2014     }
2015
2016
2017 release:
2018   /* release the aops */
2019   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2020   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2021 }
2022
2023 /*-----------------------------------------------------------------*/
2024 /* genUminusFloat - unary minus for floating points                */
2025 /*-----------------------------------------------------------------*/
2026 static void
2027 genUminusFloat (operand * op, operand * result)
2028 {
2029   int size, offset = 0;
2030   char *l;
2031
2032   D (emitcode (";", "genUminusFloat"));
2033
2034   /* for this we just copy and then flip the bit */
2035
2036   size = AOP_SIZE (op) - 1;
2037
2038   while (size--)
2039     {
2040       aopPut (result,
2041               aopGet (op, offset, FALSE, FALSE),
2042               offset);
2043       offset++;
2044     }
2045
2046   l = aopGet (op, offset, FALSE, FALSE);
2047   MOVA (l);
2048
2049   emitcode ("cpl", "acc.7");
2050   aopPut (result, "a", offset);
2051 }
2052
2053 /*-----------------------------------------------------------------*/
2054 /* genUminus - unary minus code generation                         */
2055 /*-----------------------------------------------------------------*/
2056 static void
2057 genUminus (iCode * ic)
2058 {
2059   int offset, size;
2060   sym_link *optype;
2061
2062   D (emitcode (";", "genUminus"));
2063
2064   /* assign asmops */
2065   aopOp (IC_LEFT (ic), ic, FALSE);
2066   aopOp (IC_RESULT (ic), ic, TRUE);
2067
2068   /* if both in bit space then special
2069      case */
2070   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2071       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2072     {
2073
2074       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2075       emitcode ("cpl", "c");
2076       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2077       goto release;
2078     }
2079
2080   optype = operandType (IC_LEFT (ic));
2081
2082   /* if float then do float stuff */
2083   if (IS_FLOAT (optype))
2084     {
2085       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2086       goto release;
2087     }
2088
2089   /* otherwise subtract from zero */
2090   size = AOP_SIZE (IC_LEFT (ic));
2091   offset = 0;
2092   while (size--)
2093     {
2094       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2095       if (!strcmp (l, "a"))
2096         {
2097           if (offset == 0)
2098             SETC;
2099           emitcode ("cpl", "a");
2100           emitcode ("addc", "a,#0");
2101         }
2102       else
2103         {
2104           if (offset == 0)
2105             CLRC;
2106           emitcode ("clr", "a");
2107           emitcode ("subb", "a,%s", l);
2108         }
2109       aopPut (IC_RESULT (ic), "a", offset++);
2110     }
2111
2112   /* if any remaining bytes in the result */
2113   /* we just need to propagate the sign   */
2114   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2115     {
2116       emitcode ("rlc", "a");
2117       emitcode ("subb", "a,acc");
2118       while (size--)
2119         aopPut (IC_RESULT (ic), "a", offset++);
2120     }
2121
2122 release:
2123   /* release the aops */
2124   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2125   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2126 }
2127
2128 /*-----------------------------------------------------------------*/
2129 /* saveRegisters - will look for a call and save the registers     */
2130 /*-----------------------------------------------------------------*/
2131 static void
2132 saveRegisters (iCode * lic)
2133 {
2134   int i;
2135   iCode *ic;
2136   bitVect *rsave;
2137
2138   /* look for call */
2139   for (ic = lic; ic; ic = ic->next)
2140     if (ic->op == CALL || ic->op == PCALL)
2141       break;
2142
2143   if (!ic)
2144     {
2145       fprintf (stderr, "found parameter push with no function call\n");
2146       return;
2147     }
2148
2149   /* if the registers have been saved already or don't need to be then
2150      do nothing */
2151   if (ic->regsSaved)
2152     return;
2153   if (IS_SYMOP(IC_LEFT(ic)) &&
2154       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2155        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2156     return;
2157
2158   /* save the registers in use at this time but skip the
2159      ones for the result */
2160   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2161                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2162
2163   ic->regsSaved = 1;
2164   if (options.useXstack)
2165     {
2166       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2167       int nBits = bitVectnBitsOn (rsavebits);
2168       int count = bitVectnBitsOn (rsave);
2169
2170       if (nBits != 0)
2171         {
2172           count = count - nBits + 1;
2173           /* remove all but the first bits as they are pushed all at once */
2174           rsave = bitVectCplAnd (rsave, rsavebits);
2175           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2176         }
2177
2178       if (count == 1)
2179         {
2180           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2181           if (reg->type == REG_BIT)
2182             {
2183               emitcode ("mov", "a,%s", reg->base);
2184             }
2185           else
2186             {
2187               emitcode ("mov", "a,%s", reg->name);
2188             }
2189           emitcode ("mov", "r0,%s", spname);
2190           emitcode ("inc", "%s", spname);// allocate before use
2191           emitcode ("movx", "@r0,a");
2192           if (bitVectBitValue (rsave, R0_IDX))
2193             emitcode ("mov", "r0,a");
2194         }
2195       else if (count != 0)
2196         {
2197           if (bitVectBitValue (rsave, R0_IDX))
2198             {
2199               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2200             }
2201           emitcode ("mov", "r0,%s", spname);
2202           MOVA ("r0");
2203           emitcode ("add", "a,#%d", count);
2204           emitcode ("mov", "%s,a", spname);
2205           for (i = 0; i < mcs51_nRegs; i++)
2206             {
2207               if (bitVectBitValue (rsave, i))
2208                 {
2209                   regs * reg = REG_WITH_INDEX (i);
2210                   if (i == R0_IDX)
2211                     {
2212                       emitcode ("pop", "acc");
2213                       emitcode ("push", "acc");
2214                     }
2215                   else if (reg->type == REG_BIT)
2216                     {
2217                       emitcode ("mov", "a,%s", reg->base);
2218                     }
2219                   else
2220                     {
2221                       emitcode ("mov", "a,%s", reg->name);
2222                     }
2223                   emitcode ("movx", "@r0,a");
2224                   if (--count)
2225                     {
2226                       emitcode ("inc", "r0");
2227                     }
2228                 }
2229             }
2230           if (bitVectBitValue (rsave, R0_IDX))
2231             {
2232               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2233             }
2234         }
2235     }
2236   else
2237     {
2238       bool bits_pushed = FALSE;
2239       for (i = 0; i < mcs51_nRegs; i++)
2240         {
2241           if (bitVectBitValue (rsave, i))
2242             {
2243               bits_pushed = pushReg (i, bits_pushed);
2244             }
2245         }
2246     }
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* unsaveRegisters - pop the pushed registers                      */
2251 /*-----------------------------------------------------------------*/
2252 static void
2253 unsaveRegisters (iCode * ic)
2254 {
2255   int i;
2256   bitVect *rsave;
2257
2258   /* restore the registers in use at this time but skip the
2259      ones for the result */
2260   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2261                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2262
2263   if (options.useXstack)
2264     {
2265       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2266       int nBits = bitVectnBitsOn (rsavebits);
2267       int count = bitVectnBitsOn (rsave);
2268
2269       if (nBits != 0)
2270         {
2271           count = count - nBits + 1;
2272           /* remove all but the first bits as they are popped all at once */
2273           rsave = bitVectCplAnd (rsave, rsavebits);
2274           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2275         }
2276
2277       if (count == 1)
2278         {
2279           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2280           emitcode ("mov", "r0,%s", spname);
2281           emitcode ("dec", "r0");
2282           emitcode ("movx", "a,@r0");
2283           if (reg->type == REG_BIT)
2284             {
2285               emitcode ("mov", "%s,a", reg->base);
2286             }
2287           else
2288             {
2289               emitcode ("mov", "%s,a", reg->name);
2290             }
2291           emitcode ("dec", "%s", spname);
2292         }
2293       else if (count != 0)
2294         {
2295           emitcode ("mov", "r0,%s", spname);
2296           for (i = mcs51_nRegs; i >= 0; i--)
2297             {
2298               if (bitVectBitValue (rsave, i))
2299                 {
2300                   regs * reg = REG_WITH_INDEX (i);
2301                   emitcode ("dec", "r0");
2302                   emitcode ("movx", "a,@r0");
2303                   if (i == R0_IDX)
2304                     {
2305                       emitcode ("push", "acc");
2306                     }
2307                   else if (reg->type == REG_BIT)
2308                     {
2309                       emitcode ("mov", "%s,a", reg->base);
2310                     }
2311                   else
2312                     {
2313                       emitcode ("mov", "%s,a", reg->name);
2314                     }
2315                 }
2316             }
2317           emitcode ("mov", "%s,r0", spname);
2318           if (bitVectBitValue (rsave, R0_IDX))
2319             {
2320               emitcode ("pop", "ar0");
2321             }
2322         }
2323     }
2324   else
2325     {
2326       bool bits_popped = FALSE;
2327       for (i = mcs51_nRegs; i >= 0; i--)
2328         {
2329           if (bitVectBitValue (rsave, i))
2330             {
2331               bits_popped = popReg (i, bits_popped);
2332             }
2333         }
2334     }
2335 }
2336
2337
2338 /*-----------------------------------------------------------------*/
2339 /* pushSide -                                                      */
2340 /*-----------------------------------------------------------------*/
2341 static void
2342 pushSide (operand * oper, int size)
2343 {
2344   int offset = 0;
2345   while (size--)
2346     {
2347       char *l = aopGet (oper, offset++, FALSE, TRUE);
2348       if (AOP_TYPE (oper) != AOP_REG &&
2349           AOP_TYPE (oper) != AOP_DIR &&
2350           strcmp (l, "a"))
2351         {
2352           MOVA (l);
2353           emitcode ("push", "acc");
2354         }
2355       else
2356         {
2357           emitcode ("push", "%s", l);
2358         }
2359     }
2360 }
2361
2362 /*-----------------------------------------------------------------*/
2363 /* assignResultValue - also indicates if acc is in use afterwards  */
2364 /*-----------------------------------------------------------------*/
2365 static bool
2366 assignResultValue (operand * oper, operand * func)
2367 {
2368   int offset = 0;
2369   int size = AOP_SIZE (oper);
2370   bool accuse = FALSE;
2371   bool pushedA = FALSE;
2372
2373   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2374     {
2375       outBitC (oper);
2376       return FALSE;
2377     }
2378
2379   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2380     {
2381       emitcode ("push", "acc");
2382       pushedA = TRUE;
2383     }
2384   while (size--)
2385     {
2386       if ((offset == 3) && pushedA)
2387         emitcode ("pop", "acc");
2388       accuse |= aopPut (oper, fReturn[offset], offset);
2389       offset++;
2390     }
2391   return accuse;
2392 }
2393
2394
2395 /*-----------------------------------------------------------------*/
2396 /* genXpush - pushes onto the external stack                       */
2397 /*-----------------------------------------------------------------*/
2398 static void
2399 genXpush (iCode * ic)
2400 {
2401   asmop *aop = newAsmop (0);
2402   regs *r;
2403   int size, offset = 0;
2404
2405   D (emitcode (";", "genXpush"));
2406
2407   aopOp (IC_LEFT (ic), ic, FALSE);
2408   r = getFreePtr (ic, &aop, FALSE);
2409
2410   size = AOP_SIZE (IC_LEFT (ic));
2411
2412   if (size == 1)
2413     {
2414       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2415       emitcode ("mov", "%s,%s", r->name, spname);
2416       emitcode ("inc", "%s", spname); // allocate space first
2417       emitcode ("movx", "@%s,a", r->name);
2418     }
2419   else
2420     {
2421       // allocate space first
2422       emitcode ("mov", "%s,%s", r->name, spname);
2423       MOVA (r->name);
2424       emitcode ("add", "a,#%d", size);
2425       emitcode ("mov", "%s,a", spname);
2426
2427       while (size--)
2428         {
2429           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2430           emitcode ("movx", "@%s,a", r->name);
2431           emitcode ("inc", "%s", r->name);
2432         }
2433     }
2434
2435   freeAsmop (NULL, aop, ic, TRUE);
2436   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2437 }
2438
2439 /*-----------------------------------------------------------------*/
2440 /* genIpush - generate code for pushing this gets a little complex */
2441 /*-----------------------------------------------------------------*/
2442 static void
2443 genIpush (iCode * ic)
2444 {
2445   int size, offset = 0;
2446   char *l;
2447   char *prev = "";
2448
2449   D (emitcode (";", "genIpush"));
2450
2451   /* if this is not a parm push : ie. it is spill push
2452      and spill push is always done on the local stack */
2453   if (!ic->parmPush)
2454     {
2455
2456       /* and the item is spilt then do nothing */
2457       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2458         return;
2459
2460       aopOp (IC_LEFT (ic), ic, FALSE);
2461       size = AOP_SIZE (IC_LEFT (ic));
2462       /* push it on the stack */
2463       while (size--)
2464         {
2465           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2466           if (*l == '#')
2467             {
2468               MOVA (l);
2469               l = "acc";
2470             }
2471           emitcode ("push", "%s", l);
2472         }
2473       return;
2474     }
2475
2476   /* this is a parameter push: in this case we call
2477      the routine to find the call and save those
2478      registers that need to be saved */
2479   saveRegisters (ic);
2480
2481   /* if use external stack then call the external
2482      stack pushing routine */
2483   if (options.useXstack)
2484     {
2485       genXpush (ic);
2486       return;
2487     }
2488
2489   /* then do the push */
2490   aopOp (IC_LEFT (ic), ic, FALSE);
2491
2492   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2493   size = AOP_SIZE (IC_LEFT (ic));
2494
2495   while (size--)
2496     {
2497       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2498       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2499           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2500         {
2501           if (strcmp (l, prev) || *l == '@')
2502             MOVA (l);
2503           emitcode ("push", "acc");
2504         }
2505       else
2506         {
2507           emitcode ("push", "%s", l);
2508         }
2509       prev = l;
2510     }
2511
2512   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* genIpop - recover the registers: can happen only for spilling   */
2517 /*-----------------------------------------------------------------*/
2518 static void
2519 genIpop (iCode * ic)
2520 {
2521   int size, offset;
2522
2523   D (emitcode (";", "genIpop"));
2524
2525   /* if the temp was not pushed then */
2526   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2527     return;
2528
2529   aopOp (IC_LEFT (ic), ic, FALSE);
2530   size = AOP_SIZE (IC_LEFT (ic));
2531   offset = (size - 1);
2532   while (size--)
2533     {
2534       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2535                                      FALSE, TRUE));
2536     }
2537
2538   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* saveRBank - saves an entire register bank on the stack          */
2543 /*-----------------------------------------------------------------*/
2544 static void
2545 saveRBank (int bank, iCode * ic, bool pushPsw)
2546 {
2547   int i;
2548   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2549   asmop *aop = NULL;
2550   regs *r = NULL;
2551
2552   if (options.useXstack)
2553     {
2554       if (!ic)
2555         {
2556           /* Assume r0 is available for use. */
2557           r = REG_WITH_INDEX (R0_IDX);;
2558         }
2559       else
2560         {
2561           aop = newAsmop (0);
2562           r = getFreePtr (ic, &aop, FALSE);
2563         }
2564       // allocate space first
2565       emitcode ("mov", "%s,%s", r->name, spname);
2566       MOVA (r->name);
2567       emitcode ("add", "a,#%d", count);
2568       emitcode ("mov", "%s,a", spname);
2569     }
2570
2571   for (i = 0; i < 8; i++)
2572     {
2573       if (options.useXstack)
2574         {
2575           emitcode ("mov", "a,(%s+%d)",
2576                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2577           emitcode ("movx", "@%s,a", r->name);
2578           if (--count)
2579             emitcode ("inc", "%s", r->name);
2580         }
2581       else
2582         emitcode ("push", "(%s+%d)",
2583                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2584     }
2585
2586   if (mcs51_nRegs > 8)
2587     {
2588       if (options.useXstack)
2589         {
2590           emitcode ("mov", "a,bits");
2591           emitcode ("movx", "@%s,a", r->name);
2592           if (--count)
2593             emitcode ("inc", "%s", r->name);
2594         }
2595       else
2596         {
2597           emitcode ("push", "bits");
2598         }
2599       BitBankUsed = 1;
2600     }
2601
2602   if (pushPsw)
2603     {
2604       if (options.useXstack)
2605         {
2606           emitcode ("mov", "a,psw");
2607           emitcode ("movx", "@%s,a", r->name);
2608         }
2609       else
2610         {
2611           emitcode ("push", "psw");
2612         }
2613
2614       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2615     }
2616
2617   if (aop)
2618     {
2619       freeAsmop (NULL, aop, ic, TRUE);
2620     }
2621
2622   if (ic)
2623   {
2624     ic->bankSaved = 1;
2625   }
2626 }
2627
2628 /*-----------------------------------------------------------------*/
2629 /* unsaveRBank - restores the register bank from stack             */
2630 /*-----------------------------------------------------------------*/
2631 static void
2632 unsaveRBank (int bank, iCode * ic, bool popPsw)
2633 {
2634   int i;
2635   asmop *aop = NULL;
2636   regs *r = NULL;
2637
2638   if (options.useXstack)
2639     {
2640       if (!ic)
2641         {
2642           /* Assume r0 is available for use. */
2643           r = REG_WITH_INDEX (R0_IDX);;
2644         }
2645       else
2646         {
2647           aop = newAsmop (0);
2648           r = getFreePtr (ic, &aop, FALSE);
2649         }
2650       emitcode ("mov", "%s,%s", r->name, spname);
2651     }
2652
2653   if (popPsw)
2654     {
2655       if (options.useXstack)
2656         {
2657           emitcode ("dec", "%s", r->name);
2658           emitcode ("movx", "a,@%s", r->name);
2659           emitcode ("mov", "psw,a");
2660         }
2661       else
2662         {
2663           emitcode ("pop", "psw");
2664         }
2665     }
2666
2667   if (mcs51_nRegs > 8)
2668     {
2669       if (options.useXstack)
2670         {
2671           emitcode ("dec", "%s", r->name);
2672           emitcode ("movx", "a,@%s", r->name);
2673           emitcode ("mov", "bits,a");
2674         }
2675       else
2676         {
2677           emitcode ("pop", "bits");
2678         }
2679     }
2680
2681   for (i = 7; i >= 0; i--)
2682     {
2683       if (options.useXstack)
2684         {
2685           emitcode ("dec", "%s", r->name);
2686           emitcode ("movx", "a,@%s", r->name);
2687           emitcode ("mov", "(%s+%d),a",
2688                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2689         }
2690       else
2691         {
2692           emitcode ("pop", "(%s+%d)",
2693                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2694         }
2695     }
2696
2697   if (options.useXstack)
2698     {
2699       emitcode ("mov", "%s,%s", spname, r->name);
2700     }
2701
2702   if (aop)
2703     {
2704       freeAsmop (NULL, aop, ic, TRUE);
2705     }
2706 }
2707
2708 /*-----------------------------------------------------------------*/
2709 /* genSend - gen code for SEND                                     */
2710 /*-----------------------------------------------------------------*/
2711 static void genSend(set *sendSet)
2712 {
2713   iCode *sic;
2714   int bit_count = 0;
2715
2716   /* first we do all bit parameters */
2717   for (sic = setFirstItem (sendSet); sic;
2718        sic = setNextItem (sendSet))
2719     {
2720       if (sic->argreg > 12)
2721         {
2722           int bit = sic->argreg-13;
2723
2724           aopOp (IC_LEFT (sic), sic, FALSE);
2725
2726           /* if left is a literal then
2727              we know what the value is */
2728           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2729             {
2730               if (((int) operandLitValue (IC_LEFT (sic))))
2731                   emitcode ("setb", "b[%d]", bit);
2732               else
2733                   emitcode ("clr", "b[%d]", bit);
2734             }
2735           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2736             {
2737               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2738                 if (strcmp (l, "c"))
2739                     emitcode ("mov", "c,%s", l);
2740                 emitcode ("mov", "b[%d],c", bit);
2741             }
2742           else
2743             {
2744               /* we need to or */
2745               toBoolean (IC_LEFT (sic));
2746               /* set C, if a >= 1 */
2747               emitcode ("add", "a,#0xff");
2748               emitcode ("mov", "b[%d],c", bit);
2749             }
2750           bit_count++;
2751           BitBankUsed = 1;
2752
2753           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2754         }
2755     }
2756
2757   if (bit_count)
2758     {
2759       saveRegisters (setFirstItem (sendSet));
2760       emitcode ("mov", "bits,b");
2761     }
2762
2763   /* then we do all other parameters */
2764   for (sic = setFirstItem (sendSet); sic;
2765        sic = setNextItem (sendSet))
2766     {
2767       if (sic->argreg <= 12)
2768         {
2769           int size, offset = 0;
2770           aopOp (IC_LEFT (sic), sic, FALSE);
2771           size = AOP_SIZE (IC_LEFT (sic));
2772
2773           if (sic->argreg == 1)
2774             {
2775               while (size--)
2776                 {
2777                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2778                   if (strcmp (l, fReturn[offset]))
2779                     {
2780                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2781                     }
2782                   offset++;
2783                 }
2784             }
2785           else
2786             {
2787               while (size--)
2788                 {
2789                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2790                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2791                   offset++;
2792                 }
2793             }
2794           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2795         }
2796     }
2797 }
2798
2799 /*-----------------------------------------------------------------*/
2800 /* selectRegBank - emit code to select the register bank           */
2801 /*-----------------------------------------------------------------*/
2802 static void
2803 selectRegBank (short bank, bool keepFlags)
2804 {
2805   /* if f.e. result is in carry */
2806   if (keepFlags)
2807     {
2808       emitcode ("anl", "psw,#0xE7");
2809       if (bank)
2810         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2811     }
2812   else
2813     {
2814       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2815     }
2816 }
2817
2818 /*-----------------------------------------------------------------*/
2819 /* genCall - generates a call statement                            */
2820 /*-----------------------------------------------------------------*/
2821 static void
2822 genCall (iCode * ic)
2823 {
2824   sym_link *dtype;
2825   sym_link *etype;
2826 //  bool restoreBank = FALSE;
2827   bool swapBanks = FALSE;
2828   bool accuse = FALSE;
2829   bool accPushed = FALSE;
2830   bool resultInF0 = FALSE;
2831   bool assignResultGenerated = FALSE;
2832
2833   D (emitcode (";", "genCall"));
2834
2835   dtype = operandType (IC_LEFT (ic));
2836   etype = getSpec(dtype);
2837   /* if send set is not empty then assign */
2838   if (_G.sendSet)
2839     {
2840         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2841             genSend(reverseSet(_G.sendSet));
2842         } else {
2843             genSend(_G.sendSet);
2844         }
2845       _G.sendSet = NULL;
2846     }
2847
2848   /* if we are calling a not _naked function that is not using
2849      the same register bank then we need to save the
2850      destination registers on the stack */
2851   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2852       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2853        !IFFUNC_ISISR (dtype))
2854     {
2855       swapBanks = TRUE;
2856     }
2857
2858   /* if caller saves & we have not saved then */
2859   if (!ic->regsSaved)
2860       saveRegisters (ic);
2861
2862   if (swapBanks)
2863     {
2864         emitcode ("mov", "psw,#0x%02x",
2865            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2866     }
2867
2868   /* make the call */
2869   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2870     {
2871       if (IFFUNC_CALLEESAVES(dtype))
2872         {
2873           werror (E_BANKED_WITH_CALLEESAVES);
2874         }
2875       else
2876         {
2877           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2878                      OP_SYMBOL (IC_LEFT (ic))->rname :
2879                      OP_SYMBOL (IC_LEFT (ic))->name);
2880
2881           emitcode ("mov", "r0,#%s", l);
2882           emitcode ("mov", "r1,#(%s >> 8)", l);
2883           emitcode ("mov", "r2,#(%s >> 16)", l);
2884           emitcode ("lcall", "__sdcc_banked_call");
2885         }
2886     }
2887   else
2888     {
2889       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2890                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2891                                 OP_SYMBOL (IC_LEFT (ic))->name));
2892     }
2893
2894   if (swapBanks)
2895     {
2896       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2897     }
2898
2899   /* if we need assign a result value */
2900   if ((IS_ITEMP (IC_RESULT (ic)) &&
2901        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2902        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2903         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2904         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2905       IS_TRUE_SYMOP (IC_RESULT (ic)))
2906     {
2907
2908       _G.accInUse++;
2909       aopOp (IC_RESULT (ic), ic, FALSE);
2910       _G.accInUse--;
2911
2912       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2913       assignResultGenerated = TRUE;
2914
2915       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2916     }
2917
2918   /* adjust the stack for parameters if required */
2919   if (ic->parmBytes)
2920     {
2921       int i;
2922       if (ic->parmBytes > 3)
2923         {
2924           if (accuse)
2925             {
2926               emitcode ("push", "acc");
2927               accPushed = TRUE;
2928             }
2929           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2930               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2931               !assignResultGenerated)
2932             {
2933               emitcode ("mov", "F0,c");
2934               resultInF0 = TRUE;
2935             }
2936
2937           emitcode ("mov", "a,%s", spname);
2938           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2939           emitcode ("mov", "%s,a", spname);
2940
2941           /* unsaveRegisters from xstack needs acc, but */
2942           /* unsaveRegisters from stack needs this popped */
2943           if (accPushed && !options.useXstack)
2944             {
2945               emitcode ("pop", "acc");
2946               accPushed = FALSE;
2947             }
2948         }
2949       else
2950         for (i = 0; i < ic->parmBytes; i++)
2951           emitcode ("dec", "%s", spname);
2952     }
2953
2954   /* if we had saved some registers then unsave them */
2955   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2956     {
2957       if (accuse && !accPushed && options.useXstack)
2958         {
2959           /* xstack needs acc, but doesn't touch normal stack */
2960           emitcode ("push", "acc");
2961           accPushed = TRUE;
2962         }
2963       unsaveRegisters (ic);
2964     }
2965
2966 //  /* if register bank was saved then pop them */
2967 //  if (restoreBank)
2968 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2969
2970   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2971     {
2972       if (resultInF0)
2973           emitcode ("mov", "c,F0");
2974
2975       aopOp (IC_RESULT (ic), ic, FALSE);
2976       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2977       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2978     }
2979
2980   if (accPushed)
2981     emitcode ("pop", "acc");
2982 }
2983
2984 /*-----------------------------------------------------------------*/
2985 /* genPcall - generates a call by pointer statement                */
2986 /*-----------------------------------------------------------------*/
2987 static void
2988 genPcall (iCode * ic)
2989 {
2990   sym_link *dtype;
2991   sym_link *etype;
2992   symbol *rlbl = newiTempLabel (NULL);
2993 //  bool restoreBank=FALSE;
2994   bool swapBanks = FALSE;
2995   bool resultInF0 = FALSE;
2996
2997   D (emitcode (";", "genPcall"));
2998
2999   dtype = operandType (IC_LEFT (ic))->next;
3000   etype = getSpec(dtype);
3001   /* if caller saves & we have not saved then */
3002   if (!ic->regsSaved)
3003     saveRegisters (ic);
3004
3005   /* if we are calling a not _naked function that is not using
3006      the same register bank then we need to save the
3007      destination registers on the stack */
3008   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3009       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3010       !IFFUNC_ISISR (dtype))
3011     {
3012 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3013 //    restoreBank=TRUE;
3014       swapBanks = TRUE;
3015       // need caution message to user here
3016     }
3017
3018   if (IS_LITERAL(etype))
3019     {
3020       /* if send set is not empty then assign */
3021       if (_G.sendSet)
3022         {
3023           genSend(reverseSet(_G.sendSet));
3024           _G.sendSet = NULL;
3025         }
3026
3027       if (swapBanks)
3028         {
3029           emitcode ("mov", "psw,#0x%02x",
3030            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3031         }
3032
3033       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3034         {
3035           if (IFFUNC_CALLEESAVES(dtype))
3036             {
3037               werror (E_BANKED_WITH_CALLEESAVES);
3038             }
3039           else
3040             {
3041               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3042
3043               emitcode ("mov", "r0,#%s", l);
3044               emitcode ("mov", "r1,#(%s >> 8)", l);
3045               emitcode ("mov", "r2,#(%s >> 16)", l);
3046               emitcode ("lcall", "__sdcc_banked_call");
3047             }
3048         }
3049       else
3050         {
3051           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3052         }
3053     }
3054   else
3055     {
3056       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3057         {
3058           if (IFFUNC_CALLEESAVES(dtype))
3059             {
3060               werror (E_BANKED_WITH_CALLEESAVES);
3061             }
3062           else
3063             {
3064               aopOp (IC_LEFT (ic), ic, FALSE);
3065
3066               if (!swapBanks)
3067                 {
3068                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3069                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3070                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3071                 }
3072               else
3073                 {
3074                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3075                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3076                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3077                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3078                 }
3079
3080               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3081
3082               /* if send set is not empty then assign */
3083               if (_G.sendSet)
3084                 {
3085                   genSend(reverseSet(_G.sendSet));
3086                   _G.sendSet = NULL;
3087                 }
3088
3089               if (swapBanks)
3090                 {
3091                   emitcode ("mov", "psw,#0x%02x",
3092                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3093                 }
3094
3095               /* make the call */
3096               emitcode ("lcall", "__sdcc_banked_call");
3097             }
3098         }
3099       else
3100         {
3101           /* push the return address on to the stack */
3102           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3103           emitcode ("push", "acc");
3104           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3105           emitcode ("push", "acc");
3106
3107           /* now push the calling address */
3108           aopOp (IC_LEFT (ic), ic, FALSE);
3109
3110           pushSide (IC_LEFT (ic), FPTRSIZE);
3111
3112           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3113
3114           /* if send set is not empty the assign */
3115           if (_G.sendSet)
3116             {
3117               genSend(reverseSet(_G.sendSet));
3118               _G.sendSet = NULL;
3119             }
3120
3121           if (swapBanks)
3122             {
3123               emitcode ("mov", "psw,#0x%02x",
3124                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3125             }
3126
3127           /* make the call */
3128           emitcode ("ret", "");
3129           emitLabel (rlbl);
3130         }
3131     }
3132   if (swapBanks)
3133     {
3134       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3135     }
3136
3137   /* if we need assign a result value */
3138   if ((IS_ITEMP (IC_RESULT (ic)) &&
3139        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3140        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3141         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3142       IS_TRUE_SYMOP (IC_RESULT (ic)))
3143     {
3144
3145       _G.accInUse++;
3146       aopOp (IC_RESULT (ic), ic, FALSE);
3147       _G.accInUse--;
3148
3149       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3150
3151       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3152     }
3153
3154   /* adjust the stack for parameters if required */
3155   if (ic->parmBytes)
3156     {
3157       int i;
3158       if (ic->parmBytes > 3)
3159         {
3160           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3161               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3162             {
3163               emitcode ("mov", "F0,c");
3164               resultInF0 = TRUE;
3165             }
3166
3167           emitcode ("mov", "a,%s", spname);
3168           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3169           emitcode ("mov", "%s,a", spname);
3170         }
3171       else
3172         for (i = 0; i < ic->parmBytes; i++)
3173           emitcode ("dec", "%s", spname);
3174     }
3175
3176 //  /* if register bank was saved then unsave them */
3177 //  if (restoreBank)
3178 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3179
3180   /* if we had saved some registers then unsave them */
3181   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3182     unsaveRegisters (ic);
3183
3184   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3185     {
3186       if (resultInF0)
3187           emitcode ("mov", "c,F0");
3188
3189       aopOp (IC_RESULT (ic), ic, FALSE);
3190       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3191       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3192     }
3193 }
3194
3195 /*-----------------------------------------------------------------*/
3196 /* resultRemat - result  is rematerializable                       */
3197 /*-----------------------------------------------------------------*/
3198 static int
3199 resultRemat (iCode * ic)
3200 {
3201   if (SKIP_IC (ic) || ic->op == IFX)
3202     return 0;
3203
3204   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3205     {
3206       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3207       if (sym->remat && !POINTER_SET (ic))
3208         return 1;
3209     }
3210
3211   return 0;
3212 }
3213
3214 /*-----------------------------------------------------------------*/
3215 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3216 /*-----------------------------------------------------------------*/
3217 static int
3218 regsCmp(void *p1, void *p2)
3219 {
3220   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3221 }
3222
3223 static bool
3224 inExcludeList (char *s)
3225 {
3226   const char *p = setFirstItem(options.excludeRegsSet);
3227
3228   if (p == NULL || STRCASECMP(p, "none") == 0)
3229     return FALSE;
3230
3231
3232   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3233 }
3234
3235 /*-----------------------------------------------------------------*/
3236 /* genFunction - generated code for function entry                 */
3237 /*-----------------------------------------------------------------*/
3238 static void
3239 genFunction (iCode * ic)
3240 {
3241   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3242   sym_link *ftype;
3243   bool     switchedPSW = FALSE;
3244   int      calleesaves_saved_register = -1;
3245   int      stackAdjust = sym->stack;
3246   int      accIsFree = sym->recvSize < 4;
3247   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3248   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3249
3250   _G.nRegsSaved = 0;
3251   /* create the function header */
3252   emitcode (";", "-----------------------------------------");
3253   emitcode (";", " function %s", sym->name);
3254   emitcode (";", "-----------------------------------------");
3255
3256   emitcode ("", "%s:", sym->rname);
3257   lineCurr->isLabel = 1;
3258   ftype = operandType (IC_LEFT (ic));
3259   _G.currentFunc = sym;
3260
3261   if (IFFUNC_ISNAKED(ftype))
3262   {
3263       emitcode(";", "naked function: no prologue.");
3264       return;
3265   }
3266
3267   /* here we need to generate the equates for the
3268      register bank if required */
3269   if (FUNC_REGBANK (ftype) != rbank)
3270     {
3271       int i;
3272
3273       rbank = FUNC_REGBANK (ftype);
3274       for (i = 0; i < mcs51_nRegs; i++)
3275         {
3276           if (regs8051[i].type != REG_BIT)
3277             {
3278               if (strcmp (regs8051[i].base, "0") == 0)
3279                 emitcode ("", "%s = 0x%02x",
3280                           regs8051[i].dname,
3281                           8 * rbank + regs8051[i].offset);
3282               else
3283                 emitcode ("", "%s = %s + 0x%02x",
3284                           regs8051[i].dname,
3285                           regs8051[i].base,
3286                           8 * rbank + regs8051[i].offset);
3287             }
3288         }
3289     }
3290
3291   /* if this is an interrupt service routine then
3292      save acc, b, dpl, dph  */
3293   if (IFFUNC_ISISR (sym->type))
3294     {
3295       if (!inExcludeList ("acc"))
3296         emitcode ("push", "acc");
3297       if (!inExcludeList ("b"))
3298         emitcode ("push", "b");
3299       if (!inExcludeList ("dpl"))
3300         emitcode ("push", "dpl");
3301       if (!inExcludeList ("dph"))
3302         emitcode ("push", "dph");
3303       /* if this isr has no bank i.e. is going to
3304          run with bank 0 , then we need to save more
3305          registers :-) */
3306       if (!FUNC_REGBANK (sym->type))
3307         {
3308           int i;
3309
3310           /* if this function does not call any other
3311              function then we can be economical and
3312              save only those registers that are used */
3313           if (!IFFUNC_HASFCALL(sym->type))
3314             {
3315               /* if any registers used */
3316               if (sym->regsUsed)
3317                 {
3318                   bool bits_pushed = FALSE;
3319                   /* save the registers used */
3320                   for (i = 0; i < sym->regsUsed->size; i++)
3321                     {
3322                       if (bitVectBitValue (sym->regsUsed, i))
3323                         bits_pushed = pushReg (i, bits_pushed);
3324                     }
3325                 }
3326             }
3327           else
3328             {
3329               /* this function has a function call. We cannot
3330                  determine register usage so we will have to push the
3331                  entire bank */
3332                 saveRBank (0, ic, FALSE);
3333                 if (options.parms_in_bank1) {
3334                     for (i=0; i < 8 ; i++ ) {
3335                         emitcode ("push","%s",rb1regs[i]);
3336                     }
3337                 }
3338             }
3339         }
3340         else
3341         {
3342             /* This ISR uses a non-zero bank.
3343              *
3344              * We assume that the bank is available for our
3345              * exclusive use.
3346              *
3347              * However, if this ISR calls a function which uses some
3348              * other bank, we must save that bank entirely.
3349              */
3350             unsigned long banksToSave = 0;
3351
3352             if (IFFUNC_HASFCALL(sym->type))
3353             {
3354
3355 #define MAX_REGISTER_BANKS 4
3356
3357                 iCode *i;
3358                 int ix;
3359
3360                 for (i = ic; i; i = i->next)
3361                 {
3362                     if (i->op == ENDFUNCTION)
3363                     {
3364                         /* we got to the end OK. */
3365                         break;
3366                     }
3367
3368                     if (i->op == CALL)
3369                     {
3370                         sym_link *dtype;
3371
3372                         dtype = operandType (IC_LEFT(i));
3373                         if (dtype
3374                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3375                         {
3376                              /* Mark this bank for saving. */
3377                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3378                              {
3379                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3380                              }
3381                              else
3382                              {
3383                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3384                              }
3385
3386                              /* And note that we don't need to do it in
3387                               * genCall.
3388                               */
3389                              i->bankSaved = 1;
3390                         }
3391                     }
3392                     if (i->op == PCALL)
3393                     {
3394                         /* This is a mess; we have no idea what
3395                          * register bank the called function might
3396                          * use.
3397                          *
3398                          * The only thing I can think of to do is
3399                          * throw a warning and hope.
3400                          */
3401                         werror(W_FUNCPTR_IN_USING_ISR);
3402                     }
3403                 }
3404
3405                 if (banksToSave && options.useXstack)
3406                 {
3407                     /* Since we aren't passing it an ic,
3408                      * saveRBank will assume r0 is available to abuse.
3409                      *
3410                      * So switch to our (trashable) bank now, so
3411                      * the caller's R0 isn't trashed.
3412                      */
3413                     emitcode ("push", "psw");
3414                     emitcode ("mov", "psw,#0x%02x",
3415                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3416                     switchedPSW = TRUE;
3417                 }
3418
3419                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3420                 {
3421                      if (banksToSave & (1 << ix))
3422                      {
3423                          saveRBank(ix, NULL, FALSE);
3424                      }
3425                 }
3426             }
3427             // TODO: this needs a closer look
3428             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3429         }
3430
3431       /* Set the register bank to the desired value if nothing else */
3432       /* has done so yet. */
3433       if (!switchedPSW)
3434         {
3435           emitcode ("push", "psw");
3436           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3437         }
3438     }
3439   else
3440     {
3441       /* This is a non-ISR function. The caller has already switched register */
3442       /* banks, if necessary, so just handle the callee-saves option. */
3443
3444       /* if callee-save to be used for this function
3445          then save the registers being used in this function */
3446       if (IFFUNC_CALLEESAVES(sym->type))
3447         {
3448           int i;
3449
3450           /* if any registers used */
3451           if (sym->regsUsed)
3452             {
3453               bool bits_pushed = FALSE;
3454               /* save the registers used */
3455               for (i = 0; i < sym->regsUsed->size; i++)
3456                 {
3457                   if (bitVectBitValue (sym->regsUsed, i))
3458                     {
3459                       /* remember one saved register for later usage */
3460                       if (calleesaves_saved_register < 0)
3461                         calleesaves_saved_register = i;
3462                       bits_pushed = pushReg (i, bits_pushed);
3463                       _G.nRegsSaved++;
3464                     }
3465                 }
3466             }
3467         }
3468     }
3469
3470   if (fReentrant)
3471     {
3472       if (options.useXstack)
3473         {
3474           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3475             {
3476               emitcode ("mov", "r0,%s", spname);
3477               emitcode ("inc", "%s", spname);
3478               emitcode ("xch", "a,_bpx");
3479               emitcode ("movx", "@r0,a");
3480               emitcode ("inc", "r0");
3481               emitcode ("mov", "a,r0");
3482               emitcode ("xch", "a,_bpx");
3483             }
3484           if (sym->stack)
3485             {
3486               emitcode ("push", "_bp");     /* save the callers stack  */
3487               emitcode ("mov", "_bp,sp");
3488             }
3489         }
3490       else
3491         {
3492           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3493             {
3494               /* set up the stack */
3495               emitcode ("push", "_bp");     /* save the callers stack  */
3496               emitcode ("mov", "_bp,sp");
3497             }
3498         }
3499     }
3500
3501   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3502   /* before setting up the stack frame completely. */
3503   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3504     {
3505       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3506
3507       if (rsym->isitmp)
3508         {
3509           if (rsym && rsym->regType == REG_CND)
3510             rsym = NULL;
3511           if (rsym && (rsym->accuse || rsym->ruonly))
3512             rsym = NULL;
3513           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3514             rsym = rsym->usl.spillLoc;
3515         }
3516
3517       /* If the RECEIVE operand immediately spills to the first entry on the */
3518       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3519       /* rather than the usual @r0/r1 machinations. */
3520       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3521         {
3522           int ofs;
3523
3524           _G.current_iCode = ric;
3525           D(emitcode (";     genReceive",""));
3526           for (ofs=0; ofs < sym->recvSize; ofs++)
3527             {
3528               if (!strcmp (fReturn[ofs], "a"))
3529                 emitcode ("push", "acc");
3530               else
3531                 emitcode ("push", fReturn[ofs]);
3532             }
3533           stackAdjust -= sym->recvSize;
3534           if (stackAdjust<0)
3535             {
3536               assert (stackAdjust>=0);
3537               stackAdjust = 0;
3538             }
3539           _G.current_iCode = ic;
3540           ric->generated = 1;
3541           accIsFree = 1;
3542         }
3543       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3544       /* to free up the accumulator. */
3545       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3546         {
3547           int ofs;
3548
3549           _G.current_iCode = ric;
3550           D(emitcode (";     genReceive",""));
3551           for (ofs=0; ofs < sym->recvSize; ofs++)
3552             {
3553               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3554             }
3555           _G.current_iCode = ic;
3556           ric->generated = 1;
3557           accIsFree = 1;
3558         }
3559     }
3560
3561   /* adjust the stack for the function */
3562   if (stackAdjust)
3563     {
3564       int i = stackAdjust;
3565       if (i > 256)
3566         werror (W_STACK_OVERFLOW, sym->name);
3567
3568       if (i > 3 && accIsFree)
3569         {
3570           emitcode ("mov", "a,sp");
3571           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3572           emitcode ("mov", "sp,a");
3573         }
3574       else if (i > 5)
3575         {
3576           /* The accumulator is not free, so we will need another register */
3577           /* to clobber. No need to worry about a possible conflict with */
3578           /* the above early RECEIVE optimizations since they would have */
3579           /* freed the accumulator if they were generated. */
3580
3581           if (IFFUNC_CALLEESAVES(sym->type))
3582             {
3583               /* if it's a callee-saves function we need a saved register */
3584               if (calleesaves_saved_register >= 0)
3585                 {
3586                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3587                   emitcode ("mov", "a,sp");
3588                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3589                   emitcode ("mov", "sp,a");
3590                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3591                 }
3592               else
3593                 /* do it the hard way */
3594                 while (i--)
3595                   emitcode ("inc", "sp");
3596             }
3597           else
3598             {
3599               /* not callee-saves, we can clobber r0 */
3600               emitcode ("mov", "r0,a");
3601               emitcode ("mov", "a,sp");
3602               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3603               emitcode ("mov", "sp,a");
3604               emitcode ("mov", "a,r0");
3605             }
3606         }
3607       else
3608         while (i--)
3609           emitcode ("inc", "sp");
3610     }
3611
3612   if (sym->xstack)
3613     {
3614       char i = ((char) sym->xstack & 0xff);
3615
3616       if (i > 3 && accIsFree)
3617         {
3618           emitcode ("mov", "a,_spx");
3619           emitcode ("add", "a,#0x%02x", i & 0xff);
3620           emitcode ("mov", "_spx,a");
3621         }
3622       else if (i > 5)
3623         {
3624           emitcode ("push", "acc");
3625           emitcode ("mov", "a,_spx");
3626           emitcode ("add", "a,#0x%02x", i & 0xff);
3627           emitcode ("mov", "_spx,a");
3628           emitcode ("pop", "acc");
3629         }
3630       else
3631         {
3632           while (i--)
3633             emitcode ("inc", "_spx");
3634         }
3635     }
3636
3637   /* if critical function then turn interrupts off */
3638   if (IFFUNC_ISCRITICAL (ftype))
3639     {
3640       symbol *tlbl = newiTempLabel (NULL);
3641       emitcode ("setb", "c");
3642       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3643       emitcode ("clr", "c");
3644       emitLabel (tlbl);
3645       emitcode ("push", "psw"); /* save old ea via c in psw */
3646     }
3647 }
3648
3649 /*-----------------------------------------------------------------*/
3650 /* genEndFunction - generates epilogue for functions               */
3651 /*-----------------------------------------------------------------*/
3652 static void
3653 genEndFunction (iCode * ic)
3654 {
3655   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3656   lineNode *lnp = lineCurr;
3657   bitVect  *regsUsed;
3658   bitVect  *regsUsedPrologue;
3659   bitVect  *regsUnneeded;
3660   int      idx;
3661
3662   _G.currentFunc = NULL;
3663   if (IFFUNC_ISNAKED(sym->type))
3664   {
3665       emitcode(";", "naked function: no epilogue.");
3666       if (options.debug && currFunc)
3667         debugFile->writeEndFunction (currFunc, ic, 0);
3668       return;
3669   }
3670
3671   if (IFFUNC_ISCRITICAL (sym->type))
3672     {
3673       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3674         {
3675           emitcode ("rlc", "a");   /* save c in a */
3676           emitcode ("pop", "psw"); /* restore ea via c in psw */
3677           emitcode ("mov", "ea,c");
3678           emitcode ("rrc", "a");   /* restore c from a */
3679         }
3680       else
3681         {
3682           emitcode ("pop", "psw"); /* restore ea via c in psw */
3683           emitcode ("mov", "ea,c");
3684         }
3685     }
3686
3687   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3688     {
3689       if (options.useXstack)
3690         {
3691           if (sym->stack)
3692             {
3693               emitcode ("mov", "sp,_bp");
3694               emitcode ("pop", "_bp");
3695             }
3696           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3697             {
3698               emitcode ("xch", "a,_bpx");
3699               emitcode ("mov", "r0,a");
3700               emitcode ("dec", "r0");
3701               emitcode ("movx", "a,@r0");
3702               emitcode ("xch", "a,_bpx");
3703               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3704             }
3705         }
3706       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3707         {
3708           if (sym->stack)
3709             emitcode ("mov", "sp,_bp");
3710           emitcode ("pop", "_bp");
3711         }
3712     }
3713
3714   /* restore the register bank  */
3715   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3716   {
3717     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3718      || !options.useXstack)
3719     {
3720         /* Special case of ISR using non-zero bank with useXstack
3721          * is handled below.
3722          */
3723         emitcode ("pop", "psw");
3724     }
3725   }
3726
3727   if (IFFUNC_ISISR (sym->type))
3728     {
3729
3730       /* now we need to restore the registers */
3731       /* if this isr has no bank i.e. is going to
3732          run with bank 0 , then we need to save more
3733          registers :-) */
3734       if (!FUNC_REGBANK (sym->type))
3735         {
3736           int i;
3737           /* if this function does not call any other
3738              function then we can be economical and
3739              save only those registers that are used */
3740           if (!IFFUNC_HASFCALL(sym->type))
3741             {
3742               /* if any registers used */
3743               if (sym->regsUsed)
3744                 {
3745                   bool bits_popped = FALSE;
3746                   /* save the registers used */
3747                   for (i = sym->regsUsed->size; i >= 0; i--)
3748                     {
3749                       if (bitVectBitValue (sym->regsUsed, i))
3750                         bits_popped = popReg (i, bits_popped);
3751                     }
3752                 }
3753             }
3754           else
3755             {
3756               if (options.parms_in_bank1) {
3757                   for (i = 7 ; i >= 0 ; i-- ) {
3758                       emitcode ("pop","%s",rb1regs[i]);
3759                   }
3760               }
3761               /* this function has  a function call cannot
3762                  determines register usage so we will have to pop the
3763                  entire bank */
3764               unsaveRBank (0, ic, FALSE);
3765             }
3766         }
3767         else
3768         {
3769             /* This ISR uses a non-zero bank.
3770              *
3771              * Restore any register banks saved by genFunction
3772              * in reverse order.
3773              */
3774             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3775             int ix;
3776
3777             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3778             {
3779                 if (savedBanks & (1 << ix))
3780                 {
3781                     unsaveRBank(ix, NULL, FALSE);
3782                 }
3783             }
3784
3785             if (options.useXstack)
3786             {
3787                 /* Restore bank AFTER calling unsaveRBank,
3788                  * since it can trash r0.
3789                  */
3790                 emitcode ("pop", "psw");
3791             }
3792         }
3793
3794       if (!inExcludeList ("dph"))
3795         emitcode ("pop", "dph");
3796       if (!inExcludeList ("dpl"))
3797         emitcode ("pop", "dpl");
3798       if (!inExcludeList ("b"))
3799         emitcode ("pop", "b");
3800       if (!inExcludeList ("acc"))
3801         emitcode ("pop", "acc");
3802
3803       /* if debug then send end of function */
3804       if (options.debug && currFunc)
3805         {
3806           debugFile->writeEndFunction (currFunc, ic, 1);
3807         }
3808
3809       emitcode ("reti", "");
3810     }
3811   else
3812     {
3813       if (IFFUNC_CALLEESAVES(sym->type))
3814         {
3815           int i;
3816
3817           /* if any registers used */
3818           if (sym->regsUsed)
3819             {
3820               /* save the registers used */
3821               for (i = sym->regsUsed->size; i >= 0; i--)
3822                 {
3823                   if (bitVectBitValue (sym->regsUsed, i) ||
3824                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3825                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3826                 }
3827             }
3828           else if (mcs51_ptrRegReq)
3829             {
3830               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3831               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3832             }
3833
3834         }
3835
3836       /* if debug then send end of function */
3837       if (options.debug && currFunc)
3838         {
3839           debugFile->writeEndFunction (currFunc, ic, 1);
3840         }
3841
3842       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3843         {
3844           emitcode ("ljmp", "__sdcc_banked_ret");
3845         }
3846       else
3847         {
3848           emitcode ("ret", "");
3849         }
3850     }
3851
3852   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3853     return;
3854
3855   /* If this was an interrupt handler using bank 0 that called another */
3856   /* function, then all registers must be saved; nothing to optimized. */
3857   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3858       && !FUNC_REGBANK(sym->type))
3859     return;
3860
3861   /* There are no push/pops to optimize if not callee-saves or ISR */
3862   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3863     return;
3864
3865   /* If there were stack parameters, we cannot optimize without also    */
3866   /* fixing all of the stack offsets; this is too dificult to consider. */
3867   if (FUNC_HASSTACKPARM(sym->type))
3868     return;
3869
3870   /* Compute the registers actually used */
3871   regsUsed = newBitVect (mcs51_nRegs);
3872   regsUsedPrologue = newBitVect (mcs51_nRegs);
3873   while (lnp)
3874     {
3875       if (lnp->ic && lnp->ic->op == FUNCTION)
3876         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3877       else
3878         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3879
3880       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3881           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3882         break;
3883       if (!lnp->prev)
3884         break;
3885       lnp = lnp->prev;
3886     }
3887
3888   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3889       && !bitVectBitValue (regsUsed, CND_IDX))
3890     {
3891       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3892       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3893           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3894         bitVectUnSetBit (regsUsed, CND_IDX);
3895     }
3896   else
3897     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3898
3899   /* If this was an interrupt handler that called another function */
3900   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3901   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3902     {
3903       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3904       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3905       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3906       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3907       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3908     }
3909
3910   /* Remove the unneeded push/pops */
3911   regsUnneeded = newBitVect (mcs51_nRegs);
3912   while (lnp)
3913     {
3914       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3915         {
3916           if (!strncmp(lnp->line, "push", 4))
3917             {
3918               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3919               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3920                 {
3921                   connectLine (lnp->prev, lnp->next);
3922                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3923                 }
3924             }
3925           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3926             {
3927               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3928               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3929                 {
3930                   connectLine (lnp->prev, lnp->next);
3931                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3932                 }
3933             }
3934         }
3935       lnp = lnp->next;
3936     }
3937
3938   for (idx = 0; idx < regsUnneeded->size; idx++)
3939     if (bitVectBitValue (regsUnneeded, idx))
3940       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3941
3942   freeBitVect (regsUnneeded);
3943   freeBitVect (regsUsed);
3944   freeBitVect (regsUsedPrologue);
3945 }
3946
3947 /*-----------------------------------------------------------------*/
3948 /* genRet - generate code for return statement                     */
3949 /*-----------------------------------------------------------------*/
3950 static void
3951 genRet (iCode * ic)
3952 {
3953   int size, offset = 0, pushed = 0;
3954
3955   D (emitcode (";", "genRet"));
3956
3957   /* if we have no return value then
3958      just generate the "ret" */
3959   if (!IC_LEFT (ic))
3960     goto jumpret;
3961
3962   /* we have something to return then
3963      move the return value into place */
3964   aopOp (IC_LEFT (ic), ic, FALSE);
3965   size = AOP_SIZE (IC_LEFT (ic));
3966
3967   if (IS_BIT(_G.currentFunc->etype))
3968     {
3969       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3970       size = 0;
3971     }
3972
3973   while (size--)
3974     {
3975       char *l;
3976       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3977         {
3978           /* #NOCHANGE */
3979           l = aopGet (IC_LEFT (ic), offset++,
3980                       FALSE, TRUE);
3981           emitcode ("push", "%s", l);
3982           pushed++;
3983         }
3984       else
3985         {
3986           l = aopGet (IC_LEFT (ic), offset,
3987                       FALSE, FALSE);
3988           if (strcmp (fReturn[offset], l))
3989             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3990         }
3991     }
3992
3993   while (pushed)
3994     {
3995       pushed--;
3996       if (strcmp (fReturn[pushed], "a"))
3997         emitcode ("pop", fReturn[pushed]);
3998       else
3999         emitcode ("pop", "acc");
4000     }
4001   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4002
4003 jumpret:
4004   /* generate a jump to the return label
4005      if the next is not the return statement */
4006   if (!(ic->next && ic->next->op == LABEL &&
4007         IC_LABEL (ic->next) == returnLabel))
4008
4009     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4010
4011 }
4012
4013 /*-----------------------------------------------------------------*/
4014 /* genLabel - generates a label                                    */
4015 /*-----------------------------------------------------------------*/
4016 static void
4017 genLabel (iCode * ic)
4018 {
4019   /* special case never generate */
4020   if (IC_LABEL (ic) == entryLabel)
4021     return;
4022
4023   emitLabel (IC_LABEL (ic));
4024 }
4025
4026 /*-----------------------------------------------------------------*/
4027 /* genGoto - generates a ljmp                                      */
4028 /*-----------------------------------------------------------------*/
4029 static void
4030 genGoto (iCode * ic)
4031 {
4032   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4033 }
4034
4035 /*-----------------------------------------------------------------*/
4036 /* findLabelBackwards: walks back through the iCode chain looking  */
4037 /* for the given label. Returns number of iCode instructions     */
4038 /* between that label and given ic.          */
4039 /* Returns zero if label not found.          */
4040 /*-----------------------------------------------------------------*/
4041 static int
4042 findLabelBackwards (iCode * ic, int key)
4043 {
4044   int count = 0;
4045
4046   while (ic->prev)
4047     {
4048       ic = ic->prev;
4049       count++;
4050
4051       /* If we have any pushes or pops, we cannot predict the distance.
4052          I don't like this at all, this should be dealt with in the
4053          back-end */
4054       if (ic->op == IPUSH || ic->op == IPOP) {
4055         return 0;
4056       }
4057
4058       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4059         {
4060           return count;
4061         }
4062     }
4063
4064   return 0;
4065 }
4066
4067 /*-----------------------------------------------------------------*/
4068 /* genPlusIncr :- does addition with increment if possible         */
4069 /*-----------------------------------------------------------------*/
4070 static bool
4071 genPlusIncr (iCode * ic)
4072 {
4073   unsigned int icount;
4074   unsigned int size = getDataSize (IC_RESULT (ic));
4075
4076   /* will try to generate an increment */
4077   /* if the right side is not a literal
4078      we cannot */
4079   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4080     return FALSE;
4081
4082   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4083
4084   D(emitcode (";","genPlusIncr"));
4085
4086   /* if increment >=16 bits in register or direct space */
4087   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4088         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4089         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4090       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4091       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4092       (size > 1) &&
4093       (icount == 1))
4094     {
4095       symbol *tlbl;
4096       int emitTlbl;
4097       int labelRange;
4098
4099       /* If the next instruction is a goto and the goto target
4100        * is < 10 instructions previous to this, we can generate
4101        * jumps straight to that target.
4102        */
4103       if (ic->next && ic->next->op == GOTO
4104           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4105           && labelRange <= 10)
4106         {
4107           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4108           tlbl = IC_LABEL (ic->next);
4109           emitTlbl = 0;
4110         }
4111       else
4112         {
4113           tlbl = newiTempLabel (NULL);
4114           emitTlbl = 1;
4115         }
4116       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4117       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4118           IS_AOP_PREG (IC_RESULT (ic)))
4119         emitcode ("cjne", "%s,#0x00,%05d$",
4120                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4121                   tlbl->key + 100);
4122       else
4123         {
4124           emitcode ("clr", "a");
4125           emitcode ("cjne", "a,%s,%05d$",
4126                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4127                     tlbl->key + 100);
4128         }
4129
4130       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4131       if (size > 2)
4132         {
4133           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4134               IS_AOP_PREG (IC_RESULT (ic)))
4135             emitcode ("cjne", "%s,#0x00,%05d$",
4136                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4137                       tlbl->key + 100);
4138           else
4139             emitcode ("cjne", "a,%s,%05d$",
4140                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4141                       tlbl->key + 100);
4142
4143           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4144         }
4145       if (size > 3)
4146         {
4147           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4148               IS_AOP_PREG (IC_RESULT (ic)))
4149             emitcode ("cjne", "%s,#0x00,%05d$",
4150                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4151                       tlbl->key + 100);
4152           else
4153             {
4154               emitcode ("cjne", "a,%s,%05d$",
4155                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4156                         tlbl->key + 100);
4157             }
4158           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4159         }
4160
4161       if (emitTlbl)
4162         {
4163           emitLabel (tlbl);
4164         }
4165       return TRUE;
4166     }
4167
4168   /* if result is dptr */
4169   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4170       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4171       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4172       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4173     {
4174       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4175         return FALSE;
4176
4177       if (icount > 9)
4178         return FALSE;
4179
4180       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4181         return FALSE;
4182
4183       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4184       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4185       while (icount--)
4186         emitcode ("inc", "dptr");
4187
4188       return TRUE;
4189     }
4190
4191   /* if the literal value of the right hand side
4192      is greater than 4 then it is not worth it */
4193   if (icount > 4)
4194     return FALSE;
4195
4196   /* if the sizes are greater than 1 then we cannot */
4197   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4198       AOP_SIZE (IC_LEFT (ic)) > 1)
4199     return FALSE;
4200
4201   /* we can if the aops of the left & result match or
4202      if they are in registers and the registers are the
4203      same */
4204   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4205     {
4206       if (icount > 3)
4207         {
4208           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4209           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4210           aopPut (IC_RESULT (ic), "a", 0);
4211         }
4212       else
4213         {
4214           while (icount--)
4215             {
4216               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4217             }
4218         }
4219
4220       return TRUE;
4221     }
4222
4223   if (icount == 1)
4224     {
4225       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4226       emitcode ("inc", "a");
4227       aopPut (IC_RESULT (ic), "a", 0);
4228       return TRUE;
4229     }
4230
4231   return FALSE;
4232 }
4233
4234 /*-----------------------------------------------------------------*/
4235 /* outBitAcc - output a bit in acc                                 */
4236 /*-----------------------------------------------------------------*/
4237 static void
4238 outBitAcc (operand * result)
4239 {
4240   symbol *tlbl = newiTempLabel (NULL);
4241   /* if the result is a bit */
4242   if (AOP_TYPE (result) == AOP_CRY)
4243     {
4244       aopPut (result, "a", 0);
4245     }
4246   else
4247     {
4248       emitcode ("jz", "%05d$", tlbl->key + 100);
4249       emitcode ("mov", "a,%s", one);
4250       emitLabel (tlbl);
4251       outAcc (result);
4252     }
4253 }
4254
4255 /*-----------------------------------------------------------------*/
4256 /* genPlusBits - generates code for addition of two bits           */
4257 /*-----------------------------------------------------------------*/
4258 static void
4259 genPlusBits (iCode * ic)
4260 {
4261   D (emitcode (";", "genPlusBits"));
4262
4263   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4264     {
4265       symbol *lbl = newiTempLabel (NULL);
4266       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4267       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4268       emitcode ("cpl", "c");
4269       emitLabel (lbl);
4270       outBitC (IC_RESULT (ic));
4271     }
4272   else
4273     {
4274       emitcode ("clr", "a");
4275       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4276       emitcode ("rlc", "a");
4277       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4278       emitcode ("addc", "a,%s", zero);
4279       outAcc (IC_RESULT (ic));
4280     }
4281 }
4282
4283 #if 0
4284 /* This is the original version of this code.
4285
4286  * This is being kept around for reference,
4287  * because I am not entirely sure I got it right...
4288  */
4289 static void
4290 adjustArithmeticResult (iCode * ic)
4291 {
4292   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4293       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4294       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4295     aopPut (IC_RESULT (ic),
4296             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4297             2);
4298
4299   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4300       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4301       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4302     aopPut (IC_RESULT (ic),
4303             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4304             2);
4305
4306   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4307       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4308       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4309       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4310       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4311     {
4312       char buffer[5];
4313       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4314       aopPut (IC_RESULT (ic), buffer, 2);
4315     }
4316 }
4317 #else
4318 /* This is the pure and virtuous version of this code.
4319  * I'm pretty certain it's right, but not enough to toss the old
4320  * code just yet...
4321  */
4322 static void
4323 adjustArithmeticResult (iCode * ic)
4324 {
4325   if (opIsGptr (IC_RESULT (ic)) &&
4326       opIsGptr (IC_LEFT (ic)) &&
4327       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4328     {
4329       aopPut (IC_RESULT (ic),
4330               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4331               GPTRSIZE - 1);
4332     }
4333
4334   if (opIsGptr (IC_RESULT (ic)) &&
4335       opIsGptr (IC_RIGHT (ic)) &&
4336       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4337     {
4338       aopPut (IC_RESULT (ic),
4339               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4340               GPTRSIZE - 1);
4341     }
4342
4343   if (opIsGptr (IC_RESULT (ic)) &&
4344       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4345       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4346       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4347       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4348     {
4349       char buffer[5];
4350       SNPRINTF (buffer, sizeof(buffer),
4351                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4352       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4353     }
4354 }
4355 #endif
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genPlus - generates code for addition                           */
4359 /*-----------------------------------------------------------------*/
4360 static void
4361 genPlus (iCode * ic)
4362 {
4363   int size, offset = 0;
4364   int skip_bytes = 0;
4365   char *add = "add";
4366   bool swappedLR = FALSE;
4367   operand *leftOp, *rightOp;
4368   operand * op;
4369
4370   D (emitcode (";", "genPlus"));
4371
4372   /* special cases :- */
4373
4374   aopOp (IC_LEFT (ic), ic, FALSE);
4375   aopOp (IC_RIGHT (ic), ic, FALSE);
4376   aopOp (IC_RESULT (ic), ic, TRUE);
4377
4378   /* if literal, literal on the right or
4379      if left requires ACC or right is already
4380      in ACC */
4381   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4382       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4383       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4384     {
4385       operand *t = IC_RIGHT (ic);
4386       IC_RIGHT (ic) = IC_LEFT (ic);
4387       IC_LEFT (ic) = t;
4388       swappedLR = TRUE;
4389     }
4390
4391   /* if both left & right are in bit
4392      space */
4393   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4394       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4395     {
4396       genPlusBits (ic);
4397       goto release;
4398     }
4399
4400   /* if left in bit space & right literal */
4401   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4402       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4403     {
4404       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4405       /* if result in bit space */
4406       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4407         {
4408           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4409             emitcode ("cpl", "c");
4410           outBitC (IC_RESULT (ic));
4411         }
4412       else
4413         {
4414           size = getDataSize (IC_RESULT (ic));
4415           while (size--)
4416             {
4417               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4418               emitcode ("addc", "a,%s", zero);
4419               aopPut (IC_RESULT (ic), "a", offset++);
4420             }
4421         }
4422       goto release;
4423     }
4424
4425   /* if I can do an increment instead
4426      of add then GOOD for ME */
4427   if (genPlusIncr (ic) == TRUE)
4428     goto release;
4429
4430   size = getDataSize (IC_RESULT (ic));
4431   leftOp = IC_LEFT(ic);
4432   rightOp = IC_RIGHT(ic);
4433   op = IC_LEFT(ic);
4434
4435   /* if this is an add for an array access
4436      at a 256 byte boundary */
4437   if ( 2 == size
4438        && AOP_TYPE (op) == AOP_IMMD
4439        && IS_SYMOP (op)
4440        && IS_SPEC (OP_SYM_ETYPE (op))
4441        && SPEC_ABSA (OP_SYM_ETYPE (op))
4442        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4443      )
4444     {
4445       D(emitcode (";     genPlus aligned array",""));
4446       aopPut (IC_RESULT (ic),
4447               aopGet (rightOp, 0, FALSE, FALSE),
4448               0);
4449
4450       if( 1 == getDataSize (IC_RIGHT (ic)) )
4451         {
4452           aopPut (IC_RESULT (ic),
4453                   aopGet (leftOp, 1, FALSE, FALSE),
4454                   1);
4455         }
4456       else
4457         {
4458           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4459           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4460           aopPut (IC_RESULT (ic), "a", 1);
4461         }
4462       goto release;
4463     }
4464
4465   /* if the lower bytes of a literal are zero skip the addition */
4466   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4467     {
4468        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4469               (skip_bytes+1 < size))
4470          {
4471            skip_bytes++;
4472          }
4473        if (skip_bytes)
4474          D(emitcode (";     genPlus shortcut",""));
4475     }
4476
4477   while (size--)
4478     {
4479       if( offset >= skip_bytes )
4480         {
4481           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4482             {
4483               bool pushedB;
4484               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4485               pushedB = pushB ();
4486               emitcode("xch", "a,b");
4487               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4488               emitcode (add, "a,b");
4489               popB (pushedB);
4490             }
4491           else if (aopGetUsesAcc (leftOp, offset))
4492             {
4493               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4494               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4495             }
4496           else
4497             {
4498               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4499               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4500             }
4501           aopPut (IC_RESULT (ic), "a", offset);
4502           add = "addc";  /* further adds must propagate carry */
4503         }
4504       else
4505         {
4506           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4507               isOperandVolatile (IC_RESULT (ic), FALSE))
4508             {
4509               /* just move */
4510               aopPut (IC_RESULT (ic),
4511                       aopGet (leftOp, offset, FALSE, FALSE),
4512                       offset);
4513             }
4514         }
4515       offset++;
4516     }
4517
4518   adjustArithmeticResult (ic);
4519
4520 release:
4521   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4522   if (!swappedLR)
4523     {
4524       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4525       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4526     }
4527   else
4528     {
4529       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531     }
4532 }
4533
4534 /*-----------------------------------------------------------------*/
4535 /* genMinusDec :- does subtraction with decrement if possible      */
4536 /*-----------------------------------------------------------------*/
4537 static bool
4538 genMinusDec (iCode * ic)
4539 {
4540   unsigned int icount;
4541   unsigned int size = getDataSize (IC_RESULT (ic));
4542
4543   /* will try to generate an increment */
4544   /* if the right side is not a literal
4545      we cannot */
4546   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4547     return FALSE;
4548
4549   /* if the literal value of the right hand side
4550      is greater than 4 then it is not worth it */
4551   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4552     return FALSE;
4553
4554   D (emitcode (";", "genMinusDec"));
4555
4556   /* if decrement >=16 bits in register or direct space */
4557   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4558         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4559         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4560       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4561       (size > 1) &&
4562       (icount == 1))
4563     {
4564       symbol *tlbl;
4565       int emitTlbl;
4566       int labelRange;
4567
4568       /* If the next instruction is a goto and the goto target
4569        * is <= 10 instructions previous to this, we can generate
4570        * jumps straight to that target.
4571        */
4572       if (ic->next && ic->next->op == GOTO
4573           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4574           && labelRange <= 10)
4575         {
4576           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4577           tlbl = IC_LABEL (ic->next);
4578           emitTlbl = 0;
4579         }
4580       else
4581         {
4582           tlbl = newiTempLabel (NULL);
4583           emitTlbl = 1;
4584         }
4585
4586       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4587       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4588           IS_AOP_PREG (IC_RESULT (ic)))
4589         emitcode ("cjne", "%s,#0xff,%05d$"
4590                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4591                   ,tlbl->key + 100);
4592       else
4593         {
4594           emitcode ("mov", "a,#0xff");
4595           emitcode ("cjne", "a,%s,%05d$"
4596                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4597                     ,tlbl->key + 100);
4598         }
4599       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4600       if (size > 2)
4601         {
4602           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4603               IS_AOP_PREG (IC_RESULT (ic)))
4604             emitcode ("cjne", "%s,#0xff,%05d$"
4605                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4606                       ,tlbl->key + 100);
4607           else
4608             {
4609               emitcode ("cjne", "a,%s,%05d$"
4610                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4611                         ,tlbl->key + 100);
4612             }
4613           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4614         }
4615       if (size > 3)
4616         {
4617           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4618               IS_AOP_PREG (IC_RESULT (ic)))
4619             emitcode ("cjne", "%s,#0xff,%05d$"
4620                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4621                       ,tlbl->key + 100);
4622           else
4623             {
4624               emitcode ("cjne", "a,%s,%05d$"
4625                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4626                         ,tlbl->key + 100);
4627             }
4628           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4629         }
4630       if (emitTlbl)
4631         {
4632           emitLabel (tlbl);
4633         }
4634       return TRUE;
4635     }
4636
4637   /* if the sizes are greater than 1 then we cannot */
4638   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4639       AOP_SIZE (IC_LEFT (ic)) > 1)
4640     return FALSE;
4641
4642   /* we can if the aops of the left & result match or
4643      if they are in registers and the registers are the
4644      same */
4645   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4646     {
4647       char *l;
4648
4649       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4650         {
4651           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4652           l = "a";
4653         }
4654       else
4655         {
4656           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4657         }
4658
4659       while (icount--)
4660         {
4661           emitcode ("dec", "%s", l);
4662         }
4663
4664       if (AOP_NEEDSACC (IC_RESULT (ic)))
4665         aopPut (IC_RESULT (ic), "a", 0);
4666
4667       return TRUE;
4668     }
4669
4670   if (icount == 1)
4671     {
4672       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4673       emitcode ("dec", "a");
4674       aopPut (IC_RESULT (ic), "a", 0);
4675       return TRUE;
4676     }
4677
4678   return FALSE;
4679 }
4680
4681 /*-----------------------------------------------------------------*/
4682 /* addSign - complete with sign                                    */
4683 /*-----------------------------------------------------------------*/
4684 static void
4685 addSign (operand * result, int offset, int sign)
4686 {
4687   int size = (getDataSize (result) - offset);
4688   if (size > 0)
4689     {
4690       if (sign)
4691         {
4692           emitcode ("rlc", "a");
4693           emitcode ("subb", "a,acc");
4694           while (size--)
4695             {
4696               aopPut (result, "a", offset++);
4697             }
4698         }
4699       else
4700         {
4701           while (size--)
4702             {
4703               aopPut (result, zero, offset++);
4704             }
4705         }
4706     }
4707 }
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genMinusBits - generates code for subtraction  of two bits      */
4711 /*-----------------------------------------------------------------*/
4712 static void
4713 genMinusBits (iCode * ic)
4714 {
4715   symbol *lbl = newiTempLabel (NULL);
4716
4717   D (emitcode (";", "genMinusBits"));
4718
4719   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4720     {
4721       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4722       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4723       emitcode ("cpl", "c");
4724       emitLabel (lbl);
4725       outBitC (IC_RESULT (ic));
4726     }
4727   else
4728     {
4729       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4730       emitcode ("subb", "a,acc");
4731       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4732       emitcode ("inc", "a");
4733       emitLabel (lbl);
4734       aopPut (IC_RESULT (ic), "a", 0);
4735       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4736     }
4737 }
4738
4739 /*-----------------------------------------------------------------*/
4740 /* genMinus - generates code for subtraction                       */
4741 /*-----------------------------------------------------------------*/
4742 static void
4743 genMinus (iCode * ic)
4744 {
4745   int size, offset = 0;
4746
4747   D (emitcode (";", "genMinus"));
4748
4749   aopOp (IC_LEFT (ic), ic, FALSE);
4750   aopOp (IC_RIGHT (ic), ic, FALSE);
4751   aopOp (IC_RESULT (ic), ic, TRUE);
4752
4753   /* special cases :- */
4754   /* if both left & right are in bit space */
4755   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4756       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4757     {
4758       genMinusBits (ic);
4759       goto release;
4760     }
4761
4762   /* if I can do an decrement instead
4763      of subtract then GOOD for ME */
4764   if (genMinusDec (ic) == TRUE)
4765     goto release;
4766
4767   size = getDataSize (IC_RESULT (ic));
4768
4769   /* if literal, add a,#-lit, else normal subb */
4770   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4771     {
4772       unsigned long lit = 0L;
4773       bool useCarry = FALSE;
4774
4775       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4776       lit = -(long) lit;
4777
4778       while (size--)
4779         {
4780           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4781             {
4782               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4783               if (!offset && !size && lit== (unsigned long) -1)
4784                 {
4785                   emitcode ("dec", "a");
4786                 }
4787               else if (!useCarry)
4788                 {
4789                   /* first add without previous c */
4790                   emitcode ("add", "a,#0x%02x",
4791                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4792                   useCarry = TRUE;
4793                 }
4794               else
4795                 {
4796                   emitcode ("addc", "a,#0x%02x",
4797                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4798                 }
4799               aopPut (IC_RESULT (ic), "a", offset++);
4800             }
4801           else
4802             {
4803               /* no need to add zeroes */
4804               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4805                 {
4806                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4807                           offset);
4808                 }
4809               offset++;
4810             }
4811         }
4812     }
4813   else
4814     {
4815       operand *leftOp, *rightOp;
4816
4817       leftOp = IC_LEFT(ic);
4818       rightOp = IC_RIGHT(ic);
4819
4820       while (size--)
4821         {
4822           if (aopGetUsesAcc(rightOp, offset)) {
4823             if (aopGetUsesAcc(leftOp, offset)) {
4824               bool pushedB;
4825
4826               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4827               pushedB = pushB ();
4828               emitcode ("mov", "b,a");
4829               if (offset == 0)
4830                 CLRC;
4831               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4832               emitcode ("subb", "a,b");
4833               popB (pushedB);
4834             } else {
4835               /* reverse subtraction with 2's complement */
4836               if (offset == 0)
4837                 emitcode( "setb", "c");
4838               else
4839                 emitcode( "cpl", "c");
4840               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4841               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4842               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4843               emitcode("cpl", "a");
4844               if (size) /* skip if last byte */
4845                 emitcode( "cpl", "c");
4846             }
4847           } else {
4848             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4849             if (offset == 0)
4850               CLRC;
4851             emitcode ("subb", "a,%s",
4852                       aopGet(rightOp, offset, FALSE, TRUE));
4853           }
4854
4855           aopPut (IC_RESULT (ic), "a", offset++);
4856         }
4857     }
4858
4859   adjustArithmeticResult (ic);
4860
4861 release:
4862   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4863   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865 }
4866
4867
4868 /*-----------------------------------------------------------------*/
4869 /* genMultbits :- multiplication of bits                           */
4870 /*-----------------------------------------------------------------*/
4871 static void
4872 genMultbits (operand * left,
4873              operand * right,
4874              operand * result)
4875 {
4876   D (emitcode (";", "genMultbits"));
4877
4878   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4879   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4880   outBitC (result);
4881 }
4882
4883 /*-----------------------------------------------------------------*/
4884 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4885 /*-----------------------------------------------------------------*/
4886 static void
4887 genMultOneByte (operand * left,
4888                 operand * right,
4889                 operand * result)
4890 {
4891   symbol *lbl;
4892   int size = AOP_SIZE (result);
4893   bool runtimeSign, compiletimeSign;
4894   bool lUnsigned, rUnsigned, pushedB;
4895
4896   D (emitcode (";", "genMultOneByte"));
4897
4898   if (size < 1 || size > 2)
4899     {
4900       /* this should never happen */
4901       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4902                AOP_SIZE(result), __FILE__, lineno);
4903       exit (1);
4904     }
4905
4906   /* (if two literals: the value is computed before) */
4907   /* if one literal, literal on the right */
4908   if (AOP_TYPE (left) == AOP_LIT)
4909     {
4910       operand *t = right;
4911       right = left;
4912       left = t;
4913       /* emitcode (";", "swapped left and right"); */
4914     }
4915   /* if no literal, unsigned on the right: shorter code */
4916   if (   AOP_TYPE (right) != AOP_LIT
4917       && SPEC_USIGN (getSpec (operandType (left))))
4918     {
4919       operand *t = right;
4920       right = left;
4921       left = t;
4922     }
4923
4924   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4925   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4926
4927   pushedB = pushB ();
4928
4929   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4930                    no need to take care about the signedness! */
4931       || (lUnsigned && rUnsigned))
4932     {
4933       /* just an unsigned 8 * 8 = 8 multiply
4934          or 8u * 8u = 16u */
4935       /* emitcode (";","unsigned"); */
4936       /* TODO: check for accumulator clash between left & right aops? */
4937
4938       if (AOP_TYPE (right) == AOP_LIT)
4939         {
4940           /* moving to accumulator first helps peepholes */
4941           MOVA (aopGet (left, 0, FALSE, FALSE));
4942           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4943         }
4944       else
4945         {
4946           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4947           MOVA (aopGet (left, 0, FALSE, FALSE));
4948         }
4949
4950       emitcode ("mul", "ab");
4951       aopPut (result, "a", 0);
4952       if (size == 2)
4953         aopPut (result, "b", 1);
4954
4955       popB (pushedB);
4956       return;
4957     }
4958
4959   /* we have to do a signed multiply */
4960   /* emitcode (";", "signed"); */
4961
4962   /* now sign adjust for both left & right */
4963
4964   /* let's see what's needed: */
4965   /* apply negative sign during runtime */
4966   runtimeSign = FALSE;
4967   /* negative sign from literals */
4968   compiletimeSign = FALSE;
4969
4970   if (!lUnsigned)
4971     {
4972       if (AOP_TYPE(left) == AOP_LIT)
4973         {
4974           /* signed literal */
4975           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4976           if (val < 0)
4977             compiletimeSign = TRUE;
4978         }
4979       else
4980         /* signed but not literal */
4981         runtimeSign = TRUE;
4982     }
4983
4984   if (!rUnsigned)
4985     {
4986       if (AOP_TYPE(right) == AOP_LIT)
4987         {
4988           /* signed literal */
4989           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4990           if (val < 0)
4991             compiletimeSign ^= TRUE;
4992         }
4993       else
4994         /* signed but not literal */
4995         runtimeSign = TRUE;
4996     }
4997
4998   /* initialize F0, which stores the runtime sign */
4999   if (runtimeSign)
5000     {
5001       if (compiletimeSign)
5002         emitcode ("setb", "F0"); /* set sign flag */
5003       else
5004         emitcode ("clr", "F0"); /* reset sign flag */
5005     }
5006
5007   /* save the signs of the operands */
5008   if (AOP_TYPE(right) == AOP_LIT)
5009     {
5010       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5011
5012       if (!rUnsigned && val < 0)
5013         emitcode ("mov", "b,#0x%02x", -val);
5014       else
5015         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5016     }
5017   else /* ! literal */
5018     {
5019       if (rUnsigned)  /* emitcode (";", "signed"); */
5020         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5021       else
5022         {
5023           MOVA (aopGet (right, 0, FALSE, FALSE));
5024           lbl = newiTempLabel (NULL);
5025           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5026           emitcode ("cpl", "F0"); /* complement sign flag */
5027           emitcode ("cpl", "a");  /* 2's complement */
5028           emitcode ("inc", "a");
5029           emitLabel (lbl);
5030           emitcode ("mov", "b,a");
5031         }
5032     }
5033
5034   if (AOP_TYPE(left) == AOP_LIT)
5035     {
5036       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5037
5038       if (!lUnsigned && val < 0)
5039         emitcode ("mov", "a,#0x%02x", -val);
5040       else
5041         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5042     }
5043   else /* ! literal */
5044     {
5045       MOVA (aopGet (left, 0, FALSE, FALSE));
5046
5047       if (!lUnsigned)
5048         {
5049           lbl = newiTempLabel (NULL);
5050           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5051           emitcode ("cpl", "F0"); /* complement sign flag */
5052           emitcode ("cpl", "a"); /* 2's complement */
5053           emitcode ("inc", "a");
5054           emitLabel (lbl);
5055         }
5056     }
5057
5058   /* now the multiplication */
5059   emitcode ("mul", "ab");
5060   if (runtimeSign || compiletimeSign)
5061     {
5062       lbl = newiTempLabel (NULL);
5063       if (runtimeSign)
5064         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5065       emitcode ("cpl", "a"); /* lsb 2's complement */
5066       if (size != 2)
5067         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5068       else
5069         {
5070           emitcode ("add", "a,#1"); /* this sets carry flag */
5071           emitcode ("xch", "a,b");
5072           emitcode ("cpl", "a"); /* msb 2's complement */
5073           emitcode ("addc", "a,#0");
5074           emitcode ("xch", "a,b");
5075         }
5076       emitLabel (lbl);
5077     }
5078   aopPut (result, "a", 0);
5079   if (size == 2)
5080     aopPut (result, "b", 1);
5081
5082   popB (pushedB);
5083 }
5084
5085 /*-----------------------------------------------------------------*/
5086 /* genMult - generates code for multiplication                     */
5087 /*-----------------------------------------------------------------*/
5088 static void
5089 genMult (iCode * ic)
5090 {
5091   operand *left = IC_LEFT (ic);
5092   operand *right = IC_RIGHT (ic);
5093   operand *result = IC_RESULT (ic);
5094
5095   D (emitcode (";", "genMult"));
5096
5097   /* assign the asmops */
5098   aopOp (left, ic, FALSE);
5099   aopOp (right, ic, FALSE);
5100   aopOp (result, ic, TRUE);
5101
5102   /* special cases first */
5103   /* both are bits */
5104   if (AOP_TYPE (left) == AOP_CRY &&
5105       AOP_TYPE (right) == AOP_CRY)
5106     {
5107       genMultbits (left, right, result);
5108       goto release;
5109     }
5110
5111   /* if both are of size == 1 */
5112 #if 0 // one of them can be a sloc shared with the result
5113     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5114 #else
5115   if (getSize(operandType(left)) == 1 &&
5116       getSize(operandType(right)) == 1)
5117 #endif
5118     {
5119       genMultOneByte (left, right, result);
5120       goto release;
5121     }
5122
5123   /* should have been converted to function call */
5124     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5125              getSize(OP_SYMBOL(right)->type));
5126   assert (0);
5127
5128 release:
5129   freeAsmop (result, NULL, ic, TRUE);
5130   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5131   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5132 }
5133
5134 /*-----------------------------------------------------------------*/
5135 /* genDivbits :- division of bits                                  */
5136 /*-----------------------------------------------------------------*/
5137 static void
5138 genDivbits (operand * left,
5139             operand * right,
5140             operand * result)
5141 {
5142   char *l;
5143   bool pushedB;
5144
5145   D(emitcode (";     genDivbits",""));
5146
5147   pushedB = pushB ();
5148
5149   /* the result must be bit */
5150   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5151   l = aopGet (left, 0, FALSE, FALSE);
5152
5153   MOVA (l);
5154
5155   emitcode ("div", "ab");
5156   emitcode ("rrc", "a");
5157
5158   popB (pushedB);
5159
5160   aopPut (result, "c", 0);
5161 }
5162
5163 /*-----------------------------------------------------------------*/
5164 /* genDivOneByte : 8 bit division                                  */
5165 /*-----------------------------------------------------------------*/
5166 static void
5167 genDivOneByte (operand * left,
5168                operand * right,
5169                operand * result)
5170 {
5171   bool lUnsigned, rUnsigned, pushedB;
5172   bool runtimeSign, compiletimeSign;
5173   bool accuse = FALSE;
5174   bool pushedA = FALSE;
5175   symbol *lbl;
5176   int size, offset;
5177
5178   D(emitcode (";     genDivOneByte",""));
5179
5180   /* Why is it necessary that genDivOneByte() can return an int result?
5181      Have a look at:
5182
5183         volatile unsigned char uc;
5184         volatile signed char sc1, sc2;
5185         volatile int i;
5186
5187         uc  = 255;
5188         sc1 = -1;
5189         i = uc / sc1;
5190
5191      Or:
5192
5193         sc1 = -128;
5194         sc2 = -1;
5195         i = sc1 / sc2;
5196
5197      In all cases a one byte result would overflow, the following cast to int
5198      would return the wrong result.
5199
5200      Two possible solution:
5201         a) cast operands to int, if ((unsigned) / (signed)) or
5202            ((signed) / (signed))
5203         b) return an 16 bit signed int; this is what we're doing here!
5204   */
5205
5206   size = AOP_SIZE (result) - 1;
5207   offset = 1;
5208   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5209   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5210
5211   pushedB = pushB ();
5212
5213   /* signed or unsigned */
5214   if (lUnsigned && rUnsigned)
5215     {
5216       /* unsigned is easy */
5217       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5218       MOVA (aopGet (left, 0, FALSE, FALSE));
5219       emitcode ("div", "ab");
5220       aopPut (result, "a", 0);
5221       while (size--)
5222         aopPut (result, zero, offset++);
5223
5224       popB (pushedB);
5225       return;
5226     }
5227
5228   /* signed is a little bit more difficult */
5229
5230   /* now sign adjust for both left & right */
5231
5232   /* let's see what's needed: */
5233   /* apply negative sign during runtime */
5234   runtimeSign = FALSE;
5235   /* negative sign from literals */
5236   compiletimeSign = FALSE;
5237
5238   if (!lUnsigned)
5239     {
5240       if (AOP_TYPE(left) == AOP_LIT)
5241         {
5242           /* signed literal */
5243           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5244           if (val < 0)
5245             compiletimeSign = TRUE;
5246         }
5247       else
5248         /* signed but not literal */
5249         runtimeSign = TRUE;
5250     }
5251
5252   if (!rUnsigned)
5253     {
5254       if (AOP_TYPE(right) == AOP_LIT)
5255         {
5256           /* signed literal */
5257           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5258           if (val < 0)
5259             compiletimeSign ^= TRUE;
5260         }
5261       else
5262         /* signed but not literal */
5263         runtimeSign = TRUE;
5264     }
5265
5266   /* initialize F0, which stores the runtime sign */
5267   if (runtimeSign)
5268     {
5269       if (compiletimeSign)
5270         emitcode ("setb", "F0"); /* set sign flag */
5271       else
5272         emitcode ("clr", "F0"); /* reset sign flag */
5273     }
5274
5275   /* save the signs of the operands */
5276   if (AOP_TYPE(right) == AOP_LIT)
5277     {
5278       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5279
5280       if (!rUnsigned && val < 0)
5281         emitcode ("mov", "b,#0x%02x", -val);
5282       else
5283         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5284     }
5285   else /* ! literal */
5286     {
5287       if (rUnsigned)
5288         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5289       else
5290         {
5291           MOVA (aopGet (right, 0, FALSE, FALSE));
5292           lbl = newiTempLabel (NULL);
5293           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5294           emitcode ("cpl", "F0"); /* complement sign flag */
5295           emitcode ("cpl", "a");  /* 2's complement */
5296           emitcode ("inc", "a");
5297           emitLabel (lbl);
5298           emitcode ("mov", "b,a");
5299         }
5300     }
5301
5302   if (AOP_TYPE(left) == AOP_LIT)
5303     {
5304       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5305
5306       if (!lUnsigned && val < 0)
5307         emitcode ("mov", "a,#0x%02x", -val);
5308       else
5309         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5310     }
5311   else /* ! literal */
5312     {
5313       MOVA (aopGet (left, 0, FALSE, FALSE));
5314
5315       if (!lUnsigned)
5316         {
5317           lbl = newiTempLabel (NULL);
5318           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5319           emitcode ("cpl", "F0"); /* complement sign flag */
5320           emitcode ("cpl", "a");  /* 2's complement */
5321           emitcode ("inc", "a");
5322           emitLabel (lbl);
5323         }
5324     }
5325
5326   /* now the division */
5327   emitcode ("div", "ab");
5328
5329   if (runtimeSign || compiletimeSign)
5330     {
5331       lbl = newiTempLabel (NULL);
5332       if (runtimeSign)
5333         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5334       emitcode ("cpl", "a"); /* lsb 2's complement */
5335       emitcode ("inc", "a");
5336       emitLabel (lbl);
5337
5338       accuse = aopPut (result, "a", 0);
5339       if (size > 0)
5340         {
5341           /* msb is 0x00 or 0xff depending on the sign */
5342           if (runtimeSign)
5343             {
5344               if (accuse)
5345                 {
5346                   emitcode ("push", "acc");
5347                   pushedA = TRUE;
5348                 }
5349               emitcode ("mov", "c,F0");
5350               emitcode ("subb", "a,acc");
5351               while (size--)
5352                 aopPut (result, "a", offset++);
5353             }
5354           else /* compiletimeSign */
5355             {
5356               if (aopPutUsesAcc (result, "#0xFF", offset))
5357                 {
5358                   emitcode ("push", "acc");
5359                   pushedA = TRUE;
5360                 }
5361               while (size--)
5362                 aopPut (result, "#0xff", offset++);
5363             }
5364         }
5365     }
5366   else
5367     {
5368       aopPut (result, "a", 0);
5369       while (size--)
5370         aopPut (result, zero, offset++);
5371     }
5372
5373   if (pushedA)
5374     emitcode ("pop", "acc");
5375   popB (pushedB);
5376 }
5377
5378 /*-----------------------------------------------------------------*/
5379 /* genDiv - generates code for division                            */
5380 /*-----------------------------------------------------------------*/
5381 static void
5382 genDiv (iCode * ic)
5383 {
5384   operand *left = IC_LEFT (ic);
5385   operand *right = IC_RIGHT (ic);
5386   operand *result = IC_RESULT (ic);
5387
5388   D (emitcode (";", "genDiv"));
5389
5390   /* assign the amsops */
5391   aopOp (left, ic, FALSE);
5392   aopOp (right, ic, FALSE);
5393   aopOp (result, ic, TRUE);
5394
5395   /* special cases first */
5396   /* both are bits */
5397   if (AOP_TYPE (left) == AOP_CRY &&
5398       AOP_TYPE (right) == AOP_CRY)
5399     {
5400       genDivbits (left, right, result);
5401       goto release;
5402     }
5403
5404   /* if both are of size == 1 */
5405   if (AOP_SIZE (left) == 1 &&
5406       AOP_SIZE (right) == 1)
5407     {
5408       genDivOneByte (left, right, result);
5409       goto release;
5410     }
5411
5412   /* should have been converted to function call */
5413   assert (0);
5414 release:
5415   freeAsmop (result, NULL, ic, TRUE);
5416   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5417   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418 }
5419
5420 /*-----------------------------------------------------------------*/
5421 /* genModbits :- modulus of bits                                   */
5422 /*-----------------------------------------------------------------*/
5423 static void
5424 genModbits (operand * left,
5425             operand * right,
5426             operand * result)
5427 {
5428   char *l;
5429   bool pushedB;
5430
5431   D (emitcode (";", "genModbits"));
5432
5433   pushedB = pushB ();
5434
5435   /* the result must be bit */
5436   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5437   l = aopGet (left, 0, FALSE, FALSE);
5438
5439   MOVA (l);
5440
5441   emitcode ("div", "ab");
5442   emitcode ("mov", "a,b");
5443   emitcode ("rrc", "a");
5444
5445   popB (pushedB);
5446
5447   aopPut (result, "c", 0);
5448 }
5449
5450 /*-----------------------------------------------------------------*/
5451 /* genModOneByte : 8 bit modulus                                   */
5452 /*-----------------------------------------------------------------*/
5453 static void
5454 genModOneByte (operand * left,
5455                operand * right,
5456                operand * result)
5457 {
5458   bool lUnsigned, rUnsigned, pushedB;
5459   bool runtimeSign, compiletimeSign;
5460   symbol *lbl;
5461   int size, offset;
5462
5463   D (emitcode (";", "genModOneByte"));
5464
5465   size = AOP_SIZE (result) - 1;
5466   offset = 1;
5467   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5468   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5469
5470   /* if right is a literal, check it for 2^n */
5471   if (AOP_TYPE(right) == AOP_LIT)
5472     {
5473       unsigned char val = abs((int) operandLitValue(right));
5474       symbol *lbl2 = NULL;
5475
5476       switch (val)
5477         {
5478           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5479           case 2:
5480           case 4:
5481           case 8:
5482           case 16:
5483           case 32:
5484           case 64:
5485           case 128:
5486             if (lUnsigned)
5487               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5488                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5489               /* because iCode should have been changed to genAnd  */
5490               /* see file "SDCCopt.c", function "convertToFcall()" */
5491
5492             MOVA (aopGet (left, 0, FALSE, FALSE));
5493             emitcode ("mov", "c,acc.7");
5494             emitcode ("anl", "a,#0x%02x", val - 1);
5495             lbl = newiTempLabel (NULL);
5496             emitcode ("jz", "%05d$", (lbl->key + 100));
5497             emitcode ("jnc", "%05d$", (lbl->key + 100));
5498             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5499             if (size)
5500               {
5501                 int size2 = size;
5502                 int offs2 = offset;
5503
5504                 aopPut (result, "a", 0);
5505                 while (size2--)
5506                   aopPut (result, "#0xff", offs2++);
5507                 lbl2 = newiTempLabel (NULL);
5508                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5509               }
5510             emitLabel (lbl);
5511             aopPut (result, "a", 0);
5512             while (size--)
5513               aopPut (result, zero, offset++);
5514             if (lbl2)
5515               {
5516                 emitLabel (lbl2);
5517               }
5518             return;
5519
5520           default:
5521             break;
5522         }
5523     }
5524
5525   pushedB = pushB ();
5526
5527   /* signed or unsigned */
5528   if (lUnsigned && rUnsigned)
5529     {
5530       /* unsigned is easy */
5531       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5532       MOVA (aopGet (left, 0, FALSE, FALSE));
5533       emitcode ("div", "ab");
5534       aopPut (result, "b", 0);
5535       while (size--)
5536         aopPut (result, zero, offset++);
5537
5538       popB (pushedB);
5539       return;
5540     }
5541
5542   /* signed is a little bit more difficult */
5543
5544   /* now sign adjust for both left & right */
5545
5546   /* modulus: sign of the right operand has no influence on the result! */
5547   if (AOP_TYPE(right) == AOP_LIT)
5548     {
5549       signed char val = (char) operandLitValue(right);
5550
5551       if (!rUnsigned && val < 0)
5552         emitcode ("mov", "b,#0x%02x", -val);
5553       else
5554         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5555     }
5556   else /* not literal */
5557     {
5558       if (rUnsigned)
5559         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5560       else
5561         {
5562           MOVA (aopGet (right, 0, FALSE, FALSE));
5563           lbl = newiTempLabel (NULL);
5564           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5565           emitcode ("cpl", "a"); /* 2's complement */
5566           emitcode ("inc", "a");
5567           emitLabel (lbl);
5568           emitcode ("mov", "b,a");
5569         }
5570     }
5571
5572   /* let's see what's needed: */
5573   /* apply negative sign during runtime */
5574   runtimeSign = FALSE;
5575   /* negative sign from literals */
5576   compiletimeSign = FALSE;
5577
5578   /* sign adjust left side */
5579   if (AOP_TYPE(left) == AOP_LIT)
5580     {
5581       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5582
5583       if (!lUnsigned && val < 0)
5584         {
5585           compiletimeSign = TRUE; /* set sign flag */
5586           emitcode ("mov", "a,#0x%02x", -val);
5587         }
5588       else
5589         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5590     }
5591   else /* ! literal */
5592     {
5593       MOVA (aopGet (left, 0, FALSE, FALSE));
5594
5595       if (!lUnsigned)
5596         {
5597           runtimeSign = TRUE;
5598           emitcode ("clr", "F0"); /* clear sign flag */
5599
5600           lbl = newiTempLabel (NULL);
5601           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5602           emitcode ("setb", "F0"); /* set sign flag */
5603           emitcode ("cpl", "a");   /* 2's complement */
5604           emitcode ("inc", "a");
5605           emitLabel (lbl);
5606         }
5607     }
5608
5609   /* now the modulus */
5610   emitcode ("div", "ab");
5611
5612   if (runtimeSign || compiletimeSign)
5613     {
5614       emitcode ("mov", "a,b");
5615       lbl = newiTempLabel (NULL);
5616       if (runtimeSign)
5617         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5618       emitcode ("cpl", "a"); /* 2's complement */
5619       emitcode ("inc", "a");
5620       emitLabel (lbl);
5621
5622       aopPut (result, "a", 0);
5623       if (size > 0)
5624         {
5625           /* msb is 0x00 or 0xff depending on the sign */
5626           if (runtimeSign)
5627             {
5628               emitcode ("mov", "c,F0");
5629               emitcode ("subb", "a,acc");
5630               while (size--)
5631                 aopPut (result, "a", offset++);
5632             }
5633           else /* compiletimeSign */
5634             while (size--)
5635               aopPut (result, "#0xff", offset++);
5636         }
5637     }
5638   else
5639     {
5640       aopPut (result, "b", 0);
5641       while (size--)
5642         aopPut (result, zero, offset++);
5643     }
5644
5645   popB (pushedB);
5646 }
5647
5648 /*-----------------------------------------------------------------*/
5649 /* genMod - generates code for division                            */
5650 /*-----------------------------------------------------------------*/
5651 static void
5652 genMod (iCode * ic)
5653 {
5654   operand *left = IC_LEFT (ic);
5655   operand *right = IC_RIGHT (ic);
5656   operand *result = IC_RESULT (ic);
5657
5658   D (emitcode (";", "genMod"));
5659
5660   /* assign the asmops */
5661   aopOp (left, ic, FALSE);
5662   aopOp (right, ic, FALSE);
5663   aopOp (result, ic, TRUE);
5664
5665   /* special cases first */
5666   /* both are bits */
5667   if (AOP_TYPE (left) == AOP_CRY &&
5668       AOP_TYPE (right) == AOP_CRY)
5669     {
5670       genModbits (left, right, result);
5671       goto release;
5672     }
5673
5674   /* if both are of size == 1 */
5675   if (AOP_SIZE (left) == 1 &&
5676       AOP_SIZE (right) == 1)
5677     {
5678       genModOneByte (left, right, result);
5679       goto release;
5680     }
5681
5682   /* should have been converted to function call */
5683   assert (0);
5684
5685 release:
5686   freeAsmop (result, NULL, ic, TRUE);
5687   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5688   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689 }
5690
5691 /*-----------------------------------------------------------------*/
5692 /* genIfxJump :- will create a jump depending on the ifx           */
5693 /*-----------------------------------------------------------------*/
5694 static void
5695 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5696 {
5697   symbol *jlbl;
5698   symbol *tlbl = newiTempLabel (NULL);
5699   char *inst;
5700
5701   D (emitcode (";", "genIfxJump"));
5702
5703   /* if true label then we jump if condition
5704      supplied is true */
5705   if (IC_TRUE (ic))
5706     {
5707       jlbl = IC_TRUE (ic);
5708       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5709                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5710     }
5711   else
5712     {
5713       /* false label is present */
5714       jlbl = IC_FALSE (ic);
5715       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5716                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5717     }
5718   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5719     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5720   else
5721     emitcode (inst, "%05d$", tlbl->key + 100);
5722   freeForBranchAsmop (result);
5723   freeForBranchAsmop (right);
5724   freeForBranchAsmop (left);
5725   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5726   emitLabel (tlbl);
5727
5728   /* mark the icode as generated */
5729   ic->generated = 1;
5730 }
5731
5732 /*-----------------------------------------------------------------*/
5733 /* genCmp :- greater or less than comparison                       */
5734 /*-----------------------------------------------------------------*/
5735 static void
5736 genCmp (operand * left, operand * right,
5737         operand * result, iCode * ifx, int sign, iCode *ic)
5738 {
5739   int size, offset = 0;
5740   unsigned long lit = 0L;
5741   bool rightInB;
5742
5743   D (emitcode (";", "genCmp"));
5744
5745   /* if left & right are bit variables */
5746   if (AOP_TYPE (left) == AOP_CRY &&
5747       AOP_TYPE (right) == AOP_CRY)
5748     {
5749       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5750       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5751     }
5752   else
5753     {
5754       /* subtract right from left if at the
5755          end the carry flag is set then we know that
5756          left is greater than right */
5757       size = max (AOP_SIZE (left), AOP_SIZE (right));
5758
5759       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5760       if ((size == 1) && !sign &&
5761           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5762         {
5763           symbol *lbl = newiTempLabel (NULL);
5764           emitcode ("cjne", "%s,%s,%05d$",
5765                     aopGet (left, offset, FALSE, FALSE),
5766                     aopGet (right, offset, FALSE, FALSE),
5767                     lbl->key + 100);
5768           emitLabel (lbl);
5769         }
5770       else
5771         {
5772           if (AOP_TYPE (right) == AOP_LIT)
5773             {
5774               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5775               /* optimize if(x < 0) or if(x >= 0) */
5776               if (lit == 0L)
5777                 {
5778                   if (!sign)
5779                     {
5780                       CLRC;
5781                     }
5782                   else
5783                     {
5784                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5785                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5786                         {
5787                           genIfxJump (ifx, "acc.7", left, right, result);
5788                           freeAsmop (right, NULL, ic, TRUE);
5789                           freeAsmop (left, NULL, ic, TRUE);
5790
5791                           return;
5792                         }
5793                       else
5794                         {
5795                           emitcode ("rlc", "a");
5796                         }
5797                     }
5798                   goto release;
5799                 }
5800               else
5801                 {//nonzero literal
5802                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5803                   while (size && (bytelit == 0))
5804                     {
5805                       offset++;
5806                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5807                       size--;
5808                     }
5809                   CLRC;
5810                   while (size--)
5811                     {
5812                       MOVA (aopGet (left, offset, FALSE, FALSE));
5813                       if (sign && size == 0)
5814                         {
5815                           emitcode ("xrl", "a,#0x80");
5816                           emitcode ("subb", "a,#0x%02x",
5817                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5818                         }
5819                       else
5820                         {
5821                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5822                         }
5823                       offset++;
5824                     }
5825                   goto release;
5826                 }
5827             }
5828           CLRC;
5829           while (size--)
5830             {
5831               bool pushedB = FALSE;
5832               rightInB = aopGetUsesAcc(right, offset);
5833               if (rightInB)
5834                 {
5835                   pushedB = pushB ();
5836                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5837                 }
5838               MOVA (aopGet (left, offset, FALSE, FALSE));
5839               if (sign && size == 0)
5840                 {
5841                   emitcode ("xrl", "a,#0x80");
5842                   if (!rightInB)
5843                     {
5844                       pushedB = pushB ();
5845                       rightInB++;
5846                       MOVB (aopGet (right, offset, FALSE, FALSE));
5847                     }
5848                   emitcode ("xrl", "b,#0x80");
5849                   emitcode ("subb", "a,b");
5850                 }
5851               else
5852                 {
5853                   if (rightInB)
5854                     emitcode ("subb", "a,b");
5855                   else
5856                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5857                 }
5858               if (rightInB)
5859                 popB (pushedB);
5860               offset++;
5861             }
5862         }
5863     }
5864
5865 release:
5866   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5867   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5868   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5869     {
5870       outBitC (result);
5871     }
5872   else
5873     {
5874       /* if the result is used in the next
5875          ifx conditional branch then generate
5876          code a little differently */
5877       if (ifx)
5878         {
5879           genIfxJump (ifx, "c", NULL, NULL, result);
5880         }
5881       else
5882         {
5883           outBitC (result);
5884         }
5885       /* leave the result in acc */
5886     }
5887 }
5888
5889 /*-----------------------------------------------------------------*/
5890 /* genCmpGt :- greater than comparison                             */
5891 /*-----------------------------------------------------------------*/
5892 static void
5893 genCmpGt (iCode * ic, iCode * ifx)
5894 {
5895   operand *left, *right, *result;
5896   sym_link *letype, *retype;
5897   int sign;
5898
5899   D (emitcode (";", "genCmpGt"));
5900
5901   left = IC_LEFT (ic);
5902   right = IC_RIGHT (ic);
5903   result = IC_RESULT (ic);
5904
5905   letype = getSpec (operandType (left));
5906   retype = getSpec (operandType (right));
5907   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5908            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5909   /* assign the amsops */
5910   aopOp (result, ic, TRUE);
5911   aopOp (left, ic, FALSE);
5912   aopOp (right, ic, FALSE);
5913
5914   genCmp (right, left, result, ifx, sign, ic);
5915
5916   freeAsmop (result, NULL, ic, TRUE);
5917 }
5918
5919 /*-----------------------------------------------------------------*/
5920 /* genCmpLt - less than comparisons                                */
5921 /*-----------------------------------------------------------------*/
5922 static void
5923 genCmpLt (iCode * ic, iCode * ifx)
5924 {
5925   operand *left, *right, *result;
5926   sym_link *letype, *retype;
5927   int sign;
5928
5929   D (emitcode (";", "genCmpLt"));
5930
5931   left = IC_LEFT (ic);
5932   right = IC_RIGHT (ic);
5933   result = IC_RESULT (ic);
5934
5935   letype = getSpec (operandType (left));
5936   retype = getSpec (operandType (right));
5937   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5938            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5939   /* assign the amsops */
5940   aopOp (result, ic, TRUE);
5941   aopOp (left, ic, FALSE);
5942   aopOp (right, ic, FALSE);
5943
5944   genCmp (left, right, result, ifx, sign, ic);
5945
5946   freeAsmop (result, NULL, ic, TRUE);
5947 }
5948
5949 /*-----------------------------------------------------------------*/
5950 /* gencjneshort - compare and jump if not equal                    */
5951 /*-----------------------------------------------------------------*/
5952 static void
5953 gencjneshort (operand * left, operand * right, symbol * lbl)
5954 {
5955   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5956   int offset = 0;
5957   unsigned long lit = 0L;
5958
5959   D (emitcode (";", "gencjneshort"));
5960
5961   /* if the left side is a literal or
5962      if the right is in a pointer register and left
5963      is not */
5964   if ((AOP_TYPE (left) == AOP_LIT) ||
5965       (AOP_TYPE (left) == AOP_IMMD) ||
5966       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5967     {
5968       operand *t = right;
5969       right = left;
5970       left = t;
5971     }
5972
5973   if (AOP_TYPE (right) == AOP_LIT)
5974     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5975
5976   /* if the right side is a literal then anything goes */
5977   if (AOP_TYPE (right) == AOP_LIT &&
5978       AOP_TYPE (left) != AOP_DIR  &&
5979       AOP_TYPE (left) != AOP_IMMD)
5980     {
5981       while (size--)
5982         {
5983           emitcode ("cjne", "%s,%s,%05d$",
5984                     aopGet (left, offset, FALSE, FALSE),
5985                     aopGet (right, offset, FALSE, FALSE),
5986                     lbl->key + 100);
5987           offset++;
5988         }
5989     }
5990
5991   /* if the right side is in a register or in direct space or
5992      if the left is a pointer register & right is not */
5993   else if (AOP_TYPE (right) == AOP_REG ||
5994            AOP_TYPE (right) == AOP_DIR ||
5995            AOP_TYPE (right) == AOP_LIT ||
5996            AOP_TYPE (right) == AOP_IMMD ||
5997            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5998            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5999     {
6000       while (size--)
6001         {
6002           MOVA (aopGet (left, offset, FALSE, FALSE));
6003           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6004               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6005             emitcode ("jnz", "%05d$", lbl->key + 100);
6006           else
6007             emitcode ("cjne", "a,%s,%05d$",
6008                       aopGet (right, offset, FALSE, TRUE),
6009                       lbl->key + 100);
6010           offset++;
6011         }
6012     }
6013   else
6014     {
6015       /* right is a pointer reg need both a & b */
6016       while (size--)
6017         {
6018           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6019           wassertl(!BINUSE, "B was in use");
6020           MOVB (aopGet (left, offset, FALSE, FALSE));
6021           MOVA (aopGet (right, offset, FALSE, FALSE));
6022           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6023           offset++;
6024         }
6025     }
6026 }
6027
6028 /*-----------------------------------------------------------------*/
6029 /* gencjne - compare and jump if not equal                         */
6030 /*-----------------------------------------------------------------*/
6031 static void
6032 gencjne (operand * left, operand * right, symbol * lbl)
6033 {
6034   symbol *tlbl = newiTempLabel (NULL);
6035
6036   D (emitcode (";", "gencjne"));
6037
6038   gencjneshort (left, right, lbl);
6039
6040   emitcode ("mov", "a,%s", one);
6041   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6042   emitLabel (lbl);
6043   emitcode ("clr", "a");
6044   emitLabel (tlbl);
6045 }
6046
6047 /*-----------------------------------------------------------------*/
6048 /* genCmpEq - generates code for equal to                          */
6049 /*-----------------------------------------------------------------*/
6050 static void
6051 genCmpEq (iCode * ic, iCode * ifx)
6052 {
6053   bool swappedLR = FALSE;
6054   operand *left, *right, *result;
6055
6056   D (emitcode (";", "genCmpEq"));
6057
6058   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6059   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6060   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6061
6062   /* if literal, literal on the right or
6063      if the right is in a pointer register and left
6064      is not */
6065   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6066       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6067     {
6068       operand *t = IC_RIGHT (ic);
6069       IC_RIGHT (ic) = IC_LEFT (ic);
6070       IC_LEFT (ic) = t;
6071       swappedLR = TRUE;
6072     }
6073
6074   if (ifx && !AOP_SIZE (result))
6075     {
6076       symbol *tlbl;
6077       /* if they are both bit variables */
6078       if (AOP_TYPE (left) == AOP_CRY &&
6079           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6080         {
6081           if (AOP_TYPE (right) == AOP_LIT)
6082             {
6083               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6084               if (lit == 0L)
6085                 {
6086                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6087                   emitcode ("cpl", "c");
6088                 }
6089               else if (lit == 1L)
6090                 {
6091                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6092                 }
6093               else
6094                 {
6095                   emitcode ("clr", "c");
6096                 }
6097               /* AOP_TYPE(right) == AOP_CRY */
6098             }
6099           else
6100             {
6101               symbol *lbl = newiTempLabel (NULL);
6102               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6103               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6104               emitcode ("cpl", "c");
6105               emitLabel (lbl);
6106             }
6107           /* if true label then we jump if condition
6108              supplied is true */
6109           tlbl = newiTempLabel (NULL);
6110           if (IC_TRUE (ifx))
6111             {
6112               emitcode ("jnc", "%05d$", tlbl->key + 100);
6113               freeForBranchAsmop (result);
6114               freeForBranchAsmop (right);
6115               freeForBranchAsmop (left);
6116               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6117             }
6118           else
6119             {
6120               emitcode ("jc", "%05d$", tlbl->key + 100);
6121               freeForBranchAsmop (result);
6122               freeForBranchAsmop (right);
6123               freeForBranchAsmop (left);
6124               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6125             }
6126           emitLabel (tlbl);
6127         }
6128       else
6129         {
6130           tlbl = newiTempLabel (NULL);
6131           gencjneshort (left, right, tlbl);
6132           if (IC_TRUE (ifx))
6133             {
6134               freeForBranchAsmop (result);
6135               freeForBranchAsmop (right);
6136               freeForBranchAsmop (left);
6137               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6138               emitLabel (tlbl);
6139             }
6140           else
6141             {
6142               symbol *lbl = newiTempLabel (NULL);
6143               emitcode ("sjmp", "%05d$", lbl->key + 100);
6144               emitLabel (tlbl);
6145               freeForBranchAsmop (result);
6146               freeForBranchAsmop (right);
6147               freeForBranchAsmop (left);
6148               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6149               emitLabel (lbl);
6150             }
6151         }
6152       /* mark the icode as generated */
6153       ifx->generated = 1;
6154       goto release;
6155     }
6156
6157   /* if they are both bit variables */
6158   if (AOP_TYPE (left) == AOP_CRY &&
6159       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6160     {
6161       if (AOP_TYPE (right) == AOP_LIT)
6162         {
6163           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6164           if (lit == 0L)
6165             {
6166               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6167               emitcode ("cpl", "c");
6168             }
6169           else if (lit == 1L)
6170             {
6171               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6172             }
6173           else
6174             {
6175               emitcode ("clr", "c");
6176             }
6177           /* AOP_TYPE(right) == AOP_CRY */
6178         }
6179       else
6180         {
6181           symbol *lbl = newiTempLabel (NULL);
6182           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6183           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6184           emitcode ("cpl", "c");
6185           emitLabel (lbl);
6186         }
6187       /* c = 1 if egal */
6188       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6189         {
6190           outBitC (result);
6191           goto release;
6192         }
6193       if (ifx)
6194         {
6195           genIfxJump (ifx, "c", left, right, result);
6196           goto release;
6197         }
6198       /* if the result is used in an arithmetic operation
6199          then put the result in place */
6200       outBitC (result);
6201     }
6202   else
6203     {
6204       gencjne (left, right, newiTempLabel (NULL));
6205       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6206         {
6207           aopPut (result, "a", 0);
6208           goto release;
6209         }
6210       if (ifx)
6211         {
6212           genIfxJump (ifx, "a", left, right, result);
6213           goto release;
6214         }
6215       /* if the result is used in an arithmetic operation
6216          then put the result in place */
6217       if (AOP_TYPE (result) != AOP_CRY)
6218         outAcc (result);
6219       /* leave the result in acc */
6220     }
6221
6222 release:
6223   freeAsmop (result, NULL, ic, TRUE);
6224   if (!swappedLR)
6225     {
6226       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6227       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6228     }
6229   else
6230     {
6231       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6232       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233     }
6234 }
6235
6236 /*-----------------------------------------------------------------*/
6237 /* ifxForOp - returns the icode containing the ifx for operand     */
6238 /*-----------------------------------------------------------------*/
6239 static iCode *
6240 ifxForOp (operand * op, iCode * ic)
6241 {
6242   /* if true symbol then needs to be assigned */
6243   if (IS_TRUE_SYMOP (op))
6244     return NULL;
6245
6246   /* if this has register type condition and
6247      the next instruction is ifx with the same operand
6248      and live to of the operand is upto the ifx only then */
6249   if (ic->next &&
6250       ic->next->op == IFX &&
6251       IC_COND (ic->next)->key == op->key &&
6252       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6253     return ic->next;
6254
6255   return NULL;
6256 }
6257
6258 /*-----------------------------------------------------------------*/
6259 /* hasInc - operand is incremented before any other use            */
6260 /*-----------------------------------------------------------------*/
6261 static iCode *
6262 hasInc (operand *op, iCode *ic, int osize)
6263 {
6264   sym_link *type = operandType(op);
6265   sym_link *retype = getSpec (type);
6266   iCode *lic = ic->next;
6267   int isize ;
6268
6269   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6270   if (!IS_SYMOP(op)) return NULL;
6271
6272   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6273   if (IS_AGGREGATE(type->next)) return NULL;
6274   if (osize != (isize = getSize(type->next))) return NULL;
6275
6276   while (lic) {
6277     /* if operand of the form op = op + <sizeof *op> */
6278     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6279         isOperandEqual(IC_RESULT(lic),op) &&
6280         isOperandLiteral(IC_RIGHT(lic)) &&
6281         operandLitValue(IC_RIGHT(lic)) == isize) {
6282       return lic;
6283     }
6284     /* if the operand used or deffed */
6285     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6286       return NULL;
6287     }
6288     /* if GOTO or IFX */
6289     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6290     lic = lic->next;
6291   }
6292   return NULL;
6293 }
6294
6295 /*-----------------------------------------------------------------*/
6296 /* genAndOp - for && operation                                     */
6297 /*-----------------------------------------------------------------*/
6298 static void
6299 genAndOp (iCode * ic)
6300 {
6301   operand *left, *right, *result;
6302   symbol *tlbl;
6303
6304   D (emitcode (";", "genAndOp"));
6305
6306   /* note here that && operations that are in an
6307      if statement are taken away by backPatchLabels
6308      only those used in arthmetic operations remain */
6309   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6310   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6311   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6312
6313   /* if both are bit variables */
6314   if (AOP_TYPE (left) == AOP_CRY &&
6315       AOP_TYPE (right) == AOP_CRY)
6316     {
6317       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6318       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6319       outBitC (result);
6320     }
6321   else
6322     {
6323       tlbl = newiTempLabel (NULL);
6324       toBoolean (left);
6325       emitcode ("jz", "%05d$", tlbl->key + 100);
6326       toBoolean (right);
6327       emitLabel (tlbl);
6328       outBitAcc (result);
6329     }
6330
6331   freeAsmop (result, NULL, ic, TRUE);
6332   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6333   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6334 }
6335
6336
6337 /*-----------------------------------------------------------------*/
6338 /* genOrOp - for || operation                                      */
6339 /*-----------------------------------------------------------------*/
6340 static void
6341 genOrOp (iCode * ic)
6342 {
6343   operand *left, *right, *result;
6344   symbol *tlbl;
6345
6346   D (emitcode (";", "genOrOp"));
6347
6348   /* note here that || operations that are in an
6349      if statement are taken away by backPatchLabels
6350      only those used in arthmetic operations remain */
6351   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6352   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6353   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6354
6355   /* if both are bit variables */
6356   if (AOP_TYPE (left) == AOP_CRY &&
6357       AOP_TYPE (right) == AOP_CRY)
6358     {
6359       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6360       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6361       outBitC (result);
6362     }
6363   else
6364     {
6365       tlbl = newiTempLabel (NULL);
6366       toBoolean (left);
6367       emitcode ("jnz", "%05d$", tlbl->key + 100);
6368       toBoolean (right);
6369       emitLabel (tlbl);
6370       outBitAcc (result);
6371     }
6372
6373   freeAsmop (result, NULL, ic, TRUE);
6374   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6375   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6376 }
6377
6378 /*-----------------------------------------------------------------*/
6379 /* isLiteralBit - test if lit == 2^n                               */
6380 /*-----------------------------------------------------------------*/
6381 static int
6382 isLiteralBit (unsigned long lit)
6383 {
6384   unsigned long pw[32] =
6385   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6386    0x100L, 0x200L, 0x400L, 0x800L,
6387    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6388    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6389    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6390    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6391    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6392   int idx;
6393
6394   for (idx = 0; idx < 32; idx++)
6395     if (lit == pw[idx])
6396       return idx + 1;
6397   return 0;
6398 }
6399
6400 /*-----------------------------------------------------------------*/
6401 /* continueIfTrue -                                                */
6402 /*-----------------------------------------------------------------*/
6403 static void
6404 continueIfTrue (iCode * ic)
6405 {
6406   if (IC_TRUE (ic))
6407     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6408   ic->generated = 1;
6409 }
6410
6411 /*-----------------------------------------------------------------*/
6412 /* jmpIfTrue -                                                     */
6413 /*-----------------------------------------------------------------*/
6414 static void
6415 jumpIfTrue (iCode * ic)
6416 {
6417   if (!IC_TRUE (ic))
6418     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6419   ic->generated = 1;
6420 }
6421
6422 /*-----------------------------------------------------------------*/
6423 /* jmpTrueOrFalse -                                                */
6424 /*-----------------------------------------------------------------*/
6425 static void
6426 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6427 {
6428   // ugly but optimized by peephole
6429   if (IC_TRUE (ic))
6430     {
6431       symbol *nlbl = newiTempLabel (NULL);
6432       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6433       emitLabel (tlbl);
6434       freeForBranchAsmop (result);
6435       freeForBranchAsmop (right);
6436       freeForBranchAsmop (left);
6437       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6438       emitLabel (nlbl);
6439     }
6440   else
6441     {
6442       freeForBranchAsmop (result);
6443       freeForBranchAsmop (right);
6444       freeForBranchAsmop (left);
6445       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6446       emitLabel (tlbl);
6447     }
6448   ic->generated = 1;
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* genAnd  - code for and                                          */
6453 /*-----------------------------------------------------------------*/
6454 static void
6455 genAnd (iCode * ic, iCode * ifx)
6456 {
6457   operand *left, *right, *result;
6458   int size, offset = 0;
6459   unsigned long lit = 0L;
6460   int bytelit = 0;
6461   char buffer[10];
6462
6463   D (emitcode (";", "genAnd"));
6464
6465   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6466   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6467   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6468
6469 #ifdef DEBUG_TYPE
6470   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6471             AOP_TYPE (result),
6472             AOP_TYPE (left), AOP_TYPE (right));
6473   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6474             AOP_SIZE (result),
6475             AOP_SIZE (left), AOP_SIZE (right));
6476 #endif
6477
6478   /* if left is a literal & right is not then exchange them */
6479   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6480       AOP_NEEDSACC (left))
6481     {
6482       operand *tmp = right;
6483       right = left;
6484       left = tmp;
6485     }
6486
6487   /* if result = right then exchange left and right */
6488   if (sameRegs (AOP (result), AOP (right)))
6489     {
6490       operand *tmp = right;
6491       right = left;
6492       left = tmp;
6493     }
6494
6495   /* if right is bit then exchange them */
6496   if (AOP_TYPE (right) == AOP_CRY &&
6497       AOP_TYPE (left) != AOP_CRY)
6498     {
6499       operand *tmp = right;
6500       right = left;
6501       left = tmp;
6502     }
6503   if (AOP_TYPE (right) == AOP_LIT)
6504     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6505
6506   size = AOP_SIZE (result);
6507
6508   // if(bit & yy)
6509   // result = bit & yy;
6510   if (AOP_TYPE (left) == AOP_CRY)
6511     {
6512       // c = bit & literal;
6513       if (AOP_TYPE (right) == AOP_LIT)
6514         {
6515           if (lit & 1)
6516             {
6517               if (size && sameRegs (AOP (result), AOP (left)))
6518                 // no change
6519                 goto release;
6520               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6521             }
6522           else
6523             {
6524               // bit(result) = 0;
6525               if (size && (AOP_TYPE (result) == AOP_CRY))
6526                 {
6527                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6528                   goto release;
6529                 }
6530               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6531                 {
6532                   jumpIfTrue (ifx);
6533                   goto release;
6534                 }
6535               emitcode ("clr", "c");
6536             }
6537         }
6538       else
6539         {
6540           if (AOP_TYPE (right) == AOP_CRY)
6541             {
6542               // c = bit & bit;
6543               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6544               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6545             }
6546           else
6547             {
6548               // c = bit & val;
6549               MOVA (aopGet (right, 0, FALSE, FALSE));
6550               // c = lsb
6551               emitcode ("rrc", "a");
6552               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6553             }
6554         }
6555       // bit = c
6556       // val = c
6557       if (size)
6558         outBitC (result);
6559       // if(bit & ...)
6560       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6561         genIfxJump (ifx, "c", left, right, result);
6562       goto release;
6563     }
6564
6565   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6566   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6567   if ((AOP_TYPE (right) == AOP_LIT) &&
6568       (AOP_TYPE (result) == AOP_CRY) &&
6569       (AOP_TYPE (left) != AOP_CRY))
6570     {
6571       int posbit = isLiteralBit (lit);
6572       /* left &  2^n */
6573       if (posbit)
6574         {
6575           posbit--;
6576           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6577           // bit = left & 2^n
6578           if (size)
6579             {
6580               switch (posbit & 0x07)
6581                 {
6582                   case 0: emitcode ("rrc", "a");
6583                           break;
6584                   case 7: emitcode ("rlc", "a");
6585                           break;
6586                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6587                           break;
6588                 }
6589             }
6590           // if(left &  2^n)
6591           else
6592             {
6593               if (ifx)
6594                 {
6595                   SNPRINTF (buffer, sizeof(buffer),
6596                             "acc.%d", posbit & 0x07);
6597                   genIfxJump (ifx, buffer, left, right, result);
6598                 }
6599               else
6600                 {// what is this case? just found it in ds390/gen.c
6601                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6602                 }
6603               goto release;
6604             }
6605         }
6606       else
6607         {
6608           symbol *tlbl = newiTempLabel (NULL);
6609           int sizel = AOP_SIZE (left);
6610           if (size)
6611             emitcode ("setb", "c");
6612           while (sizel--)
6613             {
6614               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6615                 {
6616                   MOVA (aopGet (left, offset, FALSE, FALSE));
6617                   // byte ==  2^n ?
6618                   if ((posbit = isLiteralBit (bytelit)) != 0)
6619                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6620                   else
6621                     {
6622                       if (bytelit != 0x0FFL)
6623                         emitcode ("anl", "a,%s",
6624                                   aopGet (right, offset, FALSE, TRUE));
6625                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6626                     }
6627                 }
6628               offset++;
6629             }
6630           // bit = left & literal
6631           if (size)
6632             {
6633               emitcode ("clr", "c");
6634               emitLabel (tlbl);
6635             }
6636           // if(left & literal)
6637           else
6638             {
6639               if (ifx)
6640                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6641               else
6642                 emitLabel (tlbl);
6643               goto release;
6644             }
6645         }
6646       outBitC (result);
6647       goto release;
6648     }
6649
6650   /* if left is same as result */
6651   if (sameRegs (AOP (result), AOP (left)))
6652     {
6653       for (; size--; offset++)
6654         {
6655           if (AOP_TYPE (right) == AOP_LIT)
6656             {
6657               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6658               if (bytelit == 0x0FF)
6659                 {
6660                   /* dummy read of volatile operand */
6661                   if (isOperandVolatile (left, FALSE))
6662                     MOVA (aopGet (left, offset, FALSE, FALSE));
6663                   else
6664                     continue;
6665                 }
6666               else if (bytelit == 0)
6667                 {
6668                   aopPut (result, zero, offset);
6669                 }
6670               else if (IS_AOP_PREG (result))
6671                 {
6672                   MOVA (aopGet (left, offset, FALSE, TRUE));
6673                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6674                   aopPut (result, "a", offset);
6675                 }
6676               else
6677                 emitcode ("anl", "%s,%s",
6678                           aopGet (left, offset, FALSE, TRUE),
6679                           aopGet (right, offset, FALSE, FALSE));
6680             }
6681           else
6682             {
6683               if (AOP_TYPE (left) == AOP_ACC)
6684                 {
6685                   if (offset)
6686                     emitcode("mov", "a,b");
6687                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6688                 }
6689               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6690                 {
6691                   MOVB (aopGet (left, offset, FALSE, FALSE));
6692                   MOVA (aopGet (right, offset, FALSE, FALSE));
6693                   emitcode ("anl", "a,b");
6694                   aopPut (result, "a", offset);
6695                 }
6696               else if (aopGetUsesAcc (left, offset))
6697                 {
6698                   MOVA (aopGet (left, offset, FALSE, FALSE));
6699                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6700                   aopPut (result, "a", offset);
6701                 }
6702               else
6703                 {
6704                   MOVA (aopGet (right, offset, FALSE, FALSE));
6705                   if (IS_AOP_PREG (result))
6706                     {
6707                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6708                       aopPut (result, "a", offset);
6709                     }
6710                   else
6711                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6712                 }
6713             }
6714         }
6715     }
6716   else
6717     {
6718       // left & result in different registers
6719       if (AOP_TYPE (result) == AOP_CRY)
6720         {
6721           // result = bit
6722           // if(size), result in bit
6723           // if(!size && ifx), conditional oper: if(left & right)
6724           symbol *tlbl = newiTempLabel (NULL);
6725           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6726           if (size)
6727             emitcode ("setb", "c");
6728           while (sizer--)
6729             {
6730               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6731                   && AOP_TYPE(left)==AOP_ACC)
6732                 {
6733                   if (offset)
6734                     emitcode("mov", "a,b");
6735                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6736                 }
6737               else if (AOP_TYPE(left)==AOP_ACC)
6738                 {
6739                   if (!offset)
6740                     {
6741                       bool pushedB = pushB ();
6742                       emitcode("mov", "b,a");
6743                       MOVA (aopGet (right, offset, FALSE, FALSE));
6744                       emitcode("anl", "a,b");
6745                       popB (pushedB);
6746                     }
6747                   else
6748                     {
6749                       MOVA (aopGet (right, offset, FALSE, FALSE));
6750                       emitcode("anl", "a,b");
6751                     }
6752                 }
6753               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6754                 {
6755                   MOVB (aopGet (left, offset, FALSE, FALSE));
6756                   MOVA (aopGet (right, offset, FALSE, FALSE));
6757                   emitcode ("anl", "a,b");
6758                 }
6759               else if (aopGetUsesAcc (left, offset))
6760                 {
6761                   MOVA (aopGet (left, offset, FALSE, FALSE));
6762                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6763                     }
6764               else
6765                 {
6766                   MOVA (aopGet (right, offset, FALSE, FALSE));
6767                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6768                 }
6769
6770               emitcode ("jnz", "%05d$", tlbl->key + 100);
6771               offset++;
6772             }
6773           if (size)
6774             {
6775               CLRC;
6776               emitLabel (tlbl);
6777               outBitC (result);
6778             }
6779           else if (ifx)
6780             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6781           else
6782             emitLabel (tlbl);
6783         }
6784       else
6785         {
6786           for (; (size--); offset++)
6787             {
6788               // normal case
6789               // result = left & right
6790               if (AOP_TYPE (right) == AOP_LIT)
6791                 {
6792                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6793                   if (bytelit == 0x0FF)
6794                     {
6795                       aopPut (result,
6796                               aopGet (left, offset, FALSE, FALSE),
6797                               offset);
6798                       continue;
6799                     }
6800                   else if (bytelit == 0)
6801                     {
6802                       /* dummy read of volatile operand */
6803                       if (isOperandVolatile (left, FALSE))
6804                         MOVA (aopGet (left, offset, FALSE, FALSE));
6805                       aopPut (result, zero, offset);
6806                       continue;
6807                     }
6808                   else if (AOP_TYPE (left) == AOP_ACC)
6809                     {
6810                       if (!offset)
6811                         {
6812                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6813                           aopPut (result, "a", offset);
6814                           continue;
6815                         }
6816                       else
6817                         {
6818                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6819                           aopPut (result, "b", offset);
6820                           continue;
6821                         }
6822                     }
6823                 }
6824               // faster than result <- left, anl result,right
6825               // and better if result is SFR
6826               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6827                   && AOP_TYPE(left)==AOP_ACC)
6828                 {
6829                   if (offset)
6830                     emitcode("mov", "a,b");
6831                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6832                 }
6833               else if (AOP_TYPE(left)==AOP_ACC)
6834                 {
6835                   if (!offset)
6836                     {
6837                       bool pushedB = pushB ();
6838                       emitcode("mov", "b,a");
6839                       MOVA (aopGet (right, offset, FALSE, FALSE));
6840                       emitcode("anl", "a,b");
6841                       popB (pushedB);
6842                     }
6843                   else
6844                     {
6845                       MOVA (aopGet (right, offset, FALSE, FALSE));
6846                       emitcode("anl", "a,b");
6847                     }
6848                 }
6849               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6850                 {
6851                   MOVB (aopGet (left, offset, FALSE, FALSE));
6852                   MOVA (aopGet (right, offset, FALSE, FALSE));
6853                   emitcode ("anl", "a,b");
6854                 }
6855               else if (aopGetUsesAcc (left, offset))
6856                 {
6857                   MOVA (aopGet (left, offset, FALSE, FALSE));
6858                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6859                 }
6860               else
6861                 {
6862                   MOVA (aopGet (right, offset, FALSE, FALSE));
6863                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6864                 }
6865               aopPut (result, "a", offset);
6866             }
6867         }
6868     }
6869
6870 release:
6871   freeAsmop (result, NULL, ic, TRUE);
6872   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6873   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6874 }
6875
6876 /*-----------------------------------------------------------------*/
6877 /* genOr  - code for or                                            */
6878 /*-----------------------------------------------------------------*/
6879 static void
6880 genOr (iCode * ic, iCode * ifx)
6881 {
6882   operand *left, *right, *result;
6883   int size, offset = 0;
6884   unsigned long lit = 0L;
6885   int bytelit = 0;
6886
6887   D (emitcode (";", "genOr"));
6888
6889   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6890   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6891   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6892
6893 #ifdef DEBUG_TYPE
6894   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6895             AOP_TYPE (result),
6896             AOP_TYPE (left), AOP_TYPE (right));
6897   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6898             AOP_SIZE (result),
6899             AOP_SIZE (left), AOP_SIZE (right));
6900 #endif
6901
6902   /* if left is a literal & right is not then exchange them */
6903   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6904       AOP_NEEDSACC (left))
6905     {
6906       operand *tmp = right;
6907       right = left;
6908       left = tmp;
6909     }
6910
6911   /* if result = right then exchange them */
6912   if (sameRegs (AOP (result), AOP (right)))
6913     {
6914       operand *tmp = right;
6915       right = left;
6916       left = tmp;
6917     }
6918
6919   /* if right is bit then exchange them */
6920   if (AOP_TYPE (right) == AOP_CRY &&
6921       AOP_TYPE (left) != AOP_CRY)
6922     {
6923       operand *tmp = right;
6924       right = left;
6925       left = tmp;
6926     }
6927   if (AOP_TYPE (right) == AOP_LIT)
6928     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6929
6930   size = AOP_SIZE (result);
6931
6932   // if(bit | yy)
6933   // xx = bit | yy;
6934   if (AOP_TYPE (left) == AOP_CRY)
6935     {
6936       if (AOP_TYPE (right) == AOP_LIT)
6937         {
6938           // c = bit | literal;
6939           if (lit)
6940             {
6941               // lit != 0 => result = 1
6942               if (AOP_TYPE (result) == AOP_CRY)
6943                 {
6944                   if (size)
6945                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6946                   else if (ifx)
6947                     continueIfTrue (ifx);
6948                   goto release;
6949                 }
6950               emitcode ("setb", "c");
6951             }
6952           else
6953             {
6954               // lit == 0 => result = left
6955               if (size && sameRegs (AOP (result), AOP (left)))
6956                 goto release;
6957               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6958             }
6959         }
6960       else
6961         {
6962           if (AOP_TYPE (right) == AOP_CRY)
6963             {
6964               // c = bit | bit;
6965               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6966               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6967             }
6968           else
6969             {
6970               // c = bit | val;
6971               symbol *tlbl = newiTempLabel (NULL);
6972               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6973                 emitcode ("setb", "c");
6974               emitcode ("jb", "%s,%05d$",
6975                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6976               toBoolean (right);
6977               emitcode ("jnz", "%05d$", tlbl->key + 100);
6978               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6979                 {
6980                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6981                   goto release;
6982                 }
6983               else
6984                 {
6985                   CLRC;
6986                   emitLabel (tlbl);
6987                 }
6988             }
6989         }
6990       // bit = c
6991       // val = c
6992       if (size)
6993         outBitC (result);
6994       // if(bit | ...)
6995       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6996         genIfxJump (ifx, "c", left, right, result);
6997       goto release;
6998     }
6999
7000   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7001   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7002   if ((AOP_TYPE (right) == AOP_LIT) &&
7003       (AOP_TYPE (result) == AOP_CRY) &&
7004       (AOP_TYPE (left) != AOP_CRY))
7005     {
7006       if (lit)
7007         {
7008           // result = 1
7009           if (size)
7010             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7011           else
7012             continueIfTrue (ifx);
7013           goto release;
7014         }
7015       else
7016         {
7017           // lit = 0, result = boolean(left)
7018           if (size)
7019             emitcode ("setb", "c");
7020           toBoolean (right);
7021           if (size)
7022             {
7023               symbol *tlbl = newiTempLabel (NULL);
7024               emitcode ("jnz", "%05d$", tlbl->key + 100);
7025               CLRC;
7026               emitLabel (tlbl);
7027             }
7028           else
7029             {
7030               genIfxJump (ifx, "a", left, right, result);
7031               goto release;
7032             }
7033         }
7034       outBitC (result);
7035       goto release;
7036     }
7037
7038   /* if left is same as result */
7039   if (sameRegs (AOP (result), AOP (left)))
7040     {
7041       for (; size--; offset++)
7042         {
7043           if (AOP_TYPE (right) == AOP_LIT)
7044             {
7045               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7046               if (bytelit == 0)
7047                 {
7048                   /* dummy read of volatile operand */
7049                   if (isOperandVolatile (left, FALSE))
7050                     MOVA (aopGet (left, offset, FALSE, FALSE));
7051                   else
7052                     continue;
7053                 }
7054               else if (bytelit == 0x0FF)
7055                 {
7056                   aopPut (result, "#0xFF", offset);
7057                 }
7058               else if (IS_AOP_PREG (left))
7059                 {
7060                   MOVA (aopGet (left, offset, FALSE, TRUE));
7061                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7062                   aopPut (result, "a", offset);
7063                 }
7064               else
7065                 {
7066                   emitcode ("orl", "%s,%s",
7067                             aopGet (left, offset, FALSE, TRUE),
7068                             aopGet (right, offset, FALSE, FALSE));
7069                 }
7070             }
7071           else
7072             {
7073               if (AOP_TYPE (left) == AOP_ACC)
7074                 {
7075                   if (offset)
7076                     emitcode("mov", "a,b");
7077                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7078                 }
7079               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7080                 {
7081                   MOVB (aopGet (left, offset, FALSE, FALSE));
7082                   MOVA (aopGet (right, offset, FALSE, FALSE));
7083                   emitcode ("orl", "a,b");
7084                   aopPut (result, "a", offset);
7085                 }
7086               else if (aopGetUsesAcc (left, offset))
7087                 {
7088                   MOVA (aopGet (left, offset, FALSE, FALSE));
7089                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7090                   aopPut (result, "a", offset);
7091                 }
7092               else
7093                 {
7094                   MOVA (aopGet (right, offset, FALSE, FALSE));
7095                   if (IS_AOP_PREG (left))
7096                     {
7097                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7098                       aopPut (result, "a", offset);
7099                     }
7100                   else
7101                     {
7102                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7103                     }
7104                 }
7105             }
7106         }
7107     }
7108   else
7109     {
7110       // left & result in different registers
7111       if (AOP_TYPE (result) == AOP_CRY)
7112         {
7113           // result = bit
7114           // if(size), result in bit
7115           // if(!size && ifx), conditional oper: if(left | right)
7116           symbol *tlbl = newiTempLabel (NULL);
7117           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7118           if (size)
7119             emitcode ("setb", "c");
7120           while (sizer--)
7121             {
7122               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7123                   && AOP_TYPE(left)==AOP_ACC)
7124                 {
7125                   if (offset)
7126                     emitcode("mov", "a,b");
7127                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7128                 }
7129               else if (AOP_TYPE(left)==AOP_ACC)
7130                 {
7131                   if (!offset)
7132                     {
7133                       bool pushedB = pushB ();
7134                       emitcode("mov", "b,a");
7135                       MOVA (aopGet (right, offset, FALSE, FALSE));
7136                       emitcode("orl", "a,b");
7137                       popB (pushedB);
7138                     }
7139                   else
7140                     {
7141                       MOVA (aopGet (right, offset, FALSE, FALSE));
7142                       emitcode("orl", "a,b");
7143                     }
7144                 }
7145               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7146                 {
7147                   MOVB (aopGet (left, offset, FALSE, FALSE));
7148                   MOVA (aopGet (right, offset, FALSE, FALSE));
7149                   emitcode ("orl", "a,b");
7150                 }
7151               else if (aopGetUsesAcc (left, offset))
7152                 {
7153                   MOVA (aopGet (left, offset, FALSE, FALSE));
7154                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7155                 }
7156               else
7157                 {
7158                   MOVA (aopGet (right, offset, FALSE, FALSE));
7159                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7160               }
7161
7162               emitcode ("jnz", "%05d$", tlbl->key + 100);
7163               offset++;
7164             }
7165           if (size)
7166             {
7167               CLRC;
7168               emitLabel (tlbl);
7169               outBitC (result);
7170             }
7171           else if (ifx)
7172             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7173           else
7174             emitLabel (tlbl);
7175         }
7176       else
7177         {
7178           for (; (size--); offset++)
7179             {
7180               // normal case
7181               // result = left | right
7182               if (AOP_TYPE (right) == AOP_LIT)
7183                 {
7184                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7185                   if (bytelit == 0)
7186                     {
7187                       aopPut (result,
7188                               aopGet (left, offset, FALSE, FALSE),
7189                               offset);
7190                       continue;
7191                     }
7192                   else if (bytelit == 0x0FF)
7193                     {
7194                       /* dummy read of volatile operand */
7195                       if (isOperandVolatile (left, FALSE))
7196                         MOVA (aopGet (left, offset, FALSE, FALSE));
7197                       aopPut (result, "#0xFF", offset);
7198                       continue;
7199                     }
7200                 }
7201               // faster than result <- left, orl result,right
7202               // and better if result is SFR
7203               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7204                   && AOP_TYPE(left)==AOP_ACC)
7205                 {
7206                   if (offset)
7207                     emitcode("mov", "a,b");
7208                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7209                 }
7210               else if (AOP_TYPE(left)==AOP_ACC)
7211                 {
7212                   if (!offset)
7213                     {
7214                       bool pushedB = pushB ();
7215                       emitcode("mov", "b,a");
7216                       MOVA (aopGet (right, offset, FALSE, FALSE));
7217                       emitcode("orl", "a,b");
7218                       popB (pushedB);
7219                     }
7220                   else
7221                     {
7222                       MOVA (aopGet (right, offset, FALSE, FALSE));
7223                       emitcode("orl", "a,b");
7224                     }
7225                 }
7226               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7227                 {
7228                   MOVB (aopGet (left, offset, FALSE, FALSE));
7229                   MOVA (aopGet (right, offset, FALSE, FALSE));
7230                   emitcode ("orl", "a,b");
7231                 }
7232               else if (aopGetUsesAcc (left, offset))
7233                 {
7234                   MOVA (aopGet (left, offset, FALSE, FALSE));
7235                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7236                 }
7237               else
7238                 {
7239                   MOVA (aopGet (right, offset, FALSE, FALSE));
7240                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7241                 }
7242               aopPut (result, "a", offset);
7243             }
7244         }
7245     }
7246
7247 release:
7248   freeAsmop (result, NULL, ic, TRUE);
7249   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7250   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* genXor - code for xclusive or                                   */
7255 /*-----------------------------------------------------------------*/
7256 static void
7257 genXor (iCode * ic, iCode * ifx)
7258 {
7259   operand *left, *right, *result;
7260   int size, offset = 0;
7261   unsigned long lit = 0L;
7262   int bytelit = 0;
7263
7264   D (emitcode (";", "genXor"));
7265
7266   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7267   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7268   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7269
7270 #ifdef DEBUG_TYPE
7271   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7272             AOP_TYPE (result),
7273             AOP_TYPE (left), AOP_TYPE (right));
7274   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7275             AOP_SIZE (result),
7276             AOP_SIZE (left), AOP_SIZE (right));
7277 #endif
7278
7279   /* if left is a literal & right is not ||
7280      if left needs acc & right does not */
7281   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7282       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7283     {
7284       operand *tmp = right;
7285       right = left;
7286       left = tmp;
7287     }
7288
7289   /* if result = right then exchange them */
7290   if (sameRegs (AOP (result), AOP (right)))
7291     {
7292       operand *tmp = right;
7293       right = left;
7294       left = tmp;
7295     }
7296
7297   /* if right is bit then exchange them */
7298   if (AOP_TYPE (right) == AOP_CRY &&
7299       AOP_TYPE (left) != AOP_CRY)
7300     {
7301       operand *tmp = right;
7302       right = left;
7303       left = tmp;
7304     }
7305   if (AOP_TYPE (right) == AOP_LIT)
7306     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7307
7308   size = AOP_SIZE (result);
7309
7310   // if(bit ^ yy)
7311   // xx = bit ^ yy;
7312   if (AOP_TYPE (left) == AOP_CRY)
7313     {
7314       if (AOP_TYPE (right) == AOP_LIT)
7315         {
7316           // c = bit & literal;
7317           if (lit >> 1)
7318             {
7319               // lit>>1  != 0 => result = 1
7320               if (AOP_TYPE (result) == AOP_CRY)
7321                 {
7322                   if (size)
7323                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7324                   else if (ifx)
7325                     continueIfTrue (ifx);
7326                   goto release;
7327                 }
7328               emitcode ("setb", "c");
7329             }
7330           else
7331             {
7332               // lit == (0 or 1)
7333               if (lit == 0)
7334                 {
7335                   // lit == 0, result = left
7336                   if (size && sameRegs (AOP (result), AOP (left)))
7337                     goto release;
7338                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7339                 }
7340               else
7341                 {
7342                   // lit == 1, result = not(left)
7343                   if (size && sameRegs (AOP (result), AOP (left)))
7344                     {
7345                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7346                       goto release;
7347                     }
7348                   else
7349                     {
7350                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7351                       emitcode ("cpl", "c");
7352                     }
7353                 }
7354             }
7355         }
7356       else
7357         {
7358           // right != literal
7359           symbol *tlbl = newiTempLabel (NULL);
7360           if (AOP_TYPE (right) == AOP_CRY)
7361             {
7362               // c = bit ^ bit;
7363               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7364             }
7365           else
7366             {
7367               int sizer = AOP_SIZE (right);
7368               // c = bit ^ val
7369               // if val>>1 != 0, result = 1
7370               emitcode ("setb", "c");
7371               while (sizer)
7372                 {
7373                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7374                   if (sizer == 1)
7375                     // test the msb of the lsb
7376                     emitcode ("anl", "a,#0xfe");
7377                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7378                   sizer--;
7379                 }
7380               // val = (0,1)
7381               emitcode ("rrc", "a");
7382             }
7383           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7384           emitcode ("cpl", "c");
7385           emitLabel (tlbl);
7386         }
7387       // bit = c
7388       // val = c
7389       if (size)
7390         outBitC (result);
7391       // if(bit | ...)
7392       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7393         genIfxJump (ifx, "c", left, right, result);
7394       goto release;
7395     }
7396
7397   /* if left is same as result */
7398   if (sameRegs (AOP (result), AOP (left)))
7399     {
7400       for (; size--; offset++)
7401         {
7402           if (AOP_TYPE (right) == AOP_LIT)
7403             {
7404               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7405               if (bytelit == 0)
7406                 {
7407                   /* dummy read of volatile operand */
7408                   if (isOperandVolatile (left, FALSE))
7409                     MOVA (aopGet (left, offset, FALSE, FALSE));
7410                   else
7411                     continue;
7412                 }
7413               else if (IS_AOP_PREG (left))
7414                 {
7415                   MOVA (aopGet (left, offset, FALSE, TRUE));
7416                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7417                   aopPut (result, "a", offset);
7418                 }
7419               else
7420                 {
7421                   emitcode ("xrl", "%s,%s",
7422                             aopGet (left, offset, FALSE, TRUE),
7423                             aopGet (right, offset, FALSE, FALSE));
7424                 }
7425             }
7426           else
7427             {
7428               if (AOP_TYPE (left) == AOP_ACC)
7429                 {
7430                   if (offset)
7431                     emitcode("mov", "a,b");
7432                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7433                 }
7434               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7435                 {
7436                   MOVB (aopGet (left, offset, FALSE, FALSE));
7437                   MOVA (aopGet (right, offset, FALSE, FALSE));
7438                   emitcode ("xrl", "a,b");
7439                   aopPut (result, "a", offset);
7440                 }
7441               else if (aopGetUsesAcc (left, offset))
7442                 {
7443                   MOVA (aopGet (left, offset, FALSE, FALSE));
7444                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7445                   aopPut (result, "a", offset);
7446                 }
7447               else
7448                 {
7449                   MOVA (aopGet (right, offset, FALSE, FALSE));
7450                   if (IS_AOP_PREG (left))
7451                     {
7452                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7453                       aopPut (result, "a", offset);
7454                     }
7455                   else
7456                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7457                 }
7458             }
7459         }
7460     }
7461   else
7462     {
7463       // left & result in different registers
7464       if (AOP_TYPE (result) == AOP_CRY)
7465         {
7466           // result = bit
7467           // if(size), result in bit
7468           // if(!size && ifx), conditional oper: if(left ^ right)
7469           symbol *tlbl = newiTempLabel (NULL);
7470           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7471
7472           if (size)
7473             emitcode ("setb", "c");
7474           while (sizer--)
7475             {
7476               if ((AOP_TYPE (right) == AOP_LIT) &&
7477                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7478                 {
7479                   MOVA (aopGet (left, offset, FALSE, FALSE));
7480                 }
7481               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7482                   && AOP_TYPE(left)==AOP_ACC)
7483                 {
7484                   if (offset)
7485                     emitcode("mov", "a,b");
7486                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7487                 }
7488               else if (AOP_TYPE(left)==AOP_ACC)
7489                 {
7490                   if (!offset)
7491                     {
7492                       bool pushedB = pushB ();
7493                       emitcode("mov", "b,a");
7494                       MOVA (aopGet (right, offset, FALSE, FALSE));
7495                       emitcode("xrl", "a,b");
7496                       popB (pushedB);
7497                     }
7498                   else
7499                     {
7500                       MOVA (aopGet (right, offset, FALSE, FALSE));
7501                       emitcode("xrl", "a,b");
7502                     }
7503                 }
7504               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7505                 {
7506                   MOVB (aopGet (left, offset, FALSE, FALSE));
7507                   MOVA (aopGet (right, offset, FALSE, FALSE));
7508                   emitcode ("xrl", "a,b");
7509                 }
7510               else if (aopGetUsesAcc (left, offset))
7511                 {
7512                   MOVA (aopGet (left, offset, FALSE, FALSE));
7513                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7514                 }
7515               else
7516                 {
7517                   MOVA (aopGet (right, offset, FALSE, FALSE));
7518                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7519                 }
7520
7521               emitcode ("jnz", "%05d$", tlbl->key + 100);
7522               offset++;
7523             }
7524           if (size)
7525             {
7526               CLRC;
7527               emitLabel (tlbl);
7528               outBitC (result);
7529             }
7530           else if (ifx)
7531             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7532         }
7533       else
7534         {
7535           for (; (size--); offset++)
7536             {
7537               // normal case
7538               // result = left ^ right
7539               if (AOP_TYPE (right) == AOP_LIT)
7540                 {
7541                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7542                   if (bytelit == 0)
7543                     {
7544                       aopPut (result,
7545                               aopGet (left, offset, FALSE, FALSE),
7546                               offset);
7547                       continue;
7548                     }
7549                 }
7550               // faster than result <- left, xrl result,right
7551               // and better if result is SFR
7552               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7553                   && AOP_TYPE(left)==AOP_ACC)
7554                 {
7555                   if (offset)
7556                     emitcode("mov", "a,b");
7557                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7558                 }
7559               else if (AOP_TYPE(left)==AOP_ACC)
7560                 {
7561                   if (!offset)
7562                     {
7563                       bool pushedB = pushB ();
7564                       emitcode("mov", "b,a");
7565                       MOVA (aopGet (right, offset, FALSE, FALSE));
7566                       emitcode("xrl", "a,b");
7567                       popB (pushedB);
7568                     }
7569                   else
7570                     {
7571                       MOVA (aopGet (right, offset, FALSE, FALSE));
7572                       emitcode("xrl", "a,b");
7573                     }
7574                 }
7575               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7576                 {
7577                   MOVB (aopGet (left, offset, FALSE, FALSE));
7578                   MOVA (aopGet (right, offset, FALSE, FALSE));
7579                   emitcode ("xrl", "a,b");
7580                 }
7581               else if (aopGetUsesAcc (left, offset))
7582                 {
7583                   MOVA (aopGet (left, offset, FALSE, FALSE));
7584                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7585                 }
7586               else
7587                 {
7588                   MOVA (aopGet (right, offset, FALSE, FALSE));
7589                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7590                 }
7591               aopPut (result, "a", offset);
7592             }
7593         }
7594     }
7595
7596 release:
7597   freeAsmop (result, NULL, ic, TRUE);
7598   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7599   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7600 }
7601
7602 /*-----------------------------------------------------------------*/
7603 /* genInline - write the inline code out                           */
7604 /*-----------------------------------------------------------------*/
7605 static void
7606 genInline (iCode * ic)
7607 {
7608   char *buffer, *bp, *bp1;
7609
7610   D (emitcode (";", "genInline"));
7611
7612   _G.inLine += (!options.asmpeep);
7613
7614   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7615
7616   /* emit each line as a code */
7617   while (*bp)
7618     {
7619       if (*bp == '\n')
7620         {
7621           *bp++ = '\0';
7622           emitcode (bp1, "");
7623           bp1 = bp;
7624         }
7625       else
7626         {
7627           /* Add \n for labels, not dirs such as c:\mydir */
7628           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7629             {
7630               bp++;
7631               *bp = '\0';
7632               bp++;
7633               emitcode (bp1, "");
7634               bp1 = bp;
7635             }
7636           else
7637             bp++;
7638         }
7639     }
7640   if (bp1 != bp)
7641     emitcode (bp1, "");
7642   /*     emitcode("",buffer); */
7643   _G.inLine -= (!options.asmpeep);
7644 }
7645
7646 /*-----------------------------------------------------------------*/
7647 /* genRRC - rotate right with carry                                */
7648 /*-----------------------------------------------------------------*/
7649 static void
7650 genRRC (iCode * ic)
7651 {
7652   operand *left, *result;
7653   int size, offset;
7654   char *l;
7655
7656   D (emitcode (";", "genRRC"));
7657
7658   /* rotate right with carry */
7659   left = IC_LEFT (ic);
7660   result = IC_RESULT (ic);
7661   aopOp (left, ic, FALSE);
7662   aopOp (result, ic, FALSE);
7663
7664   /* move it to the result */
7665   size = AOP_SIZE (result);
7666   offset = size - 1;
7667   if (size == 1) { /* special case for 1 byte */
7668       l = aopGet (left, offset, FALSE, FALSE);
7669       MOVA (l);
7670       emitcode ("rr", "a");
7671       goto release;
7672   }
7673   /* no need to clear carry, bit7 will be written later */
7674   while (size--)
7675     {
7676       l = aopGet (left, offset, FALSE, FALSE);
7677       MOVA (l);
7678       emitcode ("rrc", "a");
7679       if (AOP_SIZE (result) > 1)
7680         aopPut (result, "a", offset--);
7681     }
7682   /* now we need to put the carry into the
7683      highest order byte of the result */
7684   if (AOP_SIZE (result) > 1)
7685     {
7686       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7687       MOVA (l);
7688     }
7689   emitcode ("mov", "acc.7,c");
7690  release:
7691   aopPut (result, "a", AOP_SIZE (result) - 1);
7692   freeAsmop (result, NULL, ic, TRUE);
7693   freeAsmop (left, NULL, ic, TRUE);
7694 }
7695
7696 /*-----------------------------------------------------------------*/
7697 /* genRLC - generate code for rotate left with carry               */
7698 /*-----------------------------------------------------------------*/
7699 static void
7700 genRLC (iCode * ic)
7701 {
7702   operand *left, *result;
7703   int size, offset;
7704   char *l;
7705
7706   D (emitcode (";", "genRLC"));
7707
7708   /* rotate right with carry */
7709   left = IC_LEFT (ic);
7710   result = IC_RESULT (ic);
7711   aopOp (left, ic, FALSE);
7712   aopOp (result, ic, FALSE);
7713
7714   /* move it to the result */
7715   size = AOP_SIZE (result);
7716   offset = 0;
7717   if (size--)
7718     {
7719       l = aopGet (left, offset, FALSE, FALSE);
7720       MOVA (l);
7721       if (size == 0) { /* special case for 1 byte */
7722               emitcode("rl","a");
7723               goto release;
7724       }
7725       emitcode("rlc","a"); /* bit0 will be written later */
7726       if (AOP_SIZE (result) > 1)
7727         {
7728           aopPut (result, "a", offset++);
7729         }
7730
7731       while (size--)
7732         {
7733           l = aopGet (left, offset, FALSE, FALSE);
7734           MOVA (l);
7735           emitcode ("rlc", "a");
7736           if (AOP_SIZE (result) > 1)
7737             aopPut (result, "a", offset++);
7738         }
7739     }
7740   /* now we need to put the carry into the
7741      highest order byte of the result */
7742   if (AOP_SIZE (result) > 1)
7743     {
7744       l = aopGet (result, 0, FALSE, FALSE);
7745       MOVA (l);
7746     }
7747   emitcode ("mov", "acc.0,c");
7748  release:
7749   aopPut (result, "a", 0);
7750   freeAsmop (result, NULL, ic, TRUE);
7751   freeAsmop (left, NULL, ic, TRUE);
7752 }
7753
7754 /*-----------------------------------------------------------------*/
7755 /* genGetHbit - generates code get highest order bit               */
7756 /*-----------------------------------------------------------------*/
7757 static void
7758 genGetHbit (iCode * ic)
7759 {
7760   operand *left, *result;
7761
7762   D (emitcode (";", "genGetHbit"));
7763
7764   left = IC_LEFT (ic);
7765   result = IC_RESULT (ic);
7766   aopOp (left, ic, FALSE);
7767   aopOp (result, ic, FALSE);
7768
7769   /* get the highest order byte into a */
7770   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7771   if (AOP_TYPE (result) == AOP_CRY)
7772     {
7773       emitcode ("rlc", "a");
7774       outBitC (result);
7775     }
7776   else
7777     {
7778       emitcode ("rl", "a");
7779       emitcode ("anl", "a,#0x01");
7780       outAcc (result);
7781     }
7782
7783   freeAsmop (result, NULL, ic, TRUE);
7784   freeAsmop (left, NULL, ic, TRUE);
7785 }
7786
7787 /*-----------------------------------------------------------------*/
7788 /* genGetAbit - generates code get a single bit                    */
7789 /*-----------------------------------------------------------------*/
7790 static void
7791 genGetAbit (iCode * ic)
7792 {
7793   operand *left, *right, *result;
7794   int shCount;
7795
7796   D (emitcode (";", "genGetAbit"));
7797
7798   left = IC_LEFT (ic);
7799   right = IC_RIGHT (ic);
7800   result = IC_RESULT (ic);
7801   aopOp (left, ic, FALSE);
7802   aopOp (right, ic, FALSE);
7803   aopOp (result, ic, FALSE);
7804
7805   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7806
7807   /* get the needed byte into a */
7808   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7809   shCount %= 8;
7810   if (AOP_TYPE (result) == AOP_CRY)
7811     {
7812       if ((shCount) == 7)
7813           emitcode ("rlc", "a");
7814       else if ((shCount) == 0)
7815           emitcode ("rrc", "a");
7816       else
7817           emitcode ("mov", "c,acc[%d]", shCount);
7818       outBitC (result);
7819     }
7820   else
7821     {
7822       switch (shCount)
7823         {
7824         case 2:
7825           emitcode ("rr", "a");
7826           //fallthrough
7827         case 1:
7828           emitcode ("rr", "a");
7829           //fallthrough
7830         case 0:
7831           emitcode ("anl", "a,#0x01");
7832           break;
7833         case 3:
7834         case 5:
7835           emitcode ("mov", "c,acc[%d]", shCount);
7836           emitcode ("clr", "a");
7837           emitcode ("rlc", "a");
7838           break;
7839         case 4:
7840           emitcode ("swap", "a");
7841           emitcode ("anl", "a,#0x01");
7842           break;
7843         case 6:
7844           emitcode ("rl", "a");
7845           //fallthrough
7846         case 7:
7847           emitcode ("rl", "a");
7848           emitcode ("anl", "a,#0x01");
7849           break;
7850         }
7851       outAcc (result);
7852     }
7853
7854   freeAsmop (result, NULL, ic, TRUE);
7855   freeAsmop (right, NULL, ic, TRUE);
7856   freeAsmop (left, NULL, ic, TRUE);
7857 }
7858
7859 /*-----------------------------------------------------------------*/
7860 /* genGetByte - generates code get a single byte                   */
7861 /*-----------------------------------------------------------------*/
7862 static void
7863 genGetByte (iCode * ic)
7864 {
7865   operand *left, *right, *result;
7866   int offset;
7867
7868   D (emitcode (";", "genGetByte"));
7869
7870   left = IC_LEFT (ic);
7871   right = IC_RIGHT (ic);
7872   result = IC_RESULT (ic);
7873   aopOp (left, ic, FALSE);
7874   aopOp (right, ic, FALSE);
7875   aopOp (result, ic, FALSE);
7876
7877   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7878   aopPut (result,
7879           aopGet (left, offset, FALSE, FALSE),
7880           0);
7881
7882   freeAsmop (result, NULL, ic, TRUE);
7883   freeAsmop (right, NULL, ic, TRUE);
7884   freeAsmop (left, NULL, ic, TRUE);
7885 }
7886
7887 /*-----------------------------------------------------------------*/
7888 /* genGetWord - generates code get two bytes                       */
7889 /*-----------------------------------------------------------------*/
7890 static void
7891 genGetWord (iCode * ic)
7892 {
7893   operand *left, *right, *result;
7894   int offset;
7895
7896   D (emitcode (";", "genGetWord"));
7897
7898   left = IC_LEFT (ic);
7899   right = IC_RIGHT (ic);
7900   result = IC_RESULT (ic);
7901   aopOp (left, ic, FALSE);
7902   aopOp (right, ic, FALSE);
7903   aopOp (result, ic, FALSE);
7904
7905   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7906   aopPut (result,
7907           aopGet (left, offset, FALSE, FALSE),
7908           0);
7909   aopPut (result,
7910           aopGet (left, offset+1, FALSE, FALSE),
7911           1);
7912
7913   freeAsmop (result, NULL, ic, TRUE);
7914   freeAsmop (right, NULL, ic, TRUE);
7915   freeAsmop (left, NULL, ic, TRUE);
7916 }
7917
7918 /*-----------------------------------------------------------------*/
7919 /* genSwap - generates code to swap nibbles or bytes               */
7920 /*-----------------------------------------------------------------*/
7921 static void
7922 genSwap (iCode * ic)
7923 {
7924   operand *left, *result;
7925
7926   D(emitcode (";     genSwap",""));
7927
7928   left = IC_LEFT (ic);
7929   result = IC_RESULT (ic);
7930   aopOp (left, ic, FALSE);
7931   aopOp (result, ic, FALSE);
7932
7933   switch (AOP_SIZE (left))
7934     {
7935     case 1: /* swap nibbles in byte */
7936       MOVA (aopGet (left, 0, FALSE, FALSE));
7937       emitcode ("swap", "a");
7938       aopPut (result, "a", 0);
7939       break;
7940     case 2: /* swap bytes in word */
7941       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7942         {
7943           MOVA (aopGet (left, 0, FALSE, FALSE));
7944           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7945           aopPut (result, "a", 1);
7946         }
7947       else if (operandsEqu (left, result))
7948         {
7949           char * reg = "a";
7950           bool pushedB = FALSE, leftInB = FALSE;
7951
7952           MOVA (aopGet (left, 0, FALSE, FALSE));
7953           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7954             {
7955               pushedB = pushB ();
7956               emitcode ("mov", "b,a");
7957               reg = "b";
7958               leftInB = TRUE;
7959             }
7960           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7961           aopPut (result, reg, 1);
7962
7963           if (leftInB)
7964             popB (pushedB);
7965         }
7966       else
7967         {
7968           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7969           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7970         }
7971       break;
7972     default:
7973       wassertl(FALSE, "unsupported SWAP operand size");
7974     }
7975
7976   freeAsmop (result, NULL, ic, TRUE);
7977   freeAsmop (left, NULL, ic, TRUE);
7978 }
7979
7980 /*-----------------------------------------------------------------*/
7981 /* AccRol - rotate left accumulator by known count                 */
7982 /*-----------------------------------------------------------------*/
7983 static void
7984 AccRol (int shCount)
7985 {
7986   shCount &= 0x0007;            // shCount : 0..7
7987
7988   switch (shCount)
7989     {
7990     case 0:
7991       break;
7992     case 1:
7993       emitcode ("rl", "a");
7994       break;
7995     case 2:
7996       emitcode ("rl", "a");
7997       emitcode ("rl", "a");
7998       break;
7999     case 3:
8000       emitcode ("swap", "a");
8001       emitcode ("rr", "a");
8002       break;
8003     case 4:
8004       emitcode ("swap", "a");
8005       break;
8006     case 5:
8007       emitcode ("swap", "a");
8008       emitcode ("rl", "a");
8009       break;
8010     case 6:
8011       emitcode ("rr", "a");
8012       emitcode ("rr", "a");
8013       break;
8014     case 7:
8015       emitcode ("rr", "a");
8016       break;
8017     }
8018 }
8019
8020 /*-----------------------------------------------------------------*/
8021 /* AccLsh - left shift accumulator by known count                  */
8022 /*-----------------------------------------------------------------*/
8023 static void
8024 AccLsh (int shCount)
8025 {
8026   if (shCount != 0)
8027     {
8028       if (shCount == 1)
8029         emitcode ("add", "a,acc");
8030       else if (shCount == 2)
8031         {
8032           emitcode ("add", "a,acc");
8033           emitcode ("add", "a,acc");
8034         }
8035       else
8036         {
8037           /* rotate left accumulator */
8038           AccRol (shCount);
8039           /* and kill the lower order bits */
8040           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8041         }
8042     }
8043 }
8044
8045 /*-----------------------------------------------------------------*/
8046 /* AccRsh - right shift accumulator by known count                 */
8047 /*-----------------------------------------------------------------*/
8048 static void
8049 AccRsh (int shCount)
8050 {
8051   if (shCount != 0)
8052     {
8053       if (shCount == 1)
8054         {
8055           CLRC;
8056           emitcode ("rrc", "a");
8057         }
8058       else
8059         {
8060           /* rotate right accumulator */
8061           AccRol (8 - shCount);
8062           /* and kill the higher order bits */
8063           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8064         }
8065     }
8066 }
8067
8068 /*-----------------------------------------------------------------*/
8069 /* AccSRsh - signed right shift accumulator by known count                 */
8070 /*-----------------------------------------------------------------*/
8071 static void
8072 AccSRsh (int shCount)
8073 {
8074   symbol *tlbl;
8075   if (shCount != 0)
8076     {
8077       if (shCount == 1)
8078         {
8079           emitcode ("mov", "c,acc.7");
8080           emitcode ("rrc", "a");
8081         }
8082       else if (shCount == 2)
8083         {
8084           emitcode ("mov", "c,acc.7");
8085           emitcode ("rrc", "a");
8086           emitcode ("mov", "c,acc.7");
8087           emitcode ("rrc", "a");
8088         }
8089       else
8090         {
8091           tlbl = newiTempLabel (NULL);
8092           /* rotate right accumulator */
8093           AccRol (8 - shCount);
8094           /* and kill the higher order bits */
8095           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8096           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8097           emitcode ("orl", "a,#0x%02x",
8098                     (unsigned char) ~SRMask[shCount]);
8099           emitLabel (tlbl);
8100         }
8101     }
8102 }
8103
8104 /*-----------------------------------------------------------------*/
8105 /* shiftR1Left2Result - shift right one byte from left to result   */
8106 /*-----------------------------------------------------------------*/
8107 static void
8108 shiftR1Left2Result (operand * left, int offl,
8109                     operand * result, int offr,
8110                     int shCount, int sign)
8111 {
8112   MOVA (aopGet (left, offl, FALSE, FALSE));
8113   /* shift right accumulator */
8114   if (sign)
8115     AccSRsh (shCount);
8116   else
8117     AccRsh (shCount);
8118   aopPut (result, "a", offr);
8119 }
8120
8121 /*-----------------------------------------------------------------*/
8122 /* shiftL1Left2Result - shift left one byte from left to result    */
8123 /*-----------------------------------------------------------------*/
8124 static void
8125 shiftL1Left2Result (operand * left, int offl,
8126                     operand * result, int offr, int shCount)
8127 {
8128   char *l;
8129   l = aopGet (left, offl, FALSE, FALSE);
8130   MOVA (l);
8131   /* shift left accumulator */
8132   AccLsh (shCount);
8133   aopPut (result, "a", offr);
8134 }
8135
8136 /*-----------------------------------------------------------------*/
8137 /* movLeft2Result - move byte from left to result                  */
8138 /*-----------------------------------------------------------------*/
8139 static void
8140 movLeft2Result (operand * left, int offl,
8141                 operand * result, int offr, int sign)
8142 {
8143   char *l;
8144   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8145     {
8146       l = aopGet (left, offl, FALSE, FALSE);
8147
8148       if (*l == '@' && (IS_AOP_PREG (result)))
8149         {
8150           emitcode ("mov", "a,%s", l);
8151           aopPut (result, "a", offr);
8152         }
8153       else
8154         {
8155           if (!sign)
8156             {
8157               aopPut (result, l, offr);
8158             }
8159           else
8160             {
8161               /* MSB sign in acc.7 ! */
8162               if (getDataSize (left) == offl + 1)
8163                 {
8164                   MOVA (l);
8165                   aopPut (result, "a", offr);
8166                 }
8167             }
8168         }
8169     }
8170 }
8171
8172 /*-----------------------------------------------------------------*/
8173 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8174 /*-----------------------------------------------------------------*/
8175 static void
8176 AccAXRrl1 (char *x)
8177 {
8178   emitcode ("rrc", "a");
8179   emitcode ("xch", "a,%s", x);
8180   emitcode ("rrc", "a");
8181   emitcode ("xch", "a,%s", x);
8182 }
8183
8184 /*-----------------------------------------------------------------*/
8185 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8186 /*-----------------------------------------------------------------*/
8187 static void
8188 AccAXLrl1 (char *x)
8189 {
8190   emitcode ("xch", "a,%s", x);
8191   emitcode ("rlc", "a");
8192   emitcode ("xch", "a,%s", x);
8193   emitcode ("rlc", "a");
8194 }
8195
8196 /*-----------------------------------------------------------------*/
8197 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8198 /*-----------------------------------------------------------------*/
8199 static void
8200 AccAXLsh1 (char *x)
8201 {
8202   emitcode ("xch", "a,%s", x);
8203   emitcode ("add", "a,acc");
8204   emitcode ("xch", "a,%s", x);
8205   emitcode ("rlc", "a");
8206 }
8207
8208 /*-----------------------------------------------------------------*/
8209 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8210 /*-----------------------------------------------------------------*/
8211 static void
8212 AccAXLsh (char *x, int shCount)
8213 {
8214   switch (shCount)
8215     {
8216     case 0:
8217       break;
8218     case 1:
8219       AccAXLsh1 (x);
8220       break;
8221     case 2:
8222       AccAXLsh1 (x);
8223       AccAXLsh1 (x);
8224       break;
8225     case 3:
8226     case 4:
8227     case 5:                     // AAAAABBB:CCCCCDDD
8228
8229       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8230
8231       emitcode ("anl", "a,#0x%02x",
8232                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8233
8234       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8235
8236       AccRol (shCount);         // DDDCCCCC:BBB00000
8237
8238       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8239
8240       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8241
8242       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8243
8244       emitcode ("anl", "a,#0x%02x",
8245                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8246
8247       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8248
8249       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8250
8251       break;
8252     case 6:                     // AAAAAABB:CCCCCCDD
8253       emitcode ("anl", "a,#0x%02x",
8254                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8255       emitcode ("mov", "c,acc.0");      // c = B
8256       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8257 #if 0 // REMOVE ME
8258       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8259       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8260 #else
8261       emitcode("rrc","a");
8262       emitcode("xch","a,%s", x);
8263       emitcode("rrc","a");
8264       emitcode("mov","c,acc.0"); //<< get correct bit
8265       emitcode("xch","a,%s", x);
8266
8267       emitcode("rrc","a");
8268       emitcode("xch","a,%s", x);
8269       emitcode("rrc","a");
8270       emitcode("xch","a,%s", x);
8271 #endif
8272       break;
8273     case 7:                     // a:x <<= 7
8274
8275       emitcode ("anl", "a,#0x%02x",
8276                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8277
8278       emitcode ("mov", "c,acc.0");      // c = B
8279
8280       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8281
8282       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8283
8284       break;
8285     default:
8286       break;
8287     }
8288 }
8289
8290 /*-----------------------------------------------------------------*/
8291 /* AccAXRsh - right shift a:x known count (0..7)                   */
8292 /*-----------------------------------------------------------------*/
8293 static void
8294 AccAXRsh (char *x, int shCount)
8295 {
8296   switch (shCount)
8297     {
8298     case 0:
8299       break;
8300     case 1:
8301       CLRC;
8302       AccAXRrl1 (x);            // 0->a:x
8303
8304       break;
8305     case 2:
8306       CLRC;
8307       AccAXRrl1 (x);            // 0->a:x
8308
8309       CLRC;
8310       AccAXRrl1 (x);            // 0->a:x
8311
8312       break;
8313     case 3:
8314     case 4:
8315     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8316
8317       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8318
8319       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8320
8321       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8322
8323       emitcode ("anl", "a,#0x%02x",
8324                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8325
8326       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8327
8328       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8329
8330       emitcode ("anl", "a,#0x%02x",
8331                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8332
8333       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8334
8335       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8336
8337       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8338
8339       break;
8340     case 6:                     // AABBBBBB:CCDDDDDD
8341
8342       emitcode ("mov", "c,acc.7");
8343       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8344
8345       emitcode ("mov", "c,acc.7");
8346       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8347
8348       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8349
8350       emitcode ("anl", "a,#0x%02x",
8351                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8352
8353       break;
8354     case 7:                     // ABBBBBBB:CDDDDDDD
8355
8356       emitcode ("mov", "c,acc.7");      // c = A
8357
8358       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8359
8360       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8361
8362       emitcode ("anl", "a,#0x%02x",
8363                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8364
8365       break;
8366     default:
8367       break;
8368     }
8369 }
8370
8371 /*-----------------------------------------------------------------*/
8372 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8373 /*-----------------------------------------------------------------*/
8374 static void
8375 AccAXRshS (char *x, int shCount)
8376 {
8377   symbol *tlbl;
8378   switch (shCount)
8379     {
8380     case 0:
8381       break;
8382     case 1:
8383       emitcode ("mov", "c,acc.7");
8384       AccAXRrl1 (x);            // s->a:x
8385
8386       break;
8387     case 2:
8388       emitcode ("mov", "c,acc.7");
8389       AccAXRrl1 (x);            // s->a:x
8390
8391       emitcode ("mov", "c,acc.7");
8392       AccAXRrl1 (x);            // s->a:x
8393
8394       break;
8395     case 3:
8396     case 4:
8397     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8398
8399       tlbl = newiTempLabel (NULL);
8400       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8401
8402       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8403
8404       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8405
8406       emitcode ("anl", "a,#0x%02x",
8407                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8408
8409       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8410
8411       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8412
8413       emitcode ("anl", "a,#0x%02x",
8414                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8415
8416       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8417
8418       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8419
8420       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8421
8422       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8423       emitcode ("orl", "a,#0x%02x",
8424                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8425
8426       emitLabel (tlbl);
8427       break;                    // SSSSAAAA:BBBCCCCC
8428
8429     case 6:                     // AABBBBBB:CCDDDDDD
8430
8431       tlbl = newiTempLabel (NULL);
8432       emitcode ("mov", "c,acc.7");
8433       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8434
8435       emitcode ("mov", "c,acc.7");
8436       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8437
8438       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8439
8440       emitcode ("anl", "a,#0x%02x",
8441                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8442
8443       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8444       emitcode ("orl", "a,#0x%02x",
8445                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8446
8447       emitLabel (tlbl);
8448       break;
8449     case 7:                     // ABBBBBBB:CDDDDDDD
8450
8451       tlbl = newiTempLabel (NULL);
8452       emitcode ("mov", "c,acc.7");      // c = A
8453
8454       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8455
8456       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8457
8458       emitcode ("anl", "a,#0x%02x",
8459                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8460
8461       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8462       emitcode ("orl", "a,#0x%02x",
8463                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8464
8465       emitLabel (tlbl);
8466       break;
8467     default:
8468       break;
8469     }
8470 }
8471
8472 /*-----------------------------------------------------------------*/
8473 /* shiftL2Left2Result - shift left two bytes from left to result   */
8474 /*-----------------------------------------------------------------*/
8475 static void
8476 shiftL2Left2Result (operand * left, int offl,
8477                     operand * result, int offr, int shCount)
8478 {
8479   char * x;
8480   bool pushedB = FALSE;
8481   bool usedB = FALSE;
8482
8483   if (sameRegs (AOP (result), AOP (left)) &&
8484       ((offl + MSB16) == offr))
8485     {
8486       /* don't crash result[offr] */
8487       MOVA (aopGet (left, offl, FALSE, FALSE));
8488       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8489       usedB = !strncmp(x, "b", 1);
8490     }
8491   else if (aopGetUsesAcc (result, offr))
8492     {
8493       movLeft2Result (left, offl, result, offr, 0);
8494       pushedB = pushB ();
8495       usedB = TRUE;
8496       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8497       MOVA (aopGet (result, offr, FALSE, FALSE));
8498       emitcode ("xch", "a,b");
8499       x = "b";
8500     }
8501   else
8502     {
8503       movLeft2Result (left, offl, result, offr, 0);
8504       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8505       x = aopGet (result, offr, FALSE, FALSE);
8506     }
8507   /* ax << shCount (x = lsb(result)) */
8508   AccAXLsh (x, shCount);
8509   if (usedB)
8510     {
8511       emitcode ("xch", "a,b");
8512       aopPut (result, "a", offr);
8513       aopPut (result, "b", offr + MSB16);
8514       popB (pushedB);
8515     }
8516   else
8517     {
8518       aopPut (result, "a", offr + MSB16);
8519     }
8520 }
8521
8522
8523 /*-----------------------------------------------------------------*/
8524 /* shiftR2Left2Result - shift right two bytes from left to result  */
8525 /*-----------------------------------------------------------------*/
8526 static void
8527 shiftR2Left2Result (operand * left, int offl,
8528                     operand * result, int offr,
8529                     int shCount, int sign)
8530 {
8531   char * x;
8532   bool pushedB = FALSE;
8533   bool usedB = FALSE;
8534
8535   if (sameRegs (AOP (result), AOP (left)) &&
8536       ((offl + MSB16) == offr))
8537     {
8538       /* don't crash result[offr] */
8539       MOVA (aopGet (left, offl, FALSE, FALSE));
8540       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8541       usedB = !strncmp(x, "b", 1);
8542     }
8543   else if (aopGetUsesAcc (result, offr))
8544     {
8545       movLeft2Result (left, offl, result, offr, 0);
8546       pushedB = pushB ();
8547       usedB = TRUE;
8548       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8549       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8550       x = "b";
8551     }
8552   else
8553     {
8554       movLeft2Result (left, offl, result, offr, 0);
8555       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8556       x = aopGet (result, offr, FALSE, FALSE);
8557     }
8558   /* a:x >> shCount (x = lsb(result)) */
8559   if (sign)
8560     AccAXRshS (x, shCount);
8561   else
8562     AccAXRsh (x, shCount);
8563   if (usedB)
8564     {
8565       emitcode ("xch", "a,b");
8566       aopPut (result, "a", offr);
8567       emitcode ("xch", "a,b");
8568       popB (pushedB);
8569     }
8570   if (getDataSize (result) > 1)
8571     aopPut (result, "a", offr + MSB16);
8572 }
8573
8574 /*-----------------------------------------------------------------*/
8575 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8576 /*-----------------------------------------------------------------*/
8577 static void
8578 shiftLLeftOrResult (operand * left, int offl,
8579                     operand * result, int offr, int shCount)
8580 {
8581   MOVA (aopGet (left, offl, FALSE, FALSE));
8582   /* shift left accumulator */
8583   AccLsh (shCount);
8584   /* or with result */
8585   if (aopGetUsesAcc (result, offr))
8586     {
8587       emitcode ("xch", "a,b");
8588       MOVA (aopGet (result, offr, FALSE, FALSE));
8589       emitcode ("orl", "a,b");
8590     }
8591   else
8592     {
8593       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8594     }
8595   /* back to result */
8596   aopPut (result, "a", offr);
8597 }
8598
8599 /*-----------------------------------------------------------------*/
8600 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8601 /*-----------------------------------------------------------------*/
8602 static void
8603 shiftRLeftOrResult (operand * left, int offl,
8604                     operand * result, int offr, int shCount)
8605 {
8606   MOVA (aopGet (left, offl, FALSE, FALSE));
8607   /* shift right accumulator */
8608   AccRsh (shCount);
8609   /* or with result */
8610   if (aopGetUsesAcc(result, offr))
8611     {
8612       emitcode ("xch", "a,b");
8613       MOVA (aopGet (result, offr, FALSE, FALSE));
8614       emitcode ("orl", "a,b");
8615     }
8616   else
8617     {
8618       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8619     }
8620   /* back to result */
8621   aopPut (result, "a", offr);
8622 }
8623
8624 /*-----------------------------------------------------------------*/
8625 /* genlshOne - left shift a one byte quantity by known count       */
8626 /*-----------------------------------------------------------------*/
8627 static void
8628 genlshOne (operand * result, operand * left, int shCount)
8629 {
8630   D (emitcode (";", "genlshOne"));
8631
8632   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8633 }
8634
8635 /*-----------------------------------------------------------------*/
8636 /* genlshTwo - left shift two bytes by known amount != 0           */
8637 /*-----------------------------------------------------------------*/
8638 static void
8639 genlshTwo (operand * result, operand * left, int shCount)
8640 {
8641   int size;
8642
8643   D (emitcode (";", "genlshTwo"));
8644
8645   size = getDataSize (result);
8646
8647   /* if shCount >= 8 */
8648   if (shCount >= 8)
8649     {
8650       shCount -= 8;
8651
8652       if (size > 1)
8653         {
8654           if (shCount)
8655             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8656           else
8657             movLeft2Result (left, LSB, result, MSB16, 0);
8658         }
8659       aopPut (result, zero, LSB);
8660     }
8661
8662   /*  1 <= shCount <= 7 */
8663   else
8664     {
8665       if (size == 1)
8666         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8667       else
8668         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8669     }
8670 }
8671
8672 /*-----------------------------------------------------------------*/
8673 /* shiftLLong - shift left one long from left to result            */
8674 /* offl = LSB or MSB16                                             */
8675 /*-----------------------------------------------------------------*/
8676 static void
8677 shiftLLong (operand * left, operand * result, int offr)
8678 {
8679   char *l;
8680   int size = AOP_SIZE (result);
8681
8682   if (size >= LSB + offr)
8683     {
8684       l = aopGet (left, LSB, FALSE, FALSE);
8685       MOVA (l);
8686       emitcode ("add", "a,acc");
8687       if (sameRegs (AOP (left), AOP (result)) &&
8688           size >= MSB16 + offr && offr != LSB)
8689         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8690       else
8691         aopPut (result, "a", LSB + offr);
8692     }
8693
8694   if (size >= MSB16 + offr)
8695     {
8696       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8697         {
8698           l = aopGet (left, MSB16, FALSE, FALSE);
8699           MOVA (l);
8700         }
8701       emitcode ("rlc", "a");
8702       if (sameRegs (AOP (left), AOP (result)) &&
8703           size >= MSB24 + offr && offr != LSB)
8704         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8705       else
8706         aopPut (result, "a", MSB16 + offr);
8707     }
8708
8709   if (size >= MSB24 + offr)
8710     {
8711       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8712         {
8713           l = aopGet (left, MSB24, FALSE, FALSE);
8714           MOVA (l);
8715         }
8716       emitcode ("rlc", "a");
8717       if (sameRegs (AOP (left), AOP (result)) &&
8718           size >= MSB32 + offr && offr != LSB)
8719         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8720       else
8721         aopPut (result, "a", MSB24 + offr);
8722     }
8723
8724   if (size > MSB32 + offr)
8725     {
8726       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8727         {
8728           l = aopGet (left, MSB32, FALSE, FALSE);
8729           MOVA (l);
8730         }
8731       emitcode ("rlc", "a");
8732       aopPut (result, "a", MSB32 + offr);
8733     }
8734   if (offr != LSB)
8735     aopPut (result, zero, LSB);
8736 }
8737
8738 /*-----------------------------------------------------------------*/
8739 /* genlshFour - shift four byte by a known amount != 0             */
8740 /*-----------------------------------------------------------------*/
8741 static void
8742 genlshFour (operand * result, operand * left, int shCount)
8743 {
8744   int size;
8745
8746   D (emitcode (";", "genlshFour"));
8747
8748   size = AOP_SIZE (result);
8749
8750   /* if shifting more that 3 bytes */
8751   if (shCount >= 24)
8752     {
8753       shCount -= 24;
8754       if (shCount)
8755         /* lowest order of left goes to the highest
8756            order of the destination */
8757         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8758       else
8759         movLeft2Result (left, LSB, result, MSB32, 0);
8760       aopPut (result, zero, LSB);
8761       aopPut (result, zero, MSB16);
8762       aopPut (result, zero, MSB24);
8763       return;
8764     }
8765
8766   /* more than two bytes */
8767   else if (shCount >= 16)
8768     {
8769       /* lower order two bytes goes to higher order two bytes */
8770       shCount -= 16;
8771       /* if some more remaining */
8772       if (shCount)
8773         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8774       else
8775         {
8776           movLeft2Result (left, MSB16, result, MSB32, 0);
8777           movLeft2Result (left, LSB, result, MSB24, 0);
8778         }
8779       aopPut (result, zero, MSB16);
8780       aopPut (result, zero, LSB);
8781       return;
8782     }
8783
8784   /* if more than 1 byte */
8785   else if (shCount >= 8)
8786     {
8787       /* lower order three bytes goes to higher order  three bytes */
8788       shCount -= 8;
8789       if (size == 2)
8790         {
8791           if (shCount)
8792             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8793           else
8794             movLeft2Result (left, LSB, result, MSB16, 0);
8795         }
8796       else
8797         {                       /* size = 4 */
8798           if (shCount == 0)
8799             {
8800               movLeft2Result (left, MSB24, result, MSB32, 0);
8801               movLeft2Result (left, MSB16, result, MSB24, 0);
8802               movLeft2Result (left, LSB, result, MSB16, 0);
8803               aopPut (result, zero, LSB);
8804             }
8805           else if (shCount == 1)
8806             shiftLLong (left, result, MSB16);
8807           else
8808             {
8809               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8810               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8811               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8812               aopPut (result, zero, LSB);
8813             }
8814         }
8815     }
8816
8817   /* 1 <= shCount <= 7 */
8818   else if (shCount <= 2)
8819     {
8820       shiftLLong (left, result, LSB);
8821       if (shCount == 2)
8822         shiftLLong (result, result, LSB);
8823     }
8824   /* 3 <= shCount <= 7, optimize */
8825   else
8826     {
8827       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8828       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8829       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8830     }
8831 }
8832
8833 /*-----------------------------------------------------------------*/
8834 /* genLeftShiftLiteral - left shifting by known count              */
8835 /*-----------------------------------------------------------------*/
8836 static void
8837 genLeftShiftLiteral (operand * left,
8838                      operand * right,
8839                      operand * result,
8840                      iCode * ic)
8841 {
8842   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8843   int size;
8844
8845   D (emitcode (";", "genLeftShiftLiteral"));
8846
8847   freeAsmop (right, NULL, ic, TRUE);
8848
8849   aopOp (left, ic, FALSE);
8850   aopOp (result, ic, FALSE);
8851
8852   size = getSize (operandType (result));
8853
8854 #if VIEW_SIZE
8855   emitcode ("; shift left ", "result %d, left %d", size,
8856             AOP_SIZE (left));
8857 #endif
8858
8859   /* I suppose that the left size >= result size */
8860   if (shCount == 0)
8861     {
8862       while (size--)
8863         {
8864           movLeft2Result (left, size, result, size, 0);
8865         }
8866     }
8867   else if (shCount >= (size * 8))
8868     {
8869       while (size--)
8870         {
8871           aopPut (result, zero, size);
8872         }
8873     }
8874   else
8875     {
8876       switch (size)
8877         {
8878         case 1:
8879           genlshOne (result, left, shCount);
8880           break;
8881
8882         case 2:
8883           genlshTwo (result, left, shCount);
8884           break;
8885
8886         case 4:
8887           genlshFour (result, left, shCount);
8888           break;
8889         default:
8890           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8891                   "*** ack! mystery literal shift!\n");
8892           break;
8893         }
8894     }
8895   freeAsmop (result, NULL, ic, TRUE);
8896   freeAsmop (left, NULL, ic, TRUE);
8897 }
8898
8899 /*-----------------------------------------------------------------*/
8900 /* genLeftShift - generates code for left shifting                 */
8901 /*-----------------------------------------------------------------*/
8902 static void
8903 genLeftShift (iCode * ic)
8904 {
8905   operand *left, *right, *result;
8906   int size, offset;
8907   char *l;
8908   symbol *tlbl, *tlbl1;
8909   bool pushedB;
8910
8911   D (emitcode (";", "genLeftShift"));
8912
8913   right = IC_RIGHT (ic);
8914   left = IC_LEFT (ic);
8915   result = IC_RESULT (ic);
8916
8917   aopOp (right, ic, FALSE);
8918
8919   /* if the shift count is known then do it
8920      as efficiently as possible */
8921   if (AOP_TYPE (right) == AOP_LIT)
8922     {
8923       genLeftShiftLiteral (left, right, result, ic);
8924       return;
8925     }
8926
8927   /* shift count is unknown then we have to form
8928      a loop get the loop count in B : Note: we take
8929      only the lower order byte since shifting
8930      more that 32 bits make no sense anyway, ( the
8931      largest size of an object can be only 32 bits ) */
8932
8933   pushedB = pushB ();
8934   MOVB (aopGet (right, 0, FALSE, FALSE));
8935   emitcode ("inc", "b");
8936   freeAsmop (right, NULL, ic, TRUE);
8937   aopOp (left, ic, FALSE);
8938   aopOp (result, ic, FALSE);
8939
8940   /* now move the left to the result if they are not the same */
8941   if (!sameRegs (AOP (left), AOP (result)) &&
8942       AOP_SIZE (result) > 1)
8943     {
8944
8945       size = AOP_SIZE (result);
8946       offset = 0;
8947       while (size--)
8948         {
8949           l = aopGet (left, offset, FALSE, TRUE);
8950           if (*l == '@' && (IS_AOP_PREG (result)))
8951             {
8952
8953               emitcode ("mov", "a,%s", l);
8954               aopPut (result, "a", offset);
8955             }
8956           else
8957             aopPut (result, l, offset);
8958           offset++;
8959         }
8960     }
8961
8962   tlbl = newiTempLabel (NULL);
8963   size = AOP_SIZE (result);
8964   offset = 0;
8965   tlbl1 = newiTempLabel (NULL);
8966
8967   /* if it is only one byte then */
8968   if (size == 1)
8969     {
8970       symbol *tlbl1 = newiTempLabel (NULL);
8971
8972       l = aopGet (left, 0, FALSE, FALSE);
8973       MOVA (l);
8974       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8975       emitLabel (tlbl);
8976       emitcode ("add", "a,acc");
8977       emitLabel (tlbl1);
8978       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8979       popB (pushedB);
8980       aopPut (result, "a", 0);
8981       goto release;
8982     }
8983
8984   reAdjustPreg (AOP (result));
8985
8986   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8987   emitLabel (tlbl);
8988   l = aopGet (result, offset, FALSE, FALSE);
8989   MOVA (l);
8990   emitcode ("add", "a,acc");
8991   aopPut (result, "a", offset++);
8992   while (--size)
8993     {
8994       l = aopGet (result, offset, FALSE, FALSE);
8995       MOVA (l);
8996       emitcode ("rlc", "a");
8997       aopPut (result, "a", offset++);
8998     }
8999   reAdjustPreg (AOP (result));
9000
9001   emitLabel (tlbl1);
9002   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9003   popB (pushedB);
9004 release:
9005   freeAsmop (result, NULL, ic, TRUE);
9006   freeAsmop (left, NULL, ic, TRUE);
9007 }
9008
9009 /*-----------------------------------------------------------------*/
9010 /* genrshOne - right shift a one byte quantity by known count      */
9011 /*-----------------------------------------------------------------*/
9012 static void
9013 genrshOne (operand * result, operand * left,
9014            int shCount, int sign)
9015 {
9016   D (emitcode (";", "genrshOne"));
9017
9018   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9019 }
9020
9021 /*-----------------------------------------------------------------*/
9022 /* genrshTwo - right shift two bytes by known amount != 0          */
9023 /*-----------------------------------------------------------------*/
9024 static void
9025 genrshTwo (operand * result, operand * left,
9026            int shCount, int sign)
9027 {
9028   D (emitcode (";", "genrshTwo"));
9029
9030   /* if shCount >= 8 */
9031   if (shCount >= 8)
9032     {
9033       shCount -= 8;
9034       if (shCount)
9035         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9036       else
9037         movLeft2Result (left, MSB16, result, LSB, sign);
9038       addSign (result, MSB16, sign);
9039     }
9040
9041   /*  1 <= shCount <= 7 */
9042   else
9043     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9044 }
9045
9046 /*-----------------------------------------------------------------*/
9047 /* shiftRLong - shift right one long from left to result           */
9048 /* offl = LSB or MSB16                                             */
9049 /*-----------------------------------------------------------------*/
9050 static void
9051 shiftRLong (operand * left, int offl,
9052             operand * result, int sign)
9053 {
9054   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9055
9056   if (overlapping && offl>1)
9057     {
9058       // we are in big trouble, but this shouldn't happen
9059       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9060     }
9061
9062   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9063
9064   if (offl==MSB16)
9065     {
9066       // shift is > 8
9067       if (sign)
9068         {
9069           emitcode ("rlc", "a");
9070           emitcode ("subb", "a,acc");
9071           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9072             {
9073               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9074             }
9075           else
9076             {
9077               aopPut (result, "a", MSB32);
9078               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9079             }
9080         }
9081       else
9082         {
9083           if (aopPutUsesAcc (result, zero, MSB32))
9084             {
9085               emitcode("xch", "a,b");
9086               aopPut (result, zero, MSB32);
9087               emitcode("xch", "a,b");
9088             }
9089           else
9090             {
9091               aopPut (result, zero, MSB32);
9092             }
9093         }
9094     }
9095
9096   if (!sign)
9097     {
9098       emitcode ("clr", "c");
9099     }
9100   else
9101     {
9102       emitcode ("mov", "c,acc.7");
9103     }
9104
9105   emitcode ("rrc", "a");
9106
9107   if (overlapping && offl==MSB16 &&
9108       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9109     {
9110       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9111     }
9112   else
9113     {
9114       aopPut (result, "a", MSB32 - offl);
9115       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9116     }
9117
9118   emitcode ("rrc", "a");
9119   if (overlapping && offl==MSB16 &&
9120       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9121     {
9122       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9123     }
9124   else
9125     {
9126       aopPut (result, "a", MSB24 - offl);
9127       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9128     }
9129
9130   emitcode ("rrc", "a");
9131   if (offl != LSB)
9132     {
9133       aopPut (result, "a", MSB16 - offl);
9134     }
9135   else
9136     {
9137       if (overlapping &&
9138           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9139         {
9140           xch_a_aopGet (left, LSB, FALSE, FALSE);
9141         }
9142       else
9143         {
9144           aopPut (result, "a", MSB16 - offl);
9145           MOVA (aopGet (left, LSB, FALSE, FALSE));
9146         }
9147       emitcode ("rrc", "a");
9148       aopPut (result, "a", LSB);
9149     }
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* genrshFour - shift four byte by a known amount != 0             */
9154 /*-----------------------------------------------------------------*/
9155 static void
9156 genrshFour (operand * result, operand * left,
9157             int shCount, int sign)
9158 {
9159   D (emitcode (";", "genrshFour"));
9160
9161   /* if shifting more that 3 bytes */
9162   if (shCount >= 24)
9163     {
9164       shCount -= 24;
9165       if (shCount)
9166         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9167       else
9168         movLeft2Result (left, MSB32, result, LSB, sign);
9169       addSign (result, MSB16, sign);
9170     }
9171   else if (shCount >= 16)
9172     {
9173       shCount -= 16;
9174       if (shCount)
9175         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9176       else
9177         {
9178           movLeft2Result (left, MSB24, result, LSB, 0);
9179           movLeft2Result (left, MSB32, result, MSB16, sign);
9180         }
9181       addSign (result, MSB24, sign);
9182     }
9183   else if (shCount >= 8)
9184     {
9185       shCount -= 8;
9186       if (shCount == 1)
9187         {
9188           shiftRLong (left, MSB16, result, sign);
9189         }
9190       else if (shCount == 0)
9191         {
9192           movLeft2Result (left, MSB16, result, LSB, 0);
9193           movLeft2Result (left, MSB24, result, MSB16, 0);
9194           movLeft2Result (left, MSB32, result, MSB24, sign);
9195           addSign (result, MSB32, sign);
9196         }
9197       else
9198         {
9199           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9200           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9201           /* the last shift is signed */
9202           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9203           addSign (result, MSB32, sign);
9204         }
9205     }
9206   else
9207     {
9208       /* 1 <= shCount <= 7 */
9209       if (shCount <= 2)
9210         {
9211           shiftRLong (left, LSB, result, sign);
9212           if (shCount == 2)
9213             shiftRLong (result, LSB, result, sign);
9214         }
9215       else
9216         {
9217           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9218           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9219           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9220         }
9221     }
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genRightShiftLiteral - right shifting by known count            */
9226 /*-----------------------------------------------------------------*/
9227 static void
9228 genRightShiftLiteral (operand * left,
9229                       operand * right,
9230                       operand * result,
9231                       iCode * ic,
9232                       int sign)
9233 {
9234   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9235   int size;
9236
9237   D (emitcode (";", "genRightShiftLiteral"));
9238
9239   freeAsmop (right, NULL, ic, TRUE);
9240
9241   aopOp (left, ic, FALSE);
9242   aopOp (result, ic, FALSE);
9243
9244 #if VIEW_SIZE
9245   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9246             AOP_SIZE (left));
9247 #endif
9248
9249   size = getDataSize (left);
9250   /* test the LEFT size !!! */
9251
9252   /* I suppose that the left size >= result size */
9253   if (shCount == 0)
9254     {
9255       size = getDataSize (result);
9256       while (size--)
9257         movLeft2Result (left, size, result, size, 0);
9258     }
9259
9260   else if (shCount >= (size * 8))
9261     {
9262       if (sign)
9263         {
9264           /* get sign in acc.7 */
9265           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9266         }
9267       addSign (result, LSB, sign);
9268     }
9269   else
9270     {
9271       switch (size)
9272         {
9273         case 1:
9274           genrshOne (result, left, shCount, sign);
9275           break;
9276
9277         case 2:
9278           genrshTwo (result, left, shCount, sign);
9279           break;
9280
9281         case 4:
9282           genrshFour (result, left, shCount, sign);
9283           break;
9284         default:
9285           break;
9286         }
9287     }
9288   freeAsmop (result, NULL, ic, TRUE);
9289   freeAsmop (left, NULL, ic, TRUE);
9290 }
9291
9292 /*-----------------------------------------------------------------*/
9293 /* genSignedRightShift - right shift of signed number              */
9294 /*-----------------------------------------------------------------*/
9295 static void
9296 genSignedRightShift (iCode * ic)
9297 {
9298   operand *right, *left, *result;
9299   int size, offset;
9300   char *l;
9301   symbol *tlbl, *tlbl1;
9302   bool pushedB;
9303
9304   D (emitcode (";", "genSignedRightShift"));
9305
9306   /* we do it the hard way put the shift count in b
9307      and loop thru preserving the sign */
9308
9309   right = IC_RIGHT (ic);
9310   left = IC_LEFT (ic);
9311   result = IC_RESULT (ic);
9312
9313   aopOp (right, ic, FALSE);
9314
9315
9316   if (AOP_TYPE (right) == AOP_LIT)
9317     {
9318       genRightShiftLiteral (left, right, result, ic, 1);
9319       return;
9320     }
9321   /* shift count is unknown then we have to form
9322      a loop get the loop count in B : Note: we take
9323      only the lower order byte since shifting
9324      more that 32 bits make no sense anyway, ( the
9325      largest size of an object can be only 32 bits ) */
9326
9327   pushedB = pushB ();
9328   MOVB (aopGet (right, 0, FALSE, FALSE));
9329   emitcode ("inc", "b");
9330   freeAsmop (right, NULL, ic, TRUE);
9331   aopOp (left, ic, FALSE);
9332   aopOp (result, ic, FALSE);
9333
9334   /* now move the left to the result if they are not the
9335      same */
9336   if (!sameRegs (AOP (left), AOP (result)) &&
9337       AOP_SIZE (result) > 1)
9338     {
9339
9340       size = AOP_SIZE (result);
9341       offset = 0;
9342       while (size--)
9343         {
9344           l = aopGet (left, offset, FALSE, TRUE);
9345           if (*l == '@' && IS_AOP_PREG (result))
9346             {
9347
9348               emitcode ("mov", "a,%s", l);
9349               aopPut (result, "a", offset);
9350             }
9351           else
9352             aopPut (result, l, offset);
9353           offset++;
9354         }
9355     }
9356
9357   /* mov the highest order bit to OVR */
9358   tlbl = newiTempLabel (NULL);
9359   tlbl1 = newiTempLabel (NULL);
9360
9361   size = AOP_SIZE (result);
9362   offset = size - 1;
9363   MOVA (aopGet (left, offset, FALSE, FALSE));
9364   emitcode ("rlc", "a");
9365   emitcode ("mov", "ov,c");
9366   /* if it is only one byte then */
9367   if (size == 1)
9368     {
9369       l = aopGet (left, 0, FALSE, FALSE);
9370       MOVA (l);
9371       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9372       emitLabel (tlbl);
9373       emitcode ("mov", "c,ov");
9374       emitcode ("rrc", "a");
9375       emitLabel (tlbl1);
9376       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9377       popB (pushedB);
9378       aopPut (result, "a", 0);
9379       goto release;
9380     }
9381
9382   reAdjustPreg (AOP (result));
9383   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9384   emitLabel (tlbl);
9385   emitcode ("mov", "c,ov");
9386   while (size--)
9387     {
9388       l = aopGet (result, offset, FALSE, FALSE);
9389       MOVA (l);
9390       emitcode ("rrc", "a");
9391       aopPut (result, "a", offset--);
9392     }
9393   reAdjustPreg (AOP (result));
9394   emitLabel (tlbl1);
9395   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9396   popB (pushedB);
9397
9398 release:
9399   freeAsmop (result, NULL, ic, TRUE);
9400   freeAsmop (left, NULL, ic, TRUE);
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* genRightShift - generate code for right shifting                */
9405 /*-----------------------------------------------------------------*/
9406 static void
9407 genRightShift (iCode * ic)
9408 {
9409   operand *right, *left, *result;
9410   sym_link *letype;
9411   int size, offset;
9412   char *l;
9413   symbol *tlbl, *tlbl1;
9414   bool pushedB;
9415
9416   D (emitcode (";", "genRightShift"));
9417
9418   /* if signed then we do it the hard way preserve the
9419      sign bit moving it inwards */
9420   letype = getSpec (operandType (IC_LEFT (ic)));
9421
9422   if (!SPEC_USIGN (letype))
9423     {
9424       genSignedRightShift (ic);
9425       return;
9426     }
9427
9428   /* signed & unsigned types are treated the same : i.e. the
9429      signed is NOT propagated inwards : quoting from the
9430      ANSI - standard : "for E1 >> E2, is equivalent to division
9431      by 2**E2 if unsigned or if it has a non-negative value,
9432      otherwise the result is implementation defined ", MY definition
9433      is that the sign does not get propagated */
9434
9435   right = IC_RIGHT (ic);
9436   left = IC_LEFT (ic);
9437   result = IC_RESULT (ic);
9438
9439   aopOp (right, ic, FALSE);
9440
9441   /* if the shift count is known then do it
9442      as efficiently as possible */
9443   if (AOP_TYPE (right) == AOP_LIT)
9444     {
9445       genRightShiftLiteral (left, right, result, ic, 0);
9446       return;
9447     }
9448
9449   /* shift count is unknown then we have to form
9450      a loop get the loop count in B : Note: we take
9451      only the lower order byte since shifting
9452      more that 32 bits make no sense anyway, ( the
9453      largest size of an object can be only 32 bits ) */
9454
9455   pushedB = pushB ();
9456   MOVB (aopGet (right, 0, FALSE, FALSE));
9457   emitcode ("inc", "b");
9458   freeAsmop (right, NULL, ic, TRUE);
9459   aopOp (left, ic, FALSE);
9460   aopOp (result, ic, FALSE);
9461
9462   /* now move the left to the result if they are not the
9463      same */
9464   if (!sameRegs (AOP (left), AOP (result)) &&
9465       AOP_SIZE (result) > 1)
9466     {
9467       size = AOP_SIZE (result);
9468       offset = 0;
9469       while (size--)
9470         {
9471           l = aopGet (left, offset, FALSE, TRUE);
9472           if (*l == '@' && IS_AOP_PREG (result))
9473             {
9474
9475               emitcode ("mov", "a,%s", l);
9476               aopPut (result, "a", offset);
9477             }
9478           else
9479             aopPut (result, l, offset);
9480           offset++;
9481         }
9482     }
9483
9484   tlbl = newiTempLabel (NULL);
9485   tlbl1 = newiTempLabel (NULL);
9486   size = AOP_SIZE (result);
9487   offset = size - 1;
9488
9489   /* if it is only one byte then */
9490   if (size == 1)
9491     {
9492       l = aopGet (left, 0, FALSE, FALSE);
9493       MOVA (l);
9494       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9495       emitLabel (tlbl);
9496       CLRC;
9497       emitcode ("rrc", "a");
9498       emitLabel (tlbl1);
9499       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9500       popB (pushedB);
9501       aopPut (result, "a", 0);
9502       goto release;
9503     }
9504
9505   reAdjustPreg (AOP (result));
9506   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9507   emitLabel (tlbl);
9508   CLRC;
9509   while (size--)
9510     {
9511       l = aopGet (result, offset, FALSE, FALSE);
9512       MOVA (l);
9513       emitcode ("rrc", "a");
9514       aopPut (result, "a", offset--);
9515     }
9516   reAdjustPreg (AOP (result));
9517
9518   emitLabel (tlbl1);
9519   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9520   popB (pushedB);
9521
9522 release:
9523   freeAsmop (result, NULL, ic, TRUE);
9524   freeAsmop (left, NULL, ic, TRUE);
9525 }
9526
9527 /*-----------------------------------------------------------------*/
9528 /* emitPtrByteGet - emits code to get a byte into A through a      */
9529 /*                  pointer register (R0, R1, or DPTR). The        */
9530 /*                  original value of A can be preserved in B.     */
9531 /*-----------------------------------------------------------------*/
9532 static void
9533 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9534 {
9535   switch (p_type)
9536     {
9537     case IPOINTER:
9538     case POINTER:
9539       if (preserveAinB)
9540         emitcode ("mov", "b,a");
9541       emitcode ("mov", "a,@%s", rname);
9542       break;
9543
9544     case PPOINTER:
9545       if (preserveAinB)
9546         emitcode ("mov", "b,a");
9547       emitcode ("movx", "a,@%s", rname);
9548       break;
9549
9550     case FPOINTER:
9551       if (preserveAinB)
9552         emitcode ("mov", "b,a");
9553       emitcode ("movx", "a,@dptr");
9554       break;
9555
9556     case CPOINTER:
9557       if (preserveAinB)
9558         emitcode ("mov", "b,a");
9559       emitcode ("clr", "a");
9560       emitcode ("movc", "a,@a+dptr");
9561       break;
9562
9563     case GPOINTER:
9564       if (preserveAinB)
9565         {
9566           emitcode ("push", "b");
9567           emitcode ("push", "acc");
9568         }
9569       emitcode ("lcall", "__gptrget");
9570       if (preserveAinB)
9571         emitcode ("pop", "b");
9572       break;
9573     }
9574 }
9575
9576 /*-----------------------------------------------------------------*/
9577 /* emitPtrByteSet - emits code to set a byte from src through a    */
9578 /*                  pointer register (R0, R1, or DPTR).            */
9579 /*-----------------------------------------------------------------*/
9580 static void
9581 emitPtrByteSet (char *rname, int p_type, char *src)
9582 {
9583   switch (p_type)
9584     {
9585     case IPOINTER:
9586     case POINTER:
9587       if (*src=='@')
9588         {
9589           MOVA (src);
9590           emitcode ("mov", "@%s,a", rname);
9591         }
9592       else
9593         emitcode ("mov", "@%s,%s", rname, src);
9594       break;
9595
9596     case PPOINTER:
9597       MOVA (src);
9598       emitcode ("movx", "@%s,a", rname);
9599       break;
9600
9601     case FPOINTER:
9602       MOVA (src);
9603       emitcode ("movx", "@dptr,a");
9604       break;
9605
9606     case GPOINTER:
9607       MOVA (src);
9608       emitcode ("lcall", "__gptrput");
9609       break;
9610     }
9611 }
9612
9613 /*-----------------------------------------------------------------*/
9614 /* genUnpackBits - generates code for unpacking bits               */
9615 /*-----------------------------------------------------------------*/
9616 static void
9617 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9618 {
9619   int offset = 0;       /* result byte offset */
9620   int rsize;            /* result size */
9621   int rlen = 0;         /* remaining bitfield length */
9622   sym_link *etype;      /* bitfield type information */
9623   int blen;             /* bitfield length */
9624   int bstr;             /* bitfield starting bit within byte */
9625   char buffer[10];
9626
9627   D(emitcode (";     genUnpackBits",""));
9628
9629   etype = getSpec (operandType (result));
9630   rsize = getSize (operandType (result));
9631   blen = SPEC_BLEN (etype);
9632   bstr = SPEC_BSTR (etype);
9633
9634   if (ifx && blen <= 8)
9635     {
9636       emitPtrByteGet (rname, ptype, FALSE);
9637       if (blen == 1)
9638         {
9639           SNPRINTF (buffer, sizeof(buffer),
9640                     "acc.%d", bstr);
9641           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9642         }
9643       else
9644         {
9645           if (blen < 8)
9646             emitcode ("anl", "a,#0x%02x",
9647                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9648           genIfxJump (ifx, "a", NULL, NULL, NULL);
9649         }
9650       return;
9651     }
9652   wassert (!ifx);
9653
9654   /* If the bitfield length is less than a byte */
9655   if (blen < 8)
9656     {
9657       emitPtrByteGet (rname, ptype, FALSE);
9658       AccRol (8 - bstr);
9659       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9660       if (!SPEC_USIGN (etype))
9661         {
9662           /* signed bitfield */
9663           symbol *tlbl = newiTempLabel (NULL);
9664
9665           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9666           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9667           emitLabel (tlbl);
9668         }
9669       aopPut (result, "a", offset++);
9670       goto finish;
9671     }
9672
9673   /* Bit field did not fit in a byte. Copy all
9674      but the partial byte at the end.  */
9675   for (rlen=blen;rlen>=8;rlen-=8)
9676     {
9677       emitPtrByteGet (rname, ptype, FALSE);
9678       aopPut (result, "a", offset++);
9679       if (rlen>8)
9680         emitcode ("inc", "%s", rname);
9681     }
9682
9683   /* Handle the partial byte at the end */
9684   if (rlen)
9685     {
9686       emitPtrByteGet (rname, ptype, FALSE);
9687       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9688       if (!SPEC_USIGN (etype))
9689         {
9690           /* signed bitfield */
9691           symbol *tlbl = newiTempLabel (NULL);
9692
9693           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9694           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9695           emitLabel (tlbl);
9696         }
9697       aopPut (result, "a", offset++);
9698     }
9699
9700 finish:
9701   if (offset < rsize)
9702     {
9703       char *source;
9704
9705       if (SPEC_USIGN (etype))
9706         source = zero;
9707       else
9708         {
9709           /* signed bitfield: sign extension with 0x00 or 0xff */
9710           emitcode ("rlc", "a");
9711           emitcode ("subb", "a,acc");
9712
9713           source = "a";
9714         }
9715       rsize -= offset;
9716       while (rsize--)
9717         aopPut (result, source, offset++);
9718     }
9719 }
9720
9721
9722 /*-----------------------------------------------------------------*/
9723 /* genDataPointerGet - generates code when ptr offset is known     */
9724 /*-----------------------------------------------------------------*/
9725 static void
9726 genDataPointerGet (operand * left,
9727                    operand * result,
9728                    iCode * ic)
9729 {
9730   char *l;
9731   char buffer[256];
9732   int size, offset = 0;
9733
9734   D (emitcode (";", "genDataPointerGet"));
9735
9736   aopOp (result, ic, TRUE);
9737
9738   /* get the string representation of the name */
9739   l = aopGet (left, 0, FALSE, TRUE);
9740   l++; // remove #
9741   size = AOP_SIZE (result);
9742   while (size--)
9743     {
9744       if (offset)
9745         {
9746           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9747         }
9748       else
9749         {
9750           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9751         }
9752       aopPut (result, buffer, offset++);
9753     }
9754
9755   freeAsmop (result, NULL, ic, TRUE);
9756   freeAsmop (left, NULL, ic, TRUE);
9757 }
9758
9759 /*-----------------------------------------------------------------*/
9760 /* genNearPointerGet - emitcode for near pointer fetch             */
9761 /*-----------------------------------------------------------------*/
9762 static void
9763 genNearPointerGet (operand * left,
9764                    operand * result,
9765                    iCode * ic,
9766                    iCode * pi,
9767                    iCode * ifx)
9768 {
9769   asmop *aop = NULL;
9770   regs *preg = NULL;
9771   char *rname;
9772   sym_link *rtype, *retype;
9773   sym_link *ltype = operandType (left);
9774   char buffer[80];
9775
9776   D (emitcode (";", "genNearPointerGet"));
9777
9778   rtype = operandType (result);
9779   retype = getSpec (rtype);
9780
9781   aopOp (left, ic, FALSE);
9782
9783   /* if left is rematerialisable and
9784      result is not bitfield variable type and
9785      the left is pointer to data space i.e
9786      lower 128 bytes of space */
9787   if (AOP_TYPE (left) == AOP_IMMD &&
9788       !IS_BITFIELD (retype) &&
9789       DCL_TYPE (ltype) == POINTER)
9790     {
9791       genDataPointerGet (left, result, ic);
9792       return;
9793     }
9794
9795  /* if the value is already in a pointer register
9796      then don't need anything more */
9797   if (!AOP_INPREG (AOP (left)))
9798     {
9799       if (IS_AOP_PREG (left))
9800         {
9801           // Aha, it is a pointer, just in disguise.
9802           rname = aopGet (left, 0, FALSE, FALSE);
9803           if (*rname != '@')
9804             {
9805               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9806                       __FILE__, __LINE__);
9807             }
9808           else
9809             {
9810               // Expected case.
9811               emitcode ("mov", "a%s,%s", rname + 1, rname);
9812               rname++;  // skip the '@'.
9813             }
9814         }
9815       else
9816         {
9817           /* otherwise get a free pointer register */
9818           aop = newAsmop (0);
9819           preg = getFreePtr (ic, &aop, FALSE);
9820           emitcode ("mov", "%s,%s",
9821                     preg->name,
9822                     aopGet (left, 0, FALSE, TRUE));
9823           rname = preg->name;
9824         }
9825     }
9826   else
9827     rname = aopGet (left, 0, FALSE, FALSE);
9828
9829   //aopOp (result, ic, FALSE);
9830   aopOp (result, ic, result?TRUE:FALSE);
9831
9832   /* if bitfield then unpack the bits */
9833   if (IS_BITFIELD (retype))
9834     genUnpackBits (result, rname, POINTER, ifx);
9835   else
9836     {
9837       /* we have can just get the values */
9838       int size = AOP_SIZE (result);
9839       int offset = 0;
9840
9841       while (size--)
9842         {
9843           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9844             {
9845
9846               emitcode ("mov", "a,@%s", rname);
9847               if (!ifx)
9848                 aopPut (result, "a", offset);
9849             }
9850           else
9851             {
9852               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9853               aopPut (result, buffer, offset);
9854             }
9855           offset++;
9856           if (size || pi)
9857             emitcode ("inc", "%s", rname);
9858         }
9859     }
9860
9861   /* now some housekeeping stuff */
9862   if (aop)       /* we had to allocate for this iCode */
9863     {
9864       if (pi) { /* post increment present */
9865         aopPut (left, rname, 0);
9866       }
9867       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9868     }
9869   else
9870     {
9871       /* we did not allocate which means left
9872          already in a pointer register, then
9873          if size > 0 && this could be used again
9874          we have to point it back to where it
9875          belongs */
9876       if ((AOP_SIZE (result) > 1 &&
9877            !OP_SYMBOL (left)->remat &&
9878            (OP_SYMBOL (left)->liveTo > ic->seq ||
9879             ic->depth)) &&
9880           !pi)
9881         {
9882           int size = AOP_SIZE (result) - 1;
9883           while (size--)
9884             emitcode ("dec", "%s", rname);
9885         }
9886     }
9887
9888   if (ifx && !ifx->generated)
9889     {
9890       genIfxJump (ifx, "a", left, NULL, result);
9891     }
9892
9893   /* done */
9894   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9895   freeAsmop (left, NULL, ic, TRUE);
9896   if (pi) pi->generated = 1;
9897 }
9898
9899 /*-----------------------------------------------------------------*/
9900 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9901 /*-----------------------------------------------------------------*/
9902 static void
9903 genPagedPointerGet (operand * left,
9904                     operand * result,
9905                     iCode * ic,
9906                     iCode *pi,
9907                     iCode *ifx)
9908 {
9909   asmop *aop = NULL;
9910   regs *preg = NULL;
9911   char *rname;
9912   sym_link *rtype, *retype;
9913
9914   D (emitcode (";", "genPagedPointerGet"));
9915
9916   rtype = operandType (result);
9917   retype = getSpec (rtype);
9918
9919   aopOp (left, ic, FALSE);
9920
9921   /* if the value is already in a pointer register
9922      then don't need anything more */
9923   if (!AOP_INPREG (AOP (left)))
9924     {
9925       /* otherwise get a free pointer register */
9926       aop = newAsmop (0);
9927       preg = getFreePtr (ic, &aop, FALSE);
9928       emitcode ("mov", "%s,%s",
9929                 preg->name,
9930                 aopGet (left, 0, FALSE, TRUE));
9931       rname = preg->name;
9932     }
9933   else
9934     rname = aopGet (left, 0, FALSE, FALSE);
9935
9936   aopOp (result, ic, FALSE);
9937
9938   /* if bitfield then unpack the bits */
9939   if (IS_BITFIELD (retype))
9940     genUnpackBits (result, rname, PPOINTER, ifx);
9941   else
9942     {
9943       /* we have can just get the values */
9944       int size = AOP_SIZE (result);
9945       int offset = 0;
9946
9947       while (size--)
9948         {
9949
9950           emitcode ("movx", "a,@%s", rname);
9951           if (!ifx)
9952             aopPut (result, "a", offset);
9953
9954           offset++;
9955
9956           if (size || pi)
9957             emitcode ("inc", "%s", rname);
9958         }
9959     }
9960
9961   /* now some housekeeping stuff */
9962   if (aop) /* we had to allocate for this iCode */
9963     {
9964       if (pi)
9965         aopPut (left, rname, 0);
9966       freeAsmop (NULL, aop, ic, TRUE);
9967     }
9968   else
9969     {
9970       /* we did not allocate which means left
9971          already in a pointer register, then
9972          if size > 0 && this could be used again
9973          we have to point it back to where it
9974          belongs */
9975       if ((AOP_SIZE (result) > 1 &&
9976            !OP_SYMBOL (left)->remat &&
9977            (OP_SYMBOL (left)->liveTo > ic->seq ||
9978             ic->depth)) &&
9979           !pi)
9980         {
9981           int size = AOP_SIZE (result) - 1;
9982           while (size--)
9983             emitcode ("dec", "%s", rname);
9984         }
9985     }
9986
9987   if (ifx && !ifx->generated)
9988     {
9989       genIfxJump (ifx, "a", left, NULL, result);
9990     }
9991
9992   /* done */
9993   freeAsmop (result, NULL, ic, TRUE);
9994   freeAsmop (left, NULL, ic, TRUE);
9995   if (pi) pi->generated = 1;
9996 }
9997
9998 /*--------------------------------------------------------------------*/
9999 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10000 /*--------------------------------------------------------------------*/
10001 static void
10002 loadDptrFromOperand (operand *op, bool loadBToo)
10003 {
10004   if (AOP_TYPE (op) != AOP_STR)
10005     {
10006       /* if this is rematerializable */
10007       if (AOP_TYPE (op) == AOP_IMMD)
10008         {
10009           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10010           if (loadBToo)
10011             {
10012               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10013                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10014               else
10015                 {
10016                   wassertl(FALSE, "need pointerCode");
10017                   emitcode ("", "; mov b,???");
10018                   /* genPointerGet and genPointerSet originally did different
10019                   ** things for this case. Both seem wrong.
10020                   ** from genPointerGet:
10021                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10022                   ** from genPointerSet:
10023                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10024                   */
10025                 }
10026             }
10027         }
10028       else if (AOP_TYPE (op) == AOP_DPTR)
10029         {
10030           if (loadBToo)
10031             {
10032               MOVA (aopGet (op, 0, FALSE, FALSE));
10033               emitcode ("push", "acc");
10034               MOVA (aopGet (op, 1, FALSE, FALSE));
10035               emitcode ("push", "acc");
10036               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10037               emitcode ("pop", "dph");
10038               emitcode ("pop", "dpl");
10039             }
10040           else
10041             {
10042               MOVA (aopGet (op, 0, FALSE, FALSE));
10043               emitcode ("push", "acc");
10044               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10045               emitcode ("pop", "dpl");
10046             }
10047         }
10048       else
10049         {                       /* we need to get it byte by byte */
10050           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10051           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10052           if (loadBToo)
10053             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10054         }
10055     }
10056 }
10057
10058 /*-----------------------------------------------------------------*/
10059 /* genFarPointerGet - get value from far space                     */
10060 /*-----------------------------------------------------------------*/
10061 static void
10062 genFarPointerGet (operand * left,
10063                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10064 {
10065   int size, offset;
10066   sym_link *retype = getSpec (operandType (result));
10067
10068   D (emitcode (";", "genFarPointerGet"));
10069
10070   aopOp (left, ic, FALSE);
10071   loadDptrFromOperand (left, FALSE);
10072
10073   /* so dptr now contains the address */
10074   aopOp (result, ic, FALSE);
10075
10076   /* if bit then unpack */
10077   if (IS_BITFIELD (retype))
10078     genUnpackBits (result, "dptr", FPOINTER, ifx);
10079   else
10080     {
10081       size = AOP_SIZE (result);
10082       offset = 0;
10083
10084       while (size--)
10085         {
10086           emitcode ("movx", "a,@dptr");
10087           if (!ifx)
10088             aopPut (result, "a", offset++);
10089           if (size || pi)
10090             emitcode ("inc", "dptr");
10091         }
10092     }
10093
10094   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10095     {
10096       aopPut (left, "dpl", 0);
10097       aopPut (left, "dph", 1);
10098       pi->generated = 1;
10099     }
10100
10101   if (ifx && !ifx->generated)
10102     {
10103       genIfxJump (ifx, "a", left, NULL, result);
10104     }
10105
10106   freeAsmop (result, NULL, ic, TRUE);
10107   freeAsmop (left, NULL, ic, TRUE);
10108 }
10109
10110 /*-----------------------------------------------------------------*/
10111 /* genCodePointerGet - get value from code space                   */
10112 /*-----------------------------------------------------------------*/
10113 static void
10114 genCodePointerGet (operand * left,
10115                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10116 {
10117   int size, offset;
10118   sym_link *retype = getSpec (operandType (result));
10119
10120   D (emitcode (";", "genCodePointerGet"));
10121
10122   aopOp (left, ic, FALSE);
10123   loadDptrFromOperand (left, FALSE);
10124
10125   /* so dptr now contains the address */
10126   aopOp (result, ic, FALSE);
10127
10128   /* if bit then unpack */
10129   if (IS_BITFIELD (retype))
10130     genUnpackBits (result, "dptr", CPOINTER, ifx);
10131   else
10132     {
10133       size = AOP_SIZE (result);
10134       offset = 0;
10135
10136       while (size--)
10137         {
10138           emitcode ("clr", "a");
10139           emitcode ("movc", "a,@a+dptr");
10140           if (!ifx)
10141             aopPut (result, "a", offset++);
10142           if (size || pi)
10143             emitcode ("inc", "dptr");
10144         }
10145     }
10146
10147   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10148     {
10149       aopPut (left, "dpl", 0);
10150       aopPut (left, "dph", 1);
10151       pi->generated = 1;
10152     }
10153
10154   if (ifx && !ifx->generated)
10155     {
10156       genIfxJump (ifx, "a", left, NULL, result);
10157     }
10158
10159   freeAsmop (result, NULL, ic, TRUE);
10160   freeAsmop (left, NULL, ic, TRUE);
10161 }
10162
10163 /*-----------------------------------------------------------------*/
10164 /* genGenPointerGet - get value from generic pointer space         */
10165 /*-----------------------------------------------------------------*/
10166 static void
10167 genGenPointerGet (operand * left,
10168                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10169 {
10170   int size, offset;
10171   sym_link *retype = getSpec (operandType (result));
10172
10173   D (emitcode (";", "genGenPointerGet"));
10174
10175   aopOp (left, ic, FALSE);
10176   loadDptrFromOperand (left, TRUE);
10177
10178   /* so dptr now contains the address */
10179   aopOp (result, ic, FALSE);
10180
10181   /* if bit then unpack */
10182   if (IS_BITFIELD (retype))
10183     {
10184       genUnpackBits (result, "dptr", GPOINTER, ifx);
10185     }
10186   else
10187     {
10188       size = AOP_SIZE (result);
10189       offset = 0;
10190
10191       while (size--)
10192         {
10193           emitcode ("lcall", "__gptrget");
10194           if (!ifx)
10195             aopPut (result, "a", offset++);
10196           if (size || pi)
10197             emitcode ("inc", "dptr");
10198         }
10199     }
10200
10201   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10202     {
10203       aopPut (left, "dpl", 0);
10204       aopPut (left, "dph", 1);
10205       pi->generated = 1;
10206     }
10207
10208   if (ifx && !ifx->generated)
10209     {
10210       genIfxJump (ifx, "a", left, NULL, result);
10211     }
10212
10213   freeAsmop (result, NULL, ic, TRUE);
10214   freeAsmop (left, NULL, ic, TRUE);
10215 }
10216
10217 /*-----------------------------------------------------------------*/
10218 /* genPointerGet - generate code for pointer get                   */
10219 /*-----------------------------------------------------------------*/
10220 static void
10221 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10222 {
10223   operand *left, *result;
10224   sym_link *type, *etype;
10225   int p_type;
10226
10227   D (emitcode (";", "genPointerGet"));
10228
10229   left = IC_LEFT (ic);
10230   result = IC_RESULT (ic);
10231
10232   if (getSize (operandType (result))>1)
10233     ifx = NULL;
10234
10235   /* depending on the type of pointer we need to
10236      move it to the correct pointer register */
10237   type = operandType (left);
10238   etype = getSpec (type);
10239   /* if left is of type of pointer then it is simple */
10240   if (IS_PTR (type) && !IS_FUNC (type->next))
10241     p_type = DCL_TYPE (type);
10242   else
10243     {
10244       /* we have to go by the storage class */
10245       p_type = PTR_TYPE (SPEC_OCLS (etype));
10246     }
10247
10248   /* special case when cast remat */
10249   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10250       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10251     {
10252       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10253       type = operandType (left);
10254       p_type = DCL_TYPE (type);
10255     }
10256   /* now that we have the pointer type we assign
10257      the pointer values */
10258   switch (p_type)
10259     {
10260
10261     case POINTER:
10262     case IPOINTER:
10263       genNearPointerGet (left, result, ic, pi, ifx);
10264       break;
10265
10266     case PPOINTER:
10267       genPagedPointerGet (left, result, ic, pi, ifx);
10268       break;
10269
10270     case FPOINTER:
10271       genFarPointerGet (left, result, ic, pi, ifx);
10272       break;
10273
10274     case CPOINTER:
10275       genCodePointerGet (left, result, ic, pi, ifx);
10276       break;
10277
10278     case GPOINTER:
10279       genGenPointerGet (left, result, ic, pi, ifx);
10280       break;
10281     }
10282 }
10283
10284
10285 /*-----------------------------------------------------------------*/
10286 /* genPackBits - generates code for packed bit storage             */
10287 /*-----------------------------------------------------------------*/
10288 static void
10289 genPackBits (sym_link * etype,
10290              operand * right,
10291              char *rname, int p_type)
10292 {
10293   int offset = 0;       /* source byte offset */
10294   int rlen = 0;         /* remaining bitfield length */
10295   int blen;             /* bitfield length */
10296   int bstr;             /* bitfield starting bit within byte */
10297   int litval;           /* source literal value (if AOP_LIT) */
10298   unsigned char mask;   /* bitmask within current byte */
10299
10300   D(emitcode (";     genPackBits",""));
10301
10302   blen = SPEC_BLEN (etype);
10303   bstr = SPEC_BSTR (etype);
10304
10305   /* If the bitfield length is less than a byte */
10306   if (blen < 8)
10307     {
10308       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10309               (unsigned char) (0xFF >> (8 - bstr)));
10310
10311       if (AOP_TYPE (right) == AOP_LIT)
10312         {
10313           /* Case with a bitfield length <8 and literal source
10314           */
10315           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10316           litval <<= bstr;
10317           litval &= (~mask) & 0xff;
10318           emitPtrByteGet (rname, p_type, FALSE);
10319           if ((mask|litval)!=0xff)
10320             emitcode ("anl","a,#0x%02x", mask);
10321           if (litval)
10322             emitcode ("orl","a,#0x%02x", litval);
10323         }
10324       else
10325         {
10326           if ((blen==1) && (p_type!=GPOINTER))
10327             {
10328               /* Case with a bitfield length == 1 and no generic pointer
10329               */
10330               if (AOP_TYPE (right) == AOP_CRY)
10331                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10332               else
10333                 {
10334                   MOVA (aopGet (right, 0, FALSE, FALSE));
10335                   emitcode ("rrc","a");
10336                 }
10337               emitPtrByteGet (rname, p_type, FALSE);
10338               emitcode ("mov","acc.%d,c",bstr);
10339             }
10340           else
10341             {
10342               bool pushedB;
10343               /* Case with a bitfield length < 8 and arbitrary source
10344               */
10345               MOVA (aopGet (right, 0, FALSE, FALSE));
10346               /* shift and mask source value */
10347               AccLsh (bstr);
10348               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10349
10350               pushedB = pushB ();
10351               /* transfer A to B and get next byte */
10352               emitPtrByteGet (rname, p_type, TRUE);
10353
10354               emitcode ("anl", "a,#0x%02x", mask);
10355               emitcode ("orl", "a,b");
10356               if (p_type == GPOINTER)
10357                 emitcode ("pop", "b");
10358
10359               popB (pushedB);
10360            }
10361         }
10362
10363       emitPtrByteSet (rname, p_type, "a");
10364       return;
10365     }
10366
10367   /* Bit length is greater than 7 bits. In this case, copy  */
10368   /* all except the partial byte at the end                 */
10369   for (rlen=blen;rlen>=8;rlen-=8)
10370     {
10371       emitPtrByteSet (rname, p_type,
10372                       aopGet (right, offset++, FALSE, TRUE) );
10373       if (rlen>8)
10374         emitcode ("inc", "%s", rname);
10375     }
10376
10377   /* If there was a partial byte at the end */
10378   if (rlen)
10379     {
10380       mask = (((unsigned char) -1 << rlen) & 0xff);
10381
10382       if (AOP_TYPE (right) == AOP_LIT)
10383         {
10384           /* Case with partial byte and literal source
10385           */
10386           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10387           litval >>= (blen-rlen);
10388           litval &= (~mask) & 0xff;
10389           emitPtrByteGet (rname, p_type, FALSE);
10390           if ((mask|litval)!=0xff)
10391             emitcode ("anl","a,#0x%02x", mask);
10392           if (litval)
10393             emitcode ("orl","a,#0x%02x", litval);
10394         }
10395       else
10396         {
10397           bool pushedB;
10398           /* Case with partial byte and arbitrary source
10399           */
10400           MOVA (aopGet (right, offset++, FALSE, FALSE));
10401           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10402
10403           pushedB = pushB ();
10404           /* transfer A to B and get next byte */
10405           emitPtrByteGet (rname, p_type, TRUE);
10406
10407           emitcode ("anl", "a,#0x%02x", mask);
10408           emitcode ("orl", "a,b");
10409           if (p_type == GPOINTER)
10410             emitcode ("pop", "b");
10411
10412           popB (pushedB);
10413         }
10414       emitPtrByteSet (rname, p_type, "a");
10415     }
10416 }
10417
10418
10419 /*-----------------------------------------------------------------*/
10420 /* genDataPointerSet - remat pointer to data space                 */
10421 /*-----------------------------------------------------------------*/
10422 static void
10423 genDataPointerSet (operand * right,
10424                    operand * result,
10425                    iCode * ic)
10426 {
10427   int size, offset = 0;
10428   char *l, buffer[256];
10429
10430   D (emitcode (";", "genDataPointerSet"));
10431
10432   aopOp (right, ic, FALSE);
10433
10434   l = aopGet (result, 0, FALSE, TRUE);
10435   l++; //remove #
10436   size = AOP_SIZE (right);
10437   while (size--)
10438     {
10439       if (offset)
10440         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10441       else
10442         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10443       emitcode ("mov", "%s,%s", buffer,
10444                 aopGet (right, offset++, FALSE, FALSE));
10445     }
10446
10447   freeAsmop (result, NULL, ic, TRUE);
10448   freeAsmop (right, NULL, ic, TRUE);
10449 }
10450
10451 /*-----------------------------------------------------------------*/
10452 /* genNearPointerSet - emitcode for near pointer put                */
10453 /*-----------------------------------------------------------------*/
10454 static void
10455 genNearPointerSet (operand * right,
10456                    operand * result,
10457                    iCode * ic,
10458                    iCode * pi)
10459 {
10460   asmop *aop = NULL;
10461   regs *preg = NULL;
10462   char *rname, *l;
10463   sym_link *retype, *letype;
10464   sym_link *ptype = operandType (result);
10465
10466   D (emitcode (";", "genNearPointerSet"));
10467
10468   retype = getSpec (operandType (right));
10469   letype = getSpec (ptype);
10470
10471   aopOp (result, ic, FALSE);
10472
10473   /* if the result is rematerializable &
10474      in data space & not a bit variable */
10475   if (AOP_TYPE (result) == AOP_IMMD &&
10476       DCL_TYPE (ptype) == POINTER &&
10477       !IS_BITVAR (retype) &&
10478       !IS_BITVAR (letype))
10479     {
10480       genDataPointerSet (right, result, ic);
10481       return;
10482     }
10483
10484   /* if the value is already in a pointer register
10485      then don't need anything more */
10486   if (!AOP_INPREG (AOP (result)))
10487     {
10488         if (
10489             //AOP_TYPE (result) == AOP_STK
10490             IS_AOP_PREG(result)
10491             )
10492         {
10493             // Aha, it is a pointer, just in disguise.
10494             rname = aopGet (result, 0, FALSE, FALSE);
10495             if (*rname != '@')
10496             {
10497                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10498                         __FILE__, __LINE__);
10499             }
10500             else
10501             {
10502                 // Expected case.
10503                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10504                 rname++;  // skip the '@'.
10505             }
10506         }
10507         else
10508         {
10509             /* otherwise get a free pointer register */
10510             aop = newAsmop (0);
10511             preg = getFreePtr (ic, &aop, FALSE);
10512             emitcode ("mov", "%s,%s",
10513                       preg->name,
10514                       aopGet (result, 0, FALSE, TRUE));
10515             rname = preg->name;
10516         }
10517     }
10518     else
10519     {
10520         rname = aopGet (result, 0, FALSE, FALSE);
10521     }
10522
10523   aopOp (right, ic, FALSE);
10524
10525   /* if bitfield then unpack the bits */
10526   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10527     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10528   else
10529     {
10530       /* we can just get the values */
10531       int size = AOP_SIZE (right);
10532       int offset = 0;
10533
10534       while (size--)
10535         {
10536           l = aopGet (right, offset, FALSE, TRUE);
10537           if ((*l == '@') || (strcmp (l, "acc") == 0))
10538             {
10539               MOVA (l);
10540               emitcode ("mov", "@%s,a", rname);
10541             }
10542           else
10543             emitcode ("mov", "@%s,%s", rname, l);
10544           if (size || pi)
10545             emitcode ("inc", "%s", rname);
10546           offset++;
10547         }
10548     }
10549
10550   /* now some housekeeping stuff */
10551   if (aop) /* we had to allocate for this iCode */
10552     {
10553       if (pi)
10554         aopPut (result, rname, 0);
10555       freeAsmop (NULL, aop, ic, TRUE);
10556     }
10557   else
10558     {
10559       /* we did not allocate which means left
10560          already in a pointer register, then
10561          if size > 0 && this could be used again
10562          we have to point it back to where it
10563          belongs */
10564       if ((AOP_SIZE (right) > 1 &&
10565            !OP_SYMBOL (result)->remat &&
10566            (OP_SYMBOL (result)->liveTo > ic->seq ||
10567             ic->depth)) &&
10568           !pi)
10569         {
10570           int size = AOP_SIZE (right) - 1;
10571           while (size--)
10572             emitcode ("dec", "%s", rname);
10573         }
10574     }
10575
10576   /* done */
10577   if (pi) pi->generated = 1;
10578   freeAsmop (result, NULL, ic, TRUE);
10579   freeAsmop (right, NULL, ic, TRUE);
10580 }
10581
10582 /*-----------------------------------------------------------------*/
10583 /* genPagedPointerSet - emitcode for Paged pointer put             */
10584 /*-----------------------------------------------------------------*/
10585 static void
10586 genPagedPointerSet (operand * right,
10587                     operand * result,
10588                     iCode * ic,
10589                     iCode * pi)
10590 {
10591   asmop *aop = NULL;
10592   regs *preg = NULL;
10593   char *rname, *l;
10594   sym_link *retype, *letype;
10595
10596   D (emitcode (";", "genPagedPointerSet"));
10597
10598   retype = getSpec (operandType (right));
10599   letype = getSpec (operandType (result));
10600
10601   aopOp (result, ic, FALSE);
10602
10603   /* if the value is already in a pointer register
10604      then don't need anything more */
10605   if (!AOP_INPREG (AOP (result)))
10606     {
10607       /* otherwise get a free pointer register */
10608       aop = newAsmop (0);
10609       preg = getFreePtr (ic, &aop, FALSE);
10610       emitcode ("mov", "%s,%s",
10611                 preg->name,
10612                 aopGet (result, 0, FALSE, TRUE));
10613       rname = preg->name;
10614     }
10615   else
10616     rname = aopGet (result, 0, FALSE, FALSE);
10617
10618   aopOp (right, ic, FALSE);
10619
10620   /* if bitfield then unpack the bits */
10621   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10622     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10623   else
10624     {
10625       /* we have can just get the values */
10626       int size = AOP_SIZE (right);
10627       int offset = 0;
10628
10629       while (size--)
10630         {
10631           l = aopGet (right, offset, FALSE, TRUE);
10632           MOVA (l);
10633           emitcode ("movx", "@%s,a", rname);
10634
10635           if (size || pi)
10636             emitcode ("inc", "%s", rname);
10637
10638           offset++;
10639         }
10640     }
10641
10642   /* now some housekeeping stuff */
10643   if (aop) /* we had to allocate for this iCode */
10644     {
10645       if (pi)
10646         aopPut (result, rname, 0);
10647       freeAsmop (NULL, aop, ic, TRUE);
10648     }
10649   else
10650     {
10651       /* we did not allocate which means left
10652          already in a pointer register, then
10653          if size > 0 && this could be used again
10654          we have to point it back to where it
10655          belongs */
10656       if (AOP_SIZE (right) > 1 &&
10657           !OP_SYMBOL (result)->remat &&
10658           (OP_SYMBOL (result)->liveTo > ic->seq ||
10659            ic->depth))
10660         {
10661           int size = AOP_SIZE (right) - 1;
10662           while (size--)
10663             emitcode ("dec", "%s", rname);
10664         }
10665     }
10666
10667   /* done */
10668   if (pi) pi->generated = 1;
10669   freeAsmop (result, NULL, ic, TRUE);
10670   freeAsmop (right, NULL, ic, TRUE);
10671 }
10672
10673 /*-----------------------------------------------------------------*/
10674 /* genFarPointerSet - set value from far space                     */
10675 /*-----------------------------------------------------------------*/
10676 static void
10677 genFarPointerSet (operand * right,
10678                   operand * result, iCode * ic, iCode * pi)
10679 {
10680   int size, offset;
10681   sym_link *retype = getSpec (operandType (right));
10682   sym_link *letype = getSpec (operandType (result));
10683
10684   D(emitcode (";     genFarPointerSet",""));
10685
10686   aopOp (result, ic, FALSE);
10687   loadDptrFromOperand (result, FALSE);
10688
10689   /* so dptr now contains the address */
10690   aopOp (right, ic, FALSE);
10691
10692   /* if bit then unpack */
10693   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10694     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10695   else
10696     {
10697       size = AOP_SIZE (right);
10698       offset = 0;
10699
10700       while (size--)
10701         {
10702           char *l = aopGet (right, offset++, FALSE, FALSE);
10703           MOVA (l);
10704           emitcode ("movx", "@dptr,a");
10705           if (size || pi)
10706             emitcode ("inc", "dptr");
10707         }
10708     }
10709   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10710     aopPut (result, "dpl", 0);
10711     aopPut (result, "dph", 1);
10712     pi->generated=1;
10713   }
10714   freeAsmop (result, NULL, ic, TRUE);
10715   freeAsmop (right, NULL, ic, TRUE);
10716 }
10717
10718 /*-----------------------------------------------------------------*/
10719 /* genGenPointerSet - set value from generic pointer space         */
10720 /*-----------------------------------------------------------------*/
10721 static void
10722 genGenPointerSet (operand * right,
10723                   operand * result, iCode * ic, iCode * pi)
10724 {
10725   int size, offset;
10726   sym_link *retype = getSpec (operandType (right));
10727   sym_link *letype = getSpec (operandType (result));
10728
10729   D (emitcode (";", "genGenPointerSet"));
10730
10731   aopOp (result, ic, FALSE);
10732   loadDptrFromOperand (result, TRUE);
10733
10734   /* so dptr now contains the address */
10735   aopOp (right, ic, FALSE);
10736
10737   /* if bit then unpack */
10738   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10739     {
10740       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10741     }
10742   else
10743     {
10744       size = AOP_SIZE (right);
10745       offset = 0;
10746
10747       while (size--)
10748         {
10749           char *l = aopGet (right, offset++, FALSE, FALSE);
10750           MOVA (l);
10751           emitcode ("lcall", "__gptrput");
10752           if (size || pi)
10753             emitcode ("inc", "dptr");
10754         }
10755     }
10756
10757   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10758     aopPut (result, "dpl", 0);
10759     aopPut (result, "dph", 1);
10760     pi->generated=1;
10761   }
10762   freeAsmop (result, NULL, ic, TRUE);
10763   freeAsmop (right, NULL, ic, TRUE);
10764 }
10765
10766 /*-----------------------------------------------------------------*/
10767 /* genPointerSet - stores the value into a pointer location        */
10768 /*-----------------------------------------------------------------*/
10769 static void
10770 genPointerSet (iCode * ic, iCode *pi)
10771 {
10772   operand *right, *result;
10773   sym_link *type, *etype;
10774   int p_type;
10775
10776   D (emitcode (";", "genPointerSet"));
10777
10778   right = IC_RIGHT (ic);
10779   result = IC_RESULT (ic);
10780
10781   /* depending on the type of pointer we need to
10782      move it to the correct pointer register */
10783   type = operandType (result);
10784   etype = getSpec (type);
10785   /* if left is of type of pointer then it is simple */
10786   if (IS_PTR (type) && !IS_FUNC (type->next))
10787     {
10788       p_type = DCL_TYPE (type);
10789     }
10790   else
10791     {
10792       /* we have to go by the storage class */
10793       p_type = PTR_TYPE (SPEC_OCLS (etype));
10794     }
10795
10796   /* special case when cast remat */
10797   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10798       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10799           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10800           type = operandType (result);
10801           p_type = DCL_TYPE (type);
10802   }
10803
10804   /* now that we have the pointer type we assign
10805      the pointer values */
10806   switch (p_type)
10807     {
10808
10809     case POINTER:
10810     case IPOINTER:
10811       genNearPointerSet (right, result, ic, pi);
10812       break;
10813
10814     case PPOINTER:
10815       genPagedPointerSet (right, result, ic, pi);
10816       break;
10817
10818     case FPOINTER:
10819       genFarPointerSet (right, result, ic, pi);
10820       break;
10821
10822     case GPOINTER:
10823       genGenPointerSet (right, result, ic, pi);
10824       break;
10825
10826     default:
10827       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10828               "genPointerSet: illegal pointer type");
10829     }
10830 }
10831
10832 /*-----------------------------------------------------------------*/
10833 /* genIfx - generate code for Ifx statement                        */
10834 /*-----------------------------------------------------------------*/
10835 static void
10836 genIfx (iCode * ic, iCode * popIc)
10837 {
10838   operand *cond = IC_COND (ic);
10839   int isbit = 0;
10840   char *dup = NULL;
10841
10842   D (emitcode (";", "genIfx"));
10843
10844   aopOp (cond, ic, FALSE);
10845
10846   /* get the value into acc */
10847   if (AOP_TYPE (cond) != AOP_CRY)
10848     {
10849       toBoolean (cond);
10850     }
10851   else
10852     {
10853       isbit = 1;
10854       if (AOP(cond)->aopu.aop_dir)
10855         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10856     }
10857
10858   /* the result is now in the accumulator or a directly addressable bit */
10859   freeAsmop (cond, NULL, ic, TRUE);
10860
10861   /* if there was something to be popped then do it */
10862   if (popIc)
10863     genIpop (popIc);
10864
10865   /* if the condition is a bit variable */
10866   if (isbit && dup)
10867     genIfxJump(ic, dup, NULL, NULL, NULL);
10868   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10869     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10870   else if (isbit && !IS_ITEMP (cond))
10871     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10872   else
10873     genIfxJump (ic, "a", NULL, NULL, NULL);
10874
10875   ic->generated = 1;
10876 }
10877
10878 /*-----------------------------------------------------------------*/
10879 /* genAddrOf - generates code for address of                       */
10880 /*-----------------------------------------------------------------*/
10881 static void
10882 genAddrOf (iCode * ic)
10883 {
10884   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10885   int size, offset;
10886
10887   D (emitcode (";", "genAddrOf"));
10888
10889   aopOp (IC_RESULT (ic), ic, FALSE);
10890
10891   /* if the operand is on the stack then we
10892      need to get the stack offset of this
10893      variable */
10894   if (sym->onStack)
10895     {
10896       /* if it has an offset then we need to compute it */
10897       if (sym->stack)
10898         {
10899           int stack_offset = ((sym->stack < 0) ?
10900                               ((char) (sym->stack - _G.nRegsSaved)) :
10901                               ((char) sym->stack)) & 0xff;
10902           if ((abs(stack_offset) == 1) &&
10903               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10904               !isOperandVolatile (IC_RESULT (ic), FALSE))
10905             {
10906               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10907               if (stack_offset > 0)
10908                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10909               else
10910                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10911             }
10912           else
10913             {
10914               emitcode ("mov", "a,%s", SYM_BP (sym));
10915               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10916               aopPut (IC_RESULT (ic), "a", 0);
10917             }
10918         }
10919       else
10920         {
10921           /* we can just move _bp */
10922           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10923         }
10924       /* fill the result with zero */
10925       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10926
10927       offset = 1;
10928       while (size--)
10929         {
10930           aopPut (IC_RESULT (ic), zero, offset++);
10931         }
10932       goto release;
10933     }
10934
10935   /* object not on stack then we need the name */
10936   size = AOP_SIZE (IC_RESULT (ic));
10937   offset = 0;
10938
10939   while (size--)
10940     {
10941       char s[SDCC_NAME_MAX];
10942       if (offset)
10943         sprintf (s, "#(%s >> %d)",
10944                  sym->rname,
10945                  offset * 8);
10946       else
10947         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10948       aopPut (IC_RESULT (ic), s, offset++);
10949     }
10950
10951 release:
10952   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10953
10954 }
10955
10956 /*-----------------------------------------------------------------*/
10957 /* genFarFarAssign - assignment when both are in far space         */
10958 /*-----------------------------------------------------------------*/
10959 static void
10960 genFarFarAssign (operand * result, operand * right, iCode * ic)
10961 {
10962   int size = AOP_SIZE (right);
10963   int offset = 0;
10964   char *l;
10965
10966   D (emitcode (";", "genFarFarAssign"));
10967
10968   /* first push the right side on to the stack */
10969   while (size--)
10970     {
10971       l = aopGet (right, offset++, FALSE, FALSE);
10972       MOVA (l);
10973       emitcode ("push", "acc");
10974     }
10975
10976   freeAsmop (right, NULL, ic, FALSE);
10977   /* now assign DPTR to result */
10978   aopOp (result, ic, FALSE);
10979   size = AOP_SIZE (result);
10980   while (size--)
10981     {
10982       emitcode ("pop", "acc");
10983       aopPut (result, "a", --offset);
10984     }
10985   freeAsmop (result, NULL, ic, FALSE);
10986 }
10987
10988 /*-----------------------------------------------------------------*/
10989 /* genAssign - generate code for assignment                        */
10990 /*-----------------------------------------------------------------*/
10991 static void
10992 genAssign (iCode * ic)
10993 {
10994   operand *result, *right;
10995   int size, offset;
10996   unsigned long lit = 0L;
10997
10998   D (emitcode (";", "genAssign"));
10999
11000   result = IC_RESULT (ic);
11001   right = IC_RIGHT (ic);
11002
11003   /* if they are the same */
11004   if (operandsEqu (result, right) &&
11005       !isOperandVolatile (result, FALSE) &&
11006       !isOperandVolatile (right, FALSE))
11007     return;
11008
11009   aopOp (right, ic, FALSE);
11010
11011   /* special case both in far space */
11012   if (AOP_TYPE (right) == AOP_DPTR &&
11013       IS_TRUE_SYMOP (result) &&
11014       isOperandInFarSpace (result))
11015     {
11016       genFarFarAssign (result, right, ic);
11017       return;
11018     }
11019
11020   aopOp (result, ic, TRUE);
11021
11022   /* if they are the same registers */
11023   if (sameRegs (AOP (right), AOP (result)) &&
11024       !isOperandVolatile (result, FALSE) &&
11025       !isOperandVolatile (right, FALSE))
11026     goto release;
11027
11028   /* if the result is a bit */
11029   if (AOP_TYPE (result) == AOP_CRY)
11030     {
11031       /* if the right size is a literal then
11032          we know what the value is */
11033       if (AOP_TYPE (right) == AOP_LIT)
11034         {
11035           if (((int) operandLitValue (right)))
11036             aopPut (result, one, 0);
11037           else
11038             aopPut (result, zero, 0);
11039           goto release;
11040         }
11041
11042       /* the right is also a bit variable */
11043       if (AOP_TYPE (right) == AOP_CRY)
11044         {
11045           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11046           aopPut (result, "c", 0);
11047           goto release;
11048         }
11049
11050       /* we need to or */
11051       toBoolean (right);
11052       aopPut (result, "a", 0);
11053       goto release;
11054     }
11055
11056   /* bit variables done */
11057   /* general case */
11058   size = AOP_SIZE (result);
11059   offset = 0;
11060   if (AOP_TYPE (right) == AOP_LIT)
11061     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11062
11063   if ((size > 1) &&
11064       (AOP_TYPE (result) != AOP_REG) &&
11065       (AOP_TYPE (right) == AOP_LIT) &&
11066       !IS_FLOAT (operandType (right)) &&
11067       (lit < 256L))
11068     {
11069       while ((size) && (lit))
11070         {
11071           aopPut (result,
11072                   aopGet (right, offset, FALSE, FALSE),
11073                   offset);
11074           lit >>= 8;
11075           offset++;
11076           size--;
11077         }
11078       /* And now fill the rest with zeros. */
11079       if (size)
11080         {
11081           emitcode ("clr", "a");
11082         }
11083       while (size--)
11084         {
11085           aopPut (result, "a", offset);
11086           offset++;
11087         }
11088     }
11089   else
11090     {
11091       while (size--)
11092         {
11093           aopPut (result,
11094                   aopGet (right, offset, FALSE, FALSE),
11095                   offset);
11096           offset++;
11097         }
11098     }
11099
11100 release:
11101   freeAsmop (result, NULL, ic, TRUE);
11102   freeAsmop (right, NULL, ic, TRUE);
11103 }
11104
11105 /*-----------------------------------------------------------------*/
11106 /* genJumpTab - generates code for jump table                      */
11107 /*-----------------------------------------------------------------*/
11108 static void
11109 genJumpTab (iCode * ic)
11110 {
11111   symbol *jtab,*jtablo,*jtabhi;
11112   char *l;
11113   unsigned int count;
11114
11115   D (emitcode (";", "genJumpTab"));
11116
11117   count = elementsInSet( IC_JTLABELS (ic) );
11118
11119   if( count <= 16 )
11120     {
11121       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11122          if the switch argument is in a register.
11123          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11124       /* Peephole may not convert ljmp to sjmp or ret
11125          labelIsReturnOnly & labelInRange must check
11126          currPl->ic->op != JUMPTABLE */
11127       aopOp (IC_JTCOND (ic), ic, FALSE);
11128       /* get the condition into accumulator */
11129       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11130       MOVA (l);
11131       /* multiply by three */
11132       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11133         {
11134           emitcode ("mov", "b,#3");
11135           emitcode ("mul", "ab");
11136         }
11137       else
11138         {
11139           emitcode ("add", "a,acc");
11140           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11141         }
11142       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11143
11144       jtab = newiTempLabel (NULL);
11145       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11146       emitcode ("jmp", "@a+dptr");
11147       emitLabel (jtab);
11148       /* now generate the jump labels */
11149       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11150            jtab = setNextItem (IC_JTLABELS (ic)))
11151         emitcode ("ljmp", "%05d$", jtab->key + 100);
11152     }
11153   else
11154     {
11155       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11156          if the switch argument is in a register.
11157          For n>6 this algorithm may be more compact */
11158       jtablo = newiTempLabel (NULL);
11159       jtabhi = newiTempLabel (NULL);
11160
11161       /* get the condition into accumulator.
11162          Using b as temporary storage, if register push/pop is needed */
11163       aopOp (IC_JTCOND (ic), ic, FALSE);
11164       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11165       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11166           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11167         {
11168           // (MB) what if B is in use???
11169           wassertl(!BINUSE, "B was in use");
11170           emitcode ("mov", "b,%s", l);
11171           l = "b";
11172         }
11173       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11174       MOVA (l);
11175       if( count <= 112 )
11176         {
11177           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11178           emitcode ("movc", "a,@a+pc");
11179           emitcode ("push", "acc");
11180
11181           MOVA (l);
11182           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11183           emitcode ("movc", "a,@a+pc");
11184           emitcode ("push", "acc");
11185         }
11186       else
11187         {
11188           /* this scales up to n<=255, but needs two more bytes
11189              and changes dptr */
11190           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11191           emitcode ("movc", "a,@a+dptr");
11192           emitcode ("push", "acc");
11193
11194           MOVA (l);
11195           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11196           emitcode ("movc", "a,@a+dptr");
11197           emitcode ("push", "acc");
11198         }
11199
11200       emitcode ("ret", "");
11201
11202       /* now generate jump table, LSB */
11203       emitLabel (jtablo);
11204       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11205            jtab = setNextItem (IC_JTLABELS (ic)))
11206         emitcode (".db", "%05d$", jtab->key + 100);
11207
11208       /* now generate jump table, MSB */
11209       emitLabel (jtabhi);
11210       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11211            jtab = setNextItem (IC_JTLABELS (ic)))
11212          emitcode (".db", "%05d$>>8", jtab->key + 100);
11213     }
11214 }
11215
11216 /*-----------------------------------------------------------------*/
11217 /* genCast - gen code for casting                                  */
11218 /*-----------------------------------------------------------------*/
11219 static void
11220 genCast (iCode * ic)
11221 {
11222   operand *result = IC_RESULT (ic);
11223   sym_link *ctype = operandType (IC_LEFT (ic));
11224   sym_link *rtype = operandType (IC_RIGHT (ic));
11225   operand *right = IC_RIGHT (ic);
11226   int size, offset;
11227
11228   D (emitcode (";", "genCast"));
11229
11230   /* if they are equivalent then do nothing */
11231   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11232     return;
11233
11234   aopOp (right, ic, FALSE);
11235   aopOp (result, ic, FALSE);
11236
11237   /* if the result is a bit (and not a bitfield) */
11238   if (IS_BIT (OP_SYMBOL (result)->type))
11239     {
11240       /* if the right size is a literal then
11241          we know what the value is */
11242       if (AOP_TYPE (right) == AOP_LIT)
11243         {
11244           if (((int) operandLitValue (right)))
11245             aopPut (result, one, 0);
11246           else
11247             aopPut (result, zero, 0);
11248
11249           goto release;
11250         }
11251
11252       /* the right is also a bit variable */
11253       if (AOP_TYPE (right) == AOP_CRY)
11254         {
11255           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11256           aopPut (result, "c", 0);
11257           goto release;
11258         }
11259
11260       /* we need to or */
11261       toBoolean (right);
11262       aopPut (result, "a", 0);
11263       goto release;
11264     }
11265
11266   /* if they are the same size : or less */
11267   if (AOP_SIZE (result) <= AOP_SIZE (right))
11268     {
11269
11270       /* if they are in the same place */
11271       if (sameRegs (AOP (right), AOP (result)))
11272         goto release;
11273
11274       /* if they in different places then copy */
11275       size = AOP_SIZE (result);
11276       offset = 0;
11277       while (size--)
11278         {
11279           aopPut (result,
11280                   aopGet (right, offset, FALSE, FALSE),
11281                   offset);
11282           offset++;
11283         }
11284       goto release;
11285     }
11286
11287   /* if the result is of type pointer */
11288   if (IS_PTR (ctype))
11289     {
11290
11291       int p_type;
11292       sym_link *type = operandType (right);
11293       sym_link *etype = getSpec (type);
11294
11295       /* pointer to generic pointer */
11296       if (IS_GENPTR (ctype))
11297         {
11298           if (IS_PTR (type))
11299             {
11300               p_type = DCL_TYPE (type);
11301             }
11302           else
11303             {
11304               if (SPEC_SCLS(etype)==S_REGISTER) {
11305                 // let's assume it is a generic pointer
11306                 p_type=GPOINTER;
11307               } else {
11308                 /* we have to go by the storage class */
11309                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11310               }
11311             }
11312
11313           /* the first two bytes are known */
11314           size = GPTRSIZE - 1;
11315           offset = 0;
11316           while (size--)
11317             {
11318               aopPut (result,
11319                       aopGet (right, offset, FALSE, FALSE),
11320                       offset);
11321               offset++;
11322             }
11323           /* the last byte depending on type */
11324             {
11325                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11326                 char gpValStr[10];
11327
11328                 if (gpVal == -1)
11329                 {
11330                     // pointerTypeToGPByte will have bitched.
11331                     exit(1);
11332                 }
11333
11334                 sprintf(gpValStr, "#0x%x", gpVal);
11335                 aopPut (result, gpValStr, GPTRSIZE - 1);
11336             }
11337           goto release;
11338         }
11339
11340       /* just copy the pointers */
11341       size = AOP_SIZE (result);
11342       offset = 0;
11343       while (size--)
11344         {
11345           aopPut (result,
11346                   aopGet (right, offset, FALSE, FALSE),
11347                   offset);
11348           offset++;
11349         }
11350       goto release;
11351     }
11352
11353   /* so we now know that the size of destination is greater
11354      than the size of the source */
11355   /* we move to result for the size of source */
11356   size = AOP_SIZE (right);
11357   offset = 0;
11358   while (size--)
11359     {
11360       aopPut (result,
11361               aopGet (right, offset, FALSE, FALSE),
11362               offset);
11363       offset++;
11364     }
11365
11366   /* now depending on the sign of the source && destination */
11367   size = AOP_SIZE (result) - AOP_SIZE (right);
11368   /* if unsigned or not an integral type */
11369   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11370     {
11371       while (size--)
11372         aopPut (result, zero, offset++);
11373     }
11374   else
11375     {
11376       /* we need to extend the sign :{ */
11377       char *l = aopGet (right, AOP_SIZE (right) - 1,
11378                         FALSE, FALSE);
11379       MOVA (l);
11380       emitcode ("rlc", "a");
11381       emitcode ("subb", "a,acc");
11382       while (size--)
11383         aopPut (result, "a", offset++);
11384     }
11385
11386   /* we are done hurray !!!! */
11387
11388 release:
11389   freeAsmop (result, NULL, ic, TRUE);
11390   freeAsmop (right, NULL, ic, TRUE);
11391 }
11392
11393 /*-----------------------------------------------------------------*/
11394 /* genDjnz - generate decrement & jump if not zero instrucion      */
11395 /*-----------------------------------------------------------------*/
11396 static int
11397 genDjnz (iCode * ic, iCode * ifx)
11398 {
11399   symbol *lbl, *lbl1;
11400   if (!ifx)
11401     return 0;
11402
11403   /* if the if condition has a false label
11404      then we cannot save */
11405   if (IC_FALSE (ifx))
11406     return 0;
11407
11408   /* if the minus is not of the form a = a - 1 */
11409   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11410       !IS_OP_LITERAL (IC_RIGHT (ic)))
11411     return 0;
11412
11413   if (operandLitValue (IC_RIGHT (ic)) != 1)
11414     return 0;
11415
11416   /* if the size of this greater than one then no
11417      saving */
11418   if (getSize (operandType (IC_RESULT (ic))) > 1)
11419     return 0;
11420
11421   /* otherwise we can save BIG */
11422
11423   D (emitcode (";", "genDjnz"));
11424
11425   lbl = newiTempLabel (NULL);
11426   lbl1 = newiTempLabel (NULL);
11427
11428   aopOp (IC_RESULT (ic), ic, FALSE);
11429
11430   if (AOP_NEEDSACC(IC_RESULT(ic)))
11431   {
11432       /* If the result is accessed indirectly via
11433        * the accumulator, we must explicitly write
11434        * it back after the decrement.
11435        */
11436       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11437
11438       if (strcmp(rByte, "a"))
11439       {
11440            /* Something is hopelessly wrong */
11441            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11442                    __FILE__, __LINE__);
11443            /* We can just give up; the generated code will be inefficient,
11444             * but what the hey.
11445             */
11446            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11447            return 0;
11448       }
11449       emitcode ("dec", "%s", rByte);
11450       aopPut (IC_RESULT (ic), rByte, 0);
11451       emitcode ("jnz", "%05d$", lbl->key + 100);
11452   }
11453   else if (IS_AOP_PREG (IC_RESULT (ic)))
11454     {
11455       emitcode ("dec", "%s",
11456                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11457       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11458       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11459       ifx->generated = 1;
11460       emitcode ("jnz", "%05d$", lbl->key + 100);
11461     }
11462   else
11463     {
11464       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11465                 lbl->key + 100);
11466     }
11467   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11468   emitLabel (lbl);
11469   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11470   emitLabel (lbl1);
11471
11472   if (!ifx->generated)
11473       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11474   ifx->generated = 1;
11475   return 1;
11476 }
11477
11478 /*-----------------------------------------------------------------*/
11479 /* genReceive - generate code for a receive iCode                  */
11480 /*-----------------------------------------------------------------*/
11481 static void
11482 genReceive (iCode * ic)
11483 {
11484   int size = getSize (operandType (IC_RESULT (ic)));
11485   int offset = 0;
11486
11487   D (emitcode (";", "genReceive"));
11488
11489   if (ic->argreg == 1)
11490     { /* first parameter */
11491       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11492            isOperandInPagedSpace (IC_RESULT (ic))) &&
11493           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11494            IS_TRUE_SYMOP (IC_RESULT (ic))))
11495         {
11496           regs *tempRegs[4];
11497           int receivingA = 0;
11498           int roffset = 0;
11499
11500           for (offset = 0; offset<size; offset++)
11501             if (!strcmp (fReturn[offset], "a"))
11502               receivingA = 1;
11503
11504           if (!receivingA)
11505             {
11506               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11507                 {
11508                   for (offset = size-1; offset>0; offset--)
11509                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11510                   emitcode("mov","a,%s", fReturn[0]);
11511                   _G.accInUse++;
11512                   aopOp (IC_RESULT (ic), ic, FALSE);
11513                   _G.accInUse--;
11514                   aopPut (IC_RESULT (ic), "a", offset);
11515                   for (offset = 1; offset<size; offset++)
11516                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11517                   goto release;
11518                 }
11519             }
11520           else
11521             {
11522               if (getTempRegs(tempRegs, size, ic))
11523                 {
11524                   for (offset = 0; offset<size; offset++)
11525                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11526                   aopOp (IC_RESULT (ic), ic, FALSE);
11527                   for (offset = 0; offset<size; offset++)
11528                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11529                   goto release;
11530                 }
11531             }
11532
11533           offset = fReturnSizeMCS51 - size;
11534           while (size--)
11535             {
11536               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11537                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11538               offset++;
11539             }
11540           aopOp (IC_RESULT (ic), ic, FALSE);
11541           size = AOP_SIZE (IC_RESULT (ic));
11542           offset = 0;
11543           while (size--)
11544             {
11545               emitcode ("pop", "acc");
11546               aopPut (IC_RESULT (ic), "a", offset++);
11547             }
11548         }
11549       else
11550         {
11551           _G.accInUse++;
11552           aopOp (IC_RESULT (ic), ic, FALSE);
11553           _G.accInUse--;
11554           assignResultValue (IC_RESULT (ic), NULL);
11555         }
11556     }
11557   else if (ic->argreg > 12)
11558     { /* bit parameters */
11559       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11560         {
11561           aopOp (IC_RESULT (ic), ic, FALSE);
11562           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11563           outBitC(IC_RESULT (ic));
11564         }
11565     }
11566   else
11567     { /* other parameters */
11568       int rb1off ;
11569       aopOp (IC_RESULT (ic), ic, FALSE);
11570       rb1off = ic->argreg;
11571       while (size--)
11572         {
11573           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11574         }
11575     }
11576
11577 release:
11578   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11579 }
11580
11581 /*-----------------------------------------------------------------*/
11582 /* genDummyRead - generate code for dummy read of volatiles        */
11583 /*-----------------------------------------------------------------*/
11584 static void
11585 genDummyRead (iCode * ic)
11586 {
11587   operand *op;
11588   int size, offset;
11589
11590   D (emitcode(";", "genDummyRead"));
11591
11592   op = IC_RIGHT (ic);
11593   if (op && IS_SYMOP (op))
11594     {
11595       aopOp (op, ic, FALSE);
11596
11597       /* if the result is a bit */
11598       if (AOP_TYPE (op) == AOP_CRY)
11599         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11600       else
11601         {
11602           /* bit variables done */
11603           /* general case */
11604           size = AOP_SIZE (op);
11605           offset = 0;
11606           while (size--)
11607           {
11608             MOVA (aopGet (op, offset, FALSE, FALSE));
11609             offset++;
11610           }
11611         }
11612
11613       freeAsmop (op, NULL, ic, TRUE);
11614     }
11615
11616   op = IC_LEFT (ic);
11617   if (op && IS_SYMOP (op))
11618     {
11619       aopOp (op, ic, FALSE);
11620
11621       /* if the result is a bit */
11622       if (AOP_TYPE (op) == AOP_CRY)
11623         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11624       else
11625         {
11626           /* bit variables done */
11627           /* general case */
11628           size = AOP_SIZE (op);
11629           offset = 0;
11630           while (size--)
11631           {
11632             MOVA (aopGet (op, offset, FALSE, FALSE));
11633             offset++;
11634           }
11635         }
11636
11637       freeAsmop (op, NULL, ic, TRUE);
11638     }
11639 }
11640
11641 /*-----------------------------------------------------------------*/
11642 /* genCritical - generate code for start of a critical sequence    */
11643 /*-----------------------------------------------------------------*/
11644 static void
11645 genCritical (iCode *ic)
11646 {
11647   symbol *tlbl = newiTempLabel (NULL);
11648
11649   D (emitcode(";", "genCritical"));
11650
11651   if (IC_RESULT (ic))
11652     {
11653       aopOp (IC_RESULT (ic), ic, TRUE);
11654       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11655       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11656       aopPut (IC_RESULT (ic), zero, 0);
11657       emitLabel (tlbl);
11658       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11659     }
11660   else
11661     {
11662       emitcode ("setb", "c");
11663       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11664       emitcode ("clr", "c");
11665       emitLabel (tlbl);
11666       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11667     }
11668 }
11669
11670 /*-----------------------------------------------------------------*/
11671 /* genEndCritical - generate code for end of a critical sequence   */
11672 /*-----------------------------------------------------------------*/
11673 static void
11674 genEndCritical (iCode *ic)
11675 {
11676   D(emitcode(";     genEndCritical",""));
11677
11678   if (IC_RIGHT (ic))
11679     {
11680       aopOp (IC_RIGHT (ic), ic, FALSE);
11681       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11682         {
11683           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11684           emitcode ("mov", "ea,c");
11685         }
11686       else
11687         {
11688           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11689             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11690           emitcode ("rrc", "a");
11691           emitcode ("mov", "ea,c");
11692         }
11693       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11694     }
11695   else
11696     {
11697       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11698       emitcode ("mov", "ea,c");
11699     }
11700 }
11701
11702 /*-----------------------------------------------------------------*/
11703 /* gen51Code - generate code for 8051 based controllers            */
11704 /*-----------------------------------------------------------------*/
11705 void
11706 gen51Code (iCode * lic)
11707 {
11708   iCode *ic;
11709   int cln = 0;
11710   /* int cseq = 0; */
11711
11712   _G.currentFunc = NULL;
11713   lineHead = lineCurr = NULL;
11714
11715   /* print the allocation information */
11716   if (allocInfo && currFunc)
11717     printAllocInfo (currFunc, codeOutBuf);
11718   /* if debug information required */
11719   if (options.debug && currFunc)
11720     {
11721       debugFile->writeFunction (currFunc, lic);
11722     }
11723   /* stack pointer name */
11724   if (options.useXstack)
11725     spname = "_spx";
11726   else
11727     spname = "sp";
11728
11729
11730   for (ic = lic; ic; ic = ic->next)
11731     {
11732       _G.current_iCode = ic;
11733
11734       if (ic->lineno && cln != ic->lineno)
11735         {
11736           if (options.debug)
11737             {
11738               debugFile->writeCLine (ic);
11739             }
11740           if (!options.noCcodeInAsm) {
11741             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11742                       printCLine(ic->filename, ic->lineno));
11743           }
11744           cln = ic->lineno;
11745         }
11746       #if 0
11747       if (ic->seqPoint && ic->seqPoint != cseq)
11748         {
11749           emitcode ("", "; sequence point %d", ic->seqPoint);
11750           cseq = ic->seqPoint;
11751         }
11752       #endif
11753       if (options.iCodeInAsm) {
11754         char regsInUse[80];
11755         int i;
11756         char *iLine;
11757
11758         #if 0
11759         for (i=0; i<8; i++) {
11760           sprintf (&regsInUse[i],
11761                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11762         regsInUse[i]=0;
11763         #else
11764         strcpy (regsInUse, "--------");
11765         for (i=0; i < 8; i++) {
11766           if (bitVectBitValue (ic->rMask, i))
11767             {
11768               int offset = regs8051[i].offset;
11769               regsInUse[offset] = offset + '0'; /* show rMask */
11770             }
11771         #endif
11772         }
11773         iLine = printILine(ic);
11774         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11775         dbuf_free(iLine);
11776       }
11777       /* if the result is marked as
11778          spilt and rematerializable or code for
11779          this has already been generated then
11780          do nothing */
11781       if (resultRemat (ic) || ic->generated)
11782         continue;
11783
11784       /* depending on the operation */
11785       switch (ic->op)
11786         {
11787         case '!':
11788           genNot (ic);
11789           break;
11790
11791         case '~':
11792           genCpl (ic);
11793           break;
11794
11795         case UNARYMINUS:
11796           genUminus (ic);
11797           break;
11798
11799         case IPUSH:
11800           genIpush (ic);
11801           break;
11802
11803         case IPOP:
11804           /* IPOP happens only when trying to restore a
11805              spilt live range, if there is an ifx statement
11806              following this pop then the if statement might
11807              be using some of the registers being popped which
11808              would destory the contents of the register so
11809              we need to check for this condition and handle it */
11810           if (ic->next &&
11811               ic->next->op == IFX &&
11812               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11813             genIfx (ic->next, ic);
11814           else
11815             genIpop (ic);
11816           break;
11817
11818         case CALL:
11819           genCall (ic);
11820           break;
11821
11822         case PCALL:
11823           genPcall (ic);
11824           break;
11825
11826         case FUNCTION:
11827           genFunction (ic);
11828           break;
11829
11830         case ENDFUNCTION:
11831           genEndFunction (ic);
11832           break;
11833
11834         case RETURN:
11835           genRet (ic);
11836           break;
11837
11838         case LABEL:
11839           genLabel (ic);
11840           break;
11841
11842         case GOTO:
11843           genGoto (ic);
11844           break;
11845
11846         case '+':
11847           genPlus (ic);
11848           break;
11849
11850         case '-':
11851           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11852             genMinus (ic);
11853           break;
11854
11855         case '*':
11856           genMult (ic);
11857           break;
11858
11859         case '/':
11860           genDiv (ic);
11861           break;
11862
11863         case '%':
11864           genMod (ic);
11865           break;
11866
11867         case '>':
11868           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11869           break;
11870
11871         case '<':
11872           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11873           break;
11874
11875         case LE_OP:
11876         case GE_OP:
11877         case NE_OP:
11878
11879           /* note these two are xlated by algebraic equivalence
11880              in decorateType() in SDCCast.c */
11881           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11882                   "got '>=' or '<=' shouldn't have come here");
11883           break;
11884
11885         case EQ_OP:
11886           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11887           break;
11888
11889         case AND_OP:
11890           genAndOp (ic);
11891           break;
11892
11893         case OR_OP:
11894           genOrOp (ic);
11895           break;
11896
11897         case '^':
11898           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11899           break;
11900
11901         case '|':
11902           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11903           break;
11904
11905         case BITWISEAND:
11906           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11907           break;
11908
11909         case INLINEASM:
11910           genInline (ic);
11911           break;
11912
11913         case RRC:
11914           genRRC (ic);
11915           break;
11916
11917         case RLC:
11918           genRLC (ic);
11919           break;
11920
11921         case GETHBIT:
11922           genGetHbit (ic);
11923           break;
11924
11925         case GETABIT:
11926           genGetAbit (ic);
11927           break;
11928
11929         case GETBYTE:
11930           genGetByte (ic);
11931           break;
11932
11933         case GETWORD:
11934           genGetWord (ic);
11935           break;
11936
11937         case LEFT_OP:
11938           genLeftShift (ic);
11939           break;
11940
11941         case RIGHT_OP:
11942           genRightShift (ic);
11943           break;
11944
11945         case GET_VALUE_AT_ADDRESS:
11946           genPointerGet (ic,
11947                          hasInc (IC_LEFT (ic), ic,
11948                                  getSize (operandType (IC_RESULT (ic)))),
11949                          ifxForOp (IC_RESULT (ic), ic) );
11950           break;
11951
11952         case '=':
11953           if (POINTER_SET (ic))
11954             genPointerSet (ic,
11955                            hasInc (IC_RESULT (ic), ic,
11956                                    getSize (operandType (IC_RIGHT (ic)))));
11957           else
11958             genAssign (ic);
11959           break;
11960
11961         case IFX:
11962           genIfx (ic, NULL);
11963           break;
11964
11965         case ADDRESS_OF:
11966           genAddrOf (ic);
11967           break;
11968
11969         case JUMPTABLE:
11970           genJumpTab (ic);
11971           break;
11972
11973         case CAST:
11974           genCast (ic);
11975           break;
11976
11977         case RECEIVE:
11978           genReceive (ic);
11979           break;
11980
11981         case SEND:
11982           addSet (&_G.sendSet, ic);
11983           break;
11984
11985         case DUMMY_READ_VOLATILE:
11986           genDummyRead (ic);
11987           break;
11988
11989         case CRITICAL:
11990           genCritical (ic);
11991           break;
11992
11993         case ENDCRITICAL:
11994           genEndCritical (ic);
11995           break;
11996
11997         case SWAP:
11998           genSwap (ic);
11999           break;
12000
12001         default:
12002           ic = ic;
12003         }
12004     }
12005
12006   _G.current_iCode = NULL;
12007
12008   /* now we are ready to call the
12009      peep hole optimizer */
12010   if (!options.nopeep)
12011     peepHole (&lineHead);
12012
12013   /* now do the actual printing */
12014   printLine (lineHead, codeOutBuf);
12015   return;
12016 }