src/mcs51/gen.c (genRet): fixed RFE 1652561: added code for bit to bit moves in retur...
[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       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
3987         emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3988       else
3989         movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3990     }
3991   else
3992     {
3993       while (size--)
3994         {
3995           char *l;
3996           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3997             {
3998               /* #NOCHANGE */
3999               l = aopGet (IC_LEFT (ic), offset++,
4000                           FALSE, TRUE);
4001               emitcode ("push", "%s", l);
4002               pushed++;
4003             }
4004           else
4005             {
4006               l = aopGet (IC_LEFT (ic), offset,
4007                           FALSE, FALSE);
4008               if (strcmp (fReturn[offset], l))
4009                 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4010             }
4011         }
4012
4013       while (pushed)
4014         {
4015           pushed--;
4016           if (strcmp (fReturn[pushed], "a"))
4017             emitcode ("pop", fReturn[pushed]);
4018           else
4019             emitcode ("pop", "acc");
4020         }
4021     }
4022   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4023
4024 jumpret:
4025   /* generate a jump to the return label
4026      if the next is not the return statement */
4027   if (!(ic->next && ic->next->op == LABEL &&
4028         IC_LABEL (ic->next) == returnLabel))
4029
4030     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4031
4032 }
4033
4034 /*-----------------------------------------------------------------*/
4035 /* genLabel - generates a label                                    */
4036 /*-----------------------------------------------------------------*/
4037 static void
4038 genLabel (iCode * ic)
4039 {
4040   /* special case never generate */
4041   if (IC_LABEL (ic) == entryLabel)
4042     return;
4043
4044   emitLabel (IC_LABEL (ic));
4045 }
4046
4047 /*-----------------------------------------------------------------*/
4048 /* genGoto - generates a ljmp                                      */
4049 /*-----------------------------------------------------------------*/
4050 static void
4051 genGoto (iCode * ic)
4052 {
4053   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4054 }
4055
4056 /*-----------------------------------------------------------------*/
4057 /* findLabelBackwards: walks back through the iCode chain looking  */
4058 /* for the given label. Returns number of iCode instructions     */
4059 /* between that label and given ic.          */
4060 /* Returns zero if label not found.          */
4061 /*-----------------------------------------------------------------*/
4062 static int
4063 findLabelBackwards (iCode * ic, int key)
4064 {
4065   int count = 0;
4066
4067   while (ic->prev)
4068     {
4069       ic = ic->prev;
4070       count++;
4071
4072       /* If we have any pushes or pops, we cannot predict the distance.
4073          I don't like this at all, this should be dealt with in the
4074          back-end */
4075       if (ic->op == IPUSH || ic->op == IPOP) {
4076         return 0;
4077       }
4078
4079       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4080         {
4081           return count;
4082         }
4083     }
4084
4085   return 0;
4086 }
4087
4088 /*-----------------------------------------------------------------*/
4089 /* genPlusIncr :- does addition with increment if possible         */
4090 /*-----------------------------------------------------------------*/
4091 static bool
4092 genPlusIncr (iCode * ic)
4093 {
4094   unsigned int icount;
4095   unsigned int size = getDataSize (IC_RESULT (ic));
4096
4097   /* will try to generate an increment */
4098   /* if the right side is not a literal
4099      we cannot */
4100   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4101     return FALSE;
4102
4103   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4104
4105   D(emitcode (";","genPlusIncr"));
4106
4107   /* if increment >=16 bits in register or direct space */
4108   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4109         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4110         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4111       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4112       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4113       (size > 1) &&
4114       (icount == 1))
4115     {
4116       symbol *tlbl;
4117       int emitTlbl;
4118       int labelRange;
4119
4120       /* If the next instruction is a goto and the goto target
4121        * is < 10 instructions previous to this, we can generate
4122        * jumps straight to that target.
4123        */
4124       if (ic->next && ic->next->op == GOTO
4125           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4126           && labelRange <= 10)
4127         {
4128           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4129           tlbl = IC_LABEL (ic->next);
4130           emitTlbl = 0;
4131         }
4132       else
4133         {
4134           tlbl = newiTempLabel (NULL);
4135           emitTlbl = 1;
4136         }
4137       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4138       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4139           IS_AOP_PREG (IC_RESULT (ic)))
4140         emitcode ("cjne", "%s,#0x00,%05d$",
4141                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4142                   tlbl->key + 100);
4143       else
4144         {
4145           emitcode ("clr", "a");
4146           emitcode ("cjne", "a,%s,%05d$",
4147                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4148                     tlbl->key + 100);
4149         }
4150
4151       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4152       if (size > 2)
4153         {
4154           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4155               IS_AOP_PREG (IC_RESULT (ic)))
4156             emitcode ("cjne", "%s,#0x00,%05d$",
4157                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4158                       tlbl->key + 100);
4159           else
4160             emitcode ("cjne", "a,%s,%05d$",
4161                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4162                       tlbl->key + 100);
4163
4164           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4165         }
4166       if (size > 3)
4167         {
4168           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4169               IS_AOP_PREG (IC_RESULT (ic)))
4170             emitcode ("cjne", "%s,#0x00,%05d$",
4171                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4172                       tlbl->key + 100);
4173           else
4174             {
4175               emitcode ("cjne", "a,%s,%05d$",
4176                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4177                         tlbl->key + 100);
4178             }
4179           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4180         }
4181
4182       if (emitTlbl)
4183         {
4184           emitLabel (tlbl);
4185         }
4186       return TRUE;
4187     }
4188
4189   /* if result is dptr */
4190   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4191       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4192       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4193       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4194     {
4195       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4196         return FALSE;
4197
4198       if (icount > 9)
4199         return FALSE;
4200
4201       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4202         return FALSE;
4203
4204       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4205       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4206       while (icount--)
4207         emitcode ("inc", "dptr");
4208
4209       return TRUE;
4210     }
4211
4212   /* if the literal value of the right hand side
4213      is greater than 4 then it is not worth it */
4214   if (icount > 4)
4215     return FALSE;
4216
4217   /* if the sizes are greater than 1 then we cannot */
4218   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4219       AOP_SIZE (IC_LEFT (ic)) > 1)
4220     return FALSE;
4221
4222   /* we can if the aops of the left & result match or
4223      if they are in registers and the registers are the
4224      same */
4225   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4226     {
4227       if (icount > 3)
4228         {
4229           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4230           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4231           aopPut (IC_RESULT (ic), "a", 0);
4232         }
4233       else
4234         {
4235           while (icount--)
4236             {
4237               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4238             }
4239         }
4240
4241       return TRUE;
4242     }
4243
4244   if (icount == 1)
4245     {
4246       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4247       emitcode ("inc", "a");
4248       aopPut (IC_RESULT (ic), "a", 0);
4249       return TRUE;
4250     }
4251
4252   return FALSE;
4253 }
4254
4255 /*-----------------------------------------------------------------*/
4256 /* outBitAcc - output a bit in acc                                 */
4257 /*-----------------------------------------------------------------*/
4258 static void
4259 outBitAcc (operand * result)
4260 {
4261   symbol *tlbl = newiTempLabel (NULL);
4262   /* if the result is a bit */
4263   if (AOP_TYPE (result) == AOP_CRY)
4264     {
4265       aopPut (result, "a", 0);
4266     }
4267   else
4268     {
4269       emitcode ("jz", "%05d$", tlbl->key + 100);
4270       emitcode ("mov", "a,%s", one);
4271       emitLabel (tlbl);
4272       outAcc (result);
4273     }
4274 }
4275
4276 /*-----------------------------------------------------------------*/
4277 /* genPlusBits - generates code for addition of two bits           */
4278 /*-----------------------------------------------------------------*/
4279 static void
4280 genPlusBits (iCode * ic)
4281 {
4282   D (emitcode (";", "genPlusBits"));
4283
4284   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4285     {
4286       symbol *lbl = newiTempLabel (NULL);
4287       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4288       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4289       emitcode ("cpl", "c");
4290       emitLabel (lbl);
4291       outBitC (IC_RESULT (ic));
4292     }
4293   else
4294     {
4295       emitcode ("clr", "a");
4296       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4297       emitcode ("rlc", "a");
4298       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4299       emitcode ("addc", "a,%s", zero);
4300       outAcc (IC_RESULT (ic));
4301     }
4302 }
4303
4304 #if 0
4305 /* This is the original version of this code.
4306
4307  * This is being kept around for reference,
4308  * because I am not entirely sure I got it right...
4309  */
4310 static void
4311 adjustArithmeticResult (iCode * ic)
4312 {
4313   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4314       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4315       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4316     aopPut (IC_RESULT (ic),
4317             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4318             2);
4319
4320   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4321       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4322       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4323     aopPut (IC_RESULT (ic),
4324             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4325             2);
4326
4327   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4328       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4329       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4330       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4331       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4332     {
4333       char buffer[5];
4334       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4335       aopPut (IC_RESULT (ic), buffer, 2);
4336     }
4337 }
4338 #else
4339 /* This is the pure and virtuous version of this code.
4340  * I'm pretty certain it's right, but not enough to toss the old
4341  * code just yet...
4342  */
4343 static void
4344 adjustArithmeticResult (iCode * ic)
4345 {
4346   if (opIsGptr (IC_RESULT (ic)) &&
4347       opIsGptr (IC_LEFT (ic)) &&
4348       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4349     {
4350       aopPut (IC_RESULT (ic),
4351               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4352               GPTRSIZE - 1);
4353     }
4354
4355   if (opIsGptr (IC_RESULT (ic)) &&
4356       opIsGptr (IC_RIGHT (ic)) &&
4357       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4358     {
4359       aopPut (IC_RESULT (ic),
4360               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4361               GPTRSIZE - 1);
4362     }
4363
4364   if (opIsGptr (IC_RESULT (ic)) &&
4365       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4366       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4367       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4368       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4369     {
4370       char buffer[5];
4371       SNPRINTF (buffer, sizeof(buffer),
4372                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4373       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4374     }
4375 }
4376 #endif
4377
4378 /*-----------------------------------------------------------------*/
4379 /* genPlus - generates code for addition                           */
4380 /*-----------------------------------------------------------------*/
4381 static void
4382 genPlus (iCode * ic)
4383 {
4384   int size, offset = 0;
4385   int skip_bytes = 0;
4386   char *add = "add";
4387   bool swappedLR = FALSE;
4388   operand *leftOp, *rightOp;
4389   operand * op;
4390
4391   D (emitcode (";", "genPlus"));
4392
4393   /* special cases :- */
4394
4395   aopOp (IC_LEFT (ic), ic, FALSE);
4396   aopOp (IC_RIGHT (ic), ic, FALSE);
4397   aopOp (IC_RESULT (ic), ic, TRUE);
4398
4399   /* if literal, literal on the right or
4400      if left requires ACC or right is already
4401      in ACC */
4402   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4403       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4404       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4405     {
4406       operand *t = IC_RIGHT (ic);
4407       IC_RIGHT (ic) = IC_LEFT (ic);
4408       IC_LEFT (ic) = t;
4409       swappedLR = TRUE;
4410     }
4411
4412   /* if both left & right are in bit
4413      space */
4414   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4415       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4416     {
4417       genPlusBits (ic);
4418       goto release;
4419     }
4420
4421   /* if left in bit space & right literal */
4422   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4423       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4424     {
4425       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4426       /* if result in bit space */
4427       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4428         {
4429           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4430             emitcode ("cpl", "c");
4431           outBitC (IC_RESULT (ic));
4432         }
4433       else
4434         {
4435           size = getDataSize (IC_RESULT (ic));
4436           while (size--)
4437             {
4438               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4439               emitcode ("addc", "a,%s", zero);
4440               aopPut (IC_RESULT (ic), "a", offset++);
4441             }
4442         }
4443       goto release;
4444     }
4445
4446   /* if I can do an increment instead
4447      of add then GOOD for ME */
4448   if (genPlusIncr (ic) == TRUE)
4449     goto release;
4450
4451   size = getDataSize (IC_RESULT (ic));
4452   leftOp = IC_LEFT(ic);
4453   rightOp = IC_RIGHT(ic);
4454   op = IC_LEFT(ic);
4455
4456   /* if this is an add for an array access
4457      at a 256 byte boundary */
4458   if ( 2 == size
4459        && AOP_TYPE (op) == AOP_IMMD
4460        && IS_SYMOP (op)
4461        && IS_SPEC (OP_SYM_ETYPE (op))
4462        && SPEC_ABSA (OP_SYM_ETYPE (op))
4463        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4464      )
4465     {
4466       D(emitcode (";     genPlus aligned array",""));
4467       aopPut (IC_RESULT (ic),
4468               aopGet (rightOp, 0, FALSE, FALSE),
4469               0);
4470
4471       if( 1 == getDataSize (IC_RIGHT (ic)) )
4472         {
4473           aopPut (IC_RESULT (ic),
4474                   aopGet (leftOp, 1, FALSE, FALSE),
4475                   1);
4476         }
4477       else
4478         {
4479           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4480           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4481           aopPut (IC_RESULT (ic), "a", 1);
4482         }
4483       goto release;
4484     }
4485
4486   /* if the lower bytes of a literal are zero skip the addition */
4487   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4488     {
4489        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4490               (skip_bytes+1 < size))
4491          {
4492            skip_bytes++;
4493          }
4494        if (skip_bytes)
4495          D(emitcode (";     genPlus shortcut",""));
4496     }
4497
4498   while (size--)
4499     {
4500       if( offset >= skip_bytes )
4501         {
4502           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4503             {
4504               bool pushedB;
4505               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4506               pushedB = pushB ();
4507               emitcode("xch", "a,b");
4508               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4509               emitcode (add, "a,b");
4510               popB (pushedB);
4511             }
4512           else if (aopGetUsesAcc (leftOp, offset))
4513             {
4514               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4515               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4516             }
4517           else
4518             {
4519               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4520               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4521             }
4522           aopPut (IC_RESULT (ic), "a", offset);
4523           add = "addc";  /* further adds must propagate carry */
4524         }
4525       else
4526         {
4527           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4528               isOperandVolatile (IC_RESULT (ic), FALSE))
4529             {
4530               /* just move */
4531               aopPut (IC_RESULT (ic),
4532                       aopGet (leftOp, offset, FALSE, FALSE),
4533                       offset);
4534             }
4535         }
4536       offset++;
4537     }
4538
4539   adjustArithmeticResult (ic);
4540
4541 release:
4542   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4543   if (!swappedLR)
4544     {
4545       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4546       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4547     }
4548   else
4549     {
4550       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4551       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4552     }
4553 }
4554
4555 /*-----------------------------------------------------------------*/
4556 /* genMinusDec :- does subtraction with decrement if possible      */
4557 /*-----------------------------------------------------------------*/
4558 static bool
4559 genMinusDec (iCode * ic)
4560 {
4561   unsigned int icount;
4562   unsigned int size = getDataSize (IC_RESULT (ic));
4563
4564   /* will try to generate an increment */
4565   /* if the right side is not a literal
4566      we cannot */
4567   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4568     return FALSE;
4569
4570   /* if the literal value of the right hand side
4571      is greater than 4 then it is not worth it */
4572   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4573     return FALSE;
4574
4575   D (emitcode (";", "genMinusDec"));
4576
4577   /* if decrement >=16 bits in register or direct space */
4578   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4579         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4580         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4581       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4582       (size > 1) &&
4583       (icount == 1))
4584     {
4585       symbol *tlbl;
4586       int emitTlbl;
4587       int labelRange;
4588
4589       /* If the next instruction is a goto and the goto target
4590        * is <= 10 instructions previous to this, we can generate
4591        * jumps straight to that target.
4592        */
4593       if (ic->next && ic->next->op == GOTO
4594           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4595           && labelRange <= 10)
4596         {
4597           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4598           tlbl = IC_LABEL (ic->next);
4599           emitTlbl = 0;
4600         }
4601       else
4602         {
4603           tlbl = newiTempLabel (NULL);
4604           emitTlbl = 1;
4605         }
4606
4607       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4608       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4609           IS_AOP_PREG (IC_RESULT (ic)))
4610         emitcode ("cjne", "%s,#0xff,%05d$"
4611                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4612                   ,tlbl->key + 100);
4613       else
4614         {
4615           emitcode ("mov", "a,#0xff");
4616           emitcode ("cjne", "a,%s,%05d$"
4617                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4618                     ,tlbl->key + 100);
4619         }
4620       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4621       if (size > 2)
4622         {
4623           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4624               IS_AOP_PREG (IC_RESULT (ic)))
4625             emitcode ("cjne", "%s,#0xff,%05d$"
4626                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4627                       ,tlbl->key + 100);
4628           else
4629             {
4630               emitcode ("cjne", "a,%s,%05d$"
4631                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4632                         ,tlbl->key + 100);
4633             }
4634           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4635         }
4636       if (size > 3)
4637         {
4638           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4639               IS_AOP_PREG (IC_RESULT (ic)))
4640             emitcode ("cjne", "%s,#0xff,%05d$"
4641                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4642                       ,tlbl->key + 100);
4643           else
4644             {
4645               emitcode ("cjne", "a,%s,%05d$"
4646                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4647                         ,tlbl->key + 100);
4648             }
4649           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4650         }
4651       if (emitTlbl)
4652         {
4653           emitLabel (tlbl);
4654         }
4655       return TRUE;
4656     }
4657
4658   /* if the sizes are greater than 1 then we cannot */
4659   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4660       AOP_SIZE (IC_LEFT (ic)) > 1)
4661     return FALSE;
4662
4663   /* we can if the aops of the left & result match or
4664      if they are in registers and the registers are the
4665      same */
4666   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4667     {
4668       char *l;
4669
4670       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4671         {
4672           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4673           l = "a";
4674         }
4675       else
4676         {
4677           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4678         }
4679
4680       while (icount--)
4681         {
4682           emitcode ("dec", "%s", l);
4683         }
4684
4685       if (AOP_NEEDSACC (IC_RESULT (ic)))
4686         aopPut (IC_RESULT (ic), "a", 0);
4687
4688       return TRUE;
4689     }
4690
4691   if (icount == 1)
4692     {
4693       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4694       emitcode ("dec", "a");
4695       aopPut (IC_RESULT (ic), "a", 0);
4696       return TRUE;
4697     }
4698
4699   return FALSE;
4700 }
4701
4702 /*-----------------------------------------------------------------*/
4703 /* addSign - complete with sign                                    */
4704 /*-----------------------------------------------------------------*/
4705 static void
4706 addSign (operand * result, int offset, int sign)
4707 {
4708   int size = (getDataSize (result) - offset);
4709   if (size > 0)
4710     {
4711       if (sign)
4712         {
4713           emitcode ("rlc", "a");
4714           emitcode ("subb", "a,acc");
4715           while (size--)
4716             {
4717               aopPut (result, "a", offset++);
4718             }
4719         }
4720       else
4721         {
4722           while (size--)
4723             {
4724               aopPut (result, zero, offset++);
4725             }
4726         }
4727     }
4728 }
4729
4730 /*-----------------------------------------------------------------*/
4731 /* genMinusBits - generates code for subtraction  of two bits      */
4732 /*-----------------------------------------------------------------*/
4733 static void
4734 genMinusBits (iCode * ic)
4735 {
4736   symbol *lbl = newiTempLabel (NULL);
4737
4738   D (emitcode (";", "genMinusBits"));
4739
4740   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4741     {
4742       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4743       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4744       emitcode ("cpl", "c");
4745       emitLabel (lbl);
4746       outBitC (IC_RESULT (ic));
4747     }
4748   else
4749     {
4750       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4751       emitcode ("subb", "a,acc");
4752       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4753       emitcode ("inc", "a");
4754       emitLabel (lbl);
4755       aopPut (IC_RESULT (ic), "a", 0);
4756       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4757     }
4758 }
4759
4760 /*-----------------------------------------------------------------*/
4761 /* genMinus - generates code for subtraction                       */
4762 /*-----------------------------------------------------------------*/
4763 static void
4764 genMinus (iCode * ic)
4765 {
4766   int size, offset = 0;
4767
4768   D (emitcode (";", "genMinus"));
4769
4770   aopOp (IC_LEFT (ic), ic, FALSE);
4771   aopOp (IC_RIGHT (ic), ic, FALSE);
4772   aopOp (IC_RESULT (ic), ic, TRUE);
4773
4774   /* special cases :- */
4775   /* if both left & right are in bit space */
4776   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4777       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4778     {
4779       genMinusBits (ic);
4780       goto release;
4781     }
4782
4783   /* if I can do an decrement instead
4784      of subtract then GOOD for ME */
4785   if (genMinusDec (ic) == TRUE)
4786     goto release;
4787
4788   size = getDataSize (IC_RESULT (ic));
4789
4790   /* if literal, add a,#-lit, else normal subb */
4791   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4792     {
4793       unsigned long lit = 0L;
4794       bool useCarry = FALSE;
4795
4796       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4797       lit = -(long) lit;
4798
4799       while (size--)
4800         {
4801           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4802             {
4803               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4804               if (!offset && !size && lit== (unsigned long) -1)
4805                 {
4806                   emitcode ("dec", "a");
4807                 }
4808               else if (!useCarry)
4809                 {
4810                   /* first add without previous c */
4811                   emitcode ("add", "a,#0x%02x",
4812                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4813                   useCarry = TRUE;
4814                 }
4815               else
4816                 {
4817                   emitcode ("addc", "a,#0x%02x",
4818                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4819                 }
4820               aopPut (IC_RESULT (ic), "a", offset++);
4821             }
4822           else
4823             {
4824               /* no need to add zeroes */
4825               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4826                 {
4827                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4828                           offset);
4829                 }
4830               offset++;
4831             }
4832         }
4833     }
4834   else
4835     {
4836       operand *leftOp, *rightOp;
4837
4838       leftOp = IC_LEFT(ic);
4839       rightOp = IC_RIGHT(ic);
4840
4841       while (size--)
4842         {
4843           if (aopGetUsesAcc(rightOp, offset)) {
4844             if (aopGetUsesAcc(leftOp, offset)) {
4845               bool pushedB;
4846
4847               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4848               pushedB = pushB ();
4849               emitcode ("mov", "b,a");
4850               if (offset == 0)
4851                 CLRC;
4852               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4853               emitcode ("subb", "a,b");
4854               popB (pushedB);
4855             } else {
4856               /* reverse subtraction with 2's complement */
4857               if (offset == 0)
4858                 emitcode( "setb", "c");
4859               else
4860                 emitcode( "cpl", "c");
4861               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4862               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4863               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4864               emitcode("cpl", "a");
4865               if (size) /* skip if last byte */
4866                 emitcode( "cpl", "c");
4867             }
4868           } else {
4869             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4870             if (offset == 0)
4871               CLRC;
4872             emitcode ("subb", "a,%s",
4873                       aopGet(rightOp, offset, FALSE, TRUE));
4874           }
4875
4876           aopPut (IC_RESULT (ic), "a", offset++);
4877         }
4878     }
4879
4880   adjustArithmeticResult (ic);
4881
4882 release:
4883   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4884   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4885   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4886 }
4887
4888
4889 /*-----------------------------------------------------------------*/
4890 /* genMultbits :- multiplication of bits                           */
4891 /*-----------------------------------------------------------------*/
4892 static void
4893 genMultbits (operand * left,
4894              operand * right,
4895              operand * result)
4896 {
4897   D (emitcode (";", "genMultbits"));
4898
4899   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4900   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4901   outBitC (result);
4902 }
4903
4904 /*-----------------------------------------------------------------*/
4905 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4906 /*-----------------------------------------------------------------*/
4907 static void
4908 genMultOneByte (operand * left,
4909                 operand * right,
4910                 operand * result)
4911 {
4912   symbol *lbl;
4913   int size = AOP_SIZE (result);
4914   bool runtimeSign, compiletimeSign;
4915   bool lUnsigned, rUnsigned, pushedB;
4916
4917   D (emitcode (";", "genMultOneByte"));
4918
4919   if (size < 1 || size > 2)
4920     {
4921       /* this should never happen */
4922       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4923                AOP_SIZE(result), __FILE__, lineno);
4924       exit (1);
4925     }
4926
4927   /* (if two literals: the value is computed before) */
4928   /* if one literal, literal on the right */
4929   if (AOP_TYPE (left) == AOP_LIT)
4930     {
4931       operand *t = right;
4932       right = left;
4933       left = t;
4934       /* emitcode (";", "swapped left and right"); */
4935     }
4936   /* if no literal, unsigned on the right: shorter code */
4937   if (   AOP_TYPE (right) != AOP_LIT
4938       && SPEC_USIGN (getSpec (operandType (left))))
4939     {
4940       operand *t = right;
4941       right = left;
4942       left = t;
4943     }
4944
4945   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4946   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4947
4948   pushedB = pushB ();
4949
4950   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4951                    no need to take care about the signedness! */
4952       || (lUnsigned && rUnsigned))
4953     {
4954       /* just an unsigned 8 * 8 = 8 multiply
4955          or 8u * 8u = 16u */
4956       /* emitcode (";","unsigned"); */
4957       /* TODO: check for accumulator clash between left & right aops? */
4958
4959       if (AOP_TYPE (right) == AOP_LIT)
4960         {
4961           /* moving to accumulator first helps peepholes */
4962           MOVA (aopGet (left, 0, FALSE, FALSE));
4963           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4964         }
4965       else
4966         {
4967           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4968           MOVA (aopGet (left, 0, FALSE, FALSE));
4969         }
4970
4971       emitcode ("mul", "ab");
4972       aopPut (result, "a", 0);
4973       if (size == 2)
4974         aopPut (result, "b", 1);
4975
4976       popB (pushedB);
4977       return;
4978     }
4979
4980   /* we have to do a signed multiply */
4981   /* emitcode (";", "signed"); */
4982
4983   /* now sign adjust for both left & right */
4984
4985   /* let's see what's needed: */
4986   /* apply negative sign during runtime */
4987   runtimeSign = FALSE;
4988   /* negative sign from literals */
4989   compiletimeSign = FALSE;
4990
4991   if (!lUnsigned)
4992     {
4993       if (AOP_TYPE(left) == AOP_LIT)
4994         {
4995           /* signed literal */
4996           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4997           if (val < 0)
4998             compiletimeSign = TRUE;
4999         }
5000       else
5001         /* signed but not literal */
5002         runtimeSign = TRUE;
5003     }
5004
5005   if (!rUnsigned)
5006     {
5007       if (AOP_TYPE(right) == AOP_LIT)
5008         {
5009           /* signed literal */
5010           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5011           if (val < 0)
5012             compiletimeSign ^= TRUE;
5013         }
5014       else
5015         /* signed but not literal */
5016         runtimeSign = TRUE;
5017     }
5018
5019   /* initialize F0, which stores the runtime sign */
5020   if (runtimeSign)
5021     {
5022       if (compiletimeSign)
5023         emitcode ("setb", "F0"); /* set sign flag */
5024       else
5025         emitcode ("clr", "F0"); /* reset sign flag */
5026     }
5027
5028   /* save the signs of the operands */
5029   if (AOP_TYPE(right) == AOP_LIT)
5030     {
5031       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5032
5033       if (!rUnsigned && val < 0)
5034         emitcode ("mov", "b,#0x%02x", -val);
5035       else
5036         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5037     }
5038   else /* ! literal */
5039     {
5040       if (rUnsigned)  /* emitcode (";", "signed"); */
5041         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5042       else
5043         {
5044           MOVA (aopGet (right, 0, FALSE, FALSE));
5045           lbl = newiTempLabel (NULL);
5046           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5047           emitcode ("cpl", "F0"); /* complement sign flag */
5048           emitcode ("cpl", "a");  /* 2's complement */
5049           emitcode ("inc", "a");
5050           emitLabel (lbl);
5051           emitcode ("mov", "b,a");
5052         }
5053     }
5054
5055   if (AOP_TYPE(left) == AOP_LIT)
5056     {
5057       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5058
5059       if (!lUnsigned && val < 0)
5060         emitcode ("mov", "a,#0x%02x", -val);
5061       else
5062         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5063     }
5064   else /* ! literal */
5065     {
5066       MOVA (aopGet (left, 0, FALSE, FALSE));
5067
5068       if (!lUnsigned)
5069         {
5070           lbl = newiTempLabel (NULL);
5071           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5072           emitcode ("cpl", "F0"); /* complement sign flag */
5073           emitcode ("cpl", "a"); /* 2's complement */
5074           emitcode ("inc", "a");
5075           emitLabel (lbl);
5076         }
5077     }
5078
5079   /* now the multiplication */
5080   emitcode ("mul", "ab");
5081   if (runtimeSign || compiletimeSign)
5082     {
5083       lbl = newiTempLabel (NULL);
5084       if (runtimeSign)
5085         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5086       emitcode ("cpl", "a"); /* lsb 2's complement */
5087       if (size != 2)
5088         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5089       else
5090         {
5091           emitcode ("add", "a,#1"); /* this sets carry flag */
5092           emitcode ("xch", "a,b");
5093           emitcode ("cpl", "a"); /* msb 2's complement */
5094           emitcode ("addc", "a,#0");
5095           emitcode ("xch", "a,b");
5096         }
5097       emitLabel (lbl);
5098     }
5099   aopPut (result, "a", 0);
5100   if (size == 2)
5101     aopPut (result, "b", 1);
5102
5103   popB (pushedB);
5104 }
5105
5106 /*-----------------------------------------------------------------*/
5107 /* genMult - generates code for multiplication                     */
5108 /*-----------------------------------------------------------------*/
5109 static void
5110 genMult (iCode * ic)
5111 {
5112   operand *left = IC_LEFT (ic);
5113   operand *right = IC_RIGHT (ic);
5114   operand *result = IC_RESULT (ic);
5115
5116   D (emitcode (";", "genMult"));
5117
5118   /* assign the asmops */
5119   aopOp (left, ic, FALSE);
5120   aopOp (right, ic, FALSE);
5121   aopOp (result, ic, TRUE);
5122
5123   /* special cases first */
5124   /* both are bits */
5125   if (AOP_TYPE (left) == AOP_CRY &&
5126       AOP_TYPE (right) == AOP_CRY)
5127     {
5128       genMultbits (left, right, result);
5129       goto release;
5130     }
5131
5132   /* if both are of size == 1 */
5133 #if 0 // one of them can be a sloc shared with the result
5134     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5135 #else
5136   if (getSize(operandType(left)) == 1 &&
5137       getSize(operandType(right)) == 1)
5138 #endif
5139     {
5140       genMultOneByte (left, right, result);
5141       goto release;
5142     }
5143
5144   /* should have been converted to function call */
5145     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5146              getSize(OP_SYMBOL(right)->type));
5147   assert (0);
5148
5149 release:
5150   freeAsmop (result, NULL, ic, TRUE);
5151   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5152   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5153 }
5154
5155 /*-----------------------------------------------------------------*/
5156 /* genDivbits :- division of bits                                  */
5157 /*-----------------------------------------------------------------*/
5158 static void
5159 genDivbits (operand * left,
5160             operand * right,
5161             operand * result)
5162 {
5163   char *l;
5164   bool pushedB;
5165
5166   D(emitcode (";     genDivbits",""));
5167
5168   pushedB = pushB ();
5169
5170   /* the result must be bit */
5171   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5172   l = aopGet (left, 0, FALSE, FALSE);
5173
5174   MOVA (l);
5175
5176   emitcode ("div", "ab");
5177   emitcode ("rrc", "a");
5178
5179   popB (pushedB);
5180
5181   aopPut (result, "c", 0);
5182 }
5183
5184 /*-----------------------------------------------------------------*/
5185 /* genDivOneByte : 8 bit division                                  */
5186 /*-----------------------------------------------------------------*/
5187 static void
5188 genDivOneByte (operand * left,
5189                operand * right,
5190                operand * result)
5191 {
5192   bool lUnsigned, rUnsigned, pushedB;
5193   bool runtimeSign, compiletimeSign;
5194   bool accuse = FALSE;
5195   bool pushedA = FALSE;
5196   symbol *lbl;
5197   int size, offset;
5198
5199   D(emitcode (";     genDivOneByte",""));
5200
5201   /* Why is it necessary that genDivOneByte() can return an int result?
5202      Have a look at:
5203
5204         volatile unsigned char uc;
5205         volatile signed char sc1, sc2;
5206         volatile int i;
5207
5208         uc  = 255;
5209         sc1 = -1;
5210         i = uc / sc1;
5211
5212      Or:
5213
5214         sc1 = -128;
5215         sc2 = -1;
5216         i = sc1 / sc2;
5217
5218      In all cases a one byte result would overflow, the following cast to int
5219      would return the wrong result.
5220
5221      Two possible solution:
5222         a) cast operands to int, if ((unsigned) / (signed)) or
5223            ((signed) / (signed))
5224         b) return an 16 bit signed int; this is what we're doing here!
5225   */
5226
5227   size = AOP_SIZE (result) - 1;
5228   offset = 1;
5229   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5230   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5231
5232   pushedB = pushB ();
5233
5234   /* signed or unsigned */
5235   if (lUnsigned && rUnsigned)
5236     {
5237       /* unsigned is easy */
5238       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5239       MOVA (aopGet (left, 0, FALSE, FALSE));
5240       emitcode ("div", "ab");
5241       aopPut (result, "a", 0);
5242       while (size--)
5243         aopPut (result, zero, offset++);
5244
5245       popB (pushedB);
5246       return;
5247     }
5248
5249   /* signed is a little bit more difficult */
5250
5251   /* now sign adjust for both left & right */
5252
5253   /* let's see what's needed: */
5254   /* apply negative sign during runtime */
5255   runtimeSign = FALSE;
5256   /* negative sign from literals */
5257   compiletimeSign = FALSE;
5258
5259   if (!lUnsigned)
5260     {
5261       if (AOP_TYPE(left) == AOP_LIT)
5262         {
5263           /* signed literal */
5264           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5265           if (val < 0)
5266             compiletimeSign = TRUE;
5267         }
5268       else
5269         /* signed but not literal */
5270         runtimeSign = TRUE;
5271     }
5272
5273   if (!rUnsigned)
5274     {
5275       if (AOP_TYPE(right) == AOP_LIT)
5276         {
5277           /* signed literal */
5278           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5279           if (val < 0)
5280             compiletimeSign ^= TRUE;
5281         }
5282       else
5283         /* signed but not literal */
5284         runtimeSign = TRUE;
5285     }
5286
5287   /* initialize F0, which stores the runtime sign */
5288   if (runtimeSign)
5289     {
5290       if (compiletimeSign)
5291         emitcode ("setb", "F0"); /* set sign flag */
5292       else
5293         emitcode ("clr", "F0"); /* reset sign flag */
5294     }
5295
5296   /* save the signs of the operands */
5297   if (AOP_TYPE(right) == AOP_LIT)
5298     {
5299       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5300
5301       if (!rUnsigned && val < 0)
5302         emitcode ("mov", "b,#0x%02x", -val);
5303       else
5304         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5305     }
5306   else /* ! literal */
5307     {
5308       if (rUnsigned)
5309         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5310       else
5311         {
5312           MOVA (aopGet (right, 0, FALSE, FALSE));
5313           lbl = newiTempLabel (NULL);
5314           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5315           emitcode ("cpl", "F0"); /* complement sign flag */
5316           emitcode ("cpl", "a");  /* 2's complement */
5317           emitcode ("inc", "a");
5318           emitLabel (lbl);
5319           emitcode ("mov", "b,a");
5320         }
5321     }
5322
5323   if (AOP_TYPE(left) == AOP_LIT)
5324     {
5325       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5326
5327       if (!lUnsigned && val < 0)
5328         emitcode ("mov", "a,#0x%02x", -val);
5329       else
5330         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5331     }
5332   else /* ! literal */
5333     {
5334       MOVA (aopGet (left, 0, FALSE, FALSE));
5335
5336       if (!lUnsigned)
5337         {
5338           lbl = newiTempLabel (NULL);
5339           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5340           emitcode ("cpl", "F0"); /* complement sign flag */
5341           emitcode ("cpl", "a");  /* 2's complement */
5342           emitcode ("inc", "a");
5343           emitLabel (lbl);
5344         }
5345     }
5346
5347   /* now the division */
5348   emitcode ("div", "ab");
5349
5350   if (runtimeSign || compiletimeSign)
5351     {
5352       lbl = newiTempLabel (NULL);
5353       if (runtimeSign)
5354         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5355       emitcode ("cpl", "a"); /* lsb 2's complement */
5356       emitcode ("inc", "a");
5357       emitLabel (lbl);
5358
5359       accuse = aopPut (result, "a", 0);
5360       if (size > 0)
5361         {
5362           /* msb is 0x00 or 0xff depending on the sign */
5363           if (runtimeSign)
5364             {
5365               if (accuse)
5366                 {
5367                   emitcode ("push", "acc");
5368                   pushedA = TRUE;
5369                 }
5370               emitcode ("mov", "c,F0");
5371               emitcode ("subb", "a,acc");
5372               while (size--)
5373                 aopPut (result, "a", offset++);
5374             }
5375           else /* compiletimeSign */
5376             {
5377               if (aopPutUsesAcc (result, "#0xFF", offset))
5378                 {
5379                   emitcode ("push", "acc");
5380                   pushedA = TRUE;
5381                 }
5382               while (size--)
5383                 aopPut (result, "#0xff", offset++);
5384             }
5385         }
5386     }
5387   else
5388     {
5389       aopPut (result, "a", 0);
5390       while (size--)
5391         aopPut (result, zero, offset++);
5392     }
5393
5394   if (pushedA)
5395     emitcode ("pop", "acc");
5396   popB (pushedB);
5397 }
5398
5399 /*-----------------------------------------------------------------*/
5400 /* genDiv - generates code for division                            */
5401 /*-----------------------------------------------------------------*/
5402 static void
5403 genDiv (iCode * ic)
5404 {
5405   operand *left = IC_LEFT (ic);
5406   operand *right = IC_RIGHT (ic);
5407   operand *result = IC_RESULT (ic);
5408
5409   D (emitcode (";", "genDiv"));
5410
5411   /* assign the amsops */
5412   aopOp (left, ic, FALSE);
5413   aopOp (right, ic, FALSE);
5414   aopOp (result, ic, TRUE);
5415
5416   /* special cases first */
5417   /* both are bits */
5418   if (AOP_TYPE (left) == AOP_CRY &&
5419       AOP_TYPE (right) == AOP_CRY)
5420     {
5421       genDivbits (left, right, result);
5422       goto release;
5423     }
5424
5425   /* if both are of size == 1 */
5426   if (AOP_SIZE (left) == 1 &&
5427       AOP_SIZE (right) == 1)
5428     {
5429       genDivOneByte (left, right, result);
5430       goto release;
5431     }
5432
5433   /* should have been converted to function call */
5434   assert (0);
5435 release:
5436   freeAsmop (result, NULL, ic, TRUE);
5437   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5438   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5439 }
5440
5441 /*-----------------------------------------------------------------*/
5442 /* genModbits :- modulus of bits                                   */
5443 /*-----------------------------------------------------------------*/
5444 static void
5445 genModbits (operand * left,
5446             operand * right,
5447             operand * result)
5448 {
5449   char *l;
5450   bool pushedB;
5451
5452   D (emitcode (";", "genModbits"));
5453
5454   pushedB = pushB ();
5455
5456   /* the result must be bit */
5457   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5458   l = aopGet (left, 0, FALSE, FALSE);
5459
5460   MOVA (l);
5461
5462   emitcode ("div", "ab");
5463   emitcode ("mov", "a,b");
5464   emitcode ("rrc", "a");
5465
5466   popB (pushedB);
5467
5468   aopPut (result, "c", 0);
5469 }
5470
5471 /*-----------------------------------------------------------------*/
5472 /* genModOneByte : 8 bit modulus                                   */
5473 /*-----------------------------------------------------------------*/
5474 static void
5475 genModOneByte (operand * left,
5476                operand * right,
5477                operand * result)
5478 {
5479   bool lUnsigned, rUnsigned, pushedB;
5480   bool runtimeSign, compiletimeSign;
5481   symbol *lbl;
5482   int size, offset;
5483
5484   D (emitcode (";", "genModOneByte"));
5485
5486   size = AOP_SIZE (result) - 1;
5487   offset = 1;
5488   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5489   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5490
5491   /* if right is a literal, check it for 2^n */
5492   if (AOP_TYPE(right) == AOP_LIT)
5493     {
5494       unsigned char val = abs((int) operandLitValue(right));
5495       symbol *lbl2 = NULL;
5496
5497       switch (val)
5498         {
5499           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5500           case 2:
5501           case 4:
5502           case 8:
5503           case 16:
5504           case 32:
5505           case 64:
5506           case 128:
5507             if (lUnsigned)
5508               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5509                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5510               /* because iCode should have been changed to genAnd  */
5511               /* see file "SDCCopt.c", function "convertToFcall()" */
5512
5513             MOVA (aopGet (left, 0, FALSE, FALSE));
5514             emitcode ("mov", "c,acc.7");
5515             emitcode ("anl", "a,#0x%02x", val - 1);
5516             lbl = newiTempLabel (NULL);
5517             emitcode ("jz", "%05d$", (lbl->key + 100));
5518             emitcode ("jnc", "%05d$", (lbl->key + 100));
5519             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5520             if (size)
5521               {
5522                 int size2 = size;
5523                 int offs2 = offset;
5524
5525                 aopPut (result, "a", 0);
5526                 while (size2--)
5527                   aopPut (result, "#0xff", offs2++);
5528                 lbl2 = newiTempLabel (NULL);
5529                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5530               }
5531             emitLabel (lbl);
5532             aopPut (result, "a", 0);
5533             while (size--)
5534               aopPut (result, zero, offset++);
5535             if (lbl2)
5536               {
5537                 emitLabel (lbl2);
5538               }
5539             return;
5540
5541           default:
5542             break;
5543         }
5544     }
5545
5546   pushedB = pushB ();
5547
5548   /* signed or unsigned */
5549   if (lUnsigned && rUnsigned)
5550     {
5551       /* unsigned is easy */
5552       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5553       MOVA (aopGet (left, 0, FALSE, FALSE));
5554       emitcode ("div", "ab");
5555       aopPut (result, "b", 0);
5556       while (size--)
5557         aopPut (result, zero, offset++);
5558
5559       popB (pushedB);
5560       return;
5561     }
5562
5563   /* signed is a little bit more difficult */
5564
5565   /* now sign adjust for both left & right */
5566
5567   /* modulus: sign of the right operand has no influence on the result! */
5568   if (AOP_TYPE(right) == AOP_LIT)
5569     {
5570       signed char val = (char) operandLitValue(right);
5571
5572       if (!rUnsigned && val < 0)
5573         emitcode ("mov", "b,#0x%02x", -val);
5574       else
5575         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5576     }
5577   else /* not literal */
5578     {
5579       if (rUnsigned)
5580         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5581       else
5582         {
5583           MOVA (aopGet (right, 0, FALSE, FALSE));
5584           lbl = newiTempLabel (NULL);
5585           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5586           emitcode ("cpl", "a"); /* 2's complement */
5587           emitcode ("inc", "a");
5588           emitLabel (lbl);
5589           emitcode ("mov", "b,a");
5590         }
5591     }
5592
5593   /* let's see what's needed: */
5594   /* apply negative sign during runtime */
5595   runtimeSign = FALSE;
5596   /* negative sign from literals */
5597   compiletimeSign = FALSE;
5598
5599   /* sign adjust left side */
5600   if (AOP_TYPE(left) == AOP_LIT)
5601     {
5602       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5603
5604       if (!lUnsigned && val < 0)
5605         {
5606           compiletimeSign = TRUE; /* set sign flag */
5607           emitcode ("mov", "a,#0x%02x", -val);
5608         }
5609       else
5610         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5611     }
5612   else /* ! literal */
5613     {
5614       MOVA (aopGet (left, 0, FALSE, FALSE));
5615
5616       if (!lUnsigned)
5617         {
5618           runtimeSign = TRUE;
5619           emitcode ("clr", "F0"); /* clear sign flag */
5620
5621           lbl = newiTempLabel (NULL);
5622           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5623           emitcode ("setb", "F0"); /* set sign flag */
5624           emitcode ("cpl", "a");   /* 2's complement */
5625           emitcode ("inc", "a");
5626           emitLabel (lbl);
5627         }
5628     }
5629
5630   /* now the modulus */
5631   emitcode ("div", "ab");
5632
5633   if (runtimeSign || compiletimeSign)
5634     {
5635       emitcode ("mov", "a,b");
5636       lbl = newiTempLabel (NULL);
5637       if (runtimeSign)
5638         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5639       emitcode ("cpl", "a"); /* 2's complement */
5640       emitcode ("inc", "a");
5641       emitLabel (lbl);
5642
5643       aopPut (result, "a", 0);
5644       if (size > 0)
5645         {
5646           /* msb is 0x00 or 0xff depending on the sign */
5647           if (runtimeSign)
5648             {
5649               emitcode ("mov", "c,F0");
5650               emitcode ("subb", "a,acc");
5651               while (size--)
5652                 aopPut (result, "a", offset++);
5653             }
5654           else /* compiletimeSign */
5655             while (size--)
5656               aopPut (result, "#0xff", offset++);
5657         }
5658     }
5659   else
5660     {
5661       aopPut (result, "b", 0);
5662       while (size--)
5663         aopPut (result, zero, offset++);
5664     }
5665
5666   popB (pushedB);
5667 }
5668
5669 /*-----------------------------------------------------------------*/
5670 /* genMod - generates code for division                            */
5671 /*-----------------------------------------------------------------*/
5672 static void
5673 genMod (iCode * ic)
5674 {
5675   operand *left = IC_LEFT (ic);
5676   operand *right = IC_RIGHT (ic);
5677   operand *result = IC_RESULT (ic);
5678
5679   D (emitcode (";", "genMod"));
5680
5681   /* assign the asmops */
5682   aopOp (left, ic, FALSE);
5683   aopOp (right, ic, FALSE);
5684   aopOp (result, ic, TRUE);
5685
5686   /* special cases first */
5687   /* both are bits */
5688   if (AOP_TYPE (left) == AOP_CRY &&
5689       AOP_TYPE (right) == AOP_CRY)
5690     {
5691       genModbits (left, right, result);
5692       goto release;
5693     }
5694
5695   /* if both are of size == 1 */
5696   if (AOP_SIZE (left) == 1 &&
5697       AOP_SIZE (right) == 1)
5698     {
5699       genModOneByte (left, right, result);
5700       goto release;
5701     }
5702
5703   /* should have been converted to function call */
5704   assert (0);
5705
5706 release:
5707   freeAsmop (result, NULL, ic, TRUE);
5708   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5710 }
5711
5712 /*-----------------------------------------------------------------*/
5713 /* genIfxJump :- will create a jump depending on the ifx           */
5714 /*-----------------------------------------------------------------*/
5715 static void
5716 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5717 {
5718   symbol *jlbl;
5719   symbol *tlbl = newiTempLabel (NULL);
5720   char *inst;
5721
5722   D (emitcode (";", "genIfxJump"));
5723
5724   /* if true label then we jump if condition
5725      supplied is true */
5726   if (IC_TRUE (ic))
5727     {
5728       jlbl = IC_TRUE (ic);
5729       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5730                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5731     }
5732   else
5733     {
5734       /* false label is present */
5735       jlbl = IC_FALSE (ic);
5736       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5737                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5738     }
5739   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5740     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5741   else
5742     emitcode (inst, "%05d$", tlbl->key + 100);
5743   freeForBranchAsmop (result);
5744   freeForBranchAsmop (right);
5745   freeForBranchAsmop (left);
5746   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5747   emitLabel (tlbl);
5748
5749   /* mark the icode as generated */
5750   ic->generated = 1;
5751 }
5752
5753 /*-----------------------------------------------------------------*/
5754 /* genCmp :- greater or less than comparison                       */
5755 /*-----------------------------------------------------------------*/
5756 static void
5757 genCmp (operand * left, operand * right,
5758         operand * result, iCode * ifx, int sign, iCode *ic)
5759 {
5760   int size, offset = 0;
5761   unsigned long lit = 0L;
5762   bool rightInB;
5763
5764   D (emitcode (";", "genCmp"));
5765
5766   /* if left & right are bit variables */
5767   if (AOP_TYPE (left) == AOP_CRY &&
5768       AOP_TYPE (right) == AOP_CRY)
5769     {
5770       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5771       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5772     }
5773   else
5774     {
5775       /* subtract right from left if at the
5776          end the carry flag is set then we know that
5777          left is greater than right */
5778       size = max (AOP_SIZE (left), AOP_SIZE (right));
5779
5780       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5781       if ((size == 1) && !sign &&
5782           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5783         {
5784           symbol *lbl = newiTempLabel (NULL);
5785           emitcode ("cjne", "%s,%s,%05d$",
5786                     aopGet (left, offset, FALSE, FALSE),
5787                     aopGet (right, offset, FALSE, FALSE),
5788                     lbl->key + 100);
5789           emitLabel (lbl);
5790         }
5791       else
5792         {
5793           if (AOP_TYPE (right) == AOP_LIT)
5794             {
5795               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5796               /* optimize if(x < 0) or if(x >= 0) */
5797               if (lit == 0L)
5798                 {
5799                   if (!sign)
5800                     {
5801                       CLRC;
5802                     }
5803                   else
5804                     {
5805                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5806                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5807                         {
5808                           genIfxJump (ifx, "acc.7", left, right, result);
5809                           freeAsmop (right, NULL, ic, TRUE);
5810                           freeAsmop (left, NULL, ic, TRUE);
5811
5812                           return;
5813                         }
5814                       else
5815                         {
5816                           emitcode ("rlc", "a");
5817                         }
5818                     }
5819                   goto release;
5820                 }
5821               else
5822                 {//nonzero literal
5823                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5824                   while (size && (bytelit == 0))
5825                     {
5826                       offset++;
5827                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5828                       size--;
5829                     }
5830                   CLRC;
5831                   while (size--)
5832                     {
5833                       MOVA (aopGet (left, offset, FALSE, FALSE));
5834                       if (sign && size == 0)
5835                         {
5836                           emitcode ("xrl", "a,#0x80");
5837                           emitcode ("subb", "a,#0x%02x",
5838                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5839                         }
5840                       else
5841                         {
5842                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5843                         }
5844                       offset++;
5845                     }
5846                   goto release;
5847                 }
5848             }
5849           CLRC;
5850           while (size--)
5851             {
5852               bool pushedB = FALSE;
5853               rightInB = aopGetUsesAcc(right, offset);
5854               if (rightInB)
5855                 {
5856                   pushedB = pushB ();
5857                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5858                 }
5859               MOVA (aopGet (left, offset, FALSE, FALSE));
5860               if (sign && size == 0)
5861                 {
5862                   emitcode ("xrl", "a,#0x80");
5863                   if (!rightInB)
5864                     {
5865                       pushedB = pushB ();
5866                       rightInB++;
5867                       MOVB (aopGet (right, offset, FALSE, FALSE));
5868                     }
5869                   emitcode ("xrl", "b,#0x80");
5870                   emitcode ("subb", "a,b");
5871                 }
5872               else
5873                 {
5874                   if (rightInB)
5875                     emitcode ("subb", "a,b");
5876                   else
5877                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5878                 }
5879               if (rightInB)
5880                 popB (pushedB);
5881               offset++;
5882             }
5883         }
5884     }
5885
5886 release:
5887   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5888   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5889   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5890     {
5891       outBitC (result);
5892     }
5893   else
5894     {
5895       /* if the result is used in the next
5896          ifx conditional branch then generate
5897          code a little differently */
5898       if (ifx)
5899         {
5900           genIfxJump (ifx, "c", NULL, NULL, result);
5901         }
5902       else
5903         {
5904           outBitC (result);
5905         }
5906       /* leave the result in acc */
5907     }
5908 }
5909
5910 /*-----------------------------------------------------------------*/
5911 /* genCmpGt :- greater than comparison                             */
5912 /*-----------------------------------------------------------------*/
5913 static void
5914 genCmpGt (iCode * ic, iCode * ifx)
5915 {
5916   operand *left, *right, *result;
5917   sym_link *letype, *retype;
5918   int sign;
5919
5920   D (emitcode (";", "genCmpGt"));
5921
5922   left = IC_LEFT (ic);
5923   right = IC_RIGHT (ic);
5924   result = IC_RESULT (ic);
5925
5926   letype = getSpec (operandType (left));
5927   retype = getSpec (operandType (right));
5928   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5929            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5930   /* assign the amsops */
5931   aopOp (result, ic, TRUE);
5932   aopOp (left, ic, FALSE);
5933   aopOp (right, ic, FALSE);
5934
5935   genCmp (right, left, result, ifx, sign, ic);
5936
5937   freeAsmop (result, NULL, ic, TRUE);
5938 }
5939
5940 /*-----------------------------------------------------------------*/
5941 /* genCmpLt - less than comparisons                                */
5942 /*-----------------------------------------------------------------*/
5943 static void
5944 genCmpLt (iCode * ic, iCode * ifx)
5945 {
5946   operand *left, *right, *result;
5947   sym_link *letype, *retype;
5948   int sign;
5949
5950   D (emitcode (";", "genCmpLt"));
5951
5952   left = IC_LEFT (ic);
5953   right = IC_RIGHT (ic);
5954   result = IC_RESULT (ic);
5955
5956   letype = getSpec (operandType (left));
5957   retype = getSpec (operandType (right));
5958   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5959            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5960   /* assign the amsops */
5961   aopOp (result, ic, TRUE);
5962   aopOp (left, ic, FALSE);
5963   aopOp (right, ic, FALSE);
5964
5965   genCmp (left, right, result, ifx, sign, ic);
5966
5967   freeAsmop (result, NULL, ic, TRUE);
5968 }
5969
5970 /*-----------------------------------------------------------------*/
5971 /* gencjneshort - compare and jump if not equal                    */
5972 /*-----------------------------------------------------------------*/
5973 static void
5974 gencjneshort (operand * left, operand * right, symbol * lbl)
5975 {
5976   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5977   int offset = 0;
5978   unsigned long lit = 0L;
5979
5980   D (emitcode (";", "gencjneshort"));
5981
5982   /* if the left side is a literal or
5983      if the right is in a pointer register and left
5984      is not */
5985   if ((AOP_TYPE (left) == AOP_LIT) ||
5986       (AOP_TYPE (left) == AOP_IMMD) ||
5987       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5988     {
5989       operand *t = right;
5990       right = left;
5991       left = t;
5992     }
5993
5994   if (AOP_TYPE (right) == AOP_LIT)
5995     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5996
5997   /* if the right side is a literal then anything goes */
5998   if (AOP_TYPE (right) == AOP_LIT &&
5999       AOP_TYPE (left) != AOP_DIR  &&
6000       AOP_TYPE (left) != AOP_IMMD)
6001     {
6002       while (size--)
6003         {
6004           emitcode ("cjne", "%s,%s,%05d$",
6005                     aopGet (left, offset, FALSE, FALSE),
6006                     aopGet (right, offset, FALSE, FALSE),
6007                     lbl->key + 100);
6008           offset++;
6009         }
6010     }
6011
6012   /* if the right side is in a register or in direct space or
6013      if the left is a pointer register & right is not */
6014   else if (AOP_TYPE (right) == AOP_REG ||
6015            AOP_TYPE (right) == AOP_DIR ||
6016            AOP_TYPE (right) == AOP_LIT ||
6017            AOP_TYPE (right) == AOP_IMMD ||
6018            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6019            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6020     {
6021       while (size--)
6022         {
6023           MOVA (aopGet (left, offset, FALSE, FALSE));
6024           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6025               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6026             emitcode ("jnz", "%05d$", lbl->key + 100);
6027           else
6028             emitcode ("cjne", "a,%s,%05d$",
6029                       aopGet (right, offset, FALSE, TRUE),
6030                       lbl->key + 100);
6031           offset++;
6032         }
6033     }
6034   else
6035     {
6036       /* right is a pointer reg need both a & b */
6037       while (size--)
6038         {
6039           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6040           wassertl(!BINUSE, "B was in use");
6041           MOVB (aopGet (left, offset, FALSE, FALSE));
6042           MOVA (aopGet (right, offset, FALSE, FALSE));
6043           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6044           offset++;
6045         }
6046     }
6047 }
6048
6049 /*-----------------------------------------------------------------*/
6050 /* gencjne - compare and jump if not equal                         */
6051 /*-----------------------------------------------------------------*/
6052 static void
6053 gencjne (operand * left, operand * right, symbol * lbl)
6054 {
6055   symbol *tlbl = newiTempLabel (NULL);
6056
6057   D (emitcode (";", "gencjne"));
6058
6059   gencjneshort (left, right, lbl);
6060
6061   emitcode ("mov", "a,%s", one);
6062   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6063   emitLabel (lbl);
6064   emitcode ("clr", "a");
6065   emitLabel (tlbl);
6066 }
6067
6068 /*-----------------------------------------------------------------*/
6069 /* genCmpEq - generates code for equal to                          */
6070 /*-----------------------------------------------------------------*/
6071 static void
6072 genCmpEq (iCode * ic, iCode * ifx)
6073 {
6074   bool swappedLR = FALSE;
6075   operand *left, *right, *result;
6076
6077   D (emitcode (";", "genCmpEq"));
6078
6079   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6080   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6081   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6082
6083   /* if literal, literal on the right or
6084      if the right is in a pointer register and left
6085      is not */
6086   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6087       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6088     {
6089       operand *t = IC_RIGHT (ic);
6090       IC_RIGHT (ic) = IC_LEFT (ic);
6091       IC_LEFT (ic) = t;
6092       swappedLR = TRUE;
6093     }
6094
6095   if (ifx && !AOP_SIZE (result))
6096     {
6097       symbol *tlbl;
6098       /* if they are both bit variables */
6099       if (AOP_TYPE (left) == AOP_CRY &&
6100           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6101         {
6102           if (AOP_TYPE (right) == AOP_LIT)
6103             {
6104               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6105               if (lit == 0L)
6106                 {
6107                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6108                   emitcode ("cpl", "c");
6109                 }
6110               else if (lit == 1L)
6111                 {
6112                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6113                 }
6114               else
6115                 {
6116                   emitcode ("clr", "c");
6117                 }
6118               /* AOP_TYPE(right) == AOP_CRY */
6119             }
6120           else
6121             {
6122               symbol *lbl = newiTempLabel (NULL);
6123               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6124               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6125               emitcode ("cpl", "c");
6126               emitLabel (lbl);
6127             }
6128           /* if true label then we jump if condition
6129              supplied is true */
6130           tlbl = newiTempLabel (NULL);
6131           if (IC_TRUE (ifx))
6132             {
6133               emitcode ("jnc", "%05d$", tlbl->key + 100);
6134               freeForBranchAsmop (result);
6135               freeForBranchAsmop (right);
6136               freeForBranchAsmop (left);
6137               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6138             }
6139           else
6140             {
6141               emitcode ("jc", "%05d$", tlbl->key + 100);
6142               freeForBranchAsmop (result);
6143               freeForBranchAsmop (right);
6144               freeForBranchAsmop (left);
6145               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6146             }
6147           emitLabel (tlbl);
6148         }
6149       else
6150         {
6151           tlbl = newiTempLabel (NULL);
6152           gencjneshort (left, right, tlbl);
6153           if (IC_TRUE (ifx))
6154             {
6155               freeForBranchAsmop (result);
6156               freeForBranchAsmop (right);
6157               freeForBranchAsmop (left);
6158               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6159               emitLabel (tlbl);
6160             }
6161           else
6162             {
6163               symbol *lbl = newiTempLabel (NULL);
6164               emitcode ("sjmp", "%05d$", lbl->key + 100);
6165               emitLabel (tlbl);
6166               freeForBranchAsmop (result);
6167               freeForBranchAsmop (right);
6168               freeForBranchAsmop (left);
6169               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6170               emitLabel (lbl);
6171             }
6172         }
6173       /* mark the icode as generated */
6174       ifx->generated = 1;
6175       goto release;
6176     }
6177
6178   /* if they are both bit variables */
6179   if (AOP_TYPE (left) == AOP_CRY &&
6180       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6181     {
6182       if (AOP_TYPE (right) == AOP_LIT)
6183         {
6184           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6185           if (lit == 0L)
6186             {
6187               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6188               emitcode ("cpl", "c");
6189             }
6190           else if (lit == 1L)
6191             {
6192               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6193             }
6194           else
6195             {
6196               emitcode ("clr", "c");
6197             }
6198           /* AOP_TYPE(right) == AOP_CRY */
6199         }
6200       else
6201         {
6202           symbol *lbl = newiTempLabel (NULL);
6203           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6204           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6205           emitcode ("cpl", "c");
6206           emitLabel (lbl);
6207         }
6208       /* c = 1 if egal */
6209       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6210         {
6211           outBitC (result);
6212           goto release;
6213         }
6214       if (ifx)
6215         {
6216           genIfxJump (ifx, "c", left, right, result);
6217           goto release;
6218         }
6219       /* if the result is used in an arithmetic operation
6220          then put the result in place */
6221       outBitC (result);
6222     }
6223   else
6224     {
6225       gencjne (left, right, newiTempLabel (NULL));
6226       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6227         {
6228           aopPut (result, "a", 0);
6229           goto release;
6230         }
6231       if (ifx)
6232         {
6233           genIfxJump (ifx, "a", left, right, result);
6234           goto release;
6235         }
6236       /* if the result is used in an arithmetic operation
6237          then put the result in place */
6238       if (AOP_TYPE (result) != AOP_CRY)
6239         outAcc (result);
6240       /* leave the result in acc */
6241     }
6242
6243 release:
6244   freeAsmop (result, NULL, ic, TRUE);
6245   if (!swappedLR)
6246     {
6247       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6248       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6249     }
6250   else
6251     {
6252       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6253       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6254     }
6255 }
6256
6257 /*-----------------------------------------------------------------*/
6258 /* ifxForOp - returns the icode containing the ifx for operand     */
6259 /*-----------------------------------------------------------------*/
6260 static iCode *
6261 ifxForOp (operand * op, iCode * ic)
6262 {
6263   /* if true symbol then needs to be assigned */
6264   if (IS_TRUE_SYMOP (op))
6265     return NULL;
6266
6267   /* if this has register type condition and
6268      the next instruction is ifx with the same operand
6269      and live to of the operand is upto the ifx only then */
6270   if (ic->next &&
6271       ic->next->op == IFX &&
6272       IC_COND (ic->next)->key == op->key &&
6273       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6274     return ic->next;
6275
6276   return NULL;
6277 }
6278
6279 /*-----------------------------------------------------------------*/
6280 /* hasInc - operand is incremented before any other use            */
6281 /*-----------------------------------------------------------------*/
6282 static iCode *
6283 hasInc (operand *op, iCode *ic, int osize)
6284 {
6285   sym_link *type = operandType(op);
6286   sym_link *retype = getSpec (type);
6287   iCode *lic = ic->next;
6288   int isize ;
6289
6290   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6291   if (!IS_SYMOP(op)) return NULL;
6292
6293   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6294   if (IS_AGGREGATE(type->next)) return NULL;
6295   if (osize != (isize = getSize(type->next))) return NULL;
6296
6297   while (lic) {
6298     /* if operand of the form op = op + <sizeof *op> */
6299     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6300         isOperandEqual(IC_RESULT(lic),op) &&
6301         isOperandLiteral(IC_RIGHT(lic)) &&
6302         operandLitValue(IC_RIGHT(lic)) == isize) {
6303       return lic;
6304     }
6305     /* if the operand used or deffed */
6306     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6307       return NULL;
6308     }
6309     /* if GOTO or IFX */
6310     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6311     lic = lic->next;
6312   }
6313   return NULL;
6314 }
6315
6316 /*-----------------------------------------------------------------*/
6317 /* genAndOp - for && operation                                     */
6318 /*-----------------------------------------------------------------*/
6319 static void
6320 genAndOp (iCode * ic)
6321 {
6322   operand *left, *right, *result;
6323   symbol *tlbl;
6324
6325   D (emitcode (";", "genAndOp"));
6326
6327   /* note here that && operations that are in an
6328      if statement are taken away by backPatchLabels
6329      only those used in arthmetic operations remain */
6330   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6331   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6332   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6333
6334   /* if both are bit variables */
6335   if (AOP_TYPE (left) == AOP_CRY &&
6336       AOP_TYPE (right) == AOP_CRY)
6337     {
6338       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6339       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6340       outBitC (result);
6341     }
6342   else
6343     {
6344       tlbl = newiTempLabel (NULL);
6345       toBoolean (left);
6346       emitcode ("jz", "%05d$", tlbl->key + 100);
6347       toBoolean (right);
6348       emitLabel (tlbl);
6349       outBitAcc (result);
6350     }
6351
6352   freeAsmop (result, NULL, ic, TRUE);
6353   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6354   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6355 }
6356
6357
6358 /*-----------------------------------------------------------------*/
6359 /* genOrOp - for || operation                                      */
6360 /*-----------------------------------------------------------------*/
6361 static void
6362 genOrOp (iCode * ic)
6363 {
6364   operand *left, *right, *result;
6365   symbol *tlbl;
6366
6367   D (emitcode (";", "genOrOp"));
6368
6369   /* note here that || operations that are in an
6370      if statement are taken away by backPatchLabels
6371      only those used in arthmetic operations remain */
6372   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6373   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6374   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6375
6376   /* if both are bit variables */
6377   if (AOP_TYPE (left) == AOP_CRY &&
6378       AOP_TYPE (right) == AOP_CRY)
6379     {
6380       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6381       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6382       outBitC (result);
6383     }
6384   else
6385     {
6386       tlbl = newiTempLabel (NULL);
6387       toBoolean (left);
6388       emitcode ("jnz", "%05d$", tlbl->key + 100);
6389       toBoolean (right);
6390       emitLabel (tlbl);
6391       outBitAcc (result);
6392     }
6393
6394   freeAsmop (result, NULL, ic, TRUE);
6395   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6396   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6397 }
6398
6399 /*-----------------------------------------------------------------*/
6400 /* isLiteralBit - test if lit == 2^n                               */
6401 /*-----------------------------------------------------------------*/
6402 static int
6403 isLiteralBit (unsigned long lit)
6404 {
6405   unsigned long pw[32] =
6406   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6407    0x100L, 0x200L, 0x400L, 0x800L,
6408    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6409    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6410    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6411    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6412    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6413   int idx;
6414
6415   for (idx = 0; idx < 32; idx++)
6416     if (lit == pw[idx])
6417       return idx + 1;
6418   return 0;
6419 }
6420
6421 /*-----------------------------------------------------------------*/
6422 /* continueIfTrue -                                                */
6423 /*-----------------------------------------------------------------*/
6424 static void
6425 continueIfTrue (iCode * ic)
6426 {
6427   if (IC_TRUE (ic))
6428     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6429   ic->generated = 1;
6430 }
6431
6432 /*-----------------------------------------------------------------*/
6433 /* jmpIfTrue -                                                     */
6434 /*-----------------------------------------------------------------*/
6435 static void
6436 jumpIfTrue (iCode * ic)
6437 {
6438   if (!IC_TRUE (ic))
6439     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6440   ic->generated = 1;
6441 }
6442
6443 /*-----------------------------------------------------------------*/
6444 /* jmpTrueOrFalse -                                                */
6445 /*-----------------------------------------------------------------*/
6446 static void
6447 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6448 {
6449   // ugly but optimized by peephole
6450   if (IC_TRUE (ic))
6451     {
6452       symbol *nlbl = newiTempLabel (NULL);
6453       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6454       emitLabel (tlbl);
6455       freeForBranchAsmop (result);
6456       freeForBranchAsmop (right);
6457       freeForBranchAsmop (left);
6458       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6459       emitLabel (nlbl);
6460     }
6461   else
6462     {
6463       freeForBranchAsmop (result);
6464       freeForBranchAsmop (right);
6465       freeForBranchAsmop (left);
6466       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6467       emitLabel (tlbl);
6468     }
6469   ic->generated = 1;
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* genAnd  - code for and                                          */
6474 /*-----------------------------------------------------------------*/
6475 static void
6476 genAnd (iCode * ic, iCode * ifx)
6477 {
6478   operand *left, *right, *result;
6479   int size, offset = 0;
6480   unsigned long lit = 0L;
6481   int bytelit = 0;
6482   char buffer[10];
6483
6484   D (emitcode (";", "genAnd"));
6485
6486   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6487   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6488   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6489
6490 #ifdef DEBUG_TYPE
6491   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6492             AOP_TYPE (result),
6493             AOP_TYPE (left), AOP_TYPE (right));
6494   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6495             AOP_SIZE (result),
6496             AOP_SIZE (left), AOP_SIZE (right));
6497 #endif
6498
6499   /* if left is a literal & right is not then exchange them */
6500   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6501       AOP_NEEDSACC (left))
6502     {
6503       operand *tmp = right;
6504       right = left;
6505       left = tmp;
6506     }
6507
6508   /* if result = right then exchange left and right */
6509   if (sameRegs (AOP (result), AOP (right)))
6510     {
6511       operand *tmp = right;
6512       right = left;
6513       left = tmp;
6514     }
6515
6516   /* if right is bit then exchange them */
6517   if (AOP_TYPE (right) == AOP_CRY &&
6518       AOP_TYPE (left) != AOP_CRY)
6519     {
6520       operand *tmp = right;
6521       right = left;
6522       left = tmp;
6523     }
6524   if (AOP_TYPE (right) == AOP_LIT)
6525     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6526
6527   size = AOP_SIZE (result);
6528
6529   // if(bit & yy)
6530   // result = bit & yy;
6531   if (AOP_TYPE (left) == AOP_CRY)
6532     {
6533       // c = bit & literal;
6534       if (AOP_TYPE (right) == AOP_LIT)
6535         {
6536           if (lit & 1)
6537             {
6538               if (size && sameRegs (AOP (result), AOP (left)))
6539                 // no change
6540                 goto release;
6541               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6542             }
6543           else
6544             {
6545               // bit(result) = 0;
6546               if (size && (AOP_TYPE (result) == AOP_CRY))
6547                 {
6548                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6549                   goto release;
6550                 }
6551               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6552                 {
6553                   jumpIfTrue (ifx);
6554                   goto release;
6555                 }
6556               emitcode ("clr", "c");
6557             }
6558         }
6559       else
6560         {
6561           if (AOP_TYPE (right) == AOP_CRY)
6562             {
6563               // c = bit & bit;
6564               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6565               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6566             }
6567           else
6568             {
6569               // c = bit & val;
6570               MOVA (aopGet (right, 0, FALSE, FALSE));
6571               // c = lsb
6572               emitcode ("rrc", "a");
6573               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6574             }
6575         }
6576       // bit = c
6577       // val = c
6578       if (size)
6579         outBitC (result);
6580       // if(bit & ...)
6581       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6582         genIfxJump (ifx, "c", left, right, result);
6583       goto release;
6584     }
6585
6586   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6587   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6588   if ((AOP_TYPE (right) == AOP_LIT) &&
6589       (AOP_TYPE (result) == AOP_CRY) &&
6590       (AOP_TYPE (left) != AOP_CRY))
6591     {
6592       int posbit = isLiteralBit (lit);
6593       /* left &  2^n */
6594       if (posbit)
6595         {
6596           posbit--;
6597           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6598           // bit = left & 2^n
6599           if (size)
6600             {
6601               switch (posbit & 0x07)
6602                 {
6603                   case 0: emitcode ("rrc", "a");
6604                           break;
6605                   case 7: emitcode ("rlc", "a");
6606                           break;
6607                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6608                           break;
6609                 }
6610             }
6611           // if(left &  2^n)
6612           else
6613             {
6614               if (ifx)
6615                 {
6616                   SNPRINTF (buffer, sizeof(buffer),
6617                             "acc.%d", posbit & 0x07);
6618                   genIfxJump (ifx, buffer, left, right, result);
6619                 }
6620               else
6621                 {// what is this case? just found it in ds390/gen.c
6622                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6623                 }
6624               goto release;
6625             }
6626         }
6627       else
6628         {
6629           symbol *tlbl = newiTempLabel (NULL);
6630           int sizel = AOP_SIZE (left);
6631           if (size)
6632             emitcode ("setb", "c");
6633           while (sizel--)
6634             {
6635               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6636                 {
6637                   MOVA (aopGet (left, offset, FALSE, FALSE));
6638                   // byte ==  2^n ?
6639                   if ((posbit = isLiteralBit (bytelit)) != 0)
6640                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6641                   else
6642                     {
6643                       if (bytelit != 0x0FFL)
6644                         emitcode ("anl", "a,%s",
6645                                   aopGet (right, offset, FALSE, TRUE));
6646                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6647                     }
6648                 }
6649               offset++;
6650             }
6651           // bit = left & literal
6652           if (size)
6653             {
6654               emitcode ("clr", "c");
6655               emitLabel (tlbl);
6656             }
6657           // if(left & literal)
6658           else
6659             {
6660               if (ifx)
6661                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6662               else
6663                 emitLabel (tlbl);
6664               goto release;
6665             }
6666         }
6667       outBitC (result);
6668       goto release;
6669     }
6670
6671   /* if left is same as result */
6672   if (sameRegs (AOP (result), AOP (left)))
6673     {
6674       for (; size--; offset++)
6675         {
6676           if (AOP_TYPE (right) == AOP_LIT)
6677             {
6678               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6679               if (bytelit == 0x0FF)
6680                 {
6681                   /* dummy read of volatile operand */
6682                   if (isOperandVolatile (left, FALSE))
6683                     MOVA (aopGet (left, offset, FALSE, FALSE));
6684                   else
6685                     continue;
6686                 }
6687               else if (bytelit == 0)
6688                 {
6689                   aopPut (result, zero, offset);
6690                 }
6691               else if (IS_AOP_PREG (result))
6692                 {
6693                   MOVA (aopGet (left, offset, FALSE, TRUE));
6694                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6695                   aopPut (result, "a", offset);
6696                 }
6697               else
6698                 emitcode ("anl", "%s,%s",
6699                           aopGet (left, offset, FALSE, TRUE),
6700                           aopGet (right, offset, FALSE, FALSE));
6701             }
6702           else
6703             {
6704               if (AOP_TYPE (left) == AOP_ACC)
6705                 {
6706                   if (offset)
6707                     emitcode("mov", "a,b");
6708                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6709                 }
6710               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6711                 {
6712                   MOVB (aopGet (left, offset, FALSE, FALSE));
6713                   MOVA (aopGet (right, offset, FALSE, FALSE));
6714                   emitcode ("anl", "a,b");
6715                   aopPut (result, "a", offset);
6716                 }
6717               else if (aopGetUsesAcc (left, offset))
6718                 {
6719                   MOVA (aopGet (left, offset, FALSE, FALSE));
6720                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6721                   aopPut (result, "a", offset);
6722                 }
6723               else
6724                 {
6725                   MOVA (aopGet (right, offset, FALSE, FALSE));
6726                   if (IS_AOP_PREG (result))
6727                     {
6728                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6729                       aopPut (result, "a", offset);
6730                     }
6731                   else
6732                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6733                 }
6734             }
6735         }
6736     }
6737   else
6738     {
6739       // left & result in different registers
6740       if (AOP_TYPE (result) == AOP_CRY)
6741         {
6742           // result = bit
6743           // if(size), result in bit
6744           // if(!size && ifx), conditional oper: if(left & right)
6745           symbol *tlbl = newiTempLabel (NULL);
6746           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6747           if (size)
6748             emitcode ("setb", "c");
6749           while (sizer--)
6750             {
6751               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6752                   && AOP_TYPE(left)==AOP_ACC)
6753                 {
6754                   if (offset)
6755                     emitcode("mov", "a,b");
6756                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6757                 }
6758               else if (AOP_TYPE(left)==AOP_ACC)
6759                 {
6760                   if (!offset)
6761                     {
6762                       bool pushedB = pushB ();
6763                       emitcode("mov", "b,a");
6764                       MOVA (aopGet (right, offset, FALSE, FALSE));
6765                       emitcode("anl", "a,b");
6766                       popB (pushedB);
6767                     }
6768                   else
6769                     {
6770                       MOVA (aopGet (right, offset, FALSE, FALSE));
6771                       emitcode("anl", "a,b");
6772                     }
6773                 }
6774               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6775                 {
6776                   MOVB (aopGet (left, offset, FALSE, FALSE));
6777                   MOVA (aopGet (right, offset, FALSE, FALSE));
6778                   emitcode ("anl", "a,b");
6779                 }
6780               else if (aopGetUsesAcc (left, offset))
6781                 {
6782                   MOVA (aopGet (left, offset, FALSE, FALSE));
6783                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6784                     }
6785               else
6786                 {
6787                   MOVA (aopGet (right, offset, FALSE, FALSE));
6788                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6789                 }
6790
6791               emitcode ("jnz", "%05d$", tlbl->key + 100);
6792               offset++;
6793             }
6794           if (size)
6795             {
6796               CLRC;
6797               emitLabel (tlbl);
6798               outBitC (result);
6799             }
6800           else if (ifx)
6801             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6802           else
6803             emitLabel (tlbl);
6804         }
6805       else
6806         {
6807           for (; (size--); offset++)
6808             {
6809               // normal case
6810               // result = left & right
6811               if (AOP_TYPE (right) == AOP_LIT)
6812                 {
6813                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6814                   if (bytelit == 0x0FF)
6815                     {
6816                       aopPut (result,
6817                               aopGet (left, offset, FALSE, FALSE),
6818                               offset);
6819                       continue;
6820                     }
6821                   else if (bytelit == 0)
6822                     {
6823                       /* dummy read of volatile operand */
6824                       if (isOperandVolatile (left, FALSE))
6825                         MOVA (aopGet (left, offset, FALSE, FALSE));
6826                       aopPut (result, zero, offset);
6827                       continue;
6828                     }
6829                   else if (AOP_TYPE (left) == AOP_ACC)
6830                     {
6831                       if (!offset)
6832                         {
6833                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6834                           aopPut (result, "a", offset);
6835                           continue;
6836                         }
6837                       else
6838                         {
6839                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6840                           aopPut (result, "b", offset);
6841                           continue;
6842                         }
6843                     }
6844                 }
6845               // faster than result <- left, anl result,right
6846               // and better if result is SFR
6847               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6848                   && AOP_TYPE(left)==AOP_ACC)
6849                 {
6850                   if (offset)
6851                     emitcode("mov", "a,b");
6852                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6853                 }
6854               else if (AOP_TYPE(left)==AOP_ACC)
6855                 {
6856                   if (!offset)
6857                     {
6858                       bool pushedB = pushB ();
6859                       emitcode("mov", "b,a");
6860                       MOVA (aopGet (right, offset, FALSE, FALSE));
6861                       emitcode("anl", "a,b");
6862                       popB (pushedB);
6863                     }
6864                   else
6865                     {
6866                       MOVA (aopGet (right, offset, FALSE, FALSE));
6867                       emitcode("anl", "a,b");
6868                     }
6869                 }
6870               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6871                 {
6872                   MOVB (aopGet (left, offset, FALSE, FALSE));
6873                   MOVA (aopGet (right, offset, FALSE, FALSE));
6874                   emitcode ("anl", "a,b");
6875                 }
6876               else if (aopGetUsesAcc (left, offset))
6877                 {
6878                   MOVA (aopGet (left, offset, FALSE, FALSE));
6879                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6880                 }
6881               else
6882                 {
6883                   MOVA (aopGet (right, offset, FALSE, FALSE));
6884                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6885                 }
6886               aopPut (result, "a", offset);
6887             }
6888         }
6889     }
6890
6891 release:
6892   freeAsmop (result, NULL, ic, TRUE);
6893   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6894   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6895 }
6896
6897 /*-----------------------------------------------------------------*/
6898 /* genOr  - code for or                                            */
6899 /*-----------------------------------------------------------------*/
6900 static void
6901 genOr (iCode * ic, iCode * ifx)
6902 {
6903   operand *left, *right, *result;
6904   int size, offset = 0;
6905   unsigned long lit = 0L;
6906   int bytelit = 0;
6907
6908   D (emitcode (";", "genOr"));
6909
6910   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6911   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6912   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6913
6914 #ifdef DEBUG_TYPE
6915   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6916             AOP_TYPE (result),
6917             AOP_TYPE (left), AOP_TYPE (right));
6918   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6919             AOP_SIZE (result),
6920             AOP_SIZE (left), AOP_SIZE (right));
6921 #endif
6922
6923   /* if left is a literal & right is not then exchange them */
6924   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6925       AOP_NEEDSACC (left))
6926     {
6927       operand *tmp = right;
6928       right = left;
6929       left = tmp;
6930     }
6931
6932   /* if result = right then exchange them */
6933   if (sameRegs (AOP (result), AOP (right)))
6934     {
6935       operand *tmp = right;
6936       right = left;
6937       left = tmp;
6938     }
6939
6940   /* if right is bit then exchange them */
6941   if (AOP_TYPE (right) == AOP_CRY &&
6942       AOP_TYPE (left) != AOP_CRY)
6943     {
6944       operand *tmp = right;
6945       right = left;
6946       left = tmp;
6947     }
6948   if (AOP_TYPE (right) == AOP_LIT)
6949     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6950
6951   size = AOP_SIZE (result);
6952
6953   // if(bit | yy)
6954   // xx = bit | yy;
6955   if (AOP_TYPE (left) == AOP_CRY)
6956     {
6957       if (AOP_TYPE (right) == AOP_LIT)
6958         {
6959           // c = bit | literal;
6960           if (lit)
6961             {
6962               // lit != 0 => result = 1
6963               if (AOP_TYPE (result) == AOP_CRY)
6964                 {
6965                   if (size)
6966                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6967                   else if (ifx)
6968                     continueIfTrue (ifx);
6969                   goto release;
6970                 }
6971               emitcode ("setb", "c");
6972             }
6973           else
6974             {
6975               // lit == 0 => result = left
6976               if (size && sameRegs (AOP (result), AOP (left)))
6977                 goto release;
6978               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6979             }
6980         }
6981       else
6982         {
6983           if (AOP_TYPE (right) == AOP_CRY)
6984             {
6985               // c = bit | bit;
6986               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6987               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6988             }
6989           else
6990             {
6991               // c = bit | val;
6992               symbol *tlbl = newiTempLabel (NULL);
6993               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6994                 emitcode ("setb", "c");
6995               emitcode ("jb", "%s,%05d$",
6996                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6997               toBoolean (right);
6998               emitcode ("jnz", "%05d$", tlbl->key + 100);
6999               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7000                 {
7001                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
7002                   goto release;
7003                 }
7004               else
7005                 {
7006                   CLRC;
7007                   emitLabel (tlbl);
7008                 }
7009             }
7010         }
7011       // bit = c
7012       // val = c
7013       if (size)
7014         outBitC (result);
7015       // if(bit | ...)
7016       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7017         genIfxJump (ifx, "c", left, right, result);
7018       goto release;
7019     }
7020
7021   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7022   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7023   if ((AOP_TYPE (right) == AOP_LIT) &&
7024       (AOP_TYPE (result) == AOP_CRY) &&
7025       (AOP_TYPE (left) != AOP_CRY))
7026     {
7027       if (lit)
7028         {
7029           // result = 1
7030           if (size)
7031             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7032           else
7033             continueIfTrue (ifx);
7034           goto release;
7035         }
7036       else
7037         {
7038           // lit = 0, result = boolean(left)
7039           if (size)
7040             emitcode ("setb", "c");
7041           toBoolean (right);
7042           if (size)
7043             {
7044               symbol *tlbl = newiTempLabel (NULL);
7045               emitcode ("jnz", "%05d$", tlbl->key + 100);
7046               CLRC;
7047               emitLabel (tlbl);
7048             }
7049           else
7050             {
7051               genIfxJump (ifx, "a", left, right, result);
7052               goto release;
7053             }
7054         }
7055       outBitC (result);
7056       goto release;
7057     }
7058
7059   /* if left is same as result */
7060   if (sameRegs (AOP (result), AOP (left)))
7061     {
7062       for (; size--; offset++)
7063         {
7064           if (AOP_TYPE (right) == AOP_LIT)
7065             {
7066               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7067               if (bytelit == 0)
7068                 {
7069                   /* dummy read of volatile operand */
7070                   if (isOperandVolatile (left, FALSE))
7071                     MOVA (aopGet (left, offset, FALSE, FALSE));
7072                   else
7073                     continue;
7074                 }
7075               else if (bytelit == 0x0FF)
7076                 {
7077                   aopPut (result, "#0xFF", offset);
7078                 }
7079               else if (IS_AOP_PREG (left))
7080                 {
7081                   MOVA (aopGet (left, offset, FALSE, TRUE));
7082                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7083                   aopPut (result, "a", offset);
7084                 }
7085               else
7086                 {
7087                   emitcode ("orl", "%s,%s",
7088                             aopGet (left, offset, FALSE, TRUE),
7089                             aopGet (right, offset, FALSE, FALSE));
7090                 }
7091             }
7092           else
7093             {
7094               if (AOP_TYPE (left) == AOP_ACC)
7095                 {
7096                   if (offset)
7097                     emitcode("mov", "a,b");
7098                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7099                 }
7100               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7101                 {
7102                   MOVB (aopGet (left, offset, FALSE, FALSE));
7103                   MOVA (aopGet (right, offset, FALSE, FALSE));
7104                   emitcode ("orl", "a,b");
7105                   aopPut (result, "a", offset);
7106                 }
7107               else if (aopGetUsesAcc (left, offset))
7108                 {
7109                   MOVA (aopGet (left, offset, FALSE, FALSE));
7110                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7111                   aopPut (result, "a", offset);
7112                 }
7113               else
7114                 {
7115                   MOVA (aopGet (right, offset, FALSE, FALSE));
7116                   if (IS_AOP_PREG (left))
7117                     {
7118                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7119                       aopPut (result, "a", offset);
7120                     }
7121                   else
7122                     {
7123                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7124                     }
7125                 }
7126             }
7127         }
7128     }
7129   else
7130     {
7131       // left & result in different registers
7132       if (AOP_TYPE (result) == AOP_CRY)
7133         {
7134           // result = bit
7135           // if(size), result in bit
7136           // if(!size && ifx), conditional oper: if(left | right)
7137           symbol *tlbl = newiTempLabel (NULL);
7138           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7139           if (size)
7140             emitcode ("setb", "c");
7141           while (sizer--)
7142             {
7143               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7144                   && AOP_TYPE(left)==AOP_ACC)
7145                 {
7146                   if (offset)
7147                     emitcode("mov", "a,b");
7148                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7149                 }
7150               else if (AOP_TYPE(left)==AOP_ACC)
7151                 {
7152                   if (!offset)
7153                     {
7154                       bool pushedB = pushB ();
7155                       emitcode("mov", "b,a");
7156                       MOVA (aopGet (right, offset, FALSE, FALSE));
7157                       emitcode("orl", "a,b");
7158                       popB (pushedB);
7159                     }
7160                   else
7161                     {
7162                       MOVA (aopGet (right, offset, FALSE, FALSE));
7163                       emitcode("orl", "a,b");
7164                     }
7165                 }
7166               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7167                 {
7168                   MOVB (aopGet (left, offset, FALSE, FALSE));
7169                   MOVA (aopGet (right, offset, FALSE, FALSE));
7170                   emitcode ("orl", "a,b");
7171                 }
7172               else if (aopGetUsesAcc (left, offset))
7173                 {
7174                   MOVA (aopGet (left, offset, FALSE, FALSE));
7175                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7176                 }
7177               else
7178                 {
7179                   MOVA (aopGet (right, offset, FALSE, FALSE));
7180                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7181               }
7182
7183               emitcode ("jnz", "%05d$", tlbl->key + 100);
7184               offset++;
7185             }
7186           if (size)
7187             {
7188               CLRC;
7189               emitLabel (tlbl);
7190               outBitC (result);
7191             }
7192           else if (ifx)
7193             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7194           else
7195             emitLabel (tlbl);
7196         }
7197       else
7198         {
7199           for (; (size--); offset++)
7200             {
7201               // normal case
7202               // result = left | right
7203               if (AOP_TYPE (right) == AOP_LIT)
7204                 {
7205                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7206                   if (bytelit == 0)
7207                     {
7208                       aopPut (result,
7209                               aopGet (left, offset, FALSE, FALSE),
7210                               offset);
7211                       continue;
7212                     }
7213                   else if (bytelit == 0x0FF)
7214                     {
7215                       /* dummy read of volatile operand */
7216                       if (isOperandVolatile (left, FALSE))
7217                         MOVA (aopGet (left, offset, FALSE, FALSE));
7218                       aopPut (result, "#0xFF", offset);
7219                       continue;
7220                     }
7221                 }
7222               // faster than result <- left, orl result,right
7223               // and better if result is SFR
7224               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7225                   && AOP_TYPE(left)==AOP_ACC)
7226                 {
7227                   if (offset)
7228                     emitcode("mov", "a,b");
7229                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7230                 }
7231               else if (AOP_TYPE(left)==AOP_ACC)
7232                 {
7233                   if (!offset)
7234                     {
7235                       bool pushedB = pushB ();
7236                       emitcode("mov", "b,a");
7237                       MOVA (aopGet (right, offset, FALSE, FALSE));
7238                       emitcode("orl", "a,b");
7239                       popB (pushedB);
7240                     }
7241                   else
7242                     {
7243                       MOVA (aopGet (right, offset, FALSE, FALSE));
7244                       emitcode("orl", "a,b");
7245                     }
7246                 }
7247               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7248                 {
7249                   MOVB (aopGet (left, offset, FALSE, FALSE));
7250                   MOVA (aopGet (right, offset, FALSE, FALSE));
7251                   emitcode ("orl", "a,b");
7252                 }
7253               else if (aopGetUsesAcc (left, offset))
7254                 {
7255                   MOVA (aopGet (left, offset, FALSE, FALSE));
7256                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7257                 }
7258               else
7259                 {
7260                   MOVA (aopGet (right, offset, FALSE, FALSE));
7261                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7262                 }
7263               aopPut (result, "a", offset);
7264             }
7265         }
7266     }
7267
7268 release:
7269   freeAsmop (result, NULL, ic, TRUE);
7270   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7271   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7272 }
7273
7274 /*-----------------------------------------------------------------*/
7275 /* genXor - code for xclusive or                                   */
7276 /*-----------------------------------------------------------------*/
7277 static void
7278 genXor (iCode * ic, iCode * ifx)
7279 {
7280   operand *left, *right, *result;
7281   int size, offset = 0;
7282   unsigned long lit = 0L;
7283   int bytelit = 0;
7284
7285   D (emitcode (";", "genXor"));
7286
7287   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7288   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7289   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7290
7291 #ifdef DEBUG_TYPE
7292   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7293             AOP_TYPE (result),
7294             AOP_TYPE (left), AOP_TYPE (right));
7295   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7296             AOP_SIZE (result),
7297             AOP_SIZE (left), AOP_SIZE (right));
7298 #endif
7299
7300   /* if left is a literal & right is not ||
7301      if left needs acc & right does not */
7302   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7303       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7304     {
7305       operand *tmp = right;
7306       right = left;
7307       left = tmp;
7308     }
7309
7310   /* if result = right then exchange them */
7311   if (sameRegs (AOP (result), AOP (right)))
7312     {
7313       operand *tmp = right;
7314       right = left;
7315       left = tmp;
7316     }
7317
7318   /* if right is bit then exchange them */
7319   if (AOP_TYPE (right) == AOP_CRY &&
7320       AOP_TYPE (left) != AOP_CRY)
7321     {
7322       operand *tmp = right;
7323       right = left;
7324       left = tmp;
7325     }
7326   if (AOP_TYPE (right) == AOP_LIT)
7327     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7328
7329   size = AOP_SIZE (result);
7330
7331   // if(bit ^ yy)
7332   // xx = bit ^ yy;
7333   if (AOP_TYPE (left) == AOP_CRY)
7334     {
7335       if (AOP_TYPE (right) == AOP_LIT)
7336         {
7337           // c = bit & literal;
7338           if (lit >> 1)
7339             {
7340               // lit>>1  != 0 => result = 1
7341               if (AOP_TYPE (result) == AOP_CRY)
7342                 {
7343                   if (size)
7344                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7345                   else if (ifx)
7346                     continueIfTrue (ifx);
7347                   goto release;
7348                 }
7349               emitcode ("setb", "c");
7350             }
7351           else
7352             {
7353               // lit == (0 or 1)
7354               if (lit == 0)
7355                 {
7356                   // lit == 0, result = left
7357                   if (size && sameRegs (AOP (result), AOP (left)))
7358                     goto release;
7359                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7360                 }
7361               else
7362                 {
7363                   // lit == 1, result = not(left)
7364                   if (size && sameRegs (AOP (result), AOP (left)))
7365                     {
7366                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7367                       goto release;
7368                     }
7369                   else
7370                     {
7371                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7372                       emitcode ("cpl", "c");
7373                     }
7374                 }
7375             }
7376         }
7377       else
7378         {
7379           // right != literal
7380           symbol *tlbl = newiTempLabel (NULL);
7381           if (AOP_TYPE (right) == AOP_CRY)
7382             {
7383               // c = bit ^ bit;
7384               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7385             }
7386           else
7387             {
7388               int sizer = AOP_SIZE (right);
7389               // c = bit ^ val
7390               // if val>>1 != 0, result = 1
7391               emitcode ("setb", "c");
7392               while (sizer)
7393                 {
7394                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7395                   if (sizer == 1)
7396                     // test the msb of the lsb
7397                     emitcode ("anl", "a,#0xfe");
7398                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7399                   sizer--;
7400                 }
7401               // val = (0,1)
7402               emitcode ("rrc", "a");
7403             }
7404           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7405           emitcode ("cpl", "c");
7406           emitLabel (tlbl);
7407         }
7408       // bit = c
7409       // val = c
7410       if (size)
7411         outBitC (result);
7412       // if(bit | ...)
7413       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7414         genIfxJump (ifx, "c", left, right, result);
7415       goto release;
7416     }
7417
7418   /* if left is same as result */
7419   if (sameRegs (AOP (result), AOP (left)))
7420     {
7421       for (; size--; offset++)
7422         {
7423           if (AOP_TYPE (right) == AOP_LIT)
7424             {
7425               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7426               if (bytelit == 0)
7427                 {
7428                   /* dummy read of volatile operand */
7429                   if (isOperandVolatile (left, FALSE))
7430                     MOVA (aopGet (left, offset, FALSE, FALSE));
7431                   else
7432                     continue;
7433                 }
7434               else if (IS_AOP_PREG (left))
7435                 {
7436                   MOVA (aopGet (left, offset, FALSE, TRUE));
7437                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7438                   aopPut (result, "a", offset);
7439                 }
7440               else
7441                 {
7442                   emitcode ("xrl", "%s,%s",
7443                             aopGet (left, offset, FALSE, TRUE),
7444                             aopGet (right, offset, FALSE, FALSE));
7445                 }
7446             }
7447           else
7448             {
7449               if (AOP_TYPE (left) == AOP_ACC)
7450                 {
7451                   if (offset)
7452                     emitcode("mov", "a,b");
7453                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7454                 }
7455               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7456                 {
7457                   MOVB (aopGet (left, offset, FALSE, FALSE));
7458                   MOVA (aopGet (right, offset, FALSE, FALSE));
7459                   emitcode ("xrl", "a,b");
7460                   aopPut (result, "a", offset);
7461                 }
7462               else if (aopGetUsesAcc (left, offset))
7463                 {
7464                   MOVA (aopGet (left, offset, FALSE, FALSE));
7465                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7466                   aopPut (result, "a", offset);
7467                 }
7468               else
7469                 {
7470                   MOVA (aopGet (right, offset, FALSE, FALSE));
7471                   if (IS_AOP_PREG (left))
7472                     {
7473                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7474                       aopPut (result, "a", offset);
7475                     }
7476                   else
7477                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7478                 }
7479             }
7480         }
7481     }
7482   else
7483     {
7484       // left & result in different registers
7485       if (AOP_TYPE (result) == AOP_CRY)
7486         {
7487           // result = bit
7488           // if(size), result in bit
7489           // if(!size && ifx), conditional oper: if(left ^ right)
7490           symbol *tlbl = newiTempLabel (NULL);
7491           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7492
7493           if (size)
7494             emitcode ("setb", "c");
7495           while (sizer--)
7496             {
7497               if ((AOP_TYPE (right) == AOP_LIT) &&
7498                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7499                 {
7500                   MOVA (aopGet (left, offset, FALSE, FALSE));
7501                 }
7502               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7503                   && AOP_TYPE(left)==AOP_ACC)
7504                 {
7505                   if (offset)
7506                     emitcode("mov", "a,b");
7507                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7508                 }
7509               else if (AOP_TYPE(left)==AOP_ACC)
7510                 {
7511                   if (!offset)
7512                     {
7513                       bool pushedB = pushB ();
7514                       emitcode("mov", "b,a");
7515                       MOVA (aopGet (right, offset, FALSE, FALSE));
7516                       emitcode("xrl", "a,b");
7517                       popB (pushedB);
7518                     }
7519                   else
7520                     {
7521                       MOVA (aopGet (right, offset, FALSE, FALSE));
7522                       emitcode("xrl", "a,b");
7523                     }
7524                 }
7525               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7526                 {
7527                   MOVB (aopGet (left, offset, FALSE, FALSE));
7528                   MOVA (aopGet (right, offset, FALSE, FALSE));
7529                   emitcode ("xrl", "a,b");
7530                 }
7531               else if (aopGetUsesAcc (left, offset))
7532                 {
7533                   MOVA (aopGet (left, offset, FALSE, FALSE));
7534                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7535                 }
7536               else
7537                 {
7538                   MOVA (aopGet (right, offset, FALSE, FALSE));
7539                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7540                 }
7541
7542               emitcode ("jnz", "%05d$", tlbl->key + 100);
7543               offset++;
7544             }
7545           if (size)
7546             {
7547               CLRC;
7548               emitLabel (tlbl);
7549               outBitC (result);
7550             }
7551           else if (ifx)
7552             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7553         }
7554       else
7555         {
7556           for (; (size--); offset++)
7557             {
7558               // normal case
7559               // result = left ^ right
7560               if (AOP_TYPE (right) == AOP_LIT)
7561                 {
7562                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7563                   if (bytelit == 0)
7564                     {
7565                       aopPut (result,
7566                               aopGet (left, offset, FALSE, FALSE),
7567                               offset);
7568                       continue;
7569                     }
7570                 }
7571               // faster than result <- left, xrl result,right
7572               // and better if result is SFR
7573               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7574                   && AOP_TYPE(left)==AOP_ACC)
7575                 {
7576                   if (offset)
7577                     emitcode("mov", "a,b");
7578                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7579                 }
7580               else if (AOP_TYPE(left)==AOP_ACC)
7581                 {
7582                   if (!offset)
7583                     {
7584                       bool pushedB = pushB ();
7585                       emitcode("mov", "b,a");
7586                       MOVA (aopGet (right, offset, FALSE, FALSE));
7587                       emitcode("xrl", "a,b");
7588                       popB (pushedB);
7589                     }
7590                   else
7591                     {
7592                       MOVA (aopGet (right, offset, FALSE, FALSE));
7593                       emitcode("xrl", "a,b");
7594                     }
7595                 }
7596               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7597                 {
7598                   MOVB (aopGet (left, offset, FALSE, FALSE));
7599                   MOVA (aopGet (right, offset, FALSE, FALSE));
7600                   emitcode ("xrl", "a,b");
7601                 }
7602               else if (aopGetUsesAcc (left, offset))
7603                 {
7604                   MOVA (aopGet (left, offset, FALSE, FALSE));
7605                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7606                 }
7607               else
7608                 {
7609                   MOVA (aopGet (right, offset, FALSE, FALSE));
7610                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7611                 }
7612               aopPut (result, "a", offset);
7613             }
7614         }
7615     }
7616
7617 release:
7618   freeAsmop (result, NULL, ic, TRUE);
7619   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7620   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7621 }
7622
7623 /*-----------------------------------------------------------------*/
7624 /* genInline - write the inline code out                           */
7625 /*-----------------------------------------------------------------*/
7626 static void
7627 genInline (iCode * ic)
7628 {
7629   char *buffer, *bp, *bp1;
7630
7631   D (emitcode (";", "genInline"));
7632
7633   _G.inLine += (!options.asmpeep);
7634
7635   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7636
7637   /* emit each line as a code */
7638   while (*bp)
7639     {
7640       if (*bp == '\n')
7641         {
7642           *bp++ = '\0';
7643           emitcode (bp1, "");
7644           bp1 = bp;
7645         }
7646       else
7647         {
7648           /* Add \n for labels, not dirs such as c:\mydir */
7649           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7650             {
7651               bp++;
7652               *bp = '\0';
7653               bp++;
7654               emitcode (bp1, "");
7655               bp1 = bp;
7656             }
7657           else
7658             bp++;
7659         }
7660     }
7661   if (bp1 != bp)
7662     emitcode (bp1, "");
7663   /*     emitcode("",buffer); */
7664   _G.inLine -= (!options.asmpeep);
7665 }
7666
7667 /*-----------------------------------------------------------------*/
7668 /* genRRC - rotate right with carry                                */
7669 /*-----------------------------------------------------------------*/
7670 static void
7671 genRRC (iCode * ic)
7672 {
7673   operand *left, *result;
7674   int size, offset;
7675   char *l;
7676
7677   D (emitcode (";", "genRRC"));
7678
7679   /* rotate right with carry */
7680   left = IC_LEFT (ic);
7681   result = IC_RESULT (ic);
7682   aopOp (left, ic, FALSE);
7683   aopOp (result, ic, FALSE);
7684
7685   /* move it to the result */
7686   size = AOP_SIZE (result);
7687   offset = size - 1;
7688   if (size == 1) { /* special case for 1 byte */
7689       l = aopGet (left, offset, FALSE, FALSE);
7690       MOVA (l);
7691       emitcode ("rr", "a");
7692       goto release;
7693   }
7694   /* no need to clear carry, bit7 will be written later */
7695   while (size--)
7696     {
7697       l = aopGet (left, offset, FALSE, FALSE);
7698       MOVA (l);
7699       emitcode ("rrc", "a");
7700       if (AOP_SIZE (result) > 1)
7701         aopPut (result, "a", offset--);
7702     }
7703   /* now we need to put the carry into the
7704      highest order byte of the result */
7705   if (AOP_SIZE (result) > 1)
7706     {
7707       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7708       MOVA (l);
7709     }
7710   emitcode ("mov", "acc.7,c");
7711  release:
7712   aopPut (result, "a", AOP_SIZE (result) - 1);
7713   freeAsmop (result, NULL, ic, TRUE);
7714   freeAsmop (left, NULL, ic, TRUE);
7715 }
7716
7717 /*-----------------------------------------------------------------*/
7718 /* genRLC - generate code for rotate left with carry               */
7719 /*-----------------------------------------------------------------*/
7720 static void
7721 genRLC (iCode * ic)
7722 {
7723   operand *left, *result;
7724   int size, offset;
7725   char *l;
7726
7727   D (emitcode (";", "genRLC"));
7728
7729   /* rotate right with carry */
7730   left = IC_LEFT (ic);
7731   result = IC_RESULT (ic);
7732   aopOp (left, ic, FALSE);
7733   aopOp (result, ic, FALSE);
7734
7735   /* move it to the result */
7736   size = AOP_SIZE (result);
7737   offset = 0;
7738   if (size--)
7739     {
7740       l = aopGet (left, offset, FALSE, FALSE);
7741       MOVA (l);
7742       if (size == 0) { /* special case for 1 byte */
7743               emitcode("rl","a");
7744               goto release;
7745       }
7746       emitcode("rlc","a"); /* bit0 will be written later */
7747       if (AOP_SIZE (result) > 1)
7748         {
7749           aopPut (result, "a", offset++);
7750         }
7751
7752       while (size--)
7753         {
7754           l = aopGet (left, offset, FALSE, FALSE);
7755           MOVA (l);
7756           emitcode ("rlc", "a");
7757           if (AOP_SIZE (result) > 1)
7758             aopPut (result, "a", offset++);
7759         }
7760     }
7761   /* now we need to put the carry into the
7762      highest order byte of the result */
7763   if (AOP_SIZE (result) > 1)
7764     {
7765       l = aopGet (result, 0, FALSE, FALSE);
7766       MOVA (l);
7767     }
7768   emitcode ("mov", "acc.0,c");
7769  release:
7770   aopPut (result, "a", 0);
7771   freeAsmop (result, NULL, ic, TRUE);
7772   freeAsmop (left, NULL, ic, TRUE);
7773 }
7774
7775 /*-----------------------------------------------------------------*/
7776 /* genGetHbit - generates code get highest order bit               */
7777 /*-----------------------------------------------------------------*/
7778 static void
7779 genGetHbit (iCode * ic)
7780 {
7781   operand *left, *result;
7782
7783   D (emitcode (";", "genGetHbit"));
7784
7785   left = IC_LEFT (ic);
7786   result = IC_RESULT (ic);
7787   aopOp (left, ic, FALSE);
7788   aopOp (result, ic, FALSE);
7789
7790   /* get the highest order byte into a */
7791   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7792   if (AOP_TYPE (result) == AOP_CRY)
7793     {
7794       emitcode ("rlc", "a");
7795       outBitC (result);
7796     }
7797   else
7798     {
7799       emitcode ("rl", "a");
7800       emitcode ("anl", "a,#0x01");
7801       outAcc (result);
7802     }
7803
7804   freeAsmop (result, NULL, ic, TRUE);
7805   freeAsmop (left, NULL, ic, TRUE);
7806 }
7807
7808 /*-----------------------------------------------------------------*/
7809 /* genGetAbit - generates code get a single bit                    */
7810 /*-----------------------------------------------------------------*/
7811 static void
7812 genGetAbit (iCode * ic)
7813 {
7814   operand *left, *right, *result;
7815   int shCount;
7816
7817   D (emitcode (";", "genGetAbit"));
7818
7819   left = IC_LEFT (ic);
7820   right = IC_RIGHT (ic);
7821   result = IC_RESULT (ic);
7822   aopOp (left, ic, FALSE);
7823   aopOp (right, ic, FALSE);
7824   aopOp (result, ic, FALSE);
7825
7826   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7827
7828   /* get the needed byte into a */
7829   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7830   shCount %= 8;
7831   if (AOP_TYPE (result) == AOP_CRY)
7832     {
7833       if ((shCount) == 7)
7834           emitcode ("rlc", "a");
7835       else if ((shCount) == 0)
7836           emitcode ("rrc", "a");
7837       else
7838           emitcode ("mov", "c,acc[%d]", shCount);
7839       outBitC (result);
7840     }
7841   else
7842     {
7843       switch (shCount)
7844         {
7845         case 2:
7846           emitcode ("rr", "a");
7847           //fallthrough
7848         case 1:
7849           emitcode ("rr", "a");
7850           //fallthrough
7851         case 0:
7852           emitcode ("anl", "a,#0x01");
7853           break;
7854         case 3:
7855         case 5:
7856           emitcode ("mov", "c,acc[%d]", shCount);
7857           emitcode ("clr", "a");
7858           emitcode ("rlc", "a");
7859           break;
7860         case 4:
7861           emitcode ("swap", "a");
7862           emitcode ("anl", "a,#0x01");
7863           break;
7864         case 6:
7865           emitcode ("rl", "a");
7866           //fallthrough
7867         case 7:
7868           emitcode ("rl", "a");
7869           emitcode ("anl", "a,#0x01");
7870           break;
7871         }
7872       outAcc (result);
7873     }
7874
7875   freeAsmop (result, NULL, ic, TRUE);
7876   freeAsmop (right, NULL, ic, TRUE);
7877   freeAsmop (left, NULL, ic, TRUE);
7878 }
7879
7880 /*-----------------------------------------------------------------*/
7881 /* genGetByte - generates code get a single byte                   */
7882 /*-----------------------------------------------------------------*/
7883 static void
7884 genGetByte (iCode * ic)
7885 {
7886   operand *left, *right, *result;
7887   int offset;
7888
7889   D (emitcode (";", "genGetByte"));
7890
7891   left = IC_LEFT (ic);
7892   right = IC_RIGHT (ic);
7893   result = IC_RESULT (ic);
7894   aopOp (left, ic, FALSE);
7895   aopOp (right, ic, FALSE);
7896   aopOp (result, ic, FALSE);
7897
7898   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7899   aopPut (result,
7900           aopGet (left, offset, FALSE, FALSE),
7901           0);
7902
7903   freeAsmop (result, NULL, ic, TRUE);
7904   freeAsmop (right, NULL, ic, TRUE);
7905   freeAsmop (left, NULL, ic, TRUE);
7906 }
7907
7908 /*-----------------------------------------------------------------*/
7909 /* genGetWord - generates code get two bytes                       */
7910 /*-----------------------------------------------------------------*/
7911 static void
7912 genGetWord (iCode * ic)
7913 {
7914   operand *left, *right, *result;
7915   int offset;
7916
7917   D (emitcode (";", "genGetWord"));
7918
7919   left = IC_LEFT (ic);
7920   right = IC_RIGHT (ic);
7921   result = IC_RESULT (ic);
7922   aopOp (left, ic, FALSE);
7923   aopOp (right, ic, FALSE);
7924   aopOp (result, ic, FALSE);
7925
7926   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7927   aopPut (result,
7928           aopGet (left, offset, FALSE, FALSE),
7929           0);
7930   aopPut (result,
7931           aopGet (left, offset+1, FALSE, FALSE),
7932           1);
7933
7934   freeAsmop (result, NULL, ic, TRUE);
7935   freeAsmop (right, NULL, ic, TRUE);
7936   freeAsmop (left, NULL, ic, TRUE);
7937 }
7938
7939 /*-----------------------------------------------------------------*/
7940 /* genSwap - generates code to swap nibbles or bytes               */
7941 /*-----------------------------------------------------------------*/
7942 static void
7943 genSwap (iCode * ic)
7944 {
7945   operand *left, *result;
7946
7947   D(emitcode (";     genSwap",""));
7948
7949   left = IC_LEFT (ic);
7950   result = IC_RESULT (ic);
7951   aopOp (left, ic, FALSE);
7952   aopOp (result, ic, FALSE);
7953
7954   switch (AOP_SIZE (left))
7955     {
7956     case 1: /* swap nibbles in byte */
7957       MOVA (aopGet (left, 0, FALSE, FALSE));
7958       emitcode ("swap", "a");
7959       aopPut (result, "a", 0);
7960       break;
7961     case 2: /* swap bytes in word */
7962       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7963         {
7964           MOVA (aopGet (left, 0, FALSE, FALSE));
7965           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7966           aopPut (result, "a", 1);
7967         }
7968       else if (operandsEqu (left, result))
7969         {
7970           char * reg = "a";
7971           bool pushedB = FALSE, leftInB = FALSE;
7972
7973           MOVA (aopGet (left, 0, FALSE, FALSE));
7974           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7975             {
7976               pushedB = pushB ();
7977               emitcode ("mov", "b,a");
7978               reg = "b";
7979               leftInB = TRUE;
7980             }
7981           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7982           aopPut (result, reg, 1);
7983
7984           if (leftInB)
7985             popB (pushedB);
7986         }
7987       else
7988         {
7989           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7990           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7991         }
7992       break;
7993     default:
7994       wassertl(FALSE, "unsupported SWAP operand size");
7995     }
7996
7997   freeAsmop (result, NULL, ic, TRUE);
7998   freeAsmop (left, NULL, ic, TRUE);
7999 }
8000
8001 /*-----------------------------------------------------------------*/
8002 /* AccRol - rotate left accumulator by known count                 */
8003 /*-----------------------------------------------------------------*/
8004 static void
8005 AccRol (int shCount)
8006 {
8007   shCount &= 0x0007;            // shCount : 0..7
8008
8009   switch (shCount)
8010     {
8011     case 0:
8012       break;
8013     case 1:
8014       emitcode ("rl", "a");
8015       break;
8016     case 2:
8017       emitcode ("rl", "a");
8018       emitcode ("rl", "a");
8019       break;
8020     case 3:
8021       emitcode ("swap", "a");
8022       emitcode ("rr", "a");
8023       break;
8024     case 4:
8025       emitcode ("swap", "a");
8026       break;
8027     case 5:
8028       emitcode ("swap", "a");
8029       emitcode ("rl", "a");
8030       break;
8031     case 6:
8032       emitcode ("rr", "a");
8033       emitcode ("rr", "a");
8034       break;
8035     case 7:
8036       emitcode ("rr", "a");
8037       break;
8038     }
8039 }
8040
8041 /*-----------------------------------------------------------------*/
8042 /* AccLsh - left shift accumulator by known count                  */
8043 /*-----------------------------------------------------------------*/
8044 static void
8045 AccLsh (int shCount)
8046 {
8047   if (shCount != 0)
8048     {
8049       if (shCount == 1)
8050         emitcode ("add", "a,acc");
8051       else if (shCount == 2)
8052         {
8053           emitcode ("add", "a,acc");
8054           emitcode ("add", "a,acc");
8055         }
8056       else
8057         {
8058           /* rotate left accumulator */
8059           AccRol (shCount);
8060           /* and kill the lower order bits */
8061           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8062         }
8063     }
8064 }
8065
8066 /*-----------------------------------------------------------------*/
8067 /* AccRsh - right shift accumulator by known count                 */
8068 /*-----------------------------------------------------------------*/
8069 static void
8070 AccRsh (int shCount)
8071 {
8072   if (shCount != 0)
8073     {
8074       if (shCount == 1)
8075         {
8076           CLRC;
8077           emitcode ("rrc", "a");
8078         }
8079       else
8080         {
8081           /* rotate right accumulator */
8082           AccRol (8 - shCount);
8083           /* and kill the higher order bits */
8084           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8085         }
8086     }
8087 }
8088
8089 /*-----------------------------------------------------------------*/
8090 /* AccSRsh - signed right shift accumulator by known count                 */
8091 /*-----------------------------------------------------------------*/
8092 static void
8093 AccSRsh (int shCount)
8094 {
8095   symbol *tlbl;
8096   if (shCount != 0)
8097     {
8098       if (shCount == 1)
8099         {
8100           emitcode ("mov", "c,acc.7");
8101           emitcode ("rrc", "a");
8102         }
8103       else if (shCount == 2)
8104         {
8105           emitcode ("mov", "c,acc.7");
8106           emitcode ("rrc", "a");
8107           emitcode ("mov", "c,acc.7");
8108           emitcode ("rrc", "a");
8109         }
8110       else
8111         {
8112           tlbl = newiTempLabel (NULL);
8113           /* rotate right accumulator */
8114           AccRol (8 - shCount);
8115           /* and kill the higher order bits */
8116           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8117           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8118           emitcode ("orl", "a,#0x%02x",
8119                     (unsigned char) ~SRMask[shCount]);
8120           emitLabel (tlbl);
8121         }
8122     }
8123 }
8124
8125 /*-----------------------------------------------------------------*/
8126 /* shiftR1Left2Result - shift right one byte from left to result   */
8127 /*-----------------------------------------------------------------*/
8128 static void
8129 shiftR1Left2Result (operand * left, int offl,
8130                     operand * result, int offr,
8131                     int shCount, int sign)
8132 {
8133   MOVA (aopGet (left, offl, FALSE, FALSE));
8134   /* shift right accumulator */
8135   if (sign)
8136     AccSRsh (shCount);
8137   else
8138     AccRsh (shCount);
8139   aopPut (result, "a", offr);
8140 }
8141
8142 /*-----------------------------------------------------------------*/
8143 /* shiftL1Left2Result - shift left one byte from left to result    */
8144 /*-----------------------------------------------------------------*/
8145 static void
8146 shiftL1Left2Result (operand * left, int offl,
8147                     operand * result, int offr, int shCount)
8148 {
8149   char *l;
8150   l = aopGet (left, offl, FALSE, FALSE);
8151   MOVA (l);
8152   /* shift left accumulator */
8153   AccLsh (shCount);
8154   aopPut (result, "a", offr);
8155 }
8156
8157 /*-----------------------------------------------------------------*/
8158 /* movLeft2Result - move byte from left to result                  */
8159 /*-----------------------------------------------------------------*/
8160 static void
8161 movLeft2Result (operand * left, int offl,
8162                 operand * result, int offr, int sign)
8163 {
8164   char *l;
8165   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8166     {
8167       l = aopGet (left, offl, FALSE, FALSE);
8168
8169       if (*l == '@' && (IS_AOP_PREG (result)))
8170         {
8171           emitcode ("mov", "a,%s", l);
8172           aopPut (result, "a", offr);
8173         }
8174       else
8175         {
8176           if (!sign)
8177             {
8178               aopPut (result, l, offr);
8179             }
8180           else
8181             {
8182               /* MSB sign in acc.7 ! */
8183               if (getDataSize (left) == offl + 1)
8184                 {
8185                   MOVA (l);
8186                   aopPut (result, "a", offr);
8187                 }
8188             }
8189         }
8190     }
8191 }
8192
8193 /*-----------------------------------------------------------------*/
8194 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8195 /*-----------------------------------------------------------------*/
8196 static void
8197 AccAXRrl1 (char *x)
8198 {
8199   emitcode ("rrc", "a");
8200   emitcode ("xch", "a,%s", x);
8201   emitcode ("rrc", "a");
8202   emitcode ("xch", "a,%s", x);
8203 }
8204
8205 /*-----------------------------------------------------------------*/
8206 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8207 /*-----------------------------------------------------------------*/
8208 static void
8209 AccAXLrl1 (char *x)
8210 {
8211   emitcode ("xch", "a,%s", x);
8212   emitcode ("rlc", "a");
8213   emitcode ("xch", "a,%s", x);
8214   emitcode ("rlc", "a");
8215 }
8216
8217 /*-----------------------------------------------------------------*/
8218 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8219 /*-----------------------------------------------------------------*/
8220 static void
8221 AccAXLsh1 (char *x)
8222 {
8223   emitcode ("xch", "a,%s", x);
8224   emitcode ("add", "a,acc");
8225   emitcode ("xch", "a,%s", x);
8226   emitcode ("rlc", "a");
8227 }
8228
8229 /*-----------------------------------------------------------------*/
8230 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8231 /*-----------------------------------------------------------------*/
8232 static void
8233 AccAXLsh (char *x, int shCount)
8234 {
8235   switch (shCount)
8236     {
8237     case 0:
8238       break;
8239     case 1:
8240       AccAXLsh1 (x);
8241       break;
8242     case 2:
8243       AccAXLsh1 (x);
8244       AccAXLsh1 (x);
8245       break;
8246     case 3:
8247     case 4:
8248     case 5:                     // AAAAABBB:CCCCCDDD
8249
8250       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8251
8252       emitcode ("anl", "a,#0x%02x",
8253                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8254
8255       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8256
8257       AccRol (shCount);         // DDDCCCCC:BBB00000
8258
8259       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8260
8261       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8262
8263       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8264
8265       emitcode ("anl", "a,#0x%02x",
8266                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8267
8268       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8269
8270       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8271
8272       break;
8273     case 6:                     // AAAAAABB:CCCCCCDD
8274       emitcode ("anl", "a,#0x%02x",
8275                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8276       emitcode ("mov", "c,acc.0");      // c = B
8277       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8278 #if 0 // REMOVE ME
8279       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8280       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8281 #else
8282       emitcode("rrc","a");
8283       emitcode("xch","a,%s", x);
8284       emitcode("rrc","a");
8285       emitcode("mov","c,acc.0"); //<< get correct bit
8286       emitcode("xch","a,%s", x);
8287
8288       emitcode("rrc","a");
8289       emitcode("xch","a,%s", x);
8290       emitcode("rrc","a");
8291       emitcode("xch","a,%s", x);
8292 #endif
8293       break;
8294     case 7:                     // a:x <<= 7
8295
8296       emitcode ("anl", "a,#0x%02x",
8297                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8298
8299       emitcode ("mov", "c,acc.0");      // c = B
8300
8301       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8302
8303       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8304
8305       break;
8306     default:
8307       break;
8308     }
8309 }
8310
8311 /*-----------------------------------------------------------------*/
8312 /* AccAXRsh - right shift a:x known count (0..7)                   */
8313 /*-----------------------------------------------------------------*/
8314 static void
8315 AccAXRsh (char *x, int shCount)
8316 {
8317   switch (shCount)
8318     {
8319     case 0:
8320       break;
8321     case 1:
8322       CLRC;
8323       AccAXRrl1 (x);            // 0->a:x
8324
8325       break;
8326     case 2:
8327       CLRC;
8328       AccAXRrl1 (x);            // 0->a:x
8329
8330       CLRC;
8331       AccAXRrl1 (x);            // 0->a:x
8332
8333       break;
8334     case 3:
8335     case 4:
8336     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8337
8338       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8339
8340       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8341
8342       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8343
8344       emitcode ("anl", "a,#0x%02x",
8345                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8346
8347       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8348
8349       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8350
8351       emitcode ("anl", "a,#0x%02x",
8352                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8353
8354       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8355
8356       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8357
8358       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8359
8360       break;
8361     case 6:                     // AABBBBBB:CCDDDDDD
8362
8363       emitcode ("mov", "c,acc.7");
8364       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8365
8366       emitcode ("mov", "c,acc.7");
8367       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8368
8369       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8370
8371       emitcode ("anl", "a,#0x%02x",
8372                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8373
8374       break;
8375     case 7:                     // ABBBBBBB:CDDDDDDD
8376
8377       emitcode ("mov", "c,acc.7");      // c = A
8378
8379       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8380
8381       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8382
8383       emitcode ("anl", "a,#0x%02x",
8384                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8385
8386       break;
8387     default:
8388       break;
8389     }
8390 }
8391
8392 /*-----------------------------------------------------------------*/
8393 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8394 /*-----------------------------------------------------------------*/
8395 static void
8396 AccAXRshS (char *x, int shCount)
8397 {
8398   symbol *tlbl;
8399   switch (shCount)
8400     {
8401     case 0:
8402       break;
8403     case 1:
8404       emitcode ("mov", "c,acc.7");
8405       AccAXRrl1 (x);            // s->a:x
8406
8407       break;
8408     case 2:
8409       emitcode ("mov", "c,acc.7");
8410       AccAXRrl1 (x);            // s->a:x
8411
8412       emitcode ("mov", "c,acc.7");
8413       AccAXRrl1 (x);            // s->a:x
8414
8415       break;
8416     case 3:
8417     case 4:
8418     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8419
8420       tlbl = newiTempLabel (NULL);
8421       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8422
8423       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8424
8425       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8426
8427       emitcode ("anl", "a,#0x%02x",
8428                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8429
8430       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8431
8432       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8433
8434       emitcode ("anl", "a,#0x%02x",
8435                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8436
8437       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8438
8439       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8440
8441       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8442
8443       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8444       emitcode ("orl", "a,#0x%02x",
8445                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8446
8447       emitLabel (tlbl);
8448       break;                    // SSSSAAAA:BBBCCCCC
8449
8450     case 6:                     // AABBBBBB:CCDDDDDD
8451
8452       tlbl = newiTempLabel (NULL);
8453       emitcode ("mov", "c,acc.7");
8454       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8455
8456       emitcode ("mov", "c,acc.7");
8457       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8458
8459       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8460
8461       emitcode ("anl", "a,#0x%02x",
8462                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8463
8464       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8465       emitcode ("orl", "a,#0x%02x",
8466                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8467
8468       emitLabel (tlbl);
8469       break;
8470     case 7:                     // ABBBBBBB:CDDDDDDD
8471
8472       tlbl = newiTempLabel (NULL);
8473       emitcode ("mov", "c,acc.7");      // c = A
8474
8475       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8476
8477       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8478
8479       emitcode ("anl", "a,#0x%02x",
8480                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8481
8482       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8483       emitcode ("orl", "a,#0x%02x",
8484                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8485
8486       emitLabel (tlbl);
8487       break;
8488     default:
8489       break;
8490     }
8491 }
8492
8493 /*-----------------------------------------------------------------*/
8494 /* shiftL2Left2Result - shift left two bytes from left to result   */
8495 /*-----------------------------------------------------------------*/
8496 static void
8497 shiftL2Left2Result (operand * left, int offl,
8498                     operand * result, int offr, int shCount)
8499 {
8500   char * x;
8501   bool pushedB = FALSE;
8502   bool usedB = FALSE;
8503
8504   if (sameRegs (AOP (result), AOP (left)) &&
8505       ((offl + MSB16) == offr))
8506     {
8507       /* don't crash result[offr] */
8508       MOVA (aopGet (left, offl, FALSE, FALSE));
8509       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8510       usedB = !strncmp(x, "b", 1);
8511     }
8512   else if (aopGetUsesAcc (result, offr))
8513     {
8514       movLeft2Result (left, offl, result, offr, 0);
8515       pushedB = pushB ();
8516       usedB = TRUE;
8517       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8518       MOVA (aopGet (result, offr, FALSE, FALSE));
8519       emitcode ("xch", "a,b");
8520       x = "b";
8521     }
8522   else
8523     {
8524       movLeft2Result (left, offl, result, offr, 0);
8525       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8526       x = aopGet (result, offr, FALSE, FALSE);
8527     }
8528   /* ax << shCount (x = lsb(result)) */
8529   AccAXLsh (x, shCount);
8530   if (usedB)
8531     {
8532       emitcode ("xch", "a,b");
8533       aopPut (result, "a", offr);
8534       aopPut (result, "b", offr + MSB16);
8535       popB (pushedB);
8536     }
8537   else
8538     {
8539       aopPut (result, "a", offr + MSB16);
8540     }
8541 }
8542
8543
8544 /*-----------------------------------------------------------------*/
8545 /* shiftR2Left2Result - shift right two bytes from left to result  */
8546 /*-----------------------------------------------------------------*/
8547 static void
8548 shiftR2Left2Result (operand * left, int offl,
8549                     operand * result, int offr,
8550                     int shCount, int sign)
8551 {
8552   char * x;
8553   bool pushedB = FALSE;
8554   bool usedB = FALSE;
8555
8556   if (sameRegs (AOP (result), AOP (left)) &&
8557       ((offl + MSB16) == offr))
8558     {
8559       /* don't crash result[offr] */
8560       MOVA (aopGet (left, offl, FALSE, FALSE));
8561       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8562       usedB = !strncmp(x, "b", 1);
8563     }
8564   else if (aopGetUsesAcc (result, offr))
8565     {
8566       movLeft2Result (left, offl, result, offr, 0);
8567       pushedB = pushB ();
8568       usedB = TRUE;
8569       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8570       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8571       x = "b";
8572     }
8573   else
8574     {
8575       movLeft2Result (left, offl, result, offr, 0);
8576       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8577       x = aopGet (result, offr, FALSE, FALSE);
8578     }
8579   /* a:x >> shCount (x = lsb(result)) */
8580   if (sign)
8581     AccAXRshS (x, shCount);
8582   else
8583     AccAXRsh (x, shCount);
8584   if (usedB)
8585     {
8586       emitcode ("xch", "a,b");
8587       aopPut (result, "a", offr);
8588       emitcode ("xch", "a,b");
8589       popB (pushedB);
8590     }
8591   if (getDataSize (result) > 1)
8592     aopPut (result, "a", offr + MSB16);
8593 }
8594
8595 /*-----------------------------------------------------------------*/
8596 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8597 /*-----------------------------------------------------------------*/
8598 static void
8599 shiftLLeftOrResult (operand * left, int offl,
8600                     operand * result, int offr, int shCount)
8601 {
8602   MOVA (aopGet (left, offl, FALSE, FALSE));
8603   /* shift left accumulator */
8604   AccLsh (shCount);
8605   /* or with result */
8606   if (aopGetUsesAcc (result, offr))
8607     {
8608       emitcode ("xch", "a,b");
8609       MOVA (aopGet (result, offr, FALSE, FALSE));
8610       emitcode ("orl", "a,b");
8611     }
8612   else
8613     {
8614       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8615     }
8616   /* back to result */
8617   aopPut (result, "a", offr);
8618 }
8619
8620 /*-----------------------------------------------------------------*/
8621 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8622 /*-----------------------------------------------------------------*/
8623 static void
8624 shiftRLeftOrResult (operand * left, int offl,
8625                     operand * result, int offr, int shCount)
8626 {
8627   MOVA (aopGet (left, offl, FALSE, FALSE));
8628   /* shift right accumulator */
8629   AccRsh (shCount);
8630   /* or with result */
8631   if (aopGetUsesAcc(result, offr))
8632     {
8633       emitcode ("xch", "a,b");
8634       MOVA (aopGet (result, offr, FALSE, FALSE));
8635       emitcode ("orl", "a,b");
8636     }
8637   else
8638     {
8639       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8640     }
8641   /* back to result */
8642   aopPut (result, "a", offr);
8643 }
8644
8645 /*-----------------------------------------------------------------*/
8646 /* genlshOne - left shift a one byte quantity by known count       */
8647 /*-----------------------------------------------------------------*/
8648 static void
8649 genlshOne (operand * result, operand * left, int shCount)
8650 {
8651   D (emitcode (";", "genlshOne"));
8652
8653   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8654 }
8655
8656 /*-----------------------------------------------------------------*/
8657 /* genlshTwo - left shift two bytes by known amount != 0           */
8658 /*-----------------------------------------------------------------*/
8659 static void
8660 genlshTwo (operand * result, operand * left, int shCount)
8661 {
8662   int size;
8663
8664   D (emitcode (";", "genlshTwo"));
8665
8666   size = getDataSize (result);
8667
8668   /* if shCount >= 8 */
8669   if (shCount >= 8)
8670     {
8671       shCount -= 8;
8672
8673       if (size > 1)
8674         {
8675           if (shCount)
8676             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8677           else
8678             movLeft2Result (left, LSB, result, MSB16, 0);
8679         }
8680       aopPut (result, zero, LSB);
8681     }
8682
8683   /*  1 <= shCount <= 7 */
8684   else
8685     {
8686       if (size == 1)
8687         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8688       else
8689         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8690     }
8691 }
8692
8693 /*-----------------------------------------------------------------*/
8694 /* shiftLLong - shift left one long from left to result            */
8695 /* offl = LSB or MSB16                                             */
8696 /*-----------------------------------------------------------------*/
8697 static void
8698 shiftLLong (operand * left, operand * result, int offr)
8699 {
8700   char *l;
8701   int size = AOP_SIZE (result);
8702
8703   if (size >= LSB + offr)
8704     {
8705       l = aopGet (left, LSB, FALSE, FALSE);
8706       MOVA (l);
8707       emitcode ("add", "a,acc");
8708       if (sameRegs (AOP (left), AOP (result)) &&
8709           size >= MSB16 + offr && offr != LSB)
8710         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8711       else
8712         aopPut (result, "a", LSB + offr);
8713     }
8714
8715   if (size >= MSB16 + offr)
8716     {
8717       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8718         {
8719           l = aopGet (left, MSB16, FALSE, FALSE);
8720           MOVA (l);
8721         }
8722       emitcode ("rlc", "a");
8723       if (sameRegs (AOP (left), AOP (result)) &&
8724           size >= MSB24 + offr && offr != LSB)
8725         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8726       else
8727         aopPut (result, "a", MSB16 + offr);
8728     }
8729
8730   if (size >= MSB24 + offr)
8731     {
8732       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8733         {
8734           l = aopGet (left, MSB24, FALSE, FALSE);
8735           MOVA (l);
8736         }
8737       emitcode ("rlc", "a");
8738       if (sameRegs (AOP (left), AOP (result)) &&
8739           size >= MSB32 + offr && offr != LSB)
8740         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8741       else
8742         aopPut (result, "a", MSB24 + offr);
8743     }
8744
8745   if (size > MSB32 + offr)
8746     {
8747       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8748         {
8749           l = aopGet (left, MSB32, FALSE, FALSE);
8750           MOVA (l);
8751         }
8752       emitcode ("rlc", "a");
8753       aopPut (result, "a", MSB32 + offr);
8754     }
8755   if (offr != LSB)
8756     aopPut (result, zero, LSB);
8757 }
8758
8759 /*-----------------------------------------------------------------*/
8760 /* genlshFour - shift four byte by a known amount != 0             */
8761 /*-----------------------------------------------------------------*/
8762 static void
8763 genlshFour (operand * result, operand * left, int shCount)
8764 {
8765   int size;
8766
8767   D (emitcode (";", "genlshFour"));
8768
8769   size = AOP_SIZE (result);
8770
8771   /* if shifting more that 3 bytes */
8772   if (shCount >= 24)
8773     {
8774       shCount -= 24;
8775       if (shCount)
8776         /* lowest order of left goes to the highest
8777            order of the destination */
8778         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8779       else
8780         movLeft2Result (left, LSB, result, MSB32, 0);
8781       aopPut (result, zero, LSB);
8782       aopPut (result, zero, MSB16);
8783       aopPut (result, zero, MSB24);
8784       return;
8785     }
8786
8787   /* more than two bytes */
8788   else if (shCount >= 16)
8789     {
8790       /* lower order two bytes goes to higher order two bytes */
8791       shCount -= 16;
8792       /* if some more remaining */
8793       if (shCount)
8794         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8795       else
8796         {
8797           movLeft2Result (left, MSB16, result, MSB32, 0);
8798           movLeft2Result (left, LSB, result, MSB24, 0);
8799         }
8800       aopPut (result, zero, MSB16);
8801       aopPut (result, zero, LSB);
8802       return;
8803     }
8804
8805   /* if more than 1 byte */
8806   else if (shCount >= 8)
8807     {
8808       /* lower order three bytes goes to higher order  three bytes */
8809       shCount -= 8;
8810       if (size == 2)
8811         {
8812           if (shCount)
8813             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8814           else
8815             movLeft2Result (left, LSB, result, MSB16, 0);
8816         }
8817       else
8818         {                       /* size = 4 */
8819           if (shCount == 0)
8820             {
8821               movLeft2Result (left, MSB24, result, MSB32, 0);
8822               movLeft2Result (left, MSB16, result, MSB24, 0);
8823               movLeft2Result (left, LSB, result, MSB16, 0);
8824               aopPut (result, zero, LSB);
8825             }
8826           else if (shCount == 1)
8827             shiftLLong (left, result, MSB16);
8828           else
8829             {
8830               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8831               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8832               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8833               aopPut (result, zero, LSB);
8834             }
8835         }
8836     }
8837
8838   /* 1 <= shCount <= 7 */
8839   else if (shCount <= 2)
8840     {
8841       shiftLLong (left, result, LSB);
8842       if (shCount == 2)
8843         shiftLLong (result, result, LSB);
8844     }
8845   /* 3 <= shCount <= 7, optimize */
8846   else
8847     {
8848       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8849       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8850       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8851     }
8852 }
8853
8854 /*-----------------------------------------------------------------*/
8855 /* genLeftShiftLiteral - left shifting by known count              */
8856 /*-----------------------------------------------------------------*/
8857 static void
8858 genLeftShiftLiteral (operand * left,
8859                      operand * right,
8860                      operand * result,
8861                      iCode * ic)
8862 {
8863   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8864   int size;
8865
8866   D (emitcode (";", "genLeftShiftLiteral"));
8867
8868   freeAsmop (right, NULL, ic, TRUE);
8869
8870   aopOp (left, ic, FALSE);
8871   aopOp (result, ic, FALSE);
8872
8873   size = getSize (operandType (result));
8874
8875 #if VIEW_SIZE
8876   emitcode ("; shift left ", "result %d, left %d", size,
8877             AOP_SIZE (left));
8878 #endif
8879
8880   /* I suppose that the left size >= result size */
8881   if (shCount == 0)
8882     {
8883       while (size--)
8884         {
8885           movLeft2Result (left, size, result, size, 0);
8886         }
8887     }
8888   else if (shCount >= (size * 8))
8889     {
8890       while (size--)
8891         {
8892           aopPut (result, zero, size);
8893         }
8894     }
8895   else
8896     {
8897       switch (size)
8898         {
8899         case 1:
8900           genlshOne (result, left, shCount);
8901           break;
8902
8903         case 2:
8904           genlshTwo (result, left, shCount);
8905           break;
8906
8907         case 4:
8908           genlshFour (result, left, shCount);
8909           break;
8910         default:
8911           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8912                   "*** ack! mystery literal shift!\n");
8913           break;
8914         }
8915     }
8916   freeAsmop (result, NULL, ic, TRUE);
8917   freeAsmop (left, NULL, ic, TRUE);
8918 }
8919
8920 /*-----------------------------------------------------------------*/
8921 /* genLeftShift - generates code for left shifting                 */
8922 /*-----------------------------------------------------------------*/
8923 static void
8924 genLeftShift (iCode * ic)
8925 {
8926   operand *left, *right, *result;
8927   int size, offset;
8928   char *l;
8929   symbol *tlbl, *tlbl1;
8930   bool pushedB;
8931
8932   D (emitcode (";", "genLeftShift"));
8933
8934   right = IC_RIGHT (ic);
8935   left = IC_LEFT (ic);
8936   result = IC_RESULT (ic);
8937
8938   aopOp (right, ic, FALSE);
8939
8940   /* if the shift count is known then do it
8941      as efficiently as possible */
8942   if (AOP_TYPE (right) == AOP_LIT)
8943     {
8944       genLeftShiftLiteral (left, right, result, ic);
8945       return;
8946     }
8947
8948   /* shift count is unknown then we have to form
8949      a loop get the loop count in B : Note: we take
8950      only the lower order byte since shifting
8951      more that 32 bits make no sense anyway, ( the
8952      largest size of an object can be only 32 bits ) */
8953
8954   pushedB = pushB ();
8955   MOVB (aopGet (right, 0, FALSE, FALSE));
8956   emitcode ("inc", "b");
8957   freeAsmop (right, NULL, ic, TRUE);
8958   aopOp (left, ic, FALSE);
8959   aopOp (result, ic, FALSE);
8960
8961   /* now move the left to the result if they are not the same */
8962   if (!sameRegs (AOP (left), AOP (result)) &&
8963       AOP_SIZE (result) > 1)
8964     {
8965
8966       size = AOP_SIZE (result);
8967       offset = 0;
8968       while (size--)
8969         {
8970           l = aopGet (left, offset, FALSE, TRUE);
8971           if (*l == '@' && (IS_AOP_PREG (result)))
8972             {
8973
8974               emitcode ("mov", "a,%s", l);
8975               aopPut (result, "a", offset);
8976             }
8977           else
8978             aopPut (result, l, offset);
8979           offset++;
8980         }
8981     }
8982
8983   tlbl = newiTempLabel (NULL);
8984   size = AOP_SIZE (result);
8985   offset = 0;
8986   tlbl1 = newiTempLabel (NULL);
8987
8988   /* if it is only one byte then */
8989   if (size == 1)
8990     {
8991       symbol *tlbl1 = newiTempLabel (NULL);
8992
8993       l = aopGet (left, 0, FALSE, FALSE);
8994       MOVA (l);
8995       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8996       emitLabel (tlbl);
8997       emitcode ("add", "a,acc");
8998       emitLabel (tlbl1);
8999       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9000       popB (pushedB);
9001       aopPut (result, "a", 0);
9002       goto release;
9003     }
9004
9005   reAdjustPreg (AOP (result));
9006
9007   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9008   emitLabel (tlbl);
9009   l = aopGet (result, offset, FALSE, FALSE);
9010   MOVA (l);
9011   emitcode ("add", "a,acc");
9012   aopPut (result, "a", offset++);
9013   while (--size)
9014     {
9015       l = aopGet (result, offset, FALSE, FALSE);
9016       MOVA (l);
9017       emitcode ("rlc", "a");
9018       aopPut (result, "a", offset++);
9019     }
9020   reAdjustPreg (AOP (result));
9021
9022   emitLabel (tlbl1);
9023   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9024   popB (pushedB);
9025 release:
9026   freeAsmop (result, NULL, ic, TRUE);
9027   freeAsmop (left, NULL, ic, TRUE);
9028 }
9029
9030 /*-----------------------------------------------------------------*/
9031 /* genrshOne - right shift a one byte quantity by known count      */
9032 /*-----------------------------------------------------------------*/
9033 static void
9034 genrshOne (operand * result, operand * left,
9035            int shCount, int sign)
9036 {
9037   D (emitcode (";", "genrshOne"));
9038
9039   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9040 }
9041
9042 /*-----------------------------------------------------------------*/
9043 /* genrshTwo - right shift two bytes by known amount != 0          */
9044 /*-----------------------------------------------------------------*/
9045 static void
9046 genrshTwo (operand * result, operand * left,
9047            int shCount, int sign)
9048 {
9049   D (emitcode (";", "genrshTwo"));
9050
9051   /* if shCount >= 8 */
9052   if (shCount >= 8)
9053     {
9054       shCount -= 8;
9055       if (shCount)
9056         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9057       else
9058         movLeft2Result (left, MSB16, result, LSB, sign);
9059       addSign (result, MSB16, sign);
9060     }
9061
9062   /*  1 <= shCount <= 7 */
9063   else
9064     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9065 }
9066
9067 /*-----------------------------------------------------------------*/
9068 /* shiftRLong - shift right one long from left to result           */
9069 /* offl = LSB or MSB16                                             */
9070 /*-----------------------------------------------------------------*/
9071 static void
9072 shiftRLong (operand * left, int offl,
9073             operand * result, int sign)
9074 {
9075   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9076
9077   if (overlapping && offl>1)
9078     {
9079       // we are in big trouble, but this shouldn't happen
9080       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9081     }
9082
9083   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9084
9085   if (offl==MSB16)
9086     {
9087       // shift is > 8
9088       if (sign)
9089         {
9090           emitcode ("rlc", "a");
9091           emitcode ("subb", "a,acc");
9092           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9093             {
9094               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9095             }
9096           else
9097             {
9098               aopPut (result, "a", MSB32);
9099               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9100             }
9101         }
9102       else
9103         {
9104           if (aopPutUsesAcc (result, zero, MSB32))
9105             {
9106               emitcode("xch", "a,b");
9107               aopPut (result, zero, MSB32);
9108               emitcode("xch", "a,b");
9109             }
9110           else
9111             {
9112               aopPut (result, zero, MSB32);
9113             }
9114         }
9115     }
9116
9117   if (!sign)
9118     {
9119       emitcode ("clr", "c");
9120     }
9121   else
9122     {
9123       emitcode ("mov", "c,acc.7");
9124     }
9125
9126   emitcode ("rrc", "a");
9127
9128   if (overlapping && offl==MSB16 &&
9129       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9130     {
9131       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9132     }
9133   else
9134     {
9135       aopPut (result, "a", MSB32 - offl);
9136       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9137     }
9138
9139   emitcode ("rrc", "a");
9140   if (overlapping && offl==MSB16 &&
9141       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9142     {
9143       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9144     }
9145   else
9146     {
9147       aopPut (result, "a", MSB24 - offl);
9148       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9149     }
9150
9151   emitcode ("rrc", "a");
9152   if (offl != LSB)
9153     {
9154       aopPut (result, "a", MSB16 - offl);
9155     }
9156   else
9157     {
9158       if (overlapping &&
9159           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9160         {
9161           xch_a_aopGet (left, LSB, FALSE, FALSE);
9162         }
9163       else
9164         {
9165           aopPut (result, "a", MSB16 - offl);
9166           MOVA (aopGet (left, LSB, FALSE, FALSE));
9167         }
9168       emitcode ("rrc", "a");
9169       aopPut (result, "a", LSB);
9170     }
9171 }
9172
9173 /*-----------------------------------------------------------------*/
9174 /* genrshFour - shift four byte by a known amount != 0             */
9175 /*-----------------------------------------------------------------*/
9176 static void
9177 genrshFour (operand * result, operand * left,
9178             int shCount, int sign)
9179 {
9180   D (emitcode (";", "genrshFour"));
9181
9182   /* if shifting more that 3 bytes */
9183   if (shCount >= 24)
9184     {
9185       shCount -= 24;
9186       if (shCount)
9187         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9188       else
9189         movLeft2Result (left, MSB32, result, LSB, sign);
9190       addSign (result, MSB16, sign);
9191     }
9192   else if (shCount >= 16)
9193     {
9194       shCount -= 16;
9195       if (shCount)
9196         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9197       else
9198         {
9199           movLeft2Result (left, MSB24, result, LSB, 0);
9200           movLeft2Result (left, MSB32, result, MSB16, sign);
9201         }
9202       addSign (result, MSB24, sign);
9203     }
9204   else if (shCount >= 8)
9205     {
9206       shCount -= 8;
9207       if (shCount == 1)
9208         {
9209           shiftRLong (left, MSB16, result, sign);
9210         }
9211       else if (shCount == 0)
9212         {
9213           movLeft2Result (left, MSB16, result, LSB, 0);
9214           movLeft2Result (left, MSB24, result, MSB16, 0);
9215           movLeft2Result (left, MSB32, result, MSB24, sign);
9216           addSign (result, MSB32, sign);
9217         }
9218       else
9219         {
9220           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9221           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9222           /* the last shift is signed */
9223           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9224           addSign (result, MSB32, sign);
9225         }
9226     }
9227   else
9228     {
9229       /* 1 <= shCount <= 7 */
9230       if (shCount <= 2)
9231         {
9232           shiftRLong (left, LSB, result, sign);
9233           if (shCount == 2)
9234             shiftRLong (result, LSB, result, sign);
9235         }
9236       else
9237         {
9238           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9239           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9240           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9241         }
9242     }
9243 }
9244
9245 /*-----------------------------------------------------------------*/
9246 /* genRightShiftLiteral - right shifting by known count            */
9247 /*-----------------------------------------------------------------*/
9248 static void
9249 genRightShiftLiteral (operand * left,
9250                       operand * right,
9251                       operand * result,
9252                       iCode * ic,
9253                       int sign)
9254 {
9255   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9256   int size;
9257
9258   D (emitcode (";", "genRightShiftLiteral"));
9259
9260   freeAsmop (right, NULL, ic, TRUE);
9261
9262   aopOp (left, ic, FALSE);
9263   aopOp (result, ic, FALSE);
9264
9265 #if VIEW_SIZE
9266   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9267             AOP_SIZE (left));
9268 #endif
9269
9270   size = getDataSize (left);
9271   /* test the LEFT size !!! */
9272
9273   /* I suppose that the left size >= result size */
9274   if (shCount == 0)
9275     {
9276       size = getDataSize (result);
9277       while (size--)
9278         movLeft2Result (left, size, result, size, 0);
9279     }
9280
9281   else if (shCount >= (size * 8))
9282     {
9283       if (sign)
9284         {
9285           /* get sign in acc.7 */
9286           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9287         }
9288       addSign (result, LSB, sign);
9289     }
9290   else
9291     {
9292       switch (size)
9293         {
9294         case 1:
9295           genrshOne (result, left, shCount, sign);
9296           break;
9297
9298         case 2:
9299           genrshTwo (result, left, shCount, sign);
9300           break;
9301
9302         case 4:
9303           genrshFour (result, left, shCount, sign);
9304           break;
9305         default:
9306           break;
9307         }
9308     }
9309   freeAsmop (result, NULL, ic, TRUE);
9310   freeAsmop (left, NULL, ic, TRUE);
9311 }
9312
9313 /*-----------------------------------------------------------------*/
9314 /* genSignedRightShift - right shift of signed number              */
9315 /*-----------------------------------------------------------------*/
9316 static void
9317 genSignedRightShift (iCode * ic)
9318 {
9319   operand *right, *left, *result;
9320   int size, offset;
9321   char *l;
9322   symbol *tlbl, *tlbl1;
9323   bool pushedB;
9324
9325   D (emitcode (";", "genSignedRightShift"));
9326
9327   /* we do it the hard way put the shift count in b
9328      and loop thru preserving the sign */
9329
9330   right = IC_RIGHT (ic);
9331   left = IC_LEFT (ic);
9332   result = IC_RESULT (ic);
9333
9334   aopOp (right, ic, FALSE);
9335
9336
9337   if (AOP_TYPE (right) == AOP_LIT)
9338     {
9339       genRightShiftLiteral (left, right, result, ic, 1);
9340       return;
9341     }
9342   /* shift count is unknown then we have to form
9343      a loop get the loop count in B : Note: we take
9344      only the lower order byte since shifting
9345      more that 32 bits make no sense anyway, ( the
9346      largest size of an object can be only 32 bits ) */
9347
9348   pushedB = pushB ();
9349   MOVB (aopGet (right, 0, FALSE, FALSE));
9350   emitcode ("inc", "b");
9351   freeAsmop (right, NULL, ic, TRUE);
9352   aopOp (left, ic, FALSE);
9353   aopOp (result, ic, FALSE);
9354
9355   /* now move the left to the result if they are not the
9356      same */
9357   if (!sameRegs (AOP (left), AOP (result)) &&
9358       AOP_SIZE (result) > 1)
9359     {
9360
9361       size = AOP_SIZE (result);
9362       offset = 0;
9363       while (size--)
9364         {
9365           l = aopGet (left, offset, FALSE, TRUE);
9366           if (*l == '@' && IS_AOP_PREG (result))
9367             {
9368
9369               emitcode ("mov", "a,%s", l);
9370               aopPut (result, "a", offset);
9371             }
9372           else
9373             aopPut (result, l, offset);
9374           offset++;
9375         }
9376     }
9377
9378   /* mov the highest order bit to OVR */
9379   tlbl = newiTempLabel (NULL);
9380   tlbl1 = newiTempLabel (NULL);
9381
9382   size = AOP_SIZE (result);
9383   offset = size - 1;
9384   MOVA (aopGet (left, offset, FALSE, FALSE));
9385   emitcode ("rlc", "a");
9386   emitcode ("mov", "ov,c");
9387   /* if it is only one byte then */
9388   if (size == 1)
9389     {
9390       l = aopGet (left, 0, FALSE, FALSE);
9391       MOVA (l);
9392       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9393       emitLabel (tlbl);
9394       emitcode ("mov", "c,ov");
9395       emitcode ("rrc", "a");
9396       emitLabel (tlbl1);
9397       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9398       popB (pushedB);
9399       aopPut (result, "a", 0);
9400       goto release;
9401     }
9402
9403   reAdjustPreg (AOP (result));
9404   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9405   emitLabel (tlbl);
9406   emitcode ("mov", "c,ov");
9407   while (size--)
9408     {
9409       l = aopGet (result, offset, FALSE, FALSE);
9410       MOVA (l);
9411       emitcode ("rrc", "a");
9412       aopPut (result, "a", offset--);
9413     }
9414   reAdjustPreg (AOP (result));
9415   emitLabel (tlbl1);
9416   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9417   popB (pushedB);
9418
9419 release:
9420   freeAsmop (result, NULL, ic, TRUE);
9421   freeAsmop (left, NULL, ic, TRUE);
9422 }
9423
9424 /*-----------------------------------------------------------------*/
9425 /* genRightShift - generate code for right shifting                */
9426 /*-----------------------------------------------------------------*/
9427 static void
9428 genRightShift (iCode * ic)
9429 {
9430   operand *right, *left, *result;
9431   sym_link *letype;
9432   int size, offset;
9433   char *l;
9434   symbol *tlbl, *tlbl1;
9435   bool pushedB;
9436
9437   D (emitcode (";", "genRightShift"));
9438
9439   /* if signed then we do it the hard way preserve the
9440      sign bit moving it inwards */
9441   letype = getSpec (operandType (IC_LEFT (ic)));
9442
9443   if (!SPEC_USIGN (letype))
9444     {
9445       genSignedRightShift (ic);
9446       return;
9447     }
9448
9449   /* signed & unsigned types are treated the same : i.e. the
9450      signed is NOT propagated inwards : quoting from the
9451      ANSI - standard : "for E1 >> E2, is equivalent to division
9452      by 2**E2 if unsigned or if it has a non-negative value,
9453      otherwise the result is implementation defined ", MY definition
9454      is that the sign does not get propagated */
9455
9456   right = IC_RIGHT (ic);
9457   left = IC_LEFT (ic);
9458   result = IC_RESULT (ic);
9459
9460   aopOp (right, ic, FALSE);
9461
9462   /* if the shift count is known then do it
9463      as efficiently as possible */
9464   if (AOP_TYPE (right) == AOP_LIT)
9465     {
9466       genRightShiftLiteral (left, right, result, ic, 0);
9467       return;
9468     }
9469
9470   /* shift count is unknown then we have to form
9471      a loop get the loop count in B : Note: we take
9472      only the lower order byte since shifting
9473      more that 32 bits make no sense anyway, ( the
9474      largest size of an object can be only 32 bits ) */
9475
9476   pushedB = pushB ();
9477   MOVB (aopGet (right, 0, FALSE, FALSE));
9478   emitcode ("inc", "b");
9479   freeAsmop (right, NULL, ic, TRUE);
9480   aopOp (left, ic, FALSE);
9481   aopOp (result, ic, FALSE);
9482
9483   /* now move the left to the result if they are not the
9484      same */
9485   if (!sameRegs (AOP (left), AOP (result)) &&
9486       AOP_SIZE (result) > 1)
9487     {
9488       size = AOP_SIZE (result);
9489       offset = 0;
9490       while (size--)
9491         {
9492           l = aopGet (left, offset, FALSE, TRUE);
9493           if (*l == '@' && IS_AOP_PREG (result))
9494             {
9495
9496               emitcode ("mov", "a,%s", l);
9497               aopPut (result, "a", offset);
9498             }
9499           else
9500             aopPut (result, l, offset);
9501           offset++;
9502         }
9503     }
9504
9505   tlbl = newiTempLabel (NULL);
9506   tlbl1 = newiTempLabel (NULL);
9507   size = AOP_SIZE (result);
9508   offset = size - 1;
9509
9510   /* if it is only one byte then */
9511   if (size == 1)
9512     {
9513       l = aopGet (left, 0, FALSE, FALSE);
9514       MOVA (l);
9515       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9516       emitLabel (tlbl);
9517       CLRC;
9518       emitcode ("rrc", "a");
9519       emitLabel (tlbl1);
9520       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9521       popB (pushedB);
9522       aopPut (result, "a", 0);
9523       goto release;
9524     }
9525
9526   reAdjustPreg (AOP (result));
9527   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9528   emitLabel (tlbl);
9529   CLRC;
9530   while (size--)
9531     {
9532       l = aopGet (result, offset, FALSE, FALSE);
9533       MOVA (l);
9534       emitcode ("rrc", "a");
9535       aopPut (result, "a", offset--);
9536     }
9537   reAdjustPreg (AOP (result));
9538
9539   emitLabel (tlbl1);
9540   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9541   popB (pushedB);
9542
9543 release:
9544   freeAsmop (result, NULL, ic, TRUE);
9545   freeAsmop (left, NULL, ic, TRUE);
9546 }
9547
9548 /*-----------------------------------------------------------------*/
9549 /* emitPtrByteGet - emits code to get a byte into A through a      */
9550 /*                  pointer register (R0, R1, or DPTR). The        */
9551 /*                  original value of A can be preserved in B.     */
9552 /*-----------------------------------------------------------------*/
9553 static void
9554 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9555 {
9556   switch (p_type)
9557     {
9558     case IPOINTER:
9559     case POINTER:
9560       if (preserveAinB)
9561         emitcode ("mov", "b,a");
9562       emitcode ("mov", "a,@%s", rname);
9563       break;
9564
9565     case PPOINTER:
9566       if (preserveAinB)
9567         emitcode ("mov", "b,a");
9568       emitcode ("movx", "a,@%s", rname);
9569       break;
9570
9571     case FPOINTER:
9572       if (preserveAinB)
9573         emitcode ("mov", "b,a");
9574       emitcode ("movx", "a,@dptr");
9575       break;
9576
9577     case CPOINTER:
9578       if (preserveAinB)
9579         emitcode ("mov", "b,a");
9580       emitcode ("clr", "a");
9581       emitcode ("movc", "a,@a+dptr");
9582       break;
9583
9584     case GPOINTER:
9585       if (preserveAinB)
9586         {
9587           emitcode ("push", "b");
9588           emitcode ("push", "acc");
9589         }
9590       emitcode ("lcall", "__gptrget");
9591       if (preserveAinB)
9592         emitcode ("pop", "b");
9593       break;
9594     }
9595 }
9596
9597 /*-----------------------------------------------------------------*/
9598 /* emitPtrByteSet - emits code to set a byte from src through a    */
9599 /*                  pointer register (R0, R1, or DPTR).            */
9600 /*-----------------------------------------------------------------*/
9601 static void
9602 emitPtrByteSet (char *rname, int p_type, char *src)
9603 {
9604   switch (p_type)
9605     {
9606     case IPOINTER:
9607     case POINTER:
9608       if (*src=='@')
9609         {
9610           MOVA (src);
9611           emitcode ("mov", "@%s,a", rname);
9612         }
9613       else
9614         emitcode ("mov", "@%s,%s", rname, src);
9615       break;
9616
9617     case PPOINTER:
9618       MOVA (src);
9619       emitcode ("movx", "@%s,a", rname);
9620       break;
9621
9622     case FPOINTER:
9623       MOVA (src);
9624       emitcode ("movx", "@dptr,a");
9625       break;
9626
9627     case GPOINTER:
9628       MOVA (src);
9629       emitcode ("lcall", "__gptrput");
9630       break;
9631     }
9632 }
9633
9634 /*-----------------------------------------------------------------*/
9635 /* genUnpackBits - generates code for unpacking bits               */
9636 /*-----------------------------------------------------------------*/
9637 static void
9638 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9639 {
9640   int offset = 0;       /* result byte offset */
9641   int rsize;            /* result size */
9642   int rlen = 0;         /* remaining bitfield length */
9643   sym_link *etype;      /* bitfield type information */
9644   int blen;             /* bitfield length */
9645   int bstr;             /* bitfield starting bit within byte */
9646   char buffer[10];
9647
9648   D(emitcode (";     genUnpackBits",""));
9649
9650   etype = getSpec (operandType (result));
9651   rsize = getSize (operandType (result));
9652   blen = SPEC_BLEN (etype);
9653   bstr = SPEC_BSTR (etype);
9654
9655   if (ifx && blen <= 8)
9656     {
9657       emitPtrByteGet (rname, ptype, FALSE);
9658       if (blen == 1)
9659         {
9660           SNPRINTF (buffer, sizeof(buffer),
9661                     "acc.%d", bstr);
9662           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9663         }
9664       else
9665         {
9666           if (blen < 8)
9667             emitcode ("anl", "a,#0x%02x",
9668                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9669           genIfxJump (ifx, "a", NULL, NULL, NULL);
9670         }
9671       return;
9672     }
9673   wassert (!ifx);
9674
9675   /* If the bitfield length is less than a byte */
9676   if (blen < 8)
9677     {
9678       emitPtrByteGet (rname, ptype, FALSE);
9679       AccRol (8 - bstr);
9680       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9681       if (!SPEC_USIGN (etype))
9682         {
9683           /* signed bitfield */
9684           symbol *tlbl = newiTempLabel (NULL);
9685
9686           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9687           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9688           emitLabel (tlbl);
9689         }
9690       aopPut (result, "a", offset++);
9691       goto finish;
9692     }
9693
9694   /* Bit field did not fit in a byte. Copy all
9695      but the partial byte at the end.  */
9696   for (rlen=blen;rlen>=8;rlen-=8)
9697     {
9698       emitPtrByteGet (rname, ptype, FALSE);
9699       aopPut (result, "a", offset++);
9700       if (rlen>8)
9701         emitcode ("inc", "%s", rname);
9702     }
9703
9704   /* Handle the partial byte at the end */
9705   if (rlen)
9706     {
9707       emitPtrByteGet (rname, ptype, FALSE);
9708       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9709       if (!SPEC_USIGN (etype))
9710         {
9711           /* signed bitfield */
9712           symbol *tlbl = newiTempLabel (NULL);
9713
9714           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9715           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9716           emitLabel (tlbl);
9717         }
9718       aopPut (result, "a", offset++);
9719     }
9720
9721 finish:
9722   if (offset < rsize)
9723     {
9724       char *source;
9725
9726       if (SPEC_USIGN (etype))
9727         source = zero;
9728       else
9729         {
9730           /* signed bitfield: sign extension with 0x00 or 0xff */
9731           emitcode ("rlc", "a");
9732           emitcode ("subb", "a,acc");
9733
9734           source = "a";
9735         }
9736       rsize -= offset;
9737       while (rsize--)
9738         aopPut (result, source, offset++);
9739     }
9740 }
9741
9742
9743 /*-----------------------------------------------------------------*/
9744 /* genDataPointerGet - generates code when ptr offset is known     */
9745 /*-----------------------------------------------------------------*/
9746 static void
9747 genDataPointerGet (operand * left,
9748                    operand * result,
9749                    iCode * ic)
9750 {
9751   char *l;
9752   char buffer[256];
9753   int size, offset = 0;
9754
9755   D (emitcode (";", "genDataPointerGet"));
9756
9757   aopOp (result, ic, TRUE);
9758
9759   /* get the string representation of the name */
9760   l = aopGet (left, 0, FALSE, TRUE);
9761   l++; // remove #
9762   size = AOP_SIZE (result);
9763   while (size--)
9764     {
9765       if (offset)
9766         {
9767           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9768         }
9769       else
9770         {
9771           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9772         }
9773       aopPut (result, buffer, offset++);
9774     }
9775
9776   freeAsmop (result, NULL, ic, TRUE);
9777   freeAsmop (left, NULL, ic, TRUE);
9778 }
9779
9780 /*-----------------------------------------------------------------*/
9781 /* genNearPointerGet - emitcode for near pointer fetch             */
9782 /*-----------------------------------------------------------------*/
9783 static void
9784 genNearPointerGet (operand * left,
9785                    operand * result,
9786                    iCode * ic,
9787                    iCode * pi,
9788                    iCode * ifx)
9789 {
9790   asmop *aop = NULL;
9791   regs *preg = NULL;
9792   char *rname;
9793   sym_link *rtype, *retype;
9794   sym_link *ltype = operandType (left);
9795   char buffer[80];
9796
9797   D (emitcode (";", "genNearPointerGet"));
9798
9799   rtype = operandType (result);
9800   retype = getSpec (rtype);
9801
9802   aopOp (left, ic, FALSE);
9803
9804   /* if left is rematerialisable and
9805      result is not bitfield variable type and
9806      the left is pointer to data space i.e
9807      lower 128 bytes of space */
9808   if (AOP_TYPE (left) == AOP_IMMD &&
9809       !IS_BITFIELD (retype) &&
9810       DCL_TYPE (ltype) == POINTER)
9811     {
9812       genDataPointerGet (left, result, ic);
9813       return;
9814     }
9815
9816  /* if the value is already in a pointer register
9817      then don't need anything more */
9818   if (!AOP_INPREG (AOP (left)))
9819     {
9820       if (IS_AOP_PREG (left))
9821         {
9822           // Aha, it is a pointer, just in disguise.
9823           rname = aopGet (left, 0, FALSE, FALSE);
9824           if (*rname != '@')
9825             {
9826               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9827                       __FILE__, __LINE__);
9828             }
9829           else
9830             {
9831               // Expected case.
9832               emitcode ("mov", "a%s,%s", rname + 1, rname);
9833               rname++;  // skip the '@'.
9834             }
9835         }
9836       else
9837         {
9838           /* otherwise get a free pointer register */
9839           aop = newAsmop (0);
9840           preg = getFreePtr (ic, &aop, FALSE);
9841           emitcode ("mov", "%s,%s",
9842                     preg->name,
9843                     aopGet (left, 0, FALSE, TRUE));
9844           rname = preg->name;
9845         }
9846     }
9847   else
9848     rname = aopGet (left, 0, FALSE, FALSE);
9849
9850   //aopOp (result, ic, FALSE);
9851   aopOp (result, ic, result?TRUE:FALSE);
9852
9853   /* if bitfield then unpack the bits */
9854   if (IS_BITFIELD (retype))
9855     genUnpackBits (result, rname, POINTER, ifx);
9856   else
9857     {
9858       /* we have can just get the values */
9859       int size = AOP_SIZE (result);
9860       int offset = 0;
9861
9862       while (size--)
9863         {
9864           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9865             {
9866
9867               emitcode ("mov", "a,@%s", rname);
9868               if (!ifx)
9869                 aopPut (result, "a", offset);
9870             }
9871           else
9872             {
9873               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9874               aopPut (result, buffer, offset);
9875             }
9876           offset++;
9877           if (size || pi)
9878             emitcode ("inc", "%s", rname);
9879         }
9880     }
9881
9882   /* now some housekeeping stuff */
9883   if (aop)       /* we had to allocate for this iCode */
9884     {
9885       if (pi) { /* post increment present */
9886         aopPut (left, rname, 0);
9887       }
9888       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9889     }
9890   else
9891     {
9892       /* we did not allocate which means left
9893          already in a pointer register, then
9894          if size > 0 && this could be used again
9895          we have to point it back to where it
9896          belongs */
9897       if ((AOP_SIZE (result) > 1 &&
9898            !OP_SYMBOL (left)->remat &&
9899            (OP_SYMBOL (left)->liveTo > ic->seq ||
9900             ic->depth)) &&
9901           !pi)
9902         {
9903           int size = AOP_SIZE (result) - 1;
9904           while (size--)
9905             emitcode ("dec", "%s", rname);
9906         }
9907     }
9908
9909   if (ifx && !ifx->generated)
9910     {
9911       genIfxJump (ifx, "a", left, NULL, result);
9912     }
9913
9914   /* done */
9915   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9916   freeAsmop (left, NULL, ic, TRUE);
9917   if (pi) pi->generated = 1;
9918 }
9919
9920 /*-----------------------------------------------------------------*/
9921 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9922 /*-----------------------------------------------------------------*/
9923 static void
9924 genPagedPointerGet (operand * left,
9925                     operand * result,
9926                     iCode * ic,
9927                     iCode *pi,
9928                     iCode *ifx)
9929 {
9930   asmop *aop = NULL;
9931   regs *preg = NULL;
9932   char *rname;
9933   sym_link *rtype, *retype;
9934
9935   D (emitcode (";", "genPagedPointerGet"));
9936
9937   rtype = operandType (result);
9938   retype = getSpec (rtype);
9939
9940   aopOp (left, ic, FALSE);
9941
9942   /* if the value is already in a pointer register
9943      then don't need anything more */
9944   if (!AOP_INPREG (AOP (left)))
9945     {
9946       /* otherwise get a free pointer register */
9947       aop = newAsmop (0);
9948       preg = getFreePtr (ic, &aop, FALSE);
9949       emitcode ("mov", "%s,%s",
9950                 preg->name,
9951                 aopGet (left, 0, FALSE, TRUE));
9952       rname = preg->name;
9953     }
9954   else
9955     rname = aopGet (left, 0, FALSE, FALSE);
9956
9957   aopOp (result, ic, FALSE);
9958
9959   /* if bitfield then unpack the bits */
9960   if (IS_BITFIELD (retype))
9961     genUnpackBits (result, rname, PPOINTER, ifx);
9962   else
9963     {
9964       /* we have can just get the values */
9965       int size = AOP_SIZE (result);
9966       int offset = 0;
9967
9968       while (size--)
9969         {
9970
9971           emitcode ("movx", "a,@%s", rname);
9972           if (!ifx)
9973             aopPut (result, "a", offset);
9974
9975           offset++;
9976
9977           if (size || pi)
9978             emitcode ("inc", "%s", rname);
9979         }
9980     }
9981
9982   /* now some housekeeping stuff */
9983   if (aop) /* we had to allocate for this iCode */
9984     {
9985       if (pi)
9986         aopPut (left, rname, 0);
9987       freeAsmop (NULL, aop, ic, TRUE);
9988     }
9989   else
9990     {
9991       /* we did not allocate which means left
9992          already in a pointer register, then
9993          if size > 0 && this could be used again
9994          we have to point it back to where it
9995          belongs */
9996       if ((AOP_SIZE (result) > 1 &&
9997            !OP_SYMBOL (left)->remat &&
9998            (OP_SYMBOL (left)->liveTo > ic->seq ||
9999             ic->depth)) &&
10000           !pi)
10001         {
10002           int size = AOP_SIZE (result) - 1;
10003           while (size--)
10004             emitcode ("dec", "%s", rname);
10005         }
10006     }
10007
10008   if (ifx && !ifx->generated)
10009     {
10010       genIfxJump (ifx, "a", left, NULL, result);
10011     }
10012
10013   /* done */
10014   freeAsmop (result, NULL, ic, TRUE);
10015   freeAsmop (left, NULL, ic, TRUE);
10016   if (pi) pi->generated = 1;
10017 }
10018
10019 /*--------------------------------------------------------------------*/
10020 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10021 /*--------------------------------------------------------------------*/
10022 static void
10023 loadDptrFromOperand (operand *op, bool loadBToo)
10024 {
10025   if (AOP_TYPE (op) != AOP_STR)
10026     {
10027       /* if this is rematerializable */
10028       if (AOP_TYPE (op) == AOP_IMMD)
10029         {
10030           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10031           if (loadBToo)
10032             {
10033               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10034                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10035               else
10036                 {
10037                   wassertl(FALSE, "need pointerCode");
10038                   emitcode ("", "; mov b,???");
10039                   /* genPointerGet and genPointerSet originally did different
10040                   ** things for this case. Both seem wrong.
10041                   ** from genPointerGet:
10042                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10043                   ** from genPointerSet:
10044                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10045                   */
10046                 }
10047             }
10048         }
10049       else if (AOP_TYPE (op) == AOP_DPTR)
10050         {
10051           if (loadBToo)
10052             {
10053               MOVA (aopGet (op, 0, FALSE, FALSE));
10054               emitcode ("push", "acc");
10055               MOVA (aopGet (op, 1, FALSE, FALSE));
10056               emitcode ("push", "acc");
10057               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10058               emitcode ("pop", "dph");
10059               emitcode ("pop", "dpl");
10060             }
10061           else
10062             {
10063               MOVA (aopGet (op, 0, FALSE, FALSE));
10064               emitcode ("push", "acc");
10065               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10066               emitcode ("pop", "dpl");
10067             }
10068         }
10069       else
10070         {                       /* we need to get it byte by byte */
10071           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10072           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10073           if (loadBToo)
10074             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10075         }
10076     }
10077 }
10078
10079 /*-----------------------------------------------------------------*/
10080 /* genFarPointerGet - get value from far space                     */
10081 /*-----------------------------------------------------------------*/
10082 static void
10083 genFarPointerGet (operand * left,
10084                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10085 {
10086   int size, offset;
10087   sym_link *retype = getSpec (operandType (result));
10088
10089   D (emitcode (";", "genFarPointerGet"));
10090
10091   aopOp (left, ic, FALSE);
10092   loadDptrFromOperand (left, FALSE);
10093
10094   /* so dptr now contains the address */
10095   aopOp (result, ic, FALSE);
10096
10097   /* if bit then unpack */
10098   if (IS_BITFIELD (retype))
10099     genUnpackBits (result, "dptr", FPOINTER, ifx);
10100   else
10101     {
10102       size = AOP_SIZE (result);
10103       offset = 0;
10104
10105       while (size--)
10106         {
10107           emitcode ("movx", "a,@dptr");
10108           if (!ifx)
10109             aopPut (result, "a", offset++);
10110           if (size || pi)
10111             emitcode ("inc", "dptr");
10112         }
10113     }
10114
10115   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10116     {
10117       aopPut (left, "dpl", 0);
10118       aopPut (left, "dph", 1);
10119       pi->generated = 1;
10120     }
10121
10122   if (ifx && !ifx->generated)
10123     {
10124       genIfxJump (ifx, "a", left, NULL, result);
10125     }
10126
10127   freeAsmop (result, NULL, ic, TRUE);
10128   freeAsmop (left, NULL, ic, TRUE);
10129 }
10130
10131 /*-----------------------------------------------------------------*/
10132 /* genCodePointerGet - get value from code space                   */
10133 /*-----------------------------------------------------------------*/
10134 static void
10135 genCodePointerGet (operand * left,
10136                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10137 {
10138   int size, offset;
10139   sym_link *retype = getSpec (operandType (result));
10140
10141   D (emitcode (";", "genCodePointerGet"));
10142
10143   aopOp (left, ic, FALSE);
10144   loadDptrFromOperand (left, FALSE);
10145
10146   /* so dptr now contains the address */
10147   aopOp (result, ic, FALSE);
10148
10149   /* if bit then unpack */
10150   if (IS_BITFIELD (retype))
10151     genUnpackBits (result, "dptr", CPOINTER, ifx);
10152   else
10153     {
10154       size = AOP_SIZE (result);
10155       offset = 0;
10156
10157       while (size--)
10158         {
10159           emitcode ("clr", "a");
10160           emitcode ("movc", "a,@a+dptr");
10161           if (!ifx)
10162             aopPut (result, "a", offset++);
10163           if (size || pi)
10164             emitcode ("inc", "dptr");
10165         }
10166     }
10167
10168   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10169     {
10170       aopPut (left, "dpl", 0);
10171       aopPut (left, "dph", 1);
10172       pi->generated = 1;
10173     }
10174
10175   if (ifx && !ifx->generated)
10176     {
10177       genIfxJump (ifx, "a", left, NULL, result);
10178     }
10179
10180   freeAsmop (result, NULL, ic, TRUE);
10181   freeAsmop (left, NULL, ic, TRUE);
10182 }
10183
10184 /*-----------------------------------------------------------------*/
10185 /* genGenPointerGet - get value from generic pointer space         */
10186 /*-----------------------------------------------------------------*/
10187 static void
10188 genGenPointerGet (operand * left,
10189                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10190 {
10191   int size, offset;
10192   sym_link *retype = getSpec (operandType (result));
10193
10194   D (emitcode (";", "genGenPointerGet"));
10195
10196   aopOp (left, ic, FALSE);
10197   loadDptrFromOperand (left, TRUE);
10198
10199   /* so dptr now contains the address */
10200   aopOp (result, ic, FALSE);
10201
10202   /* if bit then unpack */
10203   if (IS_BITFIELD (retype))
10204     {
10205       genUnpackBits (result, "dptr", GPOINTER, ifx);
10206     }
10207   else
10208     {
10209       size = AOP_SIZE (result);
10210       offset = 0;
10211
10212       while (size--)
10213         {
10214           emitcode ("lcall", "__gptrget");
10215           if (!ifx)
10216             aopPut (result, "a", offset++);
10217           if (size || pi)
10218             emitcode ("inc", "dptr");
10219         }
10220     }
10221
10222   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10223     {
10224       aopPut (left, "dpl", 0);
10225       aopPut (left, "dph", 1);
10226       pi->generated = 1;
10227     }
10228
10229   if (ifx && !ifx->generated)
10230     {
10231       genIfxJump (ifx, "a", left, NULL, result);
10232     }
10233
10234   freeAsmop (result, NULL, ic, TRUE);
10235   freeAsmop (left, NULL, ic, TRUE);
10236 }
10237
10238 /*-----------------------------------------------------------------*/
10239 /* genPointerGet - generate code for pointer get                   */
10240 /*-----------------------------------------------------------------*/
10241 static void
10242 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10243 {
10244   operand *left, *result;
10245   sym_link *type, *etype;
10246   int p_type;
10247
10248   D (emitcode (";", "genPointerGet"));
10249
10250   left = IC_LEFT (ic);
10251   result = IC_RESULT (ic);
10252
10253   if (getSize (operandType (result))>1)
10254     ifx = NULL;
10255
10256   /* depending on the type of pointer we need to
10257      move it to the correct pointer register */
10258   type = operandType (left);
10259   etype = getSpec (type);
10260   /* if left is of type of pointer then it is simple */
10261   if (IS_PTR (type) && !IS_FUNC (type->next))
10262     p_type = DCL_TYPE (type);
10263   else
10264     {
10265       /* we have to go by the storage class */
10266       p_type = PTR_TYPE (SPEC_OCLS (etype));
10267     }
10268
10269   /* special case when cast remat */
10270   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10271       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10272     {
10273       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10274       type = operandType (left);
10275       p_type = DCL_TYPE (type);
10276     }
10277   /* now that we have the pointer type we assign
10278      the pointer values */
10279   switch (p_type)
10280     {
10281
10282     case POINTER:
10283     case IPOINTER:
10284       genNearPointerGet (left, result, ic, pi, ifx);
10285       break;
10286
10287     case PPOINTER:
10288       genPagedPointerGet (left, result, ic, pi, ifx);
10289       break;
10290
10291     case FPOINTER:
10292       genFarPointerGet (left, result, ic, pi, ifx);
10293       break;
10294
10295     case CPOINTER:
10296       genCodePointerGet (left, result, ic, pi, ifx);
10297       break;
10298
10299     case GPOINTER:
10300       genGenPointerGet (left, result, ic, pi, ifx);
10301       break;
10302     }
10303 }
10304
10305
10306 /*-----------------------------------------------------------------*/
10307 /* genPackBits - generates code for packed bit storage             */
10308 /*-----------------------------------------------------------------*/
10309 static void
10310 genPackBits (sym_link * etype,
10311              operand * right,
10312              char *rname, int p_type)
10313 {
10314   int offset = 0;       /* source byte offset */
10315   int rlen = 0;         /* remaining bitfield length */
10316   int blen;             /* bitfield length */
10317   int bstr;             /* bitfield starting bit within byte */
10318   int litval;           /* source literal value (if AOP_LIT) */
10319   unsigned char mask;   /* bitmask within current byte */
10320
10321   D(emitcode (";     genPackBits",""));
10322
10323   blen = SPEC_BLEN (etype);
10324   bstr = SPEC_BSTR (etype);
10325
10326   /* If the bitfield length is less than a byte */
10327   if (blen < 8)
10328     {
10329       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10330               (unsigned char) (0xFF >> (8 - bstr)));
10331
10332       if (AOP_TYPE (right) == AOP_LIT)
10333         {
10334           /* Case with a bitfield length <8 and literal source
10335           */
10336           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10337           litval <<= bstr;
10338           litval &= (~mask) & 0xff;
10339           emitPtrByteGet (rname, p_type, FALSE);
10340           if ((mask|litval)!=0xff)
10341             emitcode ("anl","a,#0x%02x", mask);
10342           if (litval)
10343             emitcode ("orl","a,#0x%02x", litval);
10344         }
10345       else
10346         {
10347           if ((blen==1) && (p_type!=GPOINTER))
10348             {
10349               /* Case with a bitfield length == 1 and no generic pointer
10350               */
10351               if (AOP_TYPE (right) == AOP_CRY)
10352                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10353               else
10354                 {
10355                   MOVA (aopGet (right, 0, FALSE, FALSE));
10356                   emitcode ("rrc","a");
10357                 }
10358               emitPtrByteGet (rname, p_type, FALSE);
10359               emitcode ("mov","acc.%d,c",bstr);
10360             }
10361           else
10362             {
10363               bool pushedB;
10364               /* Case with a bitfield length < 8 and arbitrary source
10365               */
10366               MOVA (aopGet (right, 0, FALSE, FALSE));
10367               /* shift and mask source value */
10368               AccLsh (bstr);
10369               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10370
10371               pushedB = pushB ();
10372               /* transfer A to B and get next byte */
10373               emitPtrByteGet (rname, p_type, TRUE);
10374
10375               emitcode ("anl", "a,#0x%02x", mask);
10376               emitcode ("orl", "a,b");
10377               if (p_type == GPOINTER)
10378                 emitcode ("pop", "b");
10379
10380               popB (pushedB);
10381            }
10382         }
10383
10384       emitPtrByteSet (rname, p_type, "a");
10385       return;
10386     }
10387
10388   /* Bit length is greater than 7 bits. In this case, copy  */
10389   /* all except the partial byte at the end                 */
10390   for (rlen=blen;rlen>=8;rlen-=8)
10391     {
10392       emitPtrByteSet (rname, p_type,
10393                       aopGet (right, offset++, FALSE, TRUE) );
10394       if (rlen>8)
10395         emitcode ("inc", "%s", rname);
10396     }
10397
10398   /* If there was a partial byte at the end */
10399   if (rlen)
10400     {
10401       mask = (((unsigned char) -1 << rlen) & 0xff);
10402
10403       if (AOP_TYPE (right) == AOP_LIT)
10404         {
10405           /* Case with partial byte and literal source
10406           */
10407           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10408           litval >>= (blen-rlen);
10409           litval &= (~mask) & 0xff;
10410           emitPtrByteGet (rname, p_type, FALSE);
10411           if ((mask|litval)!=0xff)
10412             emitcode ("anl","a,#0x%02x", mask);
10413           if (litval)
10414             emitcode ("orl","a,#0x%02x", litval);
10415         }
10416       else
10417         {
10418           bool pushedB;
10419           /* Case with partial byte and arbitrary source
10420           */
10421           MOVA (aopGet (right, offset++, FALSE, FALSE));
10422           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10423
10424           pushedB = pushB ();
10425           /* transfer A to B and get next byte */
10426           emitPtrByteGet (rname, p_type, TRUE);
10427
10428           emitcode ("anl", "a,#0x%02x", mask);
10429           emitcode ("orl", "a,b");
10430           if (p_type == GPOINTER)
10431             emitcode ("pop", "b");
10432
10433           popB (pushedB);
10434         }
10435       emitPtrByteSet (rname, p_type, "a");
10436     }
10437 }
10438
10439
10440 /*-----------------------------------------------------------------*/
10441 /* genDataPointerSet - remat pointer to data space                 */
10442 /*-----------------------------------------------------------------*/
10443 static void
10444 genDataPointerSet (operand * right,
10445                    operand * result,
10446                    iCode * ic)
10447 {
10448   int size, offset = 0;
10449   char *l, buffer[256];
10450
10451   D (emitcode (";", "genDataPointerSet"));
10452
10453   aopOp (right, ic, FALSE);
10454
10455   l = aopGet (result, 0, FALSE, TRUE);
10456   l++; //remove #
10457   size = AOP_SIZE (right);
10458   while (size--)
10459     {
10460       if (offset)
10461         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10462       else
10463         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10464       emitcode ("mov", "%s,%s", buffer,
10465                 aopGet (right, offset++, FALSE, FALSE));
10466     }
10467
10468   freeAsmop (result, NULL, ic, TRUE);
10469   freeAsmop (right, NULL, ic, TRUE);
10470 }
10471
10472 /*-----------------------------------------------------------------*/
10473 /* genNearPointerSet - emitcode for near pointer put                */
10474 /*-----------------------------------------------------------------*/
10475 static void
10476 genNearPointerSet (operand * right,
10477                    operand * result,
10478                    iCode * ic,
10479                    iCode * pi)
10480 {
10481   asmop *aop = NULL;
10482   regs *preg = NULL;
10483   char *rname, *l;
10484   sym_link *retype, *letype;
10485   sym_link *ptype = operandType (result);
10486
10487   D (emitcode (";", "genNearPointerSet"));
10488
10489   retype = getSpec (operandType (right));
10490   letype = getSpec (ptype);
10491
10492   aopOp (result, ic, FALSE);
10493
10494   /* if the result is rematerializable &
10495      in data space & not a bit variable */
10496   if (AOP_TYPE (result) == AOP_IMMD &&
10497       DCL_TYPE (ptype) == POINTER &&
10498       !IS_BITVAR (retype) &&
10499       !IS_BITVAR (letype))
10500     {
10501       genDataPointerSet (right, result, ic);
10502       return;
10503     }
10504
10505   /* if the value is already in a pointer register
10506      then don't need anything more */
10507   if (!AOP_INPREG (AOP (result)))
10508     {
10509         if (
10510             //AOP_TYPE (result) == AOP_STK
10511             IS_AOP_PREG(result)
10512             )
10513         {
10514             // Aha, it is a pointer, just in disguise.
10515             rname = aopGet (result, 0, FALSE, FALSE);
10516             if (*rname != '@')
10517             {
10518                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10519                         __FILE__, __LINE__);
10520             }
10521             else
10522             {
10523                 // Expected case.
10524                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10525                 rname++;  // skip the '@'.
10526             }
10527         }
10528         else
10529         {
10530             /* otherwise get a free pointer register */
10531             aop = newAsmop (0);
10532             preg = getFreePtr (ic, &aop, FALSE);
10533             emitcode ("mov", "%s,%s",
10534                       preg->name,
10535                       aopGet (result, 0, FALSE, TRUE));
10536             rname = preg->name;
10537         }
10538     }
10539     else
10540     {
10541         rname = aopGet (result, 0, FALSE, FALSE);
10542     }
10543
10544   aopOp (right, ic, FALSE);
10545
10546   /* if bitfield then unpack the bits */
10547   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10548     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10549   else
10550     {
10551       /* we can just get the values */
10552       int size = AOP_SIZE (right);
10553       int offset = 0;
10554
10555       while (size--)
10556         {
10557           l = aopGet (right, offset, FALSE, TRUE);
10558           if ((*l == '@') || (strcmp (l, "acc") == 0))
10559             {
10560               MOVA (l);
10561               emitcode ("mov", "@%s,a", rname);
10562             }
10563           else
10564             emitcode ("mov", "@%s,%s", rname, l);
10565           if (size || pi)
10566             emitcode ("inc", "%s", rname);
10567           offset++;
10568         }
10569     }
10570
10571   /* now some housekeeping stuff */
10572   if (aop) /* we had to allocate for this iCode */
10573     {
10574       if (pi)
10575         aopPut (result, rname, 0);
10576       freeAsmop (NULL, aop, ic, TRUE);
10577     }
10578   else
10579     {
10580       /* we did not allocate which means left
10581          already in a pointer register, then
10582          if size > 0 && this could be used again
10583          we have to point it back to where it
10584          belongs */
10585       if ((AOP_SIZE (right) > 1 &&
10586            !OP_SYMBOL (result)->remat &&
10587            (OP_SYMBOL (result)->liveTo > ic->seq ||
10588             ic->depth)) &&
10589           !pi)
10590         {
10591           int size = AOP_SIZE (right) - 1;
10592           while (size--)
10593             emitcode ("dec", "%s", rname);
10594         }
10595     }
10596
10597   /* done */
10598   if (pi) pi->generated = 1;
10599   freeAsmop (result, NULL, ic, TRUE);
10600   freeAsmop (right, NULL, ic, TRUE);
10601 }
10602
10603 /*-----------------------------------------------------------------*/
10604 /* genPagedPointerSet - emitcode for Paged pointer put             */
10605 /*-----------------------------------------------------------------*/
10606 static void
10607 genPagedPointerSet (operand * right,
10608                     operand * result,
10609                     iCode * ic,
10610                     iCode * pi)
10611 {
10612   asmop *aop = NULL;
10613   regs *preg = NULL;
10614   char *rname, *l;
10615   sym_link *retype, *letype;
10616
10617   D (emitcode (";", "genPagedPointerSet"));
10618
10619   retype = getSpec (operandType (right));
10620   letype = getSpec (operandType (result));
10621
10622   aopOp (result, ic, FALSE);
10623
10624   /* if the value is already in a pointer register
10625      then don't need anything more */
10626   if (!AOP_INPREG (AOP (result)))
10627     {
10628       /* otherwise get a free pointer register */
10629       aop = newAsmop (0);
10630       preg = getFreePtr (ic, &aop, FALSE);
10631       emitcode ("mov", "%s,%s",
10632                 preg->name,
10633                 aopGet (result, 0, FALSE, TRUE));
10634       rname = preg->name;
10635     }
10636   else
10637     rname = aopGet (result, 0, FALSE, FALSE);
10638
10639   aopOp (right, ic, FALSE);
10640
10641   /* if bitfield then unpack the bits */
10642   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10643     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10644   else
10645     {
10646       /* we have can just get the values */
10647       int size = AOP_SIZE (right);
10648       int offset = 0;
10649
10650       while (size--)
10651         {
10652           l = aopGet (right, offset, FALSE, TRUE);
10653           MOVA (l);
10654           emitcode ("movx", "@%s,a", rname);
10655
10656           if (size || pi)
10657             emitcode ("inc", "%s", rname);
10658
10659           offset++;
10660         }
10661     }
10662
10663   /* now some housekeeping stuff */
10664   if (aop) /* we had to allocate for this iCode */
10665     {
10666       if (pi)
10667         aopPut (result, rname, 0);
10668       freeAsmop (NULL, aop, ic, TRUE);
10669     }
10670   else
10671     {
10672       /* we did not allocate which means left
10673          already in a pointer register, then
10674          if size > 0 && this could be used again
10675          we have to point it back to where it
10676          belongs */
10677       if (AOP_SIZE (right) > 1 &&
10678           !OP_SYMBOL (result)->remat &&
10679           (OP_SYMBOL (result)->liveTo > ic->seq ||
10680            ic->depth))
10681         {
10682           int size = AOP_SIZE (right) - 1;
10683           while (size--)
10684             emitcode ("dec", "%s", rname);
10685         }
10686     }
10687
10688   /* done */
10689   if (pi) pi->generated = 1;
10690   freeAsmop (result, NULL, ic, TRUE);
10691   freeAsmop (right, NULL, ic, TRUE);
10692 }
10693
10694 /*-----------------------------------------------------------------*/
10695 /* genFarPointerSet - set value from far space                     */
10696 /*-----------------------------------------------------------------*/
10697 static void
10698 genFarPointerSet (operand * right,
10699                   operand * result, iCode * ic, iCode * pi)
10700 {
10701   int size, offset;
10702   sym_link *retype = getSpec (operandType (right));
10703   sym_link *letype = getSpec (operandType (result));
10704
10705   D(emitcode (";     genFarPointerSet",""));
10706
10707   aopOp (result, ic, FALSE);
10708   loadDptrFromOperand (result, FALSE);
10709
10710   /* so dptr now contains the address */
10711   aopOp (right, ic, FALSE);
10712
10713   /* if bit then unpack */
10714   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10715     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10716   else
10717     {
10718       size = AOP_SIZE (right);
10719       offset = 0;
10720
10721       while (size--)
10722         {
10723           char *l = aopGet (right, offset++, FALSE, FALSE);
10724           MOVA (l);
10725           emitcode ("movx", "@dptr,a");
10726           if (size || pi)
10727             emitcode ("inc", "dptr");
10728         }
10729     }
10730   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10731     aopPut (result, "dpl", 0);
10732     aopPut (result, "dph", 1);
10733     pi->generated=1;
10734   }
10735   freeAsmop (result, NULL, ic, TRUE);
10736   freeAsmop (right, NULL, ic, TRUE);
10737 }
10738
10739 /*-----------------------------------------------------------------*/
10740 /* genGenPointerSet - set value from generic pointer space         */
10741 /*-----------------------------------------------------------------*/
10742 static void
10743 genGenPointerSet (operand * right,
10744                   operand * result, iCode * ic, iCode * pi)
10745 {
10746   int size, offset;
10747   sym_link *retype = getSpec (operandType (right));
10748   sym_link *letype = getSpec (operandType (result));
10749
10750   D (emitcode (";", "genGenPointerSet"));
10751
10752   aopOp (result, ic, FALSE);
10753   loadDptrFromOperand (result, TRUE);
10754
10755   /* so dptr now contains the address */
10756   aopOp (right, ic, FALSE);
10757
10758   /* if bit then unpack */
10759   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10760     {
10761       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10762     }
10763   else
10764     {
10765       size = AOP_SIZE (right);
10766       offset = 0;
10767
10768       while (size--)
10769         {
10770           char *l = aopGet (right, offset++, FALSE, FALSE);
10771           MOVA (l);
10772           emitcode ("lcall", "__gptrput");
10773           if (size || pi)
10774             emitcode ("inc", "dptr");
10775         }
10776     }
10777
10778   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10779     aopPut (result, "dpl", 0);
10780     aopPut (result, "dph", 1);
10781     pi->generated=1;
10782   }
10783   freeAsmop (result, NULL, ic, TRUE);
10784   freeAsmop (right, NULL, ic, TRUE);
10785 }
10786
10787 /*-----------------------------------------------------------------*/
10788 /* genPointerSet - stores the value into a pointer location        */
10789 /*-----------------------------------------------------------------*/
10790 static void
10791 genPointerSet (iCode * ic, iCode *pi)
10792 {
10793   operand *right, *result;
10794   sym_link *type, *etype;
10795   int p_type;
10796
10797   D (emitcode (";", "genPointerSet"));
10798
10799   right = IC_RIGHT (ic);
10800   result = IC_RESULT (ic);
10801
10802   /* depending on the type of pointer we need to
10803      move it to the correct pointer register */
10804   type = operandType (result);
10805   etype = getSpec (type);
10806   /* if left is of type of pointer then it is simple */
10807   if (IS_PTR (type) && !IS_FUNC (type->next))
10808     {
10809       p_type = DCL_TYPE (type);
10810     }
10811   else
10812     {
10813       /* we have to go by the storage class */
10814       p_type = PTR_TYPE (SPEC_OCLS (etype));
10815     }
10816
10817   /* special case when cast remat */
10818   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10819       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10820           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10821           type = operandType (result);
10822           p_type = DCL_TYPE (type);
10823   }
10824
10825   /* now that we have the pointer type we assign
10826      the pointer values */
10827   switch (p_type)
10828     {
10829
10830     case POINTER:
10831     case IPOINTER:
10832       genNearPointerSet (right, result, ic, pi);
10833       break;
10834
10835     case PPOINTER:
10836       genPagedPointerSet (right, result, ic, pi);
10837       break;
10838
10839     case FPOINTER:
10840       genFarPointerSet (right, result, ic, pi);
10841       break;
10842
10843     case GPOINTER:
10844       genGenPointerSet (right, result, ic, pi);
10845       break;
10846
10847     default:
10848       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10849               "genPointerSet: illegal pointer type");
10850     }
10851 }
10852
10853 /*-----------------------------------------------------------------*/
10854 /* genIfx - generate code for Ifx statement                        */
10855 /*-----------------------------------------------------------------*/
10856 static void
10857 genIfx (iCode * ic, iCode * popIc)
10858 {
10859   operand *cond = IC_COND (ic);
10860   int isbit = 0;
10861   char *dup = NULL;
10862
10863   D (emitcode (";", "genIfx"));
10864
10865   aopOp (cond, ic, FALSE);
10866
10867   /* get the value into acc */
10868   if (AOP_TYPE (cond) != AOP_CRY)
10869     {
10870       toBoolean (cond);
10871     }
10872   else
10873     {
10874       isbit = 1;
10875       if (AOP(cond)->aopu.aop_dir)
10876         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10877     }
10878
10879   /* the result is now in the accumulator or a directly addressable bit */
10880   freeAsmop (cond, NULL, ic, TRUE);
10881
10882   /* if there was something to be popped then do it */
10883   if (popIc)
10884     genIpop (popIc);
10885
10886   /* if the condition is a bit variable */
10887   if (isbit && dup)
10888     genIfxJump(ic, dup, NULL, NULL, NULL);
10889   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10890     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10891   else if (isbit && !IS_ITEMP (cond))
10892     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10893   else
10894     genIfxJump (ic, "a", NULL, NULL, NULL);
10895
10896   ic->generated = 1;
10897 }
10898
10899 /*-----------------------------------------------------------------*/
10900 /* genAddrOf - generates code for address of                       */
10901 /*-----------------------------------------------------------------*/
10902 static void
10903 genAddrOf (iCode * ic)
10904 {
10905   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10906   int size, offset;
10907
10908   D (emitcode (";", "genAddrOf"));
10909
10910   aopOp (IC_RESULT (ic), ic, FALSE);
10911
10912   /* if the operand is on the stack then we
10913      need to get the stack offset of this
10914      variable */
10915   if (sym->onStack)
10916     {
10917       /* if it has an offset then we need to compute it */
10918       if (sym->stack)
10919         {
10920           int stack_offset = ((sym->stack < 0) ?
10921                               ((char) (sym->stack - _G.nRegsSaved)) :
10922                               ((char) sym->stack)) & 0xff;
10923           if ((abs(stack_offset) == 1) &&
10924               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10925               !isOperandVolatile (IC_RESULT (ic), FALSE))
10926             {
10927               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10928               if (stack_offset > 0)
10929                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10930               else
10931                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10932             }
10933           else
10934             {
10935               emitcode ("mov", "a,%s", SYM_BP (sym));
10936               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10937               aopPut (IC_RESULT (ic), "a", 0);
10938             }
10939         }
10940       else
10941         {
10942           /* we can just move _bp */
10943           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10944         }
10945       /* fill the result with zero */
10946       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10947
10948       offset = 1;
10949       while (size--)
10950         {
10951           aopPut (IC_RESULT (ic), zero, offset++);
10952         }
10953       goto release;
10954     }
10955
10956   /* object not on stack then we need the name */
10957   size = AOP_SIZE (IC_RESULT (ic));
10958   offset = 0;
10959
10960   while (size--)
10961     {
10962       char s[SDCC_NAME_MAX];
10963       if (offset)
10964         sprintf (s, "#(%s >> %d)",
10965                  sym->rname,
10966                  offset * 8);
10967       else
10968         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10969       aopPut (IC_RESULT (ic), s, offset++);
10970     }
10971
10972 release:
10973   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10974
10975 }
10976
10977 /*-----------------------------------------------------------------*/
10978 /* genFarFarAssign - assignment when both are in far space         */
10979 /*-----------------------------------------------------------------*/
10980 static void
10981 genFarFarAssign (operand * result, operand * right, iCode * ic)
10982 {
10983   int size = AOP_SIZE (right);
10984   int offset = 0;
10985   char *l;
10986
10987   D (emitcode (";", "genFarFarAssign"));
10988
10989   /* first push the right side on to the stack */
10990   while (size--)
10991     {
10992       l = aopGet (right, offset++, FALSE, FALSE);
10993       MOVA (l);
10994       emitcode ("push", "acc");
10995     }
10996
10997   freeAsmop (right, NULL, ic, FALSE);
10998   /* now assign DPTR to result */
10999   aopOp (result, ic, FALSE);
11000   size = AOP_SIZE (result);
11001   while (size--)
11002     {
11003       emitcode ("pop", "acc");
11004       aopPut (result, "a", --offset);
11005     }
11006   freeAsmop (result, NULL, ic, FALSE);
11007 }
11008
11009 /*-----------------------------------------------------------------*/
11010 /* genAssign - generate code for assignment                        */
11011 /*-----------------------------------------------------------------*/
11012 static void
11013 genAssign (iCode * ic)
11014 {
11015   operand *result, *right;
11016   int size, offset;
11017   unsigned long lit = 0L;
11018
11019   D (emitcode (";", "genAssign"));
11020
11021   result = IC_RESULT (ic);
11022   right = IC_RIGHT (ic);
11023
11024   /* if they are the same */
11025   if (operandsEqu (result, right) &&
11026       !isOperandVolatile (result, FALSE) &&
11027       !isOperandVolatile (right, FALSE))
11028     return;
11029
11030   aopOp (right, ic, FALSE);
11031
11032   /* special case both in far space */
11033   if (AOP_TYPE (right) == AOP_DPTR &&
11034       IS_TRUE_SYMOP (result) &&
11035       isOperandInFarSpace (result))
11036     {
11037       genFarFarAssign (result, right, ic);
11038       return;
11039     }
11040
11041   aopOp (result, ic, TRUE);
11042
11043   /* if they are the same registers */
11044   if (sameRegs (AOP (right), AOP (result)) &&
11045       !isOperandVolatile (result, FALSE) &&
11046       !isOperandVolatile (right, FALSE))
11047     goto release;
11048
11049   /* if the result is a bit */
11050   if (AOP_TYPE (result) == AOP_CRY)
11051     {
11052       /* if the right size is a literal then
11053          we know what the value is */
11054       if (AOP_TYPE (right) == AOP_LIT)
11055         {
11056           if (((int) operandLitValue (right)))
11057             aopPut (result, one, 0);
11058           else
11059             aopPut (result, zero, 0);
11060           goto release;
11061         }
11062
11063       /* the right is also a bit variable */
11064       if (AOP_TYPE (right) == AOP_CRY)
11065         {
11066           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11067           aopPut (result, "c", 0);
11068           goto release;
11069         }
11070
11071       /* we need to or */
11072       toBoolean (right);
11073       aopPut (result, "a", 0);
11074       goto release;
11075     }
11076
11077   /* bit variables done */
11078   /* general case */
11079   size = AOP_SIZE (result);
11080   offset = 0;
11081   if (AOP_TYPE (right) == AOP_LIT)
11082     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11083
11084   if ((size > 1) &&
11085       (AOP_TYPE (result) != AOP_REG) &&
11086       (AOP_TYPE (right) == AOP_LIT) &&
11087       !IS_FLOAT (operandType (right)) &&
11088       (lit < 256L))
11089     {
11090       while ((size) && (lit))
11091         {
11092           aopPut (result,
11093                   aopGet (right, offset, FALSE, FALSE),
11094                   offset);
11095           lit >>= 8;
11096           offset++;
11097           size--;
11098         }
11099       /* And now fill the rest with zeros. */
11100       if (size)
11101         {
11102           emitcode ("clr", "a");
11103         }
11104       while (size--)
11105         {
11106           aopPut (result, "a", offset);
11107           offset++;
11108         }
11109     }
11110   else
11111     {
11112       while (size--)
11113         {
11114           aopPut (result,
11115                   aopGet (right, offset, FALSE, FALSE),
11116                   offset);
11117           offset++;
11118         }
11119     }
11120
11121 release:
11122   freeAsmop (result, NULL, ic, TRUE);
11123   freeAsmop (right, NULL, ic, TRUE);
11124 }
11125
11126 /*-----------------------------------------------------------------*/
11127 /* genJumpTab - generates code for jump table                      */
11128 /*-----------------------------------------------------------------*/
11129 static void
11130 genJumpTab (iCode * ic)
11131 {
11132   symbol *jtab,*jtablo,*jtabhi;
11133   char *l;
11134   unsigned int count;
11135
11136   D (emitcode (";", "genJumpTab"));
11137
11138   count = elementsInSet( IC_JTLABELS (ic) );
11139
11140   if( count <= 16 )
11141     {
11142       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11143          if the switch argument is in a register.
11144          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11145       /* Peephole may not convert ljmp to sjmp or ret
11146          labelIsReturnOnly & labelInRange must check
11147          currPl->ic->op != JUMPTABLE */
11148       aopOp (IC_JTCOND (ic), ic, FALSE);
11149       /* get the condition into accumulator */
11150       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11151       MOVA (l);
11152       /* multiply by three */
11153       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11154         {
11155           emitcode ("mov", "b,#3");
11156           emitcode ("mul", "ab");
11157         }
11158       else
11159         {
11160           emitcode ("add", "a,acc");
11161           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11162         }
11163       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11164
11165       jtab = newiTempLabel (NULL);
11166       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11167       emitcode ("jmp", "@a+dptr");
11168       emitLabel (jtab);
11169       /* now generate the jump labels */
11170       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11171            jtab = setNextItem (IC_JTLABELS (ic)))
11172         emitcode ("ljmp", "%05d$", jtab->key + 100);
11173     }
11174   else
11175     {
11176       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11177          if the switch argument is in a register.
11178          For n>6 this algorithm may be more compact */
11179       jtablo = newiTempLabel (NULL);
11180       jtabhi = newiTempLabel (NULL);
11181
11182       /* get the condition into accumulator.
11183          Using b as temporary storage, if register push/pop is needed */
11184       aopOp (IC_JTCOND (ic), ic, FALSE);
11185       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11186       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11187           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11188         {
11189           // (MB) what if B is in use???
11190           wassertl(!BINUSE, "B was in use");
11191           emitcode ("mov", "b,%s", l);
11192           l = "b";
11193         }
11194       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11195       MOVA (l);
11196       if( count <= 112 )
11197         {
11198           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11199           emitcode ("movc", "a,@a+pc");
11200           emitcode ("push", "acc");
11201
11202           MOVA (l);
11203           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11204           emitcode ("movc", "a,@a+pc");
11205           emitcode ("push", "acc");
11206         }
11207       else
11208         {
11209           /* this scales up to n<=255, but needs two more bytes
11210              and changes dptr */
11211           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11212           emitcode ("movc", "a,@a+dptr");
11213           emitcode ("push", "acc");
11214
11215           MOVA (l);
11216           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11217           emitcode ("movc", "a,@a+dptr");
11218           emitcode ("push", "acc");
11219         }
11220
11221       emitcode ("ret", "");
11222
11223       /* now generate jump table, LSB */
11224       emitLabel (jtablo);
11225       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11226            jtab = setNextItem (IC_JTLABELS (ic)))
11227         emitcode (".db", "%05d$", jtab->key + 100);
11228
11229       /* now generate jump table, MSB */
11230       emitLabel (jtabhi);
11231       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11232            jtab = setNextItem (IC_JTLABELS (ic)))
11233          emitcode (".db", "%05d$>>8", jtab->key + 100);
11234     }
11235 }
11236
11237 /*-----------------------------------------------------------------*/
11238 /* genCast - gen code for casting                                  */
11239 /*-----------------------------------------------------------------*/
11240 static void
11241 genCast (iCode * ic)
11242 {
11243   operand *result = IC_RESULT (ic);
11244   sym_link *ctype = operandType (IC_LEFT (ic));
11245   sym_link *rtype = operandType (IC_RIGHT (ic));
11246   operand *right = IC_RIGHT (ic);
11247   int size, offset;
11248
11249   D (emitcode (";", "genCast"));
11250
11251   /* if they are equivalent then do nothing */
11252   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11253     return;
11254
11255   aopOp (right, ic, FALSE);
11256   aopOp (result, ic, FALSE);
11257
11258   /* if the result is a bit (and not a bitfield) */
11259   if (IS_BIT (OP_SYMBOL (result)->type))
11260     {
11261       /* if the right size is a literal then
11262          we know what the value is */
11263       if (AOP_TYPE (right) == AOP_LIT)
11264         {
11265           if (((int) operandLitValue (right)))
11266             aopPut (result, one, 0);
11267           else
11268             aopPut (result, zero, 0);
11269
11270           goto release;
11271         }
11272
11273       /* the right is also a bit variable */
11274       if (AOP_TYPE (right) == AOP_CRY)
11275         {
11276           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11277           aopPut (result, "c", 0);
11278           goto release;
11279         }
11280
11281       /* we need to or */
11282       toBoolean (right);
11283       aopPut (result, "a", 0);
11284       goto release;
11285     }
11286
11287   /* if they are the same size : or less */
11288   if (AOP_SIZE (result) <= AOP_SIZE (right))
11289     {
11290
11291       /* if they are in the same place */
11292       if (sameRegs (AOP (right), AOP (result)))
11293         goto release;
11294
11295       /* if they in different places then copy */
11296       size = AOP_SIZE (result);
11297       offset = 0;
11298       while (size--)
11299         {
11300           aopPut (result,
11301                   aopGet (right, offset, FALSE, FALSE),
11302                   offset);
11303           offset++;
11304         }
11305       goto release;
11306     }
11307
11308   /* if the result is of type pointer */
11309   if (IS_PTR (ctype))
11310     {
11311
11312       int p_type;
11313       sym_link *type = operandType (right);
11314       sym_link *etype = getSpec (type);
11315
11316       /* pointer to generic pointer */
11317       if (IS_GENPTR (ctype))
11318         {
11319           if (IS_PTR (type))
11320             {
11321               p_type = DCL_TYPE (type);
11322             }
11323           else
11324             {
11325               if (SPEC_SCLS(etype)==S_REGISTER) {
11326                 // let's assume it is a generic pointer
11327                 p_type=GPOINTER;
11328               } else {
11329                 /* we have to go by the storage class */
11330                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11331               }
11332             }
11333
11334           /* the first two bytes are known */
11335           size = GPTRSIZE - 1;
11336           offset = 0;
11337           while (size--)
11338             {
11339               aopPut (result,
11340                       aopGet (right, offset, FALSE, FALSE),
11341                       offset);
11342               offset++;
11343             }
11344           /* the last byte depending on type */
11345             {
11346                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11347                 char gpValStr[10];
11348
11349                 if (gpVal == -1)
11350                 {
11351                     // pointerTypeToGPByte will have bitched.
11352                     exit(1);
11353                 }
11354
11355                 sprintf(gpValStr, "#0x%x", gpVal);
11356                 aopPut (result, gpValStr, GPTRSIZE - 1);
11357             }
11358           goto release;
11359         }
11360
11361       /* just copy the pointers */
11362       size = AOP_SIZE (result);
11363       offset = 0;
11364       while (size--)
11365         {
11366           aopPut (result,
11367                   aopGet (right, offset, FALSE, FALSE),
11368                   offset);
11369           offset++;
11370         }
11371       goto release;
11372     }
11373
11374   /* so we now know that the size of destination is greater
11375      than the size of the source */
11376   /* we move to result for the size of source */
11377   size = AOP_SIZE (right);
11378   offset = 0;
11379   while (size--)
11380     {
11381       aopPut (result,
11382               aopGet (right, offset, FALSE, FALSE),
11383               offset);
11384       offset++;
11385     }
11386
11387   /* now depending on the sign of the source && destination */
11388   size = AOP_SIZE (result) - AOP_SIZE (right);
11389   /* if unsigned or not an integral type */
11390   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11391     {
11392       while (size--)
11393         aopPut (result, zero, offset++);
11394     }
11395   else
11396     {
11397       /* we need to extend the sign :{ */
11398       char *l = aopGet (right, AOP_SIZE (right) - 1,
11399                         FALSE, FALSE);
11400       MOVA (l);
11401       emitcode ("rlc", "a");
11402       emitcode ("subb", "a,acc");
11403       while (size--)
11404         aopPut (result, "a", offset++);
11405     }
11406
11407   /* we are done hurray !!!! */
11408
11409 release:
11410   freeAsmop (result, NULL, ic, TRUE);
11411   freeAsmop (right, NULL, ic, TRUE);
11412 }
11413
11414 /*-----------------------------------------------------------------*/
11415 /* genDjnz - generate decrement & jump if not zero instrucion      */
11416 /*-----------------------------------------------------------------*/
11417 static int
11418 genDjnz (iCode * ic, iCode * ifx)
11419 {
11420   symbol *lbl, *lbl1;
11421   if (!ifx)
11422     return 0;
11423
11424   /* if the if condition has a false label
11425      then we cannot save */
11426   if (IC_FALSE (ifx))
11427     return 0;
11428
11429   /* if the minus is not of the form a = a - 1 */
11430   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11431       !IS_OP_LITERAL (IC_RIGHT (ic)))
11432     return 0;
11433
11434   if (operandLitValue (IC_RIGHT (ic)) != 1)
11435     return 0;
11436
11437   /* if the size of this greater than one then no
11438      saving */
11439   if (getSize (operandType (IC_RESULT (ic))) > 1)
11440     return 0;
11441
11442   /* otherwise we can save BIG */
11443
11444   D (emitcode (";", "genDjnz"));
11445
11446   lbl = newiTempLabel (NULL);
11447   lbl1 = newiTempLabel (NULL);
11448
11449   aopOp (IC_RESULT (ic), ic, FALSE);
11450
11451   if (AOP_NEEDSACC(IC_RESULT(ic)))
11452   {
11453       /* If the result is accessed indirectly via
11454        * the accumulator, we must explicitly write
11455        * it back after the decrement.
11456        */
11457       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11458
11459       if (strcmp(rByte, "a"))
11460       {
11461            /* Something is hopelessly wrong */
11462            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11463                    __FILE__, __LINE__);
11464            /* We can just give up; the generated code will be inefficient,
11465             * but what the hey.
11466             */
11467            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11468            return 0;
11469       }
11470       emitcode ("dec", "%s", rByte);
11471       aopPut (IC_RESULT (ic), rByte, 0);
11472       emitcode ("jnz", "%05d$", lbl->key + 100);
11473   }
11474   else if (IS_AOP_PREG (IC_RESULT (ic)))
11475     {
11476       emitcode ("dec", "%s",
11477                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11478       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11479       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11480       ifx->generated = 1;
11481       emitcode ("jnz", "%05d$", lbl->key + 100);
11482     }
11483   else
11484     {
11485       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11486                 lbl->key + 100);
11487     }
11488   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11489   emitLabel (lbl);
11490   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11491   emitLabel (lbl1);
11492
11493   if (!ifx->generated)
11494       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11495   ifx->generated = 1;
11496   return 1;
11497 }
11498
11499 /*-----------------------------------------------------------------*/
11500 /* genReceive - generate code for a receive iCode                  */
11501 /*-----------------------------------------------------------------*/
11502 static void
11503 genReceive (iCode * ic)
11504 {
11505   int size = getSize (operandType (IC_RESULT (ic)));
11506   int offset = 0;
11507
11508   D (emitcode (";", "genReceive"));
11509
11510   if (ic->argreg == 1)
11511     { /* first parameter */
11512       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11513            isOperandInPagedSpace (IC_RESULT (ic))) &&
11514           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11515            IS_TRUE_SYMOP (IC_RESULT (ic))))
11516         {
11517           regs *tempRegs[4];
11518           int receivingA = 0;
11519           int roffset = 0;
11520
11521           for (offset = 0; offset<size; offset++)
11522             if (!strcmp (fReturn[offset], "a"))
11523               receivingA = 1;
11524
11525           if (!receivingA)
11526             {
11527               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11528                 {
11529                   for (offset = size-1; offset>0; offset--)
11530                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11531                   emitcode("mov","a,%s", fReturn[0]);
11532                   _G.accInUse++;
11533                   aopOp (IC_RESULT (ic), ic, FALSE);
11534                   _G.accInUse--;
11535                   aopPut (IC_RESULT (ic), "a", offset);
11536                   for (offset = 1; offset<size; offset++)
11537                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11538                   goto release;
11539                 }
11540             }
11541           else
11542             {
11543               if (getTempRegs(tempRegs, size, ic))
11544                 {
11545                   for (offset = 0; offset<size; offset++)
11546                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11547                   aopOp (IC_RESULT (ic), ic, FALSE);
11548                   for (offset = 0; offset<size; offset++)
11549                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11550                   goto release;
11551                 }
11552             }
11553
11554           offset = fReturnSizeMCS51 - size;
11555           while (size--)
11556             {
11557               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11558                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11559               offset++;
11560             }
11561           aopOp (IC_RESULT (ic), ic, FALSE);
11562           size = AOP_SIZE (IC_RESULT (ic));
11563           offset = 0;
11564           while (size--)
11565             {
11566               emitcode ("pop", "acc");
11567               aopPut (IC_RESULT (ic), "a", offset++);
11568             }
11569         }
11570       else
11571         {
11572           _G.accInUse++;
11573           aopOp (IC_RESULT (ic), ic, FALSE);
11574           _G.accInUse--;
11575           assignResultValue (IC_RESULT (ic), NULL);
11576         }
11577     }
11578   else if (ic->argreg > 12)
11579     { /* bit parameters */
11580       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11581         {
11582           aopOp (IC_RESULT (ic), ic, FALSE);
11583           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11584           outBitC(IC_RESULT (ic));
11585         }
11586     }
11587   else
11588     { /* other parameters */
11589       int rb1off ;
11590       aopOp (IC_RESULT (ic), ic, FALSE);
11591       rb1off = ic->argreg;
11592       while (size--)
11593         {
11594           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11595         }
11596     }
11597
11598 release:
11599   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11600 }
11601
11602 /*-----------------------------------------------------------------*/
11603 /* genDummyRead - generate code for dummy read of volatiles        */
11604 /*-----------------------------------------------------------------*/
11605 static void
11606 genDummyRead (iCode * ic)
11607 {
11608   operand *op;
11609   int size, offset;
11610
11611   D (emitcode(";", "genDummyRead"));
11612
11613   op = IC_RIGHT (ic);
11614   if (op && IS_SYMOP (op))
11615     {
11616       aopOp (op, ic, FALSE);
11617
11618       /* if the result is a bit */
11619       if (AOP_TYPE (op) == AOP_CRY)
11620         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11621       else
11622         {
11623           /* bit variables done */
11624           /* general case */
11625           size = AOP_SIZE (op);
11626           offset = 0;
11627           while (size--)
11628           {
11629             MOVA (aopGet (op, offset, FALSE, FALSE));
11630             offset++;
11631           }
11632         }
11633
11634       freeAsmop (op, NULL, ic, TRUE);
11635     }
11636
11637   op = IC_LEFT (ic);
11638   if (op && IS_SYMOP (op))
11639     {
11640       aopOp (op, ic, FALSE);
11641
11642       /* if the result is a bit */
11643       if (AOP_TYPE (op) == AOP_CRY)
11644         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11645       else
11646         {
11647           /* bit variables done */
11648           /* general case */
11649           size = AOP_SIZE (op);
11650           offset = 0;
11651           while (size--)
11652           {
11653             MOVA (aopGet (op, offset, FALSE, FALSE));
11654             offset++;
11655           }
11656         }
11657
11658       freeAsmop (op, NULL, ic, TRUE);
11659     }
11660 }
11661
11662 /*-----------------------------------------------------------------*/
11663 /* genCritical - generate code for start of a critical sequence    */
11664 /*-----------------------------------------------------------------*/
11665 static void
11666 genCritical (iCode *ic)
11667 {
11668   symbol *tlbl = newiTempLabel (NULL);
11669
11670   D (emitcode(";", "genCritical"));
11671
11672   if (IC_RESULT (ic))
11673     {
11674       aopOp (IC_RESULT (ic), ic, TRUE);
11675       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11676       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11677       aopPut (IC_RESULT (ic), zero, 0);
11678       emitLabel (tlbl);
11679       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11680     }
11681   else
11682     {
11683       emitcode ("setb", "c");
11684       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11685       emitcode ("clr", "c");
11686       emitLabel (tlbl);
11687       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11688     }
11689 }
11690
11691 /*-----------------------------------------------------------------*/
11692 /* genEndCritical - generate code for end of a critical sequence   */
11693 /*-----------------------------------------------------------------*/
11694 static void
11695 genEndCritical (iCode *ic)
11696 {
11697   D(emitcode(";     genEndCritical",""));
11698
11699   if (IC_RIGHT (ic))
11700     {
11701       aopOp (IC_RIGHT (ic), ic, FALSE);
11702       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11703         {
11704           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11705           emitcode ("mov", "ea,c");
11706         }
11707       else
11708         {
11709           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11710             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11711           emitcode ("rrc", "a");
11712           emitcode ("mov", "ea,c");
11713         }
11714       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11715     }
11716   else
11717     {
11718       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11719       emitcode ("mov", "ea,c");
11720     }
11721 }
11722
11723 /*-----------------------------------------------------------------*/
11724 /* gen51Code - generate code for 8051 based controllers            */
11725 /*-----------------------------------------------------------------*/
11726 void
11727 gen51Code (iCode * lic)
11728 {
11729   iCode *ic;
11730   int cln = 0;
11731   /* int cseq = 0; */
11732
11733   _G.currentFunc = NULL;
11734   lineHead = lineCurr = NULL;
11735
11736   /* print the allocation information */
11737   if (allocInfo && currFunc)
11738     printAllocInfo (currFunc, codeOutBuf);
11739   /* if debug information required */
11740   if (options.debug && currFunc)
11741     {
11742       debugFile->writeFunction (currFunc, lic);
11743     }
11744   /* stack pointer name */
11745   if (options.useXstack)
11746     spname = "_spx";
11747   else
11748     spname = "sp";
11749
11750
11751   for (ic = lic; ic; ic = ic->next)
11752     {
11753       _G.current_iCode = ic;
11754
11755       if (ic->lineno && cln != ic->lineno)
11756         {
11757           if (options.debug)
11758             {
11759               debugFile->writeCLine (ic);
11760             }
11761           if (!options.noCcodeInAsm) {
11762             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11763                       printCLine(ic->filename, ic->lineno));
11764           }
11765           cln = ic->lineno;
11766         }
11767       #if 0
11768       if (ic->seqPoint && ic->seqPoint != cseq)
11769         {
11770           emitcode ("", "; sequence point %d", ic->seqPoint);
11771           cseq = ic->seqPoint;
11772         }
11773       #endif
11774       if (options.iCodeInAsm) {
11775         char regsInUse[80];
11776         int i;
11777         char *iLine;
11778
11779         #if 0
11780         for (i=0; i<8; i++) {
11781           sprintf (&regsInUse[i],
11782                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11783         regsInUse[i]=0;
11784         #else
11785         strcpy (regsInUse, "--------");
11786         for (i=0; i < 8; i++) {
11787           if (bitVectBitValue (ic->rMask, i))
11788             {
11789               int offset = regs8051[i].offset;
11790               regsInUse[offset] = offset + '0'; /* show rMask */
11791             }
11792         #endif
11793         }
11794         iLine = printILine(ic);
11795         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11796         dbuf_free(iLine);
11797       }
11798       /* if the result is marked as
11799          spilt and rematerializable or code for
11800          this has already been generated then
11801          do nothing */
11802       if (resultRemat (ic) || ic->generated)
11803         continue;
11804
11805       /* depending on the operation */
11806       switch (ic->op)
11807         {
11808         case '!':
11809           genNot (ic);
11810           break;
11811
11812         case '~':
11813           genCpl (ic);
11814           break;
11815
11816         case UNARYMINUS:
11817           genUminus (ic);
11818           break;
11819
11820         case IPUSH:
11821           genIpush (ic);
11822           break;
11823
11824         case IPOP:
11825           /* IPOP happens only when trying to restore a
11826              spilt live range, if there is an ifx statement
11827              following this pop then the if statement might
11828              be using some of the registers being popped which
11829              would destory the contents of the register so
11830              we need to check for this condition and handle it */
11831           if (ic->next &&
11832               ic->next->op == IFX &&
11833               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11834             genIfx (ic->next, ic);
11835           else
11836             genIpop (ic);
11837           break;
11838
11839         case CALL:
11840           genCall (ic);
11841           break;
11842
11843         case PCALL:
11844           genPcall (ic);
11845           break;
11846
11847         case FUNCTION:
11848           genFunction (ic);
11849           break;
11850
11851         case ENDFUNCTION:
11852           genEndFunction (ic);
11853           break;
11854
11855         case RETURN:
11856           genRet (ic);
11857           break;
11858
11859         case LABEL:
11860           genLabel (ic);
11861           break;
11862
11863         case GOTO:
11864           genGoto (ic);
11865           break;
11866
11867         case '+':
11868           genPlus (ic);
11869           break;
11870
11871         case '-':
11872           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11873             genMinus (ic);
11874           break;
11875
11876         case '*':
11877           genMult (ic);
11878           break;
11879
11880         case '/':
11881           genDiv (ic);
11882           break;
11883
11884         case '%':
11885           genMod (ic);
11886           break;
11887
11888         case '>':
11889           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11890           break;
11891
11892         case '<':
11893           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11894           break;
11895
11896         case LE_OP:
11897         case GE_OP:
11898         case NE_OP:
11899
11900           /* note these two are xlated by algebraic equivalence
11901              in decorateType() in SDCCast.c */
11902           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11903                   "got '>=' or '<=' shouldn't have come here");
11904           break;
11905
11906         case EQ_OP:
11907           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11908           break;
11909
11910         case AND_OP:
11911           genAndOp (ic);
11912           break;
11913
11914         case OR_OP:
11915           genOrOp (ic);
11916           break;
11917
11918         case '^':
11919           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11920           break;
11921
11922         case '|':
11923           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11924           break;
11925
11926         case BITWISEAND:
11927           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11928           break;
11929
11930         case INLINEASM:
11931           genInline (ic);
11932           break;
11933
11934         case RRC:
11935           genRRC (ic);
11936           break;
11937
11938         case RLC:
11939           genRLC (ic);
11940           break;
11941
11942         case GETHBIT:
11943           genGetHbit (ic);
11944           break;
11945
11946         case GETABIT:
11947           genGetAbit (ic);
11948           break;
11949
11950         case GETBYTE:
11951           genGetByte (ic);
11952           break;
11953
11954         case GETWORD:
11955           genGetWord (ic);
11956           break;
11957
11958         case LEFT_OP:
11959           genLeftShift (ic);
11960           break;
11961
11962         case RIGHT_OP:
11963           genRightShift (ic);
11964           break;
11965
11966         case GET_VALUE_AT_ADDRESS:
11967           genPointerGet (ic,
11968                          hasInc (IC_LEFT (ic), ic,
11969                                  getSize (operandType (IC_RESULT (ic)))),
11970                          ifxForOp (IC_RESULT (ic), ic) );
11971           break;
11972
11973         case '=':
11974           if (POINTER_SET (ic))
11975             genPointerSet (ic,
11976                            hasInc (IC_RESULT (ic), ic,
11977                                    getSize (operandType (IC_RIGHT (ic)))));
11978           else
11979             genAssign (ic);
11980           break;
11981
11982         case IFX:
11983           genIfx (ic, NULL);
11984           break;
11985
11986         case ADDRESS_OF:
11987           genAddrOf (ic);
11988           break;
11989
11990         case JUMPTABLE:
11991           genJumpTab (ic);
11992           break;
11993
11994         case CAST:
11995           genCast (ic);
11996           break;
11997
11998         case RECEIVE:
11999           genReceive (ic);
12000           break;
12001
12002         case SEND:
12003           addSet (&_G.sendSet, ic);
12004           break;
12005
12006         case DUMMY_READ_VOLATILE:
12007           genDummyRead (ic);
12008           break;
12009
12010         case CRITICAL:
12011           genCritical (ic);
12012           break;
12013
12014         case ENDCRITICAL:
12015           genEndCritical (ic);
12016           break;
12017
12018         case SWAP:
12019           genSwap (ic);
12020           break;
12021
12022         default:
12023           ic = ic;
12024         }
12025     }
12026
12027   _G.current_iCode = NULL;
12028
12029   /* now we are ready to call the
12030      peep hole optimizer */
12031   if (!options.nopeep)
12032     peepHole (&lineHead);
12033
12034   /* now do the actual printing */
12035   printLine (lineHead, codeOutBuf);
12036   return;
12037 }