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