10487d911da49827652b921269593d2bdfe6d32e
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45 #include "dbuf_string.h"
46
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
49 extern int allocInfo;
50
51 /* this is the down and dirty file with all kinds of
52    kludgy & hacky stuff. This is what it is all about
53    CODE GENERATION for a specific MCU . some of the
54    routines may be reusable, will have to see */
55
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
58 static char *spname;
59
60 char *fReturn8051[] =
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
65 {"a", "b"};
66
67 static unsigned short rbank = -1;
68
69 #define REG_WITH_INDEX   mcs51_regWithIdx
70
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75                         AOP_TYPE(x) == AOP_R0))
76
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
78                          AOP_TYPE(x) == AOP_DPTR || \
79                          AOP(x)->paged))
80
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
82                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84
85 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86
87 #define R0INB   _G.bu.bs.r0InB
88 #define R1INB   _G.bu.bs.r1InB
89 #define OPINB   _G.bu.bs.OpInB
90 #define BINUSE  _G.bu.BInUse
91
92 static struct
93   {
94     short r0Pushed;
95     short r1Pushed;
96     union
97       {
98         struct
99           {
100             short r0InB : 2;//2 so we can see it overflow
101             short r1InB : 2;//2 so we can see it overflow
102             short OpInB : 2;//2 so we can see it overflow
103           } bs;
104         short BInUse;
105       } bu;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111     iCode *current_iCode;
112     symbol *currentFunc;
113   }
114 _G;
115
116 static char *rb1regs[] = {
117     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
119 };
120
121 extern struct dbuf_s *codeOutBuf;
122 static void saveRBank (int, iCode *, bool);
123
124 #define RESULTONSTACK(x) \
125                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
126                          IC_RESULT(x)->aop->type == AOP_STK )
127
128 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
129 #define MOVB(x)  movb(x)
130
131 #define CLRC     emitcode("clr","c")
132 #define SETC     emitcode("setb","c")
133
134 static lineNode *lineHead = NULL;
135 static lineNode *lineCurr = NULL;
136
137 static unsigned char SLMask[] =
138 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
139  0xE0, 0xC0, 0x80, 0x00};
140 static unsigned char SRMask[] =
141 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
142  0x07, 0x03, 0x01, 0x00};
143
144 #define LSB     0
145 #define MSB16   1
146 #define MSB24   2
147 #define MSB32   3
148
149 /*-----------------------------------------------------------------*/
150 /* emitcode - writes the code into a file : for now it is simple    */
151 /*-----------------------------------------------------------------*/
152 static void
153 emitcode (const char *inst, const char *fmt,...)
154 {
155   va_list ap;
156   struct dbuf_s dbuf;
157   const char *lbp, *lb;
158
159   dbuf_init (&dbuf, INITIAL_INLINEASM);
160
161   va_start (ap, fmt);
162
163   if (inst && *inst)
164     {
165       dbuf_append_str (&dbuf, inst);
166
167       if (fmt && *fmt)
168         {
169           dbuf_append_char (&dbuf, '\t');
170           dbuf_tvprintf (&dbuf, fmt, ap);
171         }
172     }
173   else
174     {
175       dbuf_tvprintf (&dbuf, fmt, ap);
176     }
177
178   lbp = lb = dbuf_c_str(&dbuf);
179
180   while (isspace ((unsigned char)*lbp))
181     {
182       lbp++;
183     }
184
185   if (lbp && *lbp)
186     {
187       lineCurr = (lineCurr ?
188                   connectLine (lineCurr, newLineNode (lb)) :
189                   (lineHead = newLineNode (lb)));
190     }
191
192   lineCurr->isInline = _G.inLine;
193   lineCurr->isDebug = _G.debugLine;
194   lineCurr->ic = _G.current_iCode;
195   lineCurr->isComment = (*lbp==';');
196   va_end (ap);
197
198   dbuf_destroy(&dbuf);
199 }
200
201 static void
202 emitLabel (symbol *tlbl)
203 {
204   emitcode ("", "%05d$:", tlbl->key + 100);
205   lineCurr->isLabel = 1;
206 }
207
208 /*-----------------------------------------------------------------*/
209 /* mcs51_emitDebuggerSymbol - associate the current code location  */
210 /*   with a debugger symbol                                        */
211 /*-----------------------------------------------------------------*/
212 void
213 mcs51_emitDebuggerSymbol (char * debugSym)
214 {
215   _G.debugLine = 1;
216   emitcode ("", "%s ==.", debugSym);
217   _G.debugLine = 0;
218 }
219
220 /*-----------------------------------------------------------------*/
221 /* mova - moves specified value into accumulator                   */
222 /*-----------------------------------------------------------------*/
223 static void
224 mova (const char *x)
225 {
226   /* do some early peephole optimization */
227   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
228     return;
229
230   emitcode("mov", "a,%s", x);
231 }
232
233 /*-----------------------------------------------------------------*/
234 /* movb - moves specified value into register b                    */
235 /*-----------------------------------------------------------------*/
236 static void
237 movb (const char *x)
238 {
239   /* do some early peephole optimization */
240   if (!strncmp(x, "b", 2))
241     return;
242
243   emitcode("mov","b,%s", x);
244 }
245
246 /*-----------------------------------------------------------------*/
247 /* movc - moves specified value into the carry                     */
248 /*-----------------------------------------------------------------*/
249 static void
250 movc (const char *s)
251 {
252   if (!strcmp (s, zero))
253     CLRC;
254   else if (!strcmp (s, one))
255     SETC;
256   else if (strcmp (s, "c"))
257     {/* it's not in carry already */
258       MOVA (s);
259       /* set C, if a >= 1 */
260       emitcode ("add", "a,#0xff");
261     }
262 }
263
264 /*-----------------------------------------------------------------*/
265 /* pushB - saves register B if necessary                           */
266 /*-----------------------------------------------------------------*/
267 static bool
268 pushB (void)
269 {
270   bool pushedB = FALSE;
271
272   if (BINUSE)
273     {
274       emitcode ("push", "b");
275 //    printf("B was in use !\n");
276       pushedB = TRUE;
277     }
278   else
279     {
280       OPINB++;
281     }
282   return pushedB;
283 }
284
285 /*-----------------------------------------------------------------*/
286 /* popB - restores value of register B if necessary                */
287 /*-----------------------------------------------------------------*/
288 static void
289 popB (bool pushedB)
290 {
291   if (pushedB)
292     {
293       emitcode ("pop", "b");
294     }
295   else
296     {
297       OPINB--;
298     }
299 }
300
301 /*-----------------------------------------------------------------*/
302 /* pushReg - saves register                                        */
303 /*-----------------------------------------------------------------*/
304 static bool
305 pushReg (int index, bool bits_pushed)
306 {
307   regs * reg = REG_WITH_INDEX (index);
308   if (reg->type == REG_BIT)
309     {
310       if (!bits_pushed)
311         emitcode ("push", "%s", reg->base);
312       return TRUE;
313     }
314   else
315     emitcode ("push", "%s", reg->dname);
316   return bits_pushed;
317 }
318
319 /*-----------------------------------------------------------------*/
320 /* popReg - restores register                                      */
321 /*-----------------------------------------------------------------*/
322 static bool
323 popReg (int index, bool bits_popped)
324 {
325   regs * reg = REG_WITH_INDEX (index);
326   if (reg->type == REG_BIT)
327     {
328       if (!bits_popped)
329         emitcode ("pop", "%s", reg->base);
330       return TRUE;
331     }
332   else
333     emitcode ("pop", "%s", reg->dname);
334   return bits_popped;
335 }
336
337 /*-----------------------------------------------------------------*/
338 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
339 /*-----------------------------------------------------------------*/
340 static regs *
341 getFreePtr (iCode * ic, asmop ** aopp, bool result)
342 {
343   bool r0iu, r1iu;
344   bool r0ou, r1ou;
345
346   /* the logic: if r0 & r1 used in the instruction
347      then we are in trouble otherwise */
348
349   /* first check if r0 & r1 are used by this
350      instruction, in which case we are in trouble */
351   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
352   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
353   if (r0iu && r1iu) {
354       goto endOfWorld;
355     }
356
357   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
358   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
359
360   /* if no usage of r0 then return it */
361   if (!r0iu && !r0ou)
362     {
363       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
364       (*aopp)->type = AOP_R0;
365
366       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
367     }
368
369   /* if no usage of r1 then return it */
370   if (!r1iu && !r1ou)
371     {
372       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
373       (*aopp)->type = AOP_R1;
374
375       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
376     }
377
378   /* now we know they both have usage */
379   /* if r0 not used in this instruction */
380   if (!r0iu)
381     {
382       /* push it if not already pushed */
383       if (ic->op == IPUSH)
384         {
385           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
386           R0INB++;
387         }
388       else if (!_G.r0Pushed)
389         {
390           emitcode ("push", "%s",
391                     REG_WITH_INDEX (R0_IDX)->dname);
392           _G.r0Pushed++;
393         }
394
395       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
396       (*aopp)->type = AOP_R0;
397
398       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
399     }
400
401   /* if r1 not used then */
402
403   if (!r1iu)
404     {
405       /* push it if not already pushed */
406       if (ic->op == IPUSH)
407         {
408           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
409           R1INB++;
410         }
411       else if (!_G.r1Pushed)
412         {
413           emitcode ("push", "%s",
414                     REG_WITH_INDEX (R1_IDX)->dname);
415           _G.r1Pushed++;
416         }
417
418       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
419       (*aopp)->type = AOP_R1;
420       return REG_WITH_INDEX (R1_IDX);
421     }
422
423 endOfWorld:
424   /* I said end of world, but not quite end of world yet */
425   /* if this is a result then we can push it on the stack */
426   if (result)
427     {
428       (*aopp)->type = AOP_STK;
429       return NULL;
430     }
431   /* in the case that result AND left AND right needs a pointer reg
432      we can safely use the result's */
433   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
434     {
435       (*aopp)->type = AOP_R0;
436       return REG_WITH_INDEX (R0_IDX);
437     }
438   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
439     {
440       (*aopp)->type = AOP_R1;
441       return REG_WITH_INDEX (R1_IDX);
442     }
443
444   /* now this is REALLY the end of the world */
445   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
446           "getFreePtr should never reach here");
447   exit (1);
448 }
449
450
451 /*-----------------------------------------------------------------*/
452 /* getTempRegs - initialize an array of pointers to GPR registers */
453 /*               that are not in use. Returns 1 if the requested   */
454 /*               number of registers were available, 0 otherwise.  */
455 /*-----------------------------------------------------------------*/
456 int
457 getTempRegs(regs **tempRegs, int size, iCode *ic)
458 {
459   bitVect * freeRegs;
460   int i;
461   int offset;
462
463   if (!ic)
464     ic = _G.current_iCode;
465   if (!ic)
466     return 0;
467   if (!_G.currentFunc)
468     return 0;
469
470   freeRegs = newBitVect(8);
471   bitVectSetBit (freeRegs, R2_IDX);
472   bitVectSetBit (freeRegs, R3_IDX);
473   bitVectSetBit (freeRegs, R4_IDX);
474   bitVectSetBit (freeRegs, R5_IDX);
475   bitVectSetBit (freeRegs, R6_IDX);
476   bitVectSetBit (freeRegs, R7_IDX);
477
478   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
479     {
480       bitVect * newfreeRegs;
481       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
482       freeBitVect(freeRegs);
483       freeRegs = newfreeRegs;
484     }
485   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
486
487   offset = 0;
488   for (i=0; i<freeRegs->size; i++)
489     {
490       if (bitVectBitValue(freeRegs,i))
491         tempRegs[offset++] = REG_WITH_INDEX(i);
492       if (offset>=size)
493         {
494           freeBitVect(freeRegs);
495           return 1;
496         }
497     }
498
499   freeBitVect(freeRegs);
500   return 0;
501 }
502
503
504 /*-----------------------------------------------------------------*/
505 /* newAsmop - creates a new asmOp                                  */
506 /*-----------------------------------------------------------------*/
507 static asmop *
508 newAsmop (short type)
509 {
510   asmop *aop;
511
512   aop = Safe_calloc (1, sizeof (asmop));
513   aop->type = type;
514   aop->allocated = 1;
515   return aop;
516 }
517
518 /*-----------------------------------------------------------------*/
519 /* pointerCode - returns the code for a pointer type               */
520 /*-----------------------------------------------------------------*/
521 static int
522 pointerCode (sym_link * etype)
523 {
524
525   return PTR_TYPE (SPEC_OCLS (etype));
526
527 }
528
529 /*-----------------------------------------------------------------*/
530 /* leftRightUseAcc - returns size of accumulator use by operands   */
531 /*-----------------------------------------------------------------*/
532 static int
533 leftRightUseAcc(iCode *ic)
534 {
535   operand *op;
536   int size;
537   int accuseSize = 0;
538   int accuse = 0;
539
540   if (!ic)
541     {
542       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
543               "null iCode pointer");
544       return 0;
545     }
546
547   if (ic->op == IFX)
548     {
549       op = IC_COND (ic);
550       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
551         {
552           accuse = 1;
553           size = getSize (OP_SYMBOL (op)->type);
554           if (size>accuseSize)
555             accuseSize = size;
556         }
557     }
558   else if (ic->op == JUMPTABLE)
559     {
560       op = IC_JTCOND (ic);
561       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
562         {
563           accuse = 1;
564           size = getSize (OP_SYMBOL (op)->type);
565           if (size>accuseSize)
566             accuseSize = size;
567         }
568     }
569   else
570     {
571       op = IC_LEFT (ic);
572       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
573         {
574           accuse = 1;
575           size = getSize (OP_SYMBOL (op)->type);
576           if (size>accuseSize)
577             accuseSize = size;
578         }
579       op = IC_RIGHT (ic);
580       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
581         {
582           accuse = 1;
583           size = getSize (OP_SYMBOL (op)->type);
584           if (size>accuseSize)
585             accuseSize = size;
586         }
587     }
588
589   if (accuseSize)
590     return accuseSize;
591   else
592     return accuse;
593 }
594
595 /*-----------------------------------------------------------------*/
596 /* aopForSym - for a true symbol                                   */
597 /*-----------------------------------------------------------------*/
598 static asmop *
599 aopForSym (iCode * ic, symbol * sym, bool result)
600 {
601   asmop *aop;
602   memmap *space;
603   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
604
605   wassertl (ic != NULL, "Got a null iCode");
606   wassertl (sym != NULL, "Got a null symbol");
607
608   space = SPEC_OCLS (sym->etype);
609
610   /* if already has one */
611   if (sym->aop)
612     {
613       sym->aop->allocated++;
614       return sym->aop;
615     }
616
617   /* assign depending on the storage class */
618   /* if it is on the stack or indirectly addressable */
619   /* space we need to assign either r0 or r1 to it   */
620   if (sym->onStack || sym->iaccess)
621     {
622       sym->aop = aop = newAsmop (0);
623       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
624       aop->size = getSize (sym->type);
625
626       /* now assign the address of the variable to
627          the pointer register */
628       if (aop->type != AOP_STK)
629         {
630           if (sym->onStack)
631             {
632               signed char offset = ((sym->stack < 0) ?
633                          ((signed char) (sym->stack - _G.nRegsSaved)) :
634                          ((signed char) sym->stack)) & 0xff;
635
636               if ((abs(offset) <= 3) ||
637                   (accuse && (abs(offset) <= 7)))
638                 {
639                   emitcode ("mov", "%s,%s",
640                             aop->aopu.aop_ptr->name, SYM_BP (sym));
641                   while (offset < 0)
642                     {
643                       emitcode ("dec", aop->aopu.aop_ptr->name);
644                       offset++;
645                     }
646                   while (offset > 0)
647                     {
648                       emitcode ("inc", aop->aopu.aop_ptr->name);
649                       offset--;
650                     }
651                 }
652               else
653                 {
654                   if (accuse)
655                     emitcode ("push", "acc");
656                   emitcode ("mov", "a,%s", SYM_BP (sym));
657                   emitcode ("add", "a,#0x%02x", offset & 0xff);
658                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
659                   if (accuse)
660                     emitcode ("pop", "acc");
661                 }
662             }
663           else
664             {
665               emitcode ("mov", "%s,#%s",
666                         aop->aopu.aop_ptr->name,
667                         sym->rname);
668             }
669           aop->paged = space->paged;
670         }
671       else
672         aop->aopu.aop_stk = sym->stack;
673       return aop;
674     }
675
676   /* if in bit space */
677   if (IN_BITSPACE (space))
678     {
679       sym->aop = aop = newAsmop (AOP_CRY);
680       aop->aopu.aop_dir = sym->rname;
681       aop->size = getSize (sym->type);
682       return aop;
683     }
684   /* if it is in direct space */
685   if (IN_DIRSPACE (space))
686     {
687       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
688       //printTypeChainRaw(sym->type, NULL);
689       //printf("space = %s\n", space ? space->sname : "NULL");
690       sym->aop = aop = newAsmop (AOP_DIR);
691       aop->aopu.aop_dir = sym->rname;
692       aop->size = getSize (sym->type);
693       return aop;
694     }
695
696   /* special case for a function */
697   if (IS_FUNC (sym->type))
698     {
699       sym->aop = aop = newAsmop (AOP_IMMD);
700       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
701       aop->size = getSize (sym->type);
702       return aop;
703     }
704
705   /* only remaining is far space */
706   /* in which case DPTR gets the address */
707   sym->aop = aop = newAsmop (AOP_DPTR);
708   emitcode ("mov", "dptr,#%s", sym->rname);
709   aop->size = getSize (sym->type);
710
711   /* if it is in code space */
712   if (IN_CODESPACE (space))
713     aop->code = 1;
714
715   return aop;
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* aopForRemat - rematerialzes an object                           */
720 /*-----------------------------------------------------------------*/
721 static asmop *
722 aopForRemat (symbol * sym)
723 {
724   iCode *ic = sym->rematiCode;
725   asmop *aop = newAsmop (AOP_IMMD);
726   int ptr_type = 0;
727   int val = 0;
728
729   for (;;)
730     {
731       if (ic->op == '+')
732         val += (int) operandLitValue (IC_RIGHT (ic));
733       else if (ic->op == '-')
734         val -= (int) operandLitValue (IC_RIGHT (ic));
735       else if (IS_CAST_ICODE(ic)) {
736               sym_link *from_type = operandType(IC_RIGHT(ic));
737               aop->aopu.aop_immd.from_cast_remat = 1;
738               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
739               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
740               continue;
741       } else break;
742
743       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
744     }
745
746   if (val)
747     {
748       SNPRINTF (buffer, sizeof(buffer),
749                 "(%s %c 0x%04x)",
750                 OP_SYMBOL (IC_LEFT (ic))->rname,
751                 val >= 0 ? '+' : '-',
752                 abs (val) & 0xffff);
753     }
754   else
755     {
756       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
757     }
758
759   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
760   /* set immd2 field if required */
761   if (aop->aopu.aop_immd.from_cast_remat)
762     {
763       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
764       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
765     }
766
767   return aop;
768 }
769
770 /*-----------------------------------------------------------------*/
771 /* regsInCommon - two operands have some registers in common       */
772 /*-----------------------------------------------------------------*/
773 static bool
774 regsInCommon (operand * op1, operand * op2)
775 {
776   symbol *sym1, *sym2;
777   int i;
778
779   /* if they have registers in common */
780   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
781     return FALSE;
782
783   sym1 = OP_SYMBOL (op1);
784   sym2 = OP_SYMBOL (op2);
785
786   if (sym1->nRegs == 0 || sym2->nRegs == 0)
787     return FALSE;
788
789   for (i = 0; i < sym1->nRegs; i++)
790     {
791       int j;
792       if (!sym1->regs[i])
793         continue;
794
795       for (j = 0; j < sym2->nRegs; j++)
796         {
797           if (!sym2->regs[j])
798             continue;
799
800           if (sym2->regs[j] == sym1->regs[i])
801             return TRUE;
802         }
803     }
804
805   return FALSE;
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* operandsEqu - equivalent                                        */
810 /*-----------------------------------------------------------------*/
811 static bool
812 operandsEqu (operand * op1, operand * op2)
813 {
814   symbol *sym1, *sym2;
815
816   /* if they're not symbols */
817   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
818     return FALSE;
819
820   sym1 = OP_SYMBOL (op1);
821   sym2 = OP_SYMBOL (op2);
822
823   /* if both are itemps & one is spilt
824      and the other is not then false */
825   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
826       sym1->isspilt != sym2->isspilt)
827     return FALSE;
828
829   /* if they are the same */
830   if (sym1 == sym2)
831     return TRUE;
832
833   /* if they have the same rname */
834   if (sym1->rname[0] && sym2->rname[0] &&
835       strcmp (sym1->rname, sym2->rname) == 0 &&
836       !(IS_PARM (op2) && IS_ITEMP (op1)))
837     return TRUE;
838
839   /* if left is a tmp & right is not */
840   if (IS_ITEMP (op1) &&
841       !IS_ITEMP (op2) &&
842       sym1->isspilt &&
843       (sym1->usl.spillLoc == sym2))
844     return TRUE;
845
846   if (IS_ITEMP (op2) &&
847       !IS_ITEMP (op1) &&
848       sym2->isspilt &&
849       sym1->level > 0 &&
850       (sym2->usl.spillLoc == sym1))
851     return TRUE;
852
853   return FALSE;
854 }
855
856 /*-----------------------------------------------------------------*/
857 /* sameByte - two asmops have the same address at given offsets    */
858 /*-----------------------------------------------------------------*/
859 static bool
860 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
861 {
862   if (aop1 == aop2 && off1 == off2)
863     return TRUE;
864
865   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
866     return FALSE;
867
868   if (aop1->type != aop2->type)
869     return FALSE;
870
871   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
872     return FALSE;
873
874   return TRUE;
875 }
876
877 /*-----------------------------------------------------------------*/
878 /* sameRegs - two asmops have the same registers                   */
879 /*-----------------------------------------------------------------*/
880 static bool
881 sameRegs (asmop * aop1, asmop * aop2)
882 {
883   int i;
884
885   if (aop1 == aop2)
886     return TRUE;
887
888   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
889     return FALSE;
890
891   if (aop1->type != aop2->type)
892     return FALSE;
893
894   if (aop1->size != aop2->size)
895     return FALSE;
896
897   for (i = 0; i < aop1->size; i++)
898     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
899       return FALSE;
900
901   return TRUE;
902 }
903
904 /*-----------------------------------------------------------------*/
905 /* aopOp - allocates an asmop for an operand  :                    */
906 /*-----------------------------------------------------------------*/
907 static void
908 aopOp (operand * op, iCode * ic, bool result)
909 {
910   asmop *aop;
911   symbol *sym;
912   int i;
913
914   if (!op)
915     return;
916
917   /* if this a literal */
918   if (IS_OP_LITERAL (op))
919     {
920       op->aop = aop = newAsmop (AOP_LIT);
921       aop->aopu.aop_lit = op->operand.valOperand;
922       aop->size = getSize (operandType (op));
923       return;
924     }
925
926   /* if already has a asmop then continue */
927   if (op->aop)
928     {
929       op->aop->allocated++;
930       return;
931     }
932
933   /* if the underlying symbol has a aop */
934   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
935     {
936       op->aop = OP_SYMBOL (op)->aop;
937       op->aop->allocated++;
938       return;
939     }
940
941   /* if this is a true symbol */
942   if (IS_TRUE_SYMOP (op))
943     {
944       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
945       return;
946     }
947
948   /* this is a temporary : this has
949      only five choices :
950      a) register
951      b) spillocation
952      c) rematerialize
953      d) conditional
954      e) can be a return use only */
955
956   sym = OP_SYMBOL (op);
957
958   /* if the type is a conditional */
959   if (sym->regType == REG_CND)
960     {
961       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
962       aop->size = 0;
963       return;
964     }
965
966   /* if it is spilt then two situations
967      a) is rematerialize
968      b) has a spill location */
969   if (sym->isspilt || sym->nRegs == 0)
970     {
971
972       /* rematerialize it NOW */
973       if (sym->remat)
974         {
975           sym->aop = op->aop = aop = aopForRemat (sym);
976           aop->size = getSize (sym->type);
977           return;
978         }
979
980       if (sym->accuse)
981         {
982           int i;
983           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
984           aop->size = getSize (sym->type);
985           for (i = 0; i < 2; i++)
986             aop->aopu.aop_str[i] = accUse[i];
987           return;
988         }
989
990       if (sym->ruonly)
991         {
992           unsigned i;
993
994           aop = op->aop = sym->aop = newAsmop (AOP_STR);
995           aop->size = getSize (sym->type);
996           for (i = 0; i < fReturnSizeMCS51; i++)
997             aop->aopu.aop_str[i] = fReturn[i];
998           return;
999         }
1000
1001       if (sym->usl.spillLoc)
1002         {
1003           asmop *oldAsmOp = NULL;
1004
1005           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1006             {
1007               /* force a new aop if sizes differ */
1008               oldAsmOp = sym->usl.spillLoc->aop;
1009               sym->usl.spillLoc->aop = NULL;
1010             }
1011           sym->aop = op->aop = aop =
1012                      aopForSym (ic, sym->usl.spillLoc, result);
1013           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1014             {
1015               /* Don't reuse the new aop, go with the last one */
1016               sym->usl.spillLoc->aop = oldAsmOp;
1017             }
1018           aop->size = getSize (sym->type);
1019           return;
1020         }
1021
1022       /* else must be a dummy iTemp */
1023       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1024       aop->size = getSize (sym->type);
1025       return;
1026     }
1027
1028   /* if the type is a bit register */
1029   if (sym->regType == REG_BIT)
1030     {
1031       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1032       aop->size = sym->nRegs;//1???
1033       aop->aopu.aop_reg[0] = sym->regs[0];
1034       aop->aopu.aop_dir = sym->regs[0]->name;
1035       return;
1036     }
1037
1038   /* must be in a register */
1039   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1040   aop->size = sym->nRegs;
1041   for (i = 0; i < sym->nRegs; i++)
1042     aop->aopu.aop_reg[i] = sym->regs[i];
1043 }
1044
1045 /*-----------------------------------------------------------------*/
1046 /* freeAsmop - free up the asmop given to an operand               */
1047 /*----------------------------------------------------------------*/
1048 static void
1049 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1050 {
1051   asmop *aop;
1052
1053   if (!op)
1054     aop = aaop;
1055   else
1056     aop = op->aop;
1057
1058   if (!aop)
1059     return;
1060
1061   aop->allocated--;
1062
1063   if (aop->allocated)
1064     goto dealloc;
1065
1066   /* depending on the asmop type only three cases need work
1067      AOP_R0, AOP_R1 & AOP_STK */
1068   switch (aop->type)
1069     {
1070     case AOP_R0:
1071       if (R0INB)
1072         {
1073           emitcode ("mov", "r0,b");
1074           R0INB--;
1075         }
1076       else if (_G.r0Pushed)
1077         {
1078           if (pop)
1079             {
1080               emitcode ("pop", "ar0");
1081               _G.r0Pushed--;
1082             }
1083         }
1084       bitVectUnSetBit (ic->rUsed, R0_IDX);
1085       break;
1086
1087     case AOP_R1:
1088       if (R1INB)
1089         {
1090           emitcode ("mov", "r1,b");
1091           R1INB--;
1092         }
1093       else if (_G.r1Pushed)
1094         {
1095           if (pop)
1096             {
1097               emitcode ("pop", "ar1");
1098               _G.r1Pushed--;
1099             }
1100         }
1101       bitVectUnSetBit (ic->rUsed, R1_IDX);
1102       break;
1103
1104     case AOP_STK:
1105       {
1106         int sz = aop->size;
1107         int stk = aop->aopu.aop_stk + aop->size - 1;
1108         bitVectUnSetBit (ic->rUsed, R0_IDX);
1109         bitVectUnSetBit (ic->rUsed, R1_IDX);
1110
1111         getFreePtr (ic, &aop, FALSE);
1112
1113         if (stk)
1114           {
1115             emitcode ("mov", "a,_bp");
1116             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1117             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1118           }
1119         else
1120           {
1121             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1122           }
1123
1124         while (sz--)
1125           {
1126             emitcode ("pop", "acc");
1127             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1128             if (!sz)
1129               break;
1130             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131           }
1132         op->aop = aop;
1133         freeAsmop (op, NULL, ic, TRUE);
1134         if (_G.r1Pushed)
1135           {
1136             emitcode ("pop", "ar1");
1137             _G.r1Pushed--;
1138           }
1139         if (_G.r0Pushed)
1140           {
1141             emitcode ("pop", "ar0");
1142             _G.r0Pushed--;
1143           }
1144       }
1145       break;
1146     }
1147
1148 dealloc:
1149   /* all other cases just dealloc */
1150   if (op)
1151     {
1152       op->aop = NULL;
1153       if (IS_SYMOP (op))
1154         {
1155           OP_SYMBOL (op)->aop = NULL;
1156           /* if the symbol has a spill */
1157           if (SPIL_LOC (op))
1158             SPIL_LOC (op)->aop = NULL;
1159         }
1160     }
1161 }
1162
1163 /*------------------------------------------------------------------*/
1164 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1165 /*                      pop r0 or r1 off stack if pushed            */
1166 /*------------------------------------------------------------------*/
1167 static void
1168 freeForBranchAsmop (operand * op)
1169 {
1170   asmop *aop;
1171
1172   if (!op)
1173     return;
1174
1175   aop = op->aop;
1176
1177   if (!aop)
1178     return;
1179
1180   if (!aop->allocated)
1181     return;
1182
1183   switch (aop->type)
1184     {
1185     case AOP_R0:
1186       if (R0INB)
1187         {
1188           emitcode ("mov", "r0,b");
1189         }
1190       else if (_G.r0Pushed)
1191         {
1192           emitcode ("pop", "ar0");
1193         }
1194       break;
1195
1196     case AOP_R1:
1197       if (R1INB)
1198         {
1199           emitcode ("mov", "r1,b");
1200         }
1201       else if (_G.r1Pushed)
1202         {
1203           emitcode ("pop", "ar1");
1204         }
1205       break;
1206
1207     case AOP_STK:
1208       {
1209         int sz = aop->size;
1210         int stk = aop->aopu.aop_stk + aop->size - 1;
1211
1212         emitcode ("mov", "b,r0");
1213         if (stk)
1214           {
1215             emitcode ("mov", "a,_bp");
1216             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1217             emitcode ("mov", "r0,a");
1218           }
1219         else
1220           {
1221             emitcode ("mov", "r0,_bp");
1222           }
1223
1224         while (sz--)
1225           {
1226             emitcode ("pop", "acc");
1227             emitcode ("mov", "@r0,a");
1228             if (!sz)
1229               break;
1230             emitcode ("dec", "r0");
1231           }
1232         emitcode ("mov", "r0,b");
1233       }
1234     }
1235
1236 }
1237
1238 /*-----------------------------------------------------------------*/
1239 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1240 /*                 clobber the accumulator                         */
1241 /*-----------------------------------------------------------------*/
1242 static bool
1243 aopGetUsesAcc (operand * oper, int offset)
1244 {
1245   asmop * aop = AOP (oper);
1246
1247   if (offset > (aop->size - 1))
1248     return FALSE;
1249
1250   switch (aop->type)
1251     {
1252
1253     case AOP_R0:
1254     case AOP_R1:
1255       if (aop->paged)
1256         return TRUE;
1257       return FALSE;
1258     case AOP_DPTR:
1259       return TRUE;
1260     case AOP_IMMD:
1261       return FALSE;
1262     case AOP_DIR:
1263       return FALSE;
1264     case AOP_REG:
1265       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1266       return FALSE;
1267     case AOP_CRY:
1268       return TRUE;
1269     case AOP_ACC:
1270       if (offset)
1271         return FALSE;
1272       return TRUE;
1273     case AOP_LIT:
1274       return FALSE;
1275     case AOP_STR:
1276       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1277         return TRUE;
1278       return FALSE;
1279     case AOP_DUMMY:
1280       return FALSE;
1281     default:
1282       /* Error case --- will have been caught already */
1283       wassert(0);
1284       return FALSE;
1285     }
1286 }
1287
1288 /*-------------------------------------------------------------------*/
1289 /* aopGet - for fetching value of the aop                            */
1290 /*-------------------------------------------------------------------*/
1291 static char *
1292 aopGet (operand * oper, int offset, bool bit16, bool dname)
1293 {
1294   asmop * aop = AOP (oper);
1295
1296   /* offset is greater than
1297      size then zero */
1298   if (offset > (aop->size - 1) &&
1299       aop->type != AOP_LIT)
1300     return zero;
1301
1302   /* depending on type */
1303   switch (aop->type)
1304     {
1305     case AOP_DUMMY:
1306       return zero;
1307
1308     case AOP_R0:
1309     case AOP_R1:
1310       /* if we need to increment it */
1311       while (offset > aop->coff)
1312         {
1313           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1314           aop->coff++;
1315         }
1316
1317       while (offset < aop->coff)
1318         {
1319           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1320           aop->coff--;
1321         }
1322
1323       aop->coff = offset;
1324       if (aop->paged)
1325         {
1326           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1327           return (dname ? "acc" : "a");
1328         }
1329       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1330       return Safe_strdup(buffer);
1331
1332     case AOP_DPTR:
1333       if (aop->code && aop->coff==0 && offset>=1) {
1334         emitcode ("mov", "a,#0x%02x", offset);
1335         emitcode ("movc", "a,@a+dptr");
1336         return (dname ? "acc" : "a");
1337       }
1338
1339       while (offset > aop->coff)
1340         {
1341           emitcode ("inc", "dptr");
1342           aop->coff++;
1343         }
1344
1345       while (offset < aop->coff)
1346         {
1347           emitcode ("lcall", "__decdptr");
1348           aop->coff--;
1349         }
1350
1351       aop->coff = offset;
1352       if (aop->code)
1353         {
1354           emitcode ("clr", "a");
1355           emitcode ("movc", "a,@a+dptr");
1356         }
1357       else
1358         {
1359           emitcode ("movx", "a,@dptr");
1360         }
1361       return (dname ? "acc" : "a");
1362
1363     case AOP_IMMD:
1364       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1365         {
1366           SNPRINTF(buffer, sizeof(buffer),
1367                    "%s",aop->aopu.aop_immd.aop_immd2);
1368         }
1369       else if (bit16)
1370         {
1371           SNPRINTF(buffer, sizeof(buffer),
1372                    "#%s", aop->aopu.aop_immd.aop_immd1);
1373         }
1374       else if (offset)
1375         {
1376           SNPRINTF (buffer, sizeof(buffer),
1377                     "#(%s >> %d)",
1378                     aop->aopu.aop_immd.aop_immd1,
1379                     offset * 8);
1380         }
1381       else
1382         {
1383           SNPRINTF (buffer, sizeof(buffer),
1384                     "#%s",
1385                     aop->aopu.aop_immd.aop_immd1);
1386         }
1387       return Safe_strdup(buffer);
1388
1389     case AOP_DIR:
1390       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1391         {
1392           SNPRINTF (buffer, sizeof(buffer),
1393                     "(%s >> %d)",
1394                     aop->aopu.aop_dir, offset * 8);
1395         }
1396       else if (offset)
1397         {
1398           SNPRINTF (buffer, sizeof(buffer),
1399                     "(%s + %d)",
1400                     aop->aopu.aop_dir,
1401                     offset);
1402         }
1403       else
1404         {
1405           SNPRINTF (buffer, sizeof(buffer),
1406                     "%s",
1407                     aop->aopu.aop_dir);
1408         }
1409
1410       return Safe_strdup(buffer);
1411
1412     case AOP_REG:
1413       if (dname)
1414         return aop->aopu.aop_reg[offset]->dname;
1415       else
1416         return aop->aopu.aop_reg[offset]->name;
1417
1418     case AOP_CRY:
1419       emitcode ("clr", "a");
1420       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1421       emitcode ("rlc", "a");
1422       return (dname ? "acc" : "a");
1423
1424     case AOP_ACC:
1425       if (!offset && dname)
1426         return "acc";
1427       return aop->aopu.aop_str[offset];
1428
1429     case AOP_LIT:
1430       return aopLiteral (aop->aopu.aop_lit, offset);
1431
1432     case AOP_STR:
1433       aop->coff = offset;
1434       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1435           dname)
1436         return "acc";
1437
1438       return aop->aopu.aop_str[offset];
1439
1440     }
1441
1442   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1443           "aopget got unsupported aop->type");
1444   exit (1);
1445 }
1446
1447 /*-----------------------------------------------------------------*/
1448 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1449 /*                 clobber the accumulator                         */
1450 /*-----------------------------------------------------------------*/
1451 static bool
1452 aopPutUsesAcc (operand * oper, const char *s, int offset)
1453 {
1454   asmop * aop = AOP (oper);
1455
1456   if (offset > (aop->size - 1))
1457     return FALSE;
1458
1459   switch (aop->type)
1460     {
1461     case AOP_DUMMY:
1462       return TRUE;
1463     case AOP_DIR:
1464       return FALSE;
1465     case AOP_REG:
1466       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1467       return FALSE;
1468     case AOP_DPTR:
1469       return TRUE;
1470     case AOP_R0:
1471     case AOP_R1:
1472       return ((aop->paged) || (*s == '@'));
1473     case AOP_STK:
1474       return (*s == '@');
1475     case AOP_CRY:
1476       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1477     case AOP_STR:
1478       return FALSE;
1479     case AOP_IMMD:
1480       return FALSE;
1481     case AOP_ACC:
1482       return FALSE;
1483     default:
1484       /* Error case --- will have been caught already */
1485       wassert(0);
1486       return FALSE;
1487     }
1488 }
1489
1490 /*-----------------------------------------------------------------*/
1491 /* aopPut - puts a string for a aop and indicates if acc is in use */
1492 /*-----------------------------------------------------------------*/
1493 static bool
1494 aopPut (operand * result, const char *s, int offset)
1495 {
1496   bool bvolatile = isOperandVolatile (result, FALSE);
1497   bool accuse = FALSE;
1498   asmop * aop = AOP (result);
1499
1500   if (aop->size && offset > (aop->size - 1))
1501     {
1502       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1503               "aopPut got offset > aop->size");
1504       exit (1);
1505     }
1506
1507   /* will assign value to value */
1508   /* depending on where it is ofcourse */
1509   switch (aop->type)
1510     {
1511     case AOP_DUMMY:
1512       MOVA (s);         /* read s in case it was volatile */
1513       accuse = TRUE;
1514       break;
1515
1516     case AOP_DIR:
1517       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1518         {
1519           SNPRINTF (buffer, sizeof(buffer),
1520                     "(%s >> %d)",
1521                     aop->aopu.aop_dir, offset * 8);
1522         }
1523       else if (offset)
1524         {
1525           SNPRINTF (buffer, sizeof(buffer),
1526                     "(%s + %d)",
1527                     aop->aopu.aop_dir, offset);
1528         }
1529       else
1530         {
1531           SNPRINTF (buffer, sizeof(buffer),
1532                     "%s",
1533                     aop->aopu.aop_dir);
1534         }
1535
1536       if (strcmp (buffer, s) || bvolatile)
1537         {
1538           emitcode ("mov", "%s,%s", buffer, s);
1539         }
1540       if (!strcmp (buffer, "acc"))
1541         {
1542           accuse = TRUE;
1543         }
1544       break;
1545
1546     case AOP_REG:
1547       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1548           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1549         {
1550           if (*s == '@' ||
1551               strcmp (s, "r0") == 0 ||
1552               strcmp (s, "r1") == 0 ||
1553               strcmp (s, "r2") == 0 ||
1554               strcmp (s, "r3") == 0 ||
1555               strcmp (s, "r4") == 0 ||
1556               strcmp (s, "r5") == 0 ||
1557               strcmp (s, "r6") == 0 ||
1558               strcmp (s, "r7") == 0)
1559             {
1560               emitcode ("mov", "%s,%s",
1561                         aop->aopu.aop_reg[offset]->dname, s);
1562             }
1563           else
1564             {
1565               emitcode ("mov", "%s,%s",
1566                         aop->aopu.aop_reg[offset]->name, s);
1567             }
1568         }
1569       break;
1570
1571     case AOP_DPTR:
1572       if (aop->code)
1573         {
1574           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1575                   "aopPut writing to code space");
1576           exit (1);
1577         }
1578
1579       while (offset > aop->coff)
1580         {
1581           aop->coff++;
1582           emitcode ("inc", "dptr");
1583         }
1584
1585       while (offset < aop->coff)
1586         {
1587           aop->coff--;
1588           emitcode ("lcall", "__decdptr");
1589         }
1590
1591       aop->coff = offset;
1592
1593       /* if not in accumulator */
1594       MOVA (s);
1595
1596       emitcode ("movx", "@dptr,a");
1597       break;
1598
1599     case AOP_R0:
1600     case AOP_R1:
1601       while (offset > aop->coff)
1602         {
1603           aop->coff++;
1604           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1605         }
1606       while (offset < aop->coff)
1607         {
1608           aop->coff--;
1609           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1610         }
1611       aop->coff = offset;
1612
1613       if (aop->paged)
1614         {
1615           MOVA (s);
1616           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1617         }
1618       else if (*s == '@')
1619         {
1620           MOVA (s);
1621           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1622         }
1623       else if (strcmp (s, "r0") == 0 ||
1624                strcmp (s, "r1") == 0 ||
1625                strcmp (s, "r2") == 0 ||
1626                strcmp (s, "r3") == 0 ||
1627                strcmp (s, "r4") == 0 ||
1628                strcmp (s, "r5") == 0 ||
1629                strcmp (s, "r6") == 0 ||
1630                strcmp (s, "r7") == 0)
1631         {
1632           char buffer[10];
1633           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1634           emitcode ("mov", "@%s,%s",
1635                     aop->aopu.aop_ptr->name, buffer);
1636         }
1637       else
1638         {
1639           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1640         }
1641       break;
1642
1643     case AOP_STK:
1644       if (strcmp (s, "a") == 0)
1645         emitcode ("push", "acc");
1646       else
1647         if (*s=='@') {
1648           MOVA(s);
1649           emitcode ("push", "acc");
1650         } else {
1651           emitcode ("push", s);
1652         }
1653
1654       break;
1655
1656     case AOP_CRY:
1657       /* if not bit variable */
1658       if (!aop->aopu.aop_dir)
1659         {
1660           /* inefficient: move carry into A and use jz/jnz */
1661           emitcode ("clr", "a");
1662           emitcode ("rlc", "a");
1663           accuse = TRUE;
1664         }
1665       else
1666         {
1667           if (s == zero)
1668             emitcode ("clr", "%s", aop->aopu.aop_dir);
1669           else if (s == one)
1670             emitcode ("setb", "%s", aop->aopu.aop_dir);
1671           else if (!strcmp (s, "c"))
1672             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1673           else if (strcmp (s, aop->aopu.aop_dir))
1674             {
1675               MOVA (s);
1676               /* set C, if a >= 1 */
1677               emitcode ("add", "a,#0xff");
1678               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1679             }
1680         }
1681       break;
1682
1683     case AOP_STR:
1684       aop->coff = offset;
1685       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1686         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1687       break;
1688
1689     case AOP_ACC:
1690       accuse = TRUE;
1691       aop->coff = offset;
1692       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1693         break;
1694
1695       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1696         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1697       break;
1698
1699     default:
1700       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1701               "aopPut got unsupported aop->type");
1702       exit (1);
1703     }
1704
1705     return accuse;
1706 }
1707
1708
1709 #if 0
1710 /*-----------------------------------------------------------------*/
1711 /* pointToEnd :- points to the last byte of the operand            */
1712 /*-----------------------------------------------------------------*/
1713 static void
1714 pointToEnd (asmop * aop)
1715 {
1716   int count;
1717   if (!aop)
1718     return;
1719
1720   aop->coff = count = (aop->size - 1);
1721   switch (aop->type)
1722     {
1723     case AOP_R0:
1724     case AOP_R1:
1725       while (count--)
1726         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1727       break;
1728     case AOP_DPTR:
1729       while (count--)
1730         emitcode ("inc", "dptr");
1731       break;
1732     }
1733
1734 }
1735 #endif
1736
1737 /*-----------------------------------------------------------------*/
1738 /* reAdjustPreg - points a register back to where it should        */
1739 /*-----------------------------------------------------------------*/
1740 static void
1741 reAdjustPreg (asmop * aop)
1742 {
1743   if ((aop->coff==0) || (aop->size <= 1))
1744     return;
1745
1746   switch (aop->type)
1747     {
1748     case AOP_R0:
1749     case AOP_R1:
1750       while (aop->coff--)
1751         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1752       break;
1753     case AOP_DPTR:
1754       while (aop->coff--)
1755         {
1756           emitcode ("lcall", "__decdptr");
1757         }
1758       break;
1759     }
1760   aop->coff = 0;
1761 }
1762
1763 /*-----------------------------------------------------------------*/
1764 /* opIsGptr: returns non-zero if the passed operand is       */
1765 /* a generic pointer type.             */
1766 /*-----------------------------------------------------------------*/
1767 static int
1768 opIsGptr (operand * op)
1769 {
1770   sym_link *type = operandType (op);
1771
1772   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1773     {
1774       return 1;
1775     }
1776   return 0;
1777 }
1778
1779 /*-----------------------------------------------------------------*/
1780 /* getDataSize - get the operand data size                         */
1781 /*-----------------------------------------------------------------*/
1782 static int
1783 getDataSize (operand * op)
1784 {
1785   int size;
1786   size = AOP_SIZE (op);
1787   if (size == GPTRSIZE)
1788     {
1789       sym_link *type = operandType (op);
1790       if (IS_GENPTR (type))
1791         {
1792           /* generic pointer; arithmetic operations
1793            * should ignore the high byte (pointer type).
1794            */
1795           size--;
1796         }
1797     }
1798   return size;
1799 }
1800
1801 /*-----------------------------------------------------------------*/
1802 /* outAcc - output Acc                                             */
1803 /*-----------------------------------------------------------------*/
1804 static void
1805 outAcc (operand * result)
1806 {
1807   int size, offset;
1808   size = getDataSize (result);
1809   if (size)
1810     {
1811       aopPut (result, "a", 0);
1812       size--;
1813       offset = 1;
1814       /* unsigned or positive */
1815       while (size--)
1816         {
1817           aopPut (result, zero, offset++);
1818         }
1819     }
1820 }
1821
1822 /*-----------------------------------------------------------------*/
1823 /* outBitC - output a bit C                                        */
1824 /*-----------------------------------------------------------------*/
1825 static void
1826 outBitC (operand * result)
1827 {
1828   /* if the result is bit */
1829   if (AOP_TYPE (result) == AOP_CRY)
1830     {
1831       aopPut (result, "c", 0);
1832     }
1833   else
1834     {
1835       emitcode ("clr", "a");
1836       emitcode ("rlc", "a");
1837       outAcc (result);
1838     }
1839 }
1840
1841 /*-----------------------------------------------------------------*/
1842 /* toBoolean - emit code for orl a,operator(sizeop)                */
1843 /*-----------------------------------------------------------------*/
1844 static void
1845 toBoolean (operand * oper)
1846 {
1847   int size = AOP_SIZE (oper) - 1;
1848   int offset = 1;
1849   bool AccUsed = FALSE;
1850   bool pushedB;
1851
1852   while (!AccUsed && size--)
1853     {
1854       AccUsed |= aopGetUsesAcc(oper, offset++);
1855     }
1856
1857   size = AOP_SIZE (oper) - 1;
1858   offset = 1;
1859   MOVA (aopGet (oper, 0, FALSE, FALSE));
1860   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1861     {
1862       pushedB = pushB ();
1863       emitcode("mov", "b,a");
1864       while (--size)
1865         {
1866           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1867           emitcode ("orl", "b,a");
1868         }
1869       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1870       emitcode ("orl", "a,b");
1871       popB (pushedB);
1872     }
1873   else
1874     {
1875       while (size--)
1876         {
1877           emitcode ("orl", "a,%s",
1878                     aopGet (oper, offset++, FALSE, FALSE));
1879         }
1880     }
1881 }
1882
1883
1884 /*-------------------------------------------------------------------*/
1885 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1886 /*-------------------------------------------------------------------*/
1887 static char *
1888 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1889 {
1890   char * l;
1891
1892   if (aopGetUsesAcc (oper, offset))
1893     {
1894       emitcode("mov", "b,a");
1895       MOVA (aopGet (oper, offset, bit16, dname));
1896       emitcode("xch", "a,b");
1897       aopPut (oper, "a", offset);
1898       emitcode("xch", "a,b");
1899       l = "b";
1900     }
1901   else
1902     {
1903       l = aopGet (oper, offset, bit16, dname);
1904       emitcode("xch", "a,%s", l);
1905     }
1906   return l;
1907 }
1908
1909
1910 /*-----------------------------------------------------------------*/
1911 /* genNot - generate code for ! operation                          */
1912 /*-----------------------------------------------------------------*/
1913 static void
1914 genNot (iCode * ic)
1915 {
1916   symbol *tlbl;
1917
1918   D (emitcode (";", "genNot"));
1919
1920   /* assign asmOps to operand & result */
1921   aopOp (IC_LEFT (ic), ic, FALSE);
1922   aopOp (IC_RESULT (ic), ic, TRUE);
1923
1924   /* if in bit space then a special case */
1925   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1926     {
1927       /* if left==result then cpl bit */
1928       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1929         {
1930           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1931         }
1932       else
1933         {
1934           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1935           emitcode ("cpl", "c");
1936           outBitC (IC_RESULT (ic));
1937         }
1938       goto release;
1939     }
1940
1941   toBoolean (IC_LEFT (ic));
1942
1943   /* set C, if a == 0 */
1944   tlbl = newiTempLabel (NULL);
1945   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1946   emitLabel (tlbl);
1947   outBitC (IC_RESULT (ic));
1948
1949 release:
1950   /* release the aops */
1951   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1952   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1953 }
1954
1955
1956 /*-----------------------------------------------------------------*/
1957 /* genCpl - generate code for complement                           */
1958 /*-----------------------------------------------------------------*/
1959 static void
1960 genCpl (iCode * ic)
1961 {
1962   int offset = 0;
1963   int size;
1964   symbol *tlbl;
1965   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1966
1967   D(emitcode (";", "genCpl"));
1968
1969   /* assign asmOps to operand & result */
1970   aopOp (IC_LEFT (ic), ic, FALSE);
1971   aopOp (IC_RESULT (ic), ic, TRUE);
1972
1973   /* special case if in bit space */
1974   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1975     {
1976       char *l;
1977
1978       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1979           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1980         {
1981           /* promotion rules are responsible for this strange result:
1982              bit -> int -> ~int -> bit
1983              uchar -> int -> ~int -> bit
1984           */
1985           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1986           goto release;
1987         }
1988
1989       tlbl=newiTempLabel(NULL);
1990       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1991       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1992           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1993           IS_AOP_PREG (IC_LEFT (ic)))
1994         {
1995           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1996         }
1997       else
1998         {
1999           MOVA (l);
2000           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2001         }
2002       emitLabel (tlbl);
2003       outBitC (IC_RESULT(ic));
2004       goto release;
2005     }
2006
2007   size = AOP_SIZE (IC_RESULT (ic));
2008   while (size--)
2009     {
2010       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2011       MOVA (l);
2012       emitcode ("cpl", "a");
2013       aopPut (IC_RESULT (ic), "a", offset++);
2014     }
2015
2016
2017 release:
2018   /* release the aops */
2019   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2020   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2021 }
2022
2023 /*-----------------------------------------------------------------*/
2024 /* genUminusFloat - unary minus for floating points                */
2025 /*-----------------------------------------------------------------*/
2026 static void
2027 genUminusFloat (operand * op, operand * result)
2028 {
2029   int size, offset = 0;
2030   char *l;
2031
2032   D (emitcode (";", "genUminusFloat"));
2033
2034   /* for this we just copy and then flip the bit */
2035
2036   size = AOP_SIZE (op) - 1;
2037
2038   while (size--)
2039     {
2040       aopPut (result,
2041               aopGet (op, offset, FALSE, FALSE),
2042               offset);
2043       offset++;
2044     }
2045
2046   l = aopGet (op, offset, FALSE, FALSE);
2047   MOVA (l);
2048
2049   emitcode ("cpl", "acc.7");
2050   aopPut (result, "a", offset);
2051 }
2052
2053 /*-----------------------------------------------------------------*/
2054 /* genUminus - unary minus code generation                         */
2055 /*-----------------------------------------------------------------*/
2056 static void
2057 genUminus (iCode * ic)
2058 {
2059   int offset, size;
2060   sym_link *optype;
2061
2062   D (emitcode (";", "genUminus"));
2063
2064   /* assign asmops */
2065   aopOp (IC_LEFT (ic), ic, FALSE);
2066   aopOp (IC_RESULT (ic), ic, TRUE);
2067
2068   /* if both in bit space then special
2069      case */
2070   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2071       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2072     {
2073
2074       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2075       emitcode ("cpl", "c");
2076       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2077       goto release;
2078     }
2079
2080   optype = operandType (IC_LEFT (ic));
2081
2082   /* if float then do float stuff */
2083   if (IS_FLOAT (optype))
2084     {
2085       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2086       goto release;
2087     }
2088
2089   /* otherwise subtract from zero */
2090   size = AOP_SIZE (IC_LEFT (ic));
2091   offset = 0;
2092   while (size--)
2093     {
2094       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2095       if (!strcmp (l, "a"))
2096         {
2097           if (offset == 0)
2098             SETC;
2099           emitcode ("cpl", "a");
2100           emitcode ("addc", "a,#0");
2101         }
2102       else
2103         {
2104           if (offset == 0)
2105             CLRC;
2106           emitcode ("clr", "a");
2107           emitcode ("subb", "a,%s", l);
2108         }
2109       aopPut (IC_RESULT (ic), "a", offset++);
2110     }
2111
2112   /* if any remaining bytes in the result */
2113   /* we just need to propagate the sign   */
2114   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2115     {
2116       emitcode ("rlc", "a");
2117       emitcode ("subb", "a,acc");
2118       while (size--)
2119         aopPut (IC_RESULT (ic), "a", offset++);
2120     }
2121
2122 release:
2123   /* release the aops */
2124   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2125   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2126 }
2127
2128 /*-----------------------------------------------------------------*/
2129 /* saveRegisters - will look for a call and save the registers     */
2130 /*-----------------------------------------------------------------*/
2131 static void
2132 saveRegisters (iCode * lic)
2133 {
2134   int i;
2135   iCode *ic;
2136   bitVect *rsave;
2137
2138   /* look for call */
2139   for (ic = lic; ic; ic = ic->next)
2140     if (ic->op == CALL || ic->op == PCALL)
2141       break;
2142
2143   if (!ic)
2144     {
2145       fprintf (stderr, "found parameter push with no function call\n");
2146       return;
2147     }
2148
2149   /* if the registers have been saved already or don't need to be then
2150      do nothing */
2151   if (ic->regsSaved)
2152     return;
2153   if (IS_SYMOP(IC_LEFT(ic)) &&
2154       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2155        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2156     return;
2157
2158   /* save the registers in use at this time but skip the
2159      ones for the result */
2160   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2161                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2162
2163   ic->regsSaved = 1;
2164   if (options.useXstack)
2165     {
2166       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2167       int nBits = bitVectnBitsOn (rsavebits);
2168       int count = bitVectnBitsOn (rsave);
2169
2170       if (nBits != 0)
2171         {
2172           count = count - nBits + 1;
2173           /* remove all but the first bits as they are pushed all at once */
2174           rsave = bitVectCplAnd (rsave, rsavebits);
2175           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2176         }
2177
2178       if (count == 1)
2179         {
2180           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2181           if (reg->type == REG_BIT)
2182             {
2183               emitcode ("mov", "a,%s", reg->base);
2184             }
2185           else
2186             {
2187               emitcode ("mov", "a,%s", reg->name);
2188             }
2189           emitcode ("mov", "r0,%s", spname);
2190           emitcode ("inc", "%s", spname);// allocate before use
2191           emitcode ("movx", "@r0,a");
2192           if (bitVectBitValue (rsave, R0_IDX))
2193             emitcode ("mov", "r0,a");
2194         }
2195       else if (count != 0)
2196         {
2197           if (bitVectBitValue (rsave, R0_IDX))
2198             {
2199               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2200             }
2201           emitcode ("mov", "r0,%s", spname);
2202           MOVA ("r0");
2203           emitcode ("add", "a,#%d", count);
2204           emitcode ("mov", "%s,a", spname);
2205           for (i = 0; i < mcs51_nRegs; i++)
2206             {
2207               if (bitVectBitValue (rsave, i))
2208                 {
2209                   regs * reg = REG_WITH_INDEX (i);
2210                   if (i == R0_IDX)
2211                     {
2212                       emitcode ("pop", "acc");
2213                       emitcode ("push", "acc");
2214                     }
2215                   else if (reg->type == REG_BIT)
2216                     {
2217                       emitcode ("mov", "a,%s", reg->base);
2218                     }
2219                   else
2220                     {
2221                       emitcode ("mov", "a,%s", reg->name);
2222                     }
2223                   emitcode ("movx", "@r0,a");
2224                   if (--count)
2225                     {
2226                       emitcode ("inc", "r0");
2227                     }
2228                 }
2229             }
2230           if (bitVectBitValue (rsave, R0_IDX))
2231             {
2232               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2233             }
2234         }
2235     }
2236   else
2237     {
2238       bool bits_pushed = FALSE;
2239       for (i = 0; i < mcs51_nRegs; i++)
2240         {
2241           if (bitVectBitValue (rsave, i))
2242             {
2243               bits_pushed = pushReg (i, bits_pushed);
2244             }
2245         }
2246     }
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* unsaveRegisters - pop the pushed registers                      */
2251 /*-----------------------------------------------------------------*/
2252 static void
2253 unsaveRegisters (iCode * ic)
2254 {
2255   int i;
2256   bitVect *rsave;
2257
2258   /* restore the registers in use at this time but skip the
2259      ones for the result */
2260   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2261                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2262
2263   if (options.useXstack)
2264     {
2265       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2266       int nBits = bitVectnBitsOn (rsavebits);
2267       int count = bitVectnBitsOn (rsave);
2268
2269       if (nBits != 0)
2270         {
2271           count = count - nBits + 1;
2272           /* remove all but the first bits as they are popped all at once */
2273           rsave = bitVectCplAnd (rsave, rsavebits);
2274           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2275         }
2276
2277       if (count == 1)
2278         {
2279           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2280           emitcode ("mov", "r0,%s", spname);
2281           emitcode ("dec", "r0");
2282           emitcode ("movx", "a,@r0");
2283           if (reg->type == REG_BIT)
2284             {
2285               emitcode ("mov", "%s,a", reg->base);
2286             }
2287           else
2288             {
2289               emitcode ("mov", "%s,a", reg->name);
2290             }
2291           emitcode ("dec", "%s", spname);
2292         }
2293       else if (count != 0)
2294         {
2295           emitcode ("mov", "r0,%s", spname);
2296           for (i = mcs51_nRegs; i >= 0; i--)
2297             {
2298               if (bitVectBitValue (rsave, i))
2299                 {
2300                   regs * reg = REG_WITH_INDEX (i);
2301                   emitcode ("dec", "r0");
2302                   emitcode ("movx", "a,@r0");
2303                   if (i == R0_IDX)
2304                     {
2305                       emitcode ("push", "acc");
2306                     }
2307                   else if (reg->type == REG_BIT)
2308                     {
2309                       emitcode ("mov", "%s,a", reg->base);
2310                     }
2311                   else
2312                     {
2313                       emitcode ("mov", "%s,a", reg->name);
2314                     }
2315                 }
2316             }
2317           emitcode ("mov", "%s,r0", spname);
2318           if (bitVectBitValue (rsave, R0_IDX))
2319             {
2320               emitcode ("pop", "ar0");
2321             }
2322         }
2323     }
2324   else
2325     {
2326       bool bits_popped = FALSE;
2327       for (i = mcs51_nRegs; i >= 0; i--)
2328         {
2329           if (bitVectBitValue (rsave, i))
2330             {
2331               bits_popped = popReg (i, bits_popped);
2332             }
2333         }
2334     }
2335 }
2336
2337
2338 /*-----------------------------------------------------------------*/
2339 /* pushSide -                                                      */
2340 /*-----------------------------------------------------------------*/
2341 static void
2342 pushSide (operand * oper, int size)
2343 {
2344   int offset = 0;
2345   while (size--)
2346     {
2347       char *l = aopGet (oper, offset++, FALSE, TRUE);
2348       if (AOP_TYPE (oper) != AOP_REG &&
2349           AOP_TYPE (oper) != AOP_DIR &&
2350           strcmp (l, "a"))
2351         {
2352           MOVA (l);
2353           emitcode ("push", "acc");
2354         }
2355       else
2356         {
2357           emitcode ("push", "%s", l);
2358         }
2359     }
2360 }
2361
2362 /*-----------------------------------------------------------------*/
2363 /* assignResultValue - also indicates if acc is in use afterwards  */
2364 /*-----------------------------------------------------------------*/
2365 static bool
2366 assignResultValue (operand * oper, operand * func)
2367 {
2368   int offset = 0;
2369   int size = AOP_SIZE (oper);
2370   bool accuse = FALSE;
2371   bool pushedA = FALSE;
2372
2373   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2374     {
2375       outBitC (oper);
2376       return FALSE;
2377     }
2378
2379   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2380     {
2381       emitcode ("push", "acc");
2382       pushedA = TRUE;
2383     }
2384   while (size--)
2385     {
2386       if ((offset == 3) && pushedA)
2387         emitcode ("pop", "acc");
2388       accuse |= aopPut (oper, fReturn[offset], offset);
2389       offset++;
2390     }
2391   return accuse;
2392 }
2393
2394
2395 /*-----------------------------------------------------------------*/
2396 /* genXpush - pushes onto the external stack                       */
2397 /*-----------------------------------------------------------------*/
2398 static void
2399 genXpush (iCode * ic)
2400 {
2401   asmop *aop = newAsmop (0);
2402   regs *r;
2403   int size, offset = 0;
2404
2405   D (emitcode (";", "genXpush"));
2406
2407   aopOp (IC_LEFT (ic), ic, FALSE);
2408   r = getFreePtr (ic, &aop, FALSE);
2409
2410   size = AOP_SIZE (IC_LEFT (ic));
2411
2412   if (size == 1)
2413     {
2414       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2415       emitcode ("mov", "%s,%s", r->name, spname);
2416       emitcode ("inc", "%s", spname); // allocate space first
2417       emitcode ("movx", "@%s,a", r->name);
2418     }
2419   else
2420     {
2421       // allocate space first
2422       emitcode ("mov", "%s,%s", r->name, spname);
2423       MOVA (r->name);
2424       emitcode ("add", "a,#%d", size);
2425       emitcode ("mov", "%s,a", spname);
2426
2427       while (size--)
2428         {
2429           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2430           emitcode ("movx", "@%s,a", r->name);
2431           emitcode ("inc", "%s", r->name);
2432         }
2433     }
2434
2435   freeAsmop (NULL, aop, ic, TRUE);
2436   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2437 }
2438
2439 /*-----------------------------------------------------------------*/
2440 /* genIpush - generate code for pushing this gets a little complex */
2441 /*-----------------------------------------------------------------*/
2442 static void
2443 genIpush (iCode * ic)
2444 {
2445   int size, offset = 0;
2446   char *l;
2447   char *prev = "";
2448
2449   D (emitcode (";", "genIpush"));
2450
2451   /* if this is not a parm push : ie. it is spill push
2452      and spill push is always done on the local stack */
2453   if (!ic->parmPush)
2454     {
2455
2456       /* and the item is spilt then do nothing */
2457       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2458         return;
2459
2460       aopOp (IC_LEFT (ic), ic, FALSE);
2461       size = AOP_SIZE (IC_LEFT (ic));
2462       /* push it on the stack */
2463       while (size--)
2464         {
2465           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2466           if (*l == '#')
2467             {
2468               MOVA (l);
2469               l = "acc";
2470             }
2471           emitcode ("push", "%s", l);
2472         }
2473       return;
2474     }
2475
2476   /* this is a parameter push: in this case we call
2477      the routine to find the call and save those
2478      registers that need to be saved */
2479   saveRegisters (ic);
2480
2481   /* if use external stack then call the external
2482      stack pushing routine */
2483   if (options.useXstack)
2484     {
2485       genXpush (ic);
2486       return;
2487     }
2488
2489   /* then do the push */
2490   aopOp (IC_LEFT (ic), ic, FALSE);
2491
2492   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2493   size = AOP_SIZE (IC_LEFT (ic));
2494
2495   while (size--)
2496     {
2497       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2498       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2499           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2500         {
2501           if (strcmp (l, prev) || *l == '@')
2502             MOVA (l);
2503           emitcode ("push", "acc");
2504         }
2505       else
2506         {
2507           emitcode ("push", "%s", l);
2508         }
2509       prev = l;
2510     }
2511
2512   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* genIpop - recover the registers: can happen only for spilling   */
2517 /*-----------------------------------------------------------------*/
2518 static void
2519 genIpop (iCode * ic)
2520 {
2521   int size, offset;
2522
2523   D (emitcode (";", "genIpop"));
2524
2525   /* if the temp was not pushed then */
2526   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2527     return;
2528
2529   aopOp (IC_LEFT (ic), ic, FALSE);
2530   size = AOP_SIZE (IC_LEFT (ic));
2531   offset = (size - 1);
2532   while (size--)
2533     {
2534       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2535                                      FALSE, TRUE));
2536     }
2537
2538   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* saveRBank - saves an entire register bank on the stack          */
2543 /*-----------------------------------------------------------------*/
2544 static void
2545 saveRBank (int bank, iCode * ic, bool pushPsw)
2546 {
2547   int i;
2548   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2549   asmop *aop = NULL;
2550   regs *r = NULL;
2551
2552   if (options.useXstack)
2553     {
2554       if (!ic)
2555         {
2556           /* Assume r0 is available for use. */
2557           r = REG_WITH_INDEX (R0_IDX);;
2558         }
2559       else
2560         {
2561           aop = newAsmop (0);
2562           r = getFreePtr (ic, &aop, FALSE);
2563         }
2564       // allocate space first
2565       emitcode ("mov", "%s,%s", r->name, spname);
2566       MOVA (r->name);
2567       emitcode ("add", "a,#%d", count);
2568       emitcode ("mov", "%s,a", spname);
2569     }
2570
2571   for (i = 0; i < 8; i++)
2572     {
2573       if (options.useXstack)
2574         {
2575           emitcode ("mov", "a,(%s+%d)",
2576                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2577           emitcode ("movx", "@%s,a", r->name);
2578           if (--count)
2579             emitcode ("inc", "%s", r->name);
2580         }
2581       else
2582         emitcode ("push", "(%s+%d)",
2583                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2584     }
2585
2586   if (mcs51_nRegs > 8)
2587     {
2588       if (options.useXstack)
2589         {
2590           emitcode ("mov", "a,bits");
2591           emitcode ("movx", "@%s,a", r->name);
2592           if (--count)
2593             emitcode ("inc", "%s", r->name);
2594         }
2595       else
2596         {
2597           emitcode ("push", "bits");
2598         }
2599       BitBankUsed = 1;
2600     }
2601
2602   if (pushPsw)
2603     {
2604       if (options.useXstack)
2605         {
2606           emitcode ("mov", "a,psw");
2607           emitcode ("movx", "@%s,a", r->name);
2608         }
2609       else
2610         {
2611           emitcode ("push", "psw");
2612         }
2613
2614       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2615     }
2616
2617   if (aop)
2618     {
2619       freeAsmop (NULL, aop, ic, TRUE);
2620     }
2621
2622   if (ic)
2623   {
2624     ic->bankSaved = 1;
2625   }
2626 }
2627
2628 /*-----------------------------------------------------------------*/
2629 /* unsaveRBank - restores the register bank from stack             */
2630 /*-----------------------------------------------------------------*/
2631 static void
2632 unsaveRBank (int bank, iCode * ic, bool popPsw)
2633 {
2634   int i;
2635   asmop *aop = NULL;
2636   regs *r = NULL;
2637
2638   if (options.useXstack)
2639     {
2640       if (!ic)
2641         {
2642           /* Assume r0 is available for use. */
2643           r = REG_WITH_INDEX (R0_IDX);;
2644         }
2645       else
2646         {
2647           aop = newAsmop (0);
2648           r = getFreePtr (ic, &aop, FALSE);
2649         }
2650       emitcode ("mov", "%s,%s", r->name, spname);
2651     }
2652
2653   if (popPsw)
2654     {
2655       if (options.useXstack)
2656         {
2657           emitcode ("dec", "%s", r->name);
2658           emitcode ("movx", "a,@%s", r->name);
2659           emitcode ("mov", "psw,a");
2660         }
2661       else
2662         {
2663           emitcode ("pop", "psw");
2664         }
2665     }
2666
2667   if (mcs51_nRegs > 8)
2668     {
2669       if (options.useXstack)
2670         {
2671           emitcode ("dec", "%s", r->name);
2672           emitcode ("movx", "a,@%s", r->name);
2673           emitcode ("mov", "bits,a");
2674         }
2675       else
2676         {
2677           emitcode ("pop", "bits");
2678         }
2679     }
2680
2681   for (i = 7; i >= 0; i--)
2682     {
2683       if (options.useXstack)
2684         {
2685           emitcode ("dec", "%s", r->name);
2686           emitcode ("movx", "a,@%s", r->name);
2687           emitcode ("mov", "(%s+%d),a",
2688                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2689         }
2690       else
2691         {
2692           emitcode ("pop", "(%s+%d)",
2693                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2694         }
2695     }
2696
2697   if (options.useXstack)
2698     {
2699       emitcode ("mov", "%s,%s", spname, r->name);
2700     }
2701
2702   if (aop)
2703     {
2704       freeAsmop (NULL, aop, ic, TRUE);
2705     }
2706 }
2707
2708 /*-----------------------------------------------------------------*/
2709 /* genSend - gen code for SEND                                     */
2710 /*-----------------------------------------------------------------*/
2711 static void genSend(set *sendSet)
2712 {
2713   iCode *sic;
2714   int bit_count = 0;
2715
2716   /* first we do all bit parameters */
2717   for (sic = setFirstItem (sendSet); sic;
2718        sic = setNextItem (sendSet))
2719     {
2720       if (sic->argreg > 12)
2721         {
2722           int bit = sic->argreg-13;
2723
2724           aopOp (IC_LEFT (sic), sic, FALSE);
2725
2726           /* if left is a literal then
2727              we know what the value is */
2728           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2729             {
2730               if (((int) operandLitValue (IC_LEFT (sic))))
2731                   emitcode ("setb", "b[%d]", bit);
2732               else
2733                   emitcode ("clr", "b[%d]", bit);
2734             }
2735           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2736             {
2737               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2738                 if (strcmp (l, "c"))
2739                     emitcode ("mov", "c,%s", l);
2740                 emitcode ("mov", "b[%d],c", bit);
2741             }
2742           else
2743             {
2744               /* we need to or */
2745               toBoolean (IC_LEFT (sic));
2746               /* set C, if a >= 1 */
2747               emitcode ("add", "a,#0xff");
2748               emitcode ("mov", "b[%d],c", bit);
2749             }
2750           bit_count++;
2751           BitBankUsed = 1;
2752
2753           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2754         }
2755     }
2756
2757   if (bit_count)
2758     {
2759       saveRegisters (setFirstItem (sendSet));
2760       emitcode ("mov", "bits,b");
2761     }
2762
2763   /* then we do all other parameters */
2764   for (sic = setFirstItem (sendSet); sic;
2765        sic = setNextItem (sendSet))
2766     {
2767       if (sic->argreg <= 12)
2768         {
2769           int size, offset = 0;
2770           aopOp (IC_LEFT (sic), sic, FALSE);
2771           size = AOP_SIZE (IC_LEFT (sic));
2772
2773           if (sic->argreg == 1)
2774             {
2775               while (size--)
2776                 {
2777                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2778                   if (strcmp (l, fReturn[offset]))
2779                     {
2780                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2781                     }
2782                   offset++;
2783                 }
2784             }
2785           else
2786             {
2787               while (size--)
2788                 {
2789                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2790                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2791                   offset++;
2792                 }
2793             }
2794           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2795         }
2796     }
2797 }
2798
2799 /*-----------------------------------------------------------------*/
2800 /* selectRegBank - emit code to select the register bank           */
2801 /*-----------------------------------------------------------------*/
2802 static void
2803 selectRegBank (short bank, bool keepFlags)
2804 {
2805   /* if f.e. result is in carry */
2806   if (keepFlags)
2807     {
2808       emitcode ("anl", "psw,#0xE7");
2809       if (bank)
2810         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2811     }
2812   else
2813     {
2814       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2815     }
2816 }
2817
2818 /*-----------------------------------------------------------------*/
2819 /* genCall - generates a call statement                            */
2820 /*-----------------------------------------------------------------*/
2821 static void
2822 genCall (iCode * ic)
2823 {
2824   sym_link *dtype;
2825   sym_link *etype;
2826 //  bool restoreBank = FALSE;
2827   bool swapBanks = FALSE;
2828   bool accuse = FALSE;
2829   bool accPushed = FALSE;
2830   bool resultInF0 = FALSE;
2831   bool assignResultGenerated = FALSE;
2832
2833   D (emitcode (";", "genCall"));
2834
2835   dtype = operandType (IC_LEFT (ic));
2836   etype = getSpec(dtype);
2837   /* if send set is not empty then assign */
2838   if (_G.sendSet)
2839     {
2840         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2841             genSend(reverseSet(_G.sendSet));
2842         } else {
2843             genSend(_G.sendSet);
2844         }
2845       _G.sendSet = NULL;
2846     }
2847
2848   /* if we are calling a not _naked function that is not using
2849      the same register bank then we need to save the
2850      destination registers on the stack */
2851   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2852       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2853        !IFFUNC_ISISR (dtype))
2854     {
2855       swapBanks = TRUE;
2856     }
2857
2858   /* if caller saves & we have not saved then */
2859   if (!ic->regsSaved)
2860       saveRegisters (ic);
2861
2862   if (swapBanks)
2863     {
2864         emitcode ("mov", "psw,#0x%02x",
2865            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2866     }
2867
2868   /* make the call */
2869   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2870     {
2871       if (IFFUNC_CALLEESAVES(dtype))
2872         {
2873           werror (E_BANKED_WITH_CALLEESAVES);
2874         }
2875       else
2876         {
2877           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2878                      OP_SYMBOL (IC_LEFT (ic))->rname :
2879                      OP_SYMBOL (IC_LEFT (ic))->name);
2880
2881           emitcode ("mov", "r0,#%s", l);
2882           emitcode ("mov", "r1,#(%s >> 8)", l);
2883           emitcode ("mov", "r2,#(%s >> 16)", l);
2884           emitcode ("lcall", "__sdcc_banked_call");
2885         }
2886     }
2887   else
2888     {
2889       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2890                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2891                                 OP_SYMBOL (IC_LEFT (ic))->name));
2892     }
2893
2894   if (swapBanks)
2895     {
2896       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2897     }
2898
2899   /* if we need assign a result value */
2900   if ((IS_ITEMP (IC_RESULT (ic)) &&
2901        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2902        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2903         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2904         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2905       IS_TRUE_SYMOP (IC_RESULT (ic)))
2906     {
2907
2908       _G.accInUse++;
2909       aopOp (IC_RESULT (ic), ic, FALSE);
2910       _G.accInUse--;
2911
2912       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2913       assignResultGenerated = TRUE;
2914
2915       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2916     }
2917
2918   /* adjust the stack for parameters if required */
2919   if (ic->parmBytes)
2920     {
2921       int i;
2922       if (ic->parmBytes > 3)
2923         {
2924           if (accuse)
2925             {
2926               emitcode ("push", "acc");
2927               accPushed = TRUE;
2928             }
2929           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2930               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2931               !assignResultGenerated)
2932             {
2933               emitcode ("mov", "F0,c");
2934               resultInF0 = TRUE;
2935             }
2936
2937           emitcode ("mov", "a,%s", spname);
2938           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2939           emitcode ("mov", "%s,a", spname);
2940
2941           /* unsaveRegisters from xstack needs acc, but */
2942           /* unsaveRegisters from stack needs this popped */
2943           if (accPushed && !options.useXstack)
2944             {
2945               emitcode ("pop", "acc");
2946               accPushed = FALSE;
2947             }
2948         }
2949       else
2950         for (i = 0; i < ic->parmBytes; i++)
2951           emitcode ("dec", "%s", spname);
2952     }
2953
2954   /* if we had saved some registers then unsave them */
2955   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2956     {
2957       if (accuse && !accPushed && options.useXstack)
2958         {
2959           /* xstack needs acc, but doesn't touch normal stack */
2960           emitcode ("push", "acc");
2961           accPushed = TRUE;
2962         }
2963       unsaveRegisters (ic);
2964     }
2965
2966 //  /* if register bank was saved then pop them */
2967 //  if (restoreBank)
2968 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2969
2970   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2971     {
2972       if (resultInF0)
2973           emitcode ("mov", "c,F0");
2974
2975       aopOp (IC_RESULT (ic), ic, FALSE);
2976       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2977       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2978     }
2979
2980   if (accPushed)
2981     emitcode ("pop", "acc");
2982 }
2983
2984 /*-----------------------------------------------------------------*/
2985 /* genPcall - generates a call by pointer statement                */
2986 /*-----------------------------------------------------------------*/
2987 static void
2988 genPcall (iCode * ic)
2989 {
2990   sym_link *dtype;
2991   sym_link *etype;
2992   symbol *rlbl = newiTempLabel (NULL);
2993 //  bool restoreBank=FALSE;
2994   bool swapBanks = FALSE;
2995   bool resultInF0 = FALSE;
2996
2997   D (emitcode (";", "genPcall"));
2998
2999   dtype = operandType (IC_LEFT (ic))->next;
3000   etype = getSpec(dtype);
3001   /* if caller saves & we have not saved then */
3002   if (!ic->regsSaved)
3003     saveRegisters (ic);
3004
3005   /* if we are calling a not _naked function that is not using
3006      the same register bank then we need to save the
3007      destination registers on the stack */
3008   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
3009       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3010       !IFFUNC_ISISR (dtype))
3011     {
3012 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3013 //    restoreBank=TRUE;
3014       swapBanks = TRUE;
3015       // need caution message to user here
3016     }
3017
3018   if (IS_LITERAL(etype))
3019     {
3020       /* if send set is not empty then assign */
3021       if (_G.sendSet)
3022         {
3023           genSend(reverseSet(_G.sendSet));
3024           _G.sendSet = NULL;
3025         }
3026
3027       if (swapBanks)
3028         {
3029           emitcode ("mov", "psw,#0x%02x",
3030            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3031         }
3032
3033       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3034         {
3035           if (IFFUNC_CALLEESAVES(dtype))
3036             {
3037               werror (E_BANKED_WITH_CALLEESAVES);
3038             }
3039           else
3040             {
3041               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3042
3043               emitcode ("mov", "r0,#%s", l);
3044               emitcode ("mov", "r1,#(%s >> 8)", l);
3045               emitcode ("mov", "r2,#(%s >> 16)", l);
3046               emitcode ("lcall", "__sdcc_banked_call");
3047             }
3048         }
3049       else
3050         {
3051           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3052         }
3053     }
3054   else
3055     {
3056       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
3057         {
3058           if (IFFUNC_CALLEESAVES(dtype))
3059             {
3060               werror (E_BANKED_WITH_CALLEESAVES);
3061             }
3062           else
3063             {
3064               aopOp (IC_LEFT (ic), ic, FALSE);
3065
3066               if (!swapBanks)
3067                 {
3068                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3069                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3070                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3071                 }
3072               else
3073                 {
3074                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3075                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3076                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3077                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3078                 }
3079
3080               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3081
3082               /* if send set is not empty then assign */
3083               if (_G.sendSet)
3084                 {
3085                   genSend(reverseSet(_G.sendSet));
3086                   _G.sendSet = NULL;
3087                 }
3088
3089               if (swapBanks)
3090                 {
3091                   emitcode ("mov", "psw,#0x%02x",
3092                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3093                 }
3094
3095               /* make the call */
3096               emitcode ("lcall", "__sdcc_banked_call");
3097             }
3098         }
3099       else
3100         {
3101           /* push the return address on to the stack */
3102           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3103           emitcode ("push", "acc");
3104           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3105           emitcode ("push", "acc");
3106
3107           /* now push the calling address */
3108           aopOp (IC_LEFT (ic), ic, FALSE);
3109
3110           pushSide (IC_LEFT (ic), FPTRSIZE);
3111
3112           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3113
3114           /* if send set is not empty the assign */
3115           if (_G.sendSet)
3116             {
3117               genSend(reverseSet(_G.sendSet));
3118               _G.sendSet = NULL;
3119             }
3120
3121           if (swapBanks)
3122             {
3123               emitcode ("mov", "psw,#0x%02x",
3124                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3125             }
3126
3127           /* make the call */
3128           emitcode ("ret", "");
3129           emitLabel (rlbl);
3130         }
3131     }
3132   if (swapBanks)
3133     {
3134       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3135     }
3136
3137   /* if we need assign a result value */
3138   if ((IS_ITEMP (IC_RESULT (ic)) &&
3139        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3140        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3141         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3142       IS_TRUE_SYMOP (IC_RESULT (ic)))
3143     {
3144
3145       _G.accInUse++;
3146       aopOp (IC_RESULT (ic), ic, FALSE);
3147       _G.accInUse--;
3148
3149       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3150
3151       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3152     }
3153
3154   /* adjust the stack for parameters if required */
3155   if (ic->parmBytes)
3156     {
3157       int i;
3158       if (ic->parmBytes > 3)
3159         {
3160           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3161               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3162             {
3163               emitcode ("mov", "F0,c");
3164               resultInF0 = TRUE;
3165             }
3166
3167           emitcode ("mov", "a,%s", spname);
3168           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3169           emitcode ("mov", "%s,a", spname);
3170         }
3171       else
3172         for (i = 0; i < ic->parmBytes; i++)
3173           emitcode ("dec", "%s", spname);
3174     }
3175
3176 //  /* if register bank was saved then unsave them */
3177 //  if (restoreBank)
3178 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3179
3180   /* if we had saved some registers then unsave them */
3181   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3182     unsaveRegisters (ic);
3183
3184   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3185     {
3186       if (resultInF0)
3187           emitcode ("mov", "c,F0");
3188
3189       aopOp (IC_RESULT (ic), ic, FALSE);
3190       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3191       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3192     }
3193 }
3194
3195 /*-----------------------------------------------------------------*/
3196 /* resultRemat - result  is rematerializable                       */
3197 /*-----------------------------------------------------------------*/
3198 static int
3199 resultRemat (iCode * ic)
3200 {
3201   if (SKIP_IC (ic) || ic->op == IFX)
3202     return 0;
3203
3204   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3205     {
3206       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3207       if (sym->remat && !POINTER_SET (ic))
3208         return 1;
3209     }
3210
3211   return 0;
3212 }
3213
3214 #if defined(__BORLANDC__) || defined(_MSC_VER)
3215 #define STRCASECMP stricmp
3216 #else
3217 #define STRCASECMP strcasecmp
3218 #endif
3219
3220 /*-----------------------------------------------------------------*/
3221 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3222 /*-----------------------------------------------------------------*/
3223 static int
3224 regsCmp(void *p1, void *p2)
3225 {
3226   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3227 }
3228
3229 static bool
3230 inExcludeList (char *s)
3231 {
3232   const char *p = setFirstItem(options.excludeRegsSet);
3233
3234   if (p == NULL || STRCASECMP(p, "none") == 0)
3235     return FALSE;
3236
3237
3238   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3239 }
3240
3241 /*-----------------------------------------------------------------*/
3242 /* genFunction - generated code for function entry                 */
3243 /*-----------------------------------------------------------------*/
3244 static void
3245 genFunction (iCode * ic)
3246 {
3247   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3248   sym_link *ftype;
3249   bool     switchedPSW = FALSE;
3250   int      calleesaves_saved_register = -1;
3251   int      stackAdjust = sym->stack;
3252   int      accIsFree = sym->recvSize < 4;
3253   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3254   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3255
3256   _G.nRegsSaved = 0;
3257   /* create the function header */
3258   emitcode (";", "-----------------------------------------");
3259   emitcode (";", " function %s", sym->name);
3260   emitcode (";", "-----------------------------------------");
3261
3262   emitcode ("", "%s:", sym->rname);
3263   lineCurr->isLabel = 1;
3264   ftype = operandType (IC_LEFT (ic));
3265   _G.currentFunc = sym;
3266
3267   if (IFFUNC_ISNAKED(ftype))
3268   {
3269       emitcode(";", "naked function: no prologue.");
3270       return;
3271   }
3272
3273   /* here we need to generate the equates for the
3274      register bank if required */
3275   if (FUNC_REGBANK (ftype) != rbank)
3276     {
3277       int i;
3278
3279       rbank = FUNC_REGBANK (ftype);
3280       for (i = 0; i < mcs51_nRegs; i++)
3281         {
3282           if (regs8051[i].type != REG_BIT)
3283             {
3284               if (strcmp (regs8051[i].base, "0") == 0)
3285                 emitcode ("", "%s = 0x%02x",
3286                           regs8051[i].dname,
3287                           8 * rbank + regs8051[i].offset);
3288               else
3289                 emitcode ("", "%s = %s + 0x%02x",
3290                           regs8051[i].dname,
3291                           regs8051[i].base,
3292                           8 * rbank + regs8051[i].offset);
3293             }
3294         }
3295     }
3296
3297   /* if this is an interrupt service routine then
3298      save acc, b, dpl, dph  */
3299   if (IFFUNC_ISISR (sym->type))
3300     {
3301       if (!inExcludeList ("acc"))
3302         emitcode ("push", "acc");
3303       if (!inExcludeList ("b"))
3304         emitcode ("push", "b");
3305       if (!inExcludeList ("dpl"))
3306         emitcode ("push", "dpl");
3307       if (!inExcludeList ("dph"))
3308         emitcode ("push", "dph");
3309       /* if this isr has no bank i.e. is going to
3310          run with bank 0 , then we need to save more
3311          registers :-) */
3312       if (!FUNC_REGBANK (sym->type))
3313         {
3314           int i;
3315
3316           /* if this function does not call any other
3317              function then we can be economical and
3318              save only those registers that are used */
3319           if (!IFFUNC_HASFCALL(sym->type))
3320             {
3321               /* if any registers used */
3322               if (sym->regsUsed)
3323                 {
3324                   bool bits_pushed = FALSE;
3325                   /* save the registers used */
3326                   for (i = 0; i < sym->regsUsed->size; i++)
3327                     {
3328                       if (bitVectBitValue (sym->regsUsed, i))
3329                         bits_pushed = pushReg (i, bits_pushed);
3330                     }
3331                 }
3332             }
3333           else
3334             {
3335               /* this function has a function call. We cannot
3336                  determine register usage so we will have to push the
3337                  entire bank */
3338                 saveRBank (0, ic, FALSE);
3339                 if (options.parms_in_bank1) {
3340                     for (i=0; i < 8 ; i++ ) {
3341                         emitcode ("push","%s",rb1regs[i]);
3342                     }
3343                 }
3344             }
3345         }
3346         else
3347         {
3348             /* This ISR uses a non-zero bank.
3349              *
3350              * We assume that the bank is available for our
3351              * exclusive use.
3352              *
3353              * However, if this ISR calls a function which uses some
3354              * other bank, we must save that bank entirely.
3355              */
3356             unsigned long banksToSave = 0;
3357
3358             if (IFFUNC_HASFCALL(sym->type))
3359             {
3360
3361 #define MAX_REGISTER_BANKS 4
3362
3363                 iCode *i;
3364                 int ix;
3365
3366                 for (i = ic; i; i = i->next)
3367                 {
3368                     if (i->op == ENDFUNCTION)
3369                     {
3370                         /* we got to the end OK. */
3371                         break;
3372                     }
3373
3374                     if (i->op == CALL)
3375                     {
3376                         sym_link *dtype;
3377
3378                         dtype = operandType (IC_LEFT(i));
3379                         if (dtype
3380                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3381                         {
3382                              /* Mark this bank for saving. */
3383                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3384                              {
3385                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3386                              }
3387                              else
3388                              {
3389                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3390                              }
3391
3392                              /* And note that we don't need to do it in
3393                               * genCall.
3394                               */
3395                              i->bankSaved = 1;
3396                         }
3397                     }
3398                     if (i->op == PCALL)
3399                     {
3400                         /* This is a mess; we have no idea what
3401                          * register bank the called function might
3402                          * use.
3403                          *
3404                          * The only thing I can think of to do is
3405                          * throw a warning and hope.
3406                          */
3407                         werror(W_FUNCPTR_IN_USING_ISR);
3408                     }
3409                 }
3410
3411                 if (banksToSave && options.useXstack)
3412                 {
3413                     /* Since we aren't passing it an ic,
3414                      * saveRBank will assume r0 is available to abuse.
3415                      *
3416                      * So switch to our (trashable) bank now, so
3417                      * the caller's R0 isn't trashed.
3418                      */
3419                     emitcode ("push", "psw");
3420                     emitcode ("mov", "psw,#0x%02x",
3421                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3422                     switchedPSW = TRUE;
3423                 }
3424
3425                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3426                 {
3427                      if (banksToSave & (1 << ix))
3428                      {
3429                          saveRBank(ix, NULL, FALSE);
3430                      }
3431                 }
3432             }
3433             // TODO: this needs a closer look
3434             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3435         }
3436
3437       /* Set the register bank to the desired value if nothing else */
3438       /* has done so yet. */
3439       if (!switchedPSW)
3440         {
3441           emitcode ("push", "psw");
3442           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3443         }
3444     }
3445   else
3446     {
3447       /* This is a non-ISR function. The caller has already switched register */
3448       /* banks, if necessary, so just handle the callee-saves option. */
3449
3450       /* if callee-save to be used for this function
3451          then save the registers being used in this function */
3452       if (IFFUNC_CALLEESAVES(sym->type))
3453         {
3454           int i;
3455
3456           /* if any registers used */
3457           if (sym->regsUsed)
3458             {
3459               bool bits_pushed = FALSE;
3460               /* save the registers used */
3461               for (i = 0; i < sym->regsUsed->size; i++)
3462                 {
3463                   if (bitVectBitValue (sym->regsUsed, i))
3464                     {
3465                       /* remember one saved register for later usage */
3466                       if (calleesaves_saved_register < 0)
3467                         calleesaves_saved_register = i;
3468                       bits_pushed = pushReg (i, bits_pushed);
3469                       _G.nRegsSaved++;
3470                     }
3471                 }
3472             }
3473         }
3474     }
3475
3476   if (fReentrant)
3477     {
3478       if (options.useXstack)
3479         {
3480           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3481             {
3482               emitcode ("mov", "r0,%s", spname);
3483               emitcode ("inc", "%s", spname);
3484               emitcode ("xch", "a,_bpx");
3485               emitcode ("movx", "@r0,a");
3486               emitcode ("inc", "r0");
3487               emitcode ("mov", "a,r0");
3488               emitcode ("xch", "a,_bpx");
3489             }
3490           if (sym->stack)
3491             {
3492               emitcode ("push", "_bp");     /* save the callers stack  */
3493               emitcode ("mov", "_bp,sp");
3494             }
3495         }
3496       else
3497         {
3498           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3499             {
3500               /* set up the stack */
3501               emitcode ("push", "_bp");     /* save the callers stack  */
3502               emitcode ("mov", "_bp,sp");
3503             }
3504         }
3505     }
3506
3507   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3508   /* before setting up the stack frame completely. */
3509   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3510     {
3511       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3512
3513       if (rsym->isitmp)
3514         {
3515           if (rsym && rsym->regType == REG_CND)
3516             rsym = NULL;
3517           if (rsym && (rsym->accuse || rsym->ruonly))
3518             rsym = NULL;
3519           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3520             rsym = rsym->usl.spillLoc;
3521         }
3522
3523       /* If the RECEIVE operand immediately spills to the first entry on the */
3524       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3525       /* rather than the usual @r0/r1 machinations. */
3526       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3527         {
3528           int ofs;
3529
3530           _G.current_iCode = ric;
3531           D(emitcode (";     genReceive",""));
3532           for (ofs=0; ofs < sym->recvSize; ofs++)
3533             {
3534               if (!strcmp (fReturn[ofs], "a"))
3535                 emitcode ("push", "acc");
3536               else
3537                 emitcode ("push", fReturn[ofs]);
3538             }
3539           stackAdjust -= sym->recvSize;
3540           if (stackAdjust<0)
3541             {
3542               assert (stackAdjust>=0);
3543               stackAdjust = 0;
3544             }
3545           _G.current_iCode = ic;
3546           ric->generated = 1;
3547           accIsFree = 1;
3548         }
3549       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3550       /* to free up the accumulator. */
3551       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3552         {
3553           int ofs;
3554
3555           _G.current_iCode = ric;
3556           D(emitcode (";     genReceive",""));
3557           for (ofs=0; ofs < sym->recvSize; ofs++)
3558             {
3559               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3560             }
3561           _G.current_iCode = ic;
3562           ric->generated = 1;
3563           accIsFree = 1;
3564         }
3565     }
3566
3567   /* adjust the stack for the function */
3568   if (stackAdjust)
3569     {
3570       int i = stackAdjust;
3571       if (i > 256)
3572         werror (W_STACK_OVERFLOW, sym->name);
3573
3574       if (i > 3 && accIsFree)
3575         {
3576           emitcode ("mov", "a,sp");
3577           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3578           emitcode ("mov", "sp,a");
3579         }
3580       else if (i > 5)
3581         {
3582           /* The accumulator is not free, so we will need another register */
3583           /* to clobber. No need to worry about a possible conflict with */
3584           /* the above early RECEIVE optimizations since they would have */
3585           /* freed the accumulator if they were generated. */
3586
3587           if (IFFUNC_CALLEESAVES(sym->type))
3588             {
3589               /* if it's a callee-saves function we need a saved register */
3590               if (calleesaves_saved_register >= 0)
3591                 {
3592                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3593                   emitcode ("mov", "a,sp");
3594                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3595                   emitcode ("mov", "sp,a");
3596                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3597                 }
3598               else
3599                 /* do it the hard way */
3600                 while (i--)
3601                   emitcode ("inc", "sp");
3602             }
3603           else
3604             {
3605               /* not callee-saves, we can clobber r0 */
3606               emitcode ("mov", "r0,a");
3607               emitcode ("mov", "a,sp");
3608               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3609               emitcode ("mov", "sp,a");
3610               emitcode ("mov", "a,r0");
3611             }
3612         }
3613       else
3614         while (i--)
3615           emitcode ("inc", "sp");
3616     }
3617
3618   if (sym->xstack)
3619     {
3620       char i = ((char) sym->xstack & 0xff);
3621
3622       if (i > 3 && accIsFree)
3623         {
3624           emitcode ("mov", "a,_spx");
3625           emitcode ("add", "a,#0x%02x", i & 0xff);
3626           emitcode ("mov", "_spx,a");
3627         }
3628       else if (i > 5)
3629         {
3630           emitcode ("push", "acc");
3631           emitcode ("mov", "a,_spx");
3632           emitcode ("add", "a,#0x%02x", i & 0xff);
3633           emitcode ("mov", "_spx,a");
3634           emitcode ("pop", "acc");
3635         }
3636       else
3637         {
3638           while (i--)
3639             emitcode ("inc", "_spx");
3640         }
3641     }
3642
3643   /* if critical function then turn interrupts off */
3644   if (IFFUNC_ISCRITICAL (ftype))
3645     {
3646       symbol *tlbl = newiTempLabel (NULL);
3647       emitcode ("setb", "c");
3648       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3649       emitcode ("clr", "c");
3650       emitLabel (tlbl);
3651       emitcode ("push", "psw"); /* save old ea via c in psw */
3652     }
3653 }
3654
3655 /*-----------------------------------------------------------------*/
3656 /* genEndFunction - generates epilogue for functions               */
3657 /*-----------------------------------------------------------------*/
3658 static void
3659 genEndFunction (iCode * ic)
3660 {
3661   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3662   lineNode *lnp = lineCurr;
3663   bitVect  *regsUsed;
3664   bitVect  *regsUsedPrologue;
3665   bitVect  *regsUnneeded;
3666   int      idx;
3667
3668   _G.currentFunc = NULL;
3669   if (IFFUNC_ISNAKED(sym->type))
3670   {
3671       emitcode(";", "naked function: no epilogue.");
3672       if (options.debug && currFunc)
3673         debugFile->writeEndFunction (currFunc, ic, 0);
3674       return;
3675   }
3676
3677   if (IFFUNC_ISCRITICAL (sym->type))
3678     {
3679       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3680         {
3681           emitcode ("rlc", "a");   /* save c in a */
3682           emitcode ("pop", "psw"); /* restore ea via c in psw */
3683           emitcode ("mov", "ea,c");
3684           emitcode ("rrc", "a");   /* restore c from a */
3685         }
3686       else
3687         {
3688           emitcode ("pop", "psw"); /* restore ea via c in psw */
3689           emitcode ("mov", "ea,c");
3690         }
3691     }
3692
3693   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3694     {
3695       if (options.useXstack)
3696         {
3697           if (sym->stack)
3698             {
3699               emitcode ("mov", "sp,_bp");
3700               emitcode ("pop", "_bp");
3701             }
3702           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3703             {
3704               emitcode ("xch", "a,_bpx");
3705               emitcode ("mov", "r0,a");
3706               emitcode ("dec", "r0");
3707               emitcode ("movx", "a,@r0");
3708               emitcode ("xch", "a,_bpx");
3709               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3710             }
3711         }
3712       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3713         {
3714           if (sym->stack)
3715             emitcode ("mov", "sp,_bp");
3716           emitcode ("pop", "_bp");
3717         }
3718     }
3719
3720   /* restore the register bank  */
3721   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3722   {
3723     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3724      || !options.useXstack)
3725     {
3726         /* Special case of ISR using non-zero bank with useXstack
3727          * is handled below.
3728          */
3729         emitcode ("pop", "psw");
3730     }
3731   }
3732
3733   if (IFFUNC_ISISR (sym->type))
3734     {
3735
3736       /* now we need to restore the registers */
3737       /* if this isr has no bank i.e. is going to
3738          run with bank 0 , then we need to save more
3739          registers :-) */
3740       if (!FUNC_REGBANK (sym->type))
3741         {
3742           int i;
3743           /* if this function does not call any other
3744              function then we can be economical and
3745              save only those registers that are used */
3746           if (!IFFUNC_HASFCALL(sym->type))
3747             {
3748               /* if any registers used */
3749               if (sym->regsUsed)
3750                 {
3751                   bool bits_popped = FALSE;
3752                   /* save the registers used */
3753                   for (i = sym->regsUsed->size; i >= 0; i--)
3754                     {
3755                       if (bitVectBitValue (sym->regsUsed, i))
3756                         bits_popped = popReg (i, bits_popped);
3757                     }
3758                 }
3759             }
3760           else
3761             {
3762               if (options.parms_in_bank1) {
3763                   for (i = 7 ; i >= 0 ; i-- ) {
3764                       emitcode ("pop","%s",rb1regs[i]);
3765                   }
3766               }
3767               /* this function has  a function call cannot
3768                  determines register usage so we will have to pop the
3769                  entire bank */
3770               unsaveRBank (0, ic, FALSE);
3771             }
3772         }
3773         else
3774         {
3775             /* This ISR uses a non-zero bank.
3776              *
3777              * Restore any register banks saved by genFunction
3778              * in reverse order.
3779              */
3780             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3781             int ix;
3782
3783             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3784             {
3785                 if (savedBanks & (1 << ix))
3786                 {
3787                     unsaveRBank(ix, NULL, FALSE);
3788                 }
3789             }
3790
3791             if (options.useXstack)
3792             {
3793                 /* Restore bank AFTER calling unsaveRBank,
3794                  * since it can trash r0.
3795                  */
3796                 emitcode ("pop", "psw");
3797             }
3798         }
3799
3800       if (!inExcludeList ("dph"))
3801         emitcode ("pop", "dph");
3802       if (!inExcludeList ("dpl"))
3803         emitcode ("pop", "dpl");
3804       if (!inExcludeList ("b"))
3805         emitcode ("pop", "b");
3806       if (!inExcludeList ("acc"))
3807         emitcode ("pop", "acc");
3808
3809       /* if debug then send end of function */
3810       if (options.debug && currFunc)
3811         {
3812           debugFile->writeEndFunction (currFunc, ic, 1);
3813         }
3814
3815       emitcode ("reti", "");
3816     }
3817   else
3818     {
3819       if (IFFUNC_CALLEESAVES(sym->type))
3820         {
3821           int i;
3822
3823           /* if any registers used */
3824           if (sym->regsUsed)
3825             {
3826               /* save the registers used */
3827               for (i = sym->regsUsed->size; i >= 0; i--)
3828                 {
3829                   if (bitVectBitValue (sym->regsUsed, i) ||
3830                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3831                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3832                 }
3833             }
3834           else if (mcs51_ptrRegReq)
3835             {
3836               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3837               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3838             }
3839
3840         }
3841
3842       /* if debug then send end of function */
3843       if (options.debug && currFunc)
3844         {
3845           debugFile->writeEndFunction (currFunc, ic, 1);
3846         }
3847
3848       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3849         {
3850           emitcode ("ljmp", "__sdcc_banked_ret");
3851         }
3852       else
3853         {
3854           emitcode ("ret", "");
3855         }
3856     }
3857
3858   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3859     return;
3860
3861   /* If this was an interrupt handler using bank 0 that called another */
3862   /* function, then all registers must be saved; nothing to optimized. */
3863   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3864       && !FUNC_REGBANK(sym->type))
3865     return;
3866
3867   /* There are no push/pops to optimize if not callee-saves or ISR */
3868   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3869     return;
3870
3871   /* If there were stack parameters, we cannot optimize without also    */
3872   /* fixing all of the stack offsets; this is too dificult to consider. */
3873   if (FUNC_HASSTACKPARM(sym->type))
3874     return;
3875
3876   /* Compute the registers actually used */
3877   regsUsed = newBitVect (mcs51_nRegs);
3878   regsUsedPrologue = newBitVect (mcs51_nRegs);
3879   while (lnp)
3880     {
3881       if (lnp->ic && lnp->ic->op == FUNCTION)
3882         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3883       else
3884         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3885
3886       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3887           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3888         break;
3889       if (!lnp->prev)
3890         break;
3891       lnp = lnp->prev;
3892     }
3893
3894   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3895       && !bitVectBitValue (regsUsed, CND_IDX))
3896     {
3897       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3898       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3899           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3900         bitVectUnSetBit (regsUsed, CND_IDX);
3901     }
3902   else
3903     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3904
3905   /* If this was an interrupt handler that called another function */
3906   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3907   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3908     {
3909       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3910       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3911       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3912       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3913       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3914     }
3915
3916   /* Remove the unneeded push/pops */
3917   regsUnneeded = newBitVect (mcs51_nRegs);
3918   while (lnp)
3919     {
3920       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3921         {
3922           if (!strncmp(lnp->line, "push", 4))
3923             {
3924               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3925               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3926                 {
3927                   connectLine (lnp->prev, lnp->next);
3928                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3929                 }
3930             }
3931           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3932             {
3933               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3934               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3935                 {
3936                   connectLine (lnp->prev, lnp->next);
3937                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3938                 }
3939             }
3940         }
3941       lnp = lnp->next;
3942     }
3943
3944   for (idx = 0; idx < regsUnneeded->size; idx++)
3945     if (bitVectBitValue (regsUnneeded, idx))
3946       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
3947
3948   freeBitVect (regsUnneeded);
3949   freeBitVect (regsUsed);
3950   freeBitVect (regsUsedPrologue);
3951 }
3952
3953 /*-----------------------------------------------------------------*/
3954 /* genRet - generate code for return statement                     */
3955 /*-----------------------------------------------------------------*/
3956 static void
3957 genRet (iCode * ic)
3958 {
3959   int size, offset = 0, pushed = 0;
3960
3961   D (emitcode (";", "genRet"));
3962
3963   /* if we have no return value then
3964      just generate the "ret" */
3965   if (!IC_LEFT (ic))
3966     goto jumpret;
3967
3968   /* we have something to return then
3969      move the return value into place */
3970   aopOp (IC_LEFT (ic), ic, FALSE);
3971   size = AOP_SIZE (IC_LEFT (ic));
3972
3973   if (IS_BIT(_G.currentFunc->etype))
3974     {
3975       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3976       size = 0;
3977     }
3978
3979   while (size--)
3980     {
3981       char *l;
3982       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3983         {
3984           /* #NOCHANGE */
3985           l = aopGet (IC_LEFT (ic), offset++,
3986                       FALSE, TRUE);
3987           emitcode ("push", "%s", l);
3988           pushed++;
3989         }
3990       else
3991         {
3992           l = aopGet (IC_LEFT (ic), offset,
3993                       FALSE, FALSE);
3994           if (strcmp (fReturn[offset], l))
3995             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3996         }
3997     }
3998
3999   while (pushed)
4000     {
4001       pushed--;
4002       if (strcmp (fReturn[pushed], "a"))
4003         emitcode ("pop", fReturn[pushed]);
4004       else
4005         emitcode ("pop", "acc");
4006     }
4007   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4008
4009 jumpret:
4010   /* generate a jump to the return label
4011      if the next is not the return statement */
4012   if (!(ic->next && ic->next->op == LABEL &&
4013         IC_LABEL (ic->next) == returnLabel))
4014
4015     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4016
4017 }
4018
4019 /*-----------------------------------------------------------------*/
4020 /* genLabel - generates a label                                    */
4021 /*-----------------------------------------------------------------*/
4022 static void
4023 genLabel (iCode * ic)
4024 {
4025   /* special case never generate */
4026   if (IC_LABEL (ic) == entryLabel)
4027     return;
4028
4029   emitLabel (IC_LABEL (ic));
4030 }
4031
4032 /*-----------------------------------------------------------------*/
4033 /* genGoto - generates a ljmp                                      */
4034 /*-----------------------------------------------------------------*/
4035 static void
4036 genGoto (iCode * ic)
4037 {
4038   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4039 }
4040
4041 /*-----------------------------------------------------------------*/
4042 /* findLabelBackwards: walks back through the iCode chain looking  */
4043 /* for the given label. Returns number of iCode instructions     */
4044 /* between that label and given ic.          */
4045 /* Returns zero if label not found.          */
4046 /*-----------------------------------------------------------------*/
4047 static int
4048 findLabelBackwards (iCode * ic, int key)
4049 {
4050   int count = 0;
4051
4052   while (ic->prev)
4053     {
4054       ic = ic->prev;
4055       count++;
4056
4057       /* If we have any pushes or pops, we cannot predict the distance.
4058          I don't like this at all, this should be dealt with in the
4059          back-end */
4060       if (ic->op == IPUSH || ic->op == IPOP) {
4061         return 0;
4062       }
4063
4064       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4065         {
4066           return count;
4067         }
4068     }
4069
4070   return 0;
4071 }
4072
4073 /*-----------------------------------------------------------------*/
4074 /* genPlusIncr :- does addition with increment if possible         */
4075 /*-----------------------------------------------------------------*/
4076 static bool
4077 genPlusIncr (iCode * ic)
4078 {
4079   unsigned int icount;
4080   unsigned int size = getDataSize (IC_RESULT (ic));
4081
4082   /* will try to generate an increment */
4083   /* if the right side is not a literal
4084      we cannot */
4085   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4086     return FALSE;
4087
4088   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4089
4090   D(emitcode (";","genPlusIncr"));
4091
4092   /* if increment >=16 bits in register or direct space */
4093   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4094         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4095         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4096       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4097       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4098       (size > 1) &&
4099       (icount == 1))
4100     {
4101       symbol *tlbl;
4102       int emitTlbl;
4103       int labelRange;
4104
4105       /* If the next instruction is a goto and the goto target
4106        * is < 10 instructions previous to this, we can generate
4107        * jumps straight to that target.
4108        */
4109       if (ic->next && ic->next->op == GOTO
4110           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4111           && labelRange <= 10)
4112         {
4113           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4114           tlbl = IC_LABEL (ic->next);
4115           emitTlbl = 0;
4116         }
4117       else
4118         {
4119           tlbl = newiTempLabel (NULL);
4120           emitTlbl = 1;
4121         }
4122       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4123       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4124           IS_AOP_PREG (IC_RESULT (ic)))
4125         emitcode ("cjne", "%s,#0x00,%05d$",
4126                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4127                   tlbl->key + 100);
4128       else
4129         {
4130           emitcode ("clr", "a");
4131           emitcode ("cjne", "a,%s,%05d$",
4132                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4133                     tlbl->key + 100);
4134         }
4135
4136       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4137       if (size > 2)
4138         {
4139           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4140               IS_AOP_PREG (IC_RESULT (ic)))
4141             emitcode ("cjne", "%s,#0x00,%05d$",
4142                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4143                       tlbl->key + 100);
4144           else
4145             emitcode ("cjne", "a,%s,%05d$",
4146                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4147                       tlbl->key + 100);
4148
4149           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4150         }
4151       if (size > 3)
4152         {
4153           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4154               IS_AOP_PREG (IC_RESULT (ic)))
4155             emitcode ("cjne", "%s,#0x00,%05d$",
4156                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4157                       tlbl->key + 100);
4158           else
4159             {
4160               emitcode ("cjne", "a,%s,%05d$",
4161                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4162                         tlbl->key + 100);
4163             }
4164           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4165         }
4166
4167       if (emitTlbl)
4168         {
4169           emitLabel (tlbl);
4170         }
4171       return TRUE;
4172     }
4173
4174   /* if result is dptr */
4175   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4176       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4177       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4178       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4179     {
4180       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4181         return FALSE;
4182
4183       if (icount > 9)
4184         return FALSE;
4185
4186       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4187         return FALSE;
4188
4189       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4190       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4191       while (icount--)
4192         emitcode ("inc", "dptr");
4193
4194       return TRUE;
4195     }
4196
4197   /* if the literal value of the right hand side
4198      is greater than 4 then it is not worth it */
4199   if (icount > 4)
4200     return FALSE;
4201
4202   /* if the sizes are greater than 1 then we cannot */
4203   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4204       AOP_SIZE (IC_LEFT (ic)) > 1)
4205     return FALSE;
4206
4207   /* we can if the aops of the left & result match or
4208      if they are in registers and the registers are the
4209      same */
4210   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4211     {
4212       if (icount > 3)
4213         {
4214           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4215           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4216           aopPut (IC_RESULT (ic), "a", 0);
4217         }
4218       else
4219         {
4220           while (icount--)
4221             {
4222               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4223             }
4224         }
4225
4226       return TRUE;
4227     }
4228
4229   if (icount == 1)
4230     {
4231       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4232       emitcode ("inc", "a");
4233       aopPut (IC_RESULT (ic), "a", 0);
4234       return TRUE;
4235     }
4236
4237   return FALSE;
4238 }
4239
4240 /*-----------------------------------------------------------------*/
4241 /* outBitAcc - output a bit in acc                                 */
4242 /*-----------------------------------------------------------------*/
4243 static void
4244 outBitAcc (operand * result)
4245 {
4246   symbol *tlbl = newiTempLabel (NULL);
4247   /* if the result is a bit */
4248   if (AOP_TYPE (result) == AOP_CRY)
4249     {
4250       aopPut (result, "a", 0);
4251     }
4252   else
4253     {
4254       emitcode ("jz", "%05d$", tlbl->key + 100);
4255       emitcode ("mov", "a,%s", one);
4256       emitLabel (tlbl);
4257       outAcc (result);
4258     }
4259 }
4260
4261 /*-----------------------------------------------------------------*/
4262 /* genPlusBits - generates code for addition of two bits           */
4263 /*-----------------------------------------------------------------*/
4264 static void
4265 genPlusBits (iCode * ic)
4266 {
4267   D (emitcode (";", "genPlusBits"));
4268
4269   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4270     {
4271       symbol *lbl = newiTempLabel (NULL);
4272       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4273       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4274       emitcode ("cpl", "c");
4275       emitLabel (lbl);
4276       outBitC (IC_RESULT (ic));
4277     }
4278   else
4279     {
4280       emitcode ("clr", "a");
4281       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4282       emitcode ("rlc", "a");
4283       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4284       emitcode ("addc", "a,%s", zero);
4285       outAcc (IC_RESULT (ic));
4286     }
4287 }
4288
4289 #if 0
4290 /* This is the original version of this code.
4291
4292  * This is being kept around for reference,
4293  * because I am not entirely sure I got it right...
4294  */
4295 static void
4296 adjustArithmeticResult (iCode * ic)
4297 {
4298   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4299       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4300       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4301     aopPut (IC_RESULT (ic),
4302             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4303             2);
4304
4305   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4306       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4307       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4308     aopPut (IC_RESULT (ic),
4309             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4310             2);
4311
4312   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4313       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4314       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4315       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4316       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4317     {
4318       char buffer[5];
4319       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4320       aopPut (IC_RESULT (ic), buffer, 2);
4321     }
4322 }
4323 #else
4324 /* This is the pure and virtuous version of this code.
4325  * I'm pretty certain it's right, but not enough to toss the old
4326  * code just yet...
4327  */
4328 static void
4329 adjustArithmeticResult (iCode * ic)
4330 {
4331   if (opIsGptr (IC_RESULT (ic)) &&
4332       opIsGptr (IC_LEFT (ic)) &&
4333       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4334     {
4335       aopPut (IC_RESULT (ic),
4336               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4337               GPTRSIZE - 1);
4338     }
4339
4340   if (opIsGptr (IC_RESULT (ic)) &&
4341       opIsGptr (IC_RIGHT (ic)) &&
4342       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4343     {
4344       aopPut (IC_RESULT (ic),
4345               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4346               GPTRSIZE - 1);
4347     }
4348
4349   if (opIsGptr (IC_RESULT (ic)) &&
4350       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4351       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4352       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4353       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4354     {
4355       char buffer[5];
4356       SNPRINTF (buffer, sizeof(buffer),
4357                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4358       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4359     }
4360 }
4361 #endif
4362
4363 /*-----------------------------------------------------------------*/
4364 /* genPlus - generates code for addition                           */
4365 /*-----------------------------------------------------------------*/
4366 static void
4367 genPlus (iCode * ic)
4368 {
4369   int size, offset = 0;
4370   int skip_bytes = 0;
4371   char *add = "add";
4372   bool swappedLR = FALSE;
4373   operand *leftOp, *rightOp;
4374   operand * op;
4375
4376   D (emitcode (";", "genPlus"));
4377
4378   /* special cases :- */
4379
4380   aopOp (IC_LEFT (ic), ic, FALSE);
4381   aopOp (IC_RIGHT (ic), ic, FALSE);
4382   aopOp (IC_RESULT (ic), ic, TRUE);
4383
4384   /* if literal, literal on the right or
4385      if left requires ACC or right is already
4386      in ACC */
4387   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4388       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4389       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4390     {
4391       operand *t = IC_RIGHT (ic);
4392       IC_RIGHT (ic) = IC_LEFT (ic);
4393       IC_LEFT (ic) = t;
4394       swappedLR = TRUE;
4395     }
4396
4397   /* if both left & right are in bit
4398      space */
4399   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4400       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4401     {
4402       genPlusBits (ic);
4403       goto release;
4404     }
4405
4406   /* if left in bit space & right literal */
4407   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4408       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4409     {
4410       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4411       /* if result in bit space */
4412       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4413         {
4414           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4415             emitcode ("cpl", "c");
4416           outBitC (IC_RESULT (ic));
4417         }
4418       else
4419         {
4420           size = getDataSize (IC_RESULT (ic));
4421           while (size--)
4422             {
4423               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4424               emitcode ("addc", "a,%s", zero);
4425               aopPut (IC_RESULT (ic), "a", offset++);
4426             }
4427         }
4428       goto release;
4429     }
4430
4431   /* if I can do an increment instead
4432      of add then GOOD for ME */
4433   if (genPlusIncr (ic) == TRUE)
4434     goto release;
4435
4436   size = getDataSize (IC_RESULT (ic));
4437   leftOp = IC_LEFT(ic);
4438   rightOp = IC_RIGHT(ic);
4439   op = IC_LEFT(ic);
4440
4441   /* if this is an add for an array access
4442      at a 256 byte boundary */
4443   if ( 2 == size
4444        && AOP_TYPE (op) == AOP_IMMD
4445        && IS_SYMOP (op)
4446        && IS_SPEC (OP_SYM_ETYPE (op))
4447        && SPEC_ABSA (OP_SYM_ETYPE (op))
4448        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4449      )
4450     {
4451       D(emitcode (";     genPlus aligned array",""));
4452       aopPut (IC_RESULT (ic),
4453               aopGet (rightOp, 0, FALSE, FALSE),
4454               0);
4455
4456       if( 1 == getDataSize (IC_RIGHT (ic)) )
4457         {
4458           aopPut (IC_RESULT (ic),
4459                   aopGet (leftOp, 1, FALSE, FALSE),
4460                   1);
4461         }
4462       else
4463         {
4464           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4465           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4466           aopPut (IC_RESULT (ic), "a", 1);
4467         }
4468       goto release;
4469     }
4470
4471   /* if the lower bytes of a literal are zero skip the addition */
4472   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4473     {
4474        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4475               (skip_bytes+1 < size))
4476          {
4477            skip_bytes++;
4478          }
4479        if (skip_bytes)
4480          D(emitcode (";     genPlus shortcut",""));
4481     }
4482
4483   while (size--)
4484     {
4485       if( offset >= skip_bytes )
4486         {
4487           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4488             {
4489               bool pushedB;
4490               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4491               pushedB = pushB ();
4492               emitcode("xch", "a,b");
4493               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4494               emitcode (add, "a,b");
4495               popB (pushedB);
4496             }
4497           else if (aopGetUsesAcc (leftOp, offset))
4498             {
4499               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4500               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4501             }
4502           else
4503             {
4504               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4505               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4506             }
4507           aopPut (IC_RESULT (ic), "a", offset);
4508           add = "addc";  /* further adds must propagate carry */
4509         }
4510       else
4511         {
4512           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4513               isOperandVolatile (IC_RESULT (ic), FALSE))
4514             {
4515               /* just move */
4516               aopPut (IC_RESULT (ic),
4517                       aopGet (leftOp, offset, FALSE, FALSE),
4518                       offset);
4519             }
4520         }
4521       offset++;
4522     }
4523
4524   adjustArithmeticResult (ic);
4525
4526 release:
4527   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4528   if (!swappedLR)
4529     {
4530       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4531       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4532     }
4533   else
4534     {
4535       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4536       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4537     }
4538 }
4539
4540 /*-----------------------------------------------------------------*/
4541 /* genMinusDec :- does subtraction with decrement if possible      */
4542 /*-----------------------------------------------------------------*/
4543 static bool
4544 genMinusDec (iCode * ic)
4545 {
4546   unsigned int icount;
4547   unsigned int size = getDataSize (IC_RESULT (ic));
4548
4549   /* will try to generate an increment */
4550   /* if the right side is not a literal
4551      we cannot */
4552   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4553     return FALSE;
4554
4555   /* if the literal value of the right hand side
4556      is greater than 4 then it is not worth it */
4557   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4558     return FALSE;
4559
4560   D (emitcode (";", "genMinusDec"));
4561
4562   /* if decrement >=16 bits in register or direct space */
4563   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4564         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4565         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4566       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4567       (size > 1) &&
4568       (icount == 1))
4569     {
4570       symbol *tlbl;
4571       int emitTlbl;
4572       int labelRange;
4573
4574       /* If the next instruction is a goto and the goto target
4575        * is <= 10 instructions previous to this, we can generate
4576        * jumps straight to that target.
4577        */
4578       if (ic->next && ic->next->op == GOTO
4579           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4580           && labelRange <= 10)
4581         {
4582           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4583           tlbl = IC_LABEL (ic->next);
4584           emitTlbl = 0;
4585         }
4586       else
4587         {
4588           tlbl = newiTempLabel (NULL);
4589           emitTlbl = 1;
4590         }
4591
4592       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4593       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4594           IS_AOP_PREG (IC_RESULT (ic)))
4595         emitcode ("cjne", "%s,#0xff,%05d$"
4596                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4597                   ,tlbl->key + 100);
4598       else
4599         {
4600           emitcode ("mov", "a,#0xff");
4601           emitcode ("cjne", "a,%s,%05d$"
4602                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4603                     ,tlbl->key + 100);
4604         }
4605       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4606       if (size > 2)
4607         {
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), MSB16, FALSE, FALSE)
4612                       ,tlbl->key + 100);
4613           else
4614             {
4615               emitcode ("cjne", "a,%s,%05d$"
4616                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4617                         ,tlbl->key + 100);
4618             }
4619           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4620         }
4621       if (size > 3)
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), MSB24, FALSE, FALSE)
4627                       ,tlbl->key + 100);
4628           else
4629             {
4630               emitcode ("cjne", "a,%s,%05d$"
4631                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4632                         ,tlbl->key + 100);
4633             }
4634           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4635         }
4636       if (emitTlbl)
4637         {
4638           emitLabel (tlbl);
4639         }
4640       return TRUE;
4641     }
4642
4643   /* if the sizes are greater than 1 then we cannot */
4644   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4645       AOP_SIZE (IC_LEFT (ic)) > 1)
4646     return FALSE;
4647
4648   /* we can if the aops of the left & result match or
4649      if they are in registers and the registers are the
4650      same */
4651   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4652     {
4653       char *l;
4654
4655       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4656         {
4657           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4658           l = "a";
4659         }
4660       else
4661         {
4662           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4663         }
4664
4665       while (icount--)
4666         {
4667           emitcode ("dec", "%s", l);
4668         }
4669
4670       if (AOP_NEEDSACC (IC_RESULT (ic)))
4671         aopPut (IC_RESULT (ic), "a", 0);
4672
4673       return TRUE;
4674     }
4675
4676   if (icount == 1)
4677     {
4678       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4679       emitcode ("dec", "a");
4680       aopPut (IC_RESULT (ic), "a", 0);
4681       return TRUE;
4682     }
4683
4684   return FALSE;
4685 }
4686
4687 /*-----------------------------------------------------------------*/
4688 /* addSign - complete with sign                                    */
4689 /*-----------------------------------------------------------------*/
4690 static void
4691 addSign (operand * result, int offset, int sign)
4692 {
4693   int size = (getDataSize (result) - offset);
4694   if (size > 0)
4695     {
4696       if (sign)
4697         {
4698           emitcode ("rlc", "a");
4699           emitcode ("subb", "a,acc");
4700           while (size--)
4701             {
4702               aopPut (result, "a", offset++);
4703             }
4704         }
4705       else
4706         {
4707           while (size--)
4708             {
4709               aopPut (result, zero, offset++);
4710             }
4711         }
4712     }
4713 }
4714
4715 /*-----------------------------------------------------------------*/
4716 /* genMinusBits - generates code for subtraction  of two bits      */
4717 /*-----------------------------------------------------------------*/
4718 static void
4719 genMinusBits (iCode * ic)
4720 {
4721   symbol *lbl = newiTempLabel (NULL);
4722
4723   D (emitcode (";", "genMinusBits"));
4724
4725   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4726     {
4727       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4728       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4729       emitcode ("cpl", "c");
4730       emitLabel (lbl);
4731       outBitC (IC_RESULT (ic));
4732     }
4733   else
4734     {
4735       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4736       emitcode ("subb", "a,acc");
4737       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4738       emitcode ("inc", "a");
4739       emitLabel (lbl);
4740       aopPut (IC_RESULT (ic), "a", 0);
4741       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4742     }
4743 }
4744
4745 /*-----------------------------------------------------------------*/
4746 /* genMinus - generates code for subtraction                       */
4747 /*-----------------------------------------------------------------*/
4748 static void
4749 genMinus (iCode * ic)
4750 {
4751   int size, offset = 0;
4752
4753   D (emitcode (";", "genMinus"));
4754
4755   aopOp (IC_LEFT (ic), ic, FALSE);
4756   aopOp (IC_RIGHT (ic), ic, FALSE);
4757   aopOp (IC_RESULT (ic), ic, TRUE);
4758
4759   /* special cases :- */
4760   /* if both left & right are in bit space */
4761   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4762       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4763     {
4764       genMinusBits (ic);
4765       goto release;
4766     }
4767
4768   /* if I can do an decrement instead
4769      of subtract then GOOD for ME */
4770   if (genMinusDec (ic) == TRUE)
4771     goto release;
4772
4773   size = getDataSize (IC_RESULT (ic));
4774
4775   /* if literal, add a,#-lit, else normal subb */
4776   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4777     {
4778       unsigned long lit = 0L;
4779       bool useCarry = FALSE;
4780
4781       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4782       lit = -(long) lit;
4783
4784       while (size--)
4785         {
4786           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4787             {
4788               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4789               if (!offset && !size && lit== (unsigned long) -1)
4790                 {
4791                   emitcode ("dec", "a");
4792                 }
4793               else if (!useCarry)
4794                 {
4795                   /* first add without previous c */
4796                   emitcode ("add", "a,#0x%02x",
4797                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4798                   useCarry = TRUE;
4799                 }
4800               else
4801                 {
4802                   emitcode ("addc", "a,#0x%02x",
4803                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4804                 }
4805               aopPut (IC_RESULT (ic), "a", offset++);
4806             }
4807           else
4808             {
4809               /* no need to add zeroes */
4810               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4811                 {
4812                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4813                           offset);
4814                 }
4815               offset++;
4816             }
4817         }
4818     }
4819   else
4820     {
4821       operand *leftOp, *rightOp;
4822
4823       leftOp = IC_LEFT(ic);
4824       rightOp = IC_RIGHT(ic);
4825
4826       while (size--)
4827         {
4828           if (aopGetUsesAcc(rightOp, offset)) {
4829             if (aopGetUsesAcc(leftOp, offset)) {
4830               bool pushedB;
4831
4832               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4833               pushedB = pushB ();
4834               emitcode ("mov", "b,a");
4835               if (offset == 0)
4836                 CLRC;
4837               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4838               emitcode ("subb", "a,b");
4839               popB (pushedB);
4840             } else {
4841               /* reverse subtraction with 2's complement */
4842               if (offset == 0)
4843                 emitcode( "setb", "c");
4844               else
4845                 emitcode( "cpl", "c");
4846               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4847               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4848               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4849               emitcode("cpl", "a");
4850               if (size) /* skip if last byte */
4851                 emitcode( "cpl", "c");
4852             }
4853           } else {
4854             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4855             if (offset == 0)
4856               CLRC;
4857             emitcode ("subb", "a,%s",
4858                       aopGet(rightOp, offset, FALSE, TRUE));
4859           }
4860
4861           aopPut (IC_RESULT (ic), "a", offset++);
4862         }
4863     }
4864
4865   adjustArithmeticResult (ic);
4866
4867 release:
4868   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4869   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4870   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4871 }
4872
4873
4874 /*-----------------------------------------------------------------*/
4875 /* genMultbits :- multiplication of bits                           */
4876 /*-----------------------------------------------------------------*/
4877 static void
4878 genMultbits (operand * left,
4879              operand * right,
4880              operand * result)
4881 {
4882   D (emitcode (";", "genMultbits"));
4883
4884   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4885   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4886   outBitC (result);
4887 }
4888
4889 /*-----------------------------------------------------------------*/
4890 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4891 /*-----------------------------------------------------------------*/
4892 static void
4893 genMultOneByte (operand * left,
4894                 operand * right,
4895                 operand * result)
4896 {
4897   symbol *lbl;
4898   int size = AOP_SIZE (result);
4899   bool runtimeSign, compiletimeSign;
4900   bool lUnsigned, rUnsigned, pushedB;
4901
4902   D (emitcode (";", "genMultOneByte"));
4903
4904   if (size < 1 || size > 2)
4905     {
4906       /* this should never happen */
4907       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4908                AOP_SIZE(result), __FILE__, lineno);
4909       exit (1);
4910     }
4911
4912   /* (if two literals: the value is computed before) */
4913   /* if one literal, literal on the right */
4914   if (AOP_TYPE (left) == AOP_LIT)
4915     {
4916       operand *t = right;
4917       right = left;
4918       left = t;
4919       /* emitcode (";", "swapped left and right"); */
4920     }
4921   /* if no literal, unsigned on the right: shorter code */
4922   if (   AOP_TYPE (right) != AOP_LIT
4923       && SPEC_USIGN (getSpec (operandType (left))))
4924     {
4925       operand *t = right;
4926       right = left;
4927       left = t;
4928     }
4929
4930   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4931   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4932
4933   pushedB = pushB ();
4934
4935   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4936                    no need to take care about the signedness! */
4937       || (lUnsigned && rUnsigned))
4938     {
4939       /* just an unsigned 8 * 8 = 8 multiply
4940          or 8u * 8u = 16u */
4941       /* emitcode (";","unsigned"); */
4942       /* TODO: check for accumulator clash between left & right aops? */
4943
4944       if (AOP_TYPE (right) == AOP_LIT)
4945         {
4946           /* moving to accumulator first helps peepholes */
4947           MOVA (aopGet (left, 0, FALSE, FALSE));
4948           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4949         }
4950       else
4951         {
4952           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4953           MOVA (aopGet (left, 0, FALSE, FALSE));
4954         }
4955
4956       emitcode ("mul", "ab");
4957       aopPut (result, "a", 0);
4958       if (size == 2)
4959         aopPut (result, "b", 1);
4960
4961       popB (pushedB);
4962       return;
4963     }
4964
4965   /* we have to do a signed multiply */
4966   /* emitcode (";", "signed"); */
4967
4968   /* now sign adjust for both left & right */
4969
4970   /* let's see what's needed: */
4971   /* apply negative sign during runtime */
4972   runtimeSign = FALSE;
4973   /* negative sign from literals */
4974   compiletimeSign = FALSE;
4975
4976   if (!lUnsigned)
4977     {
4978       if (AOP_TYPE(left) == AOP_LIT)
4979         {
4980           /* signed literal */
4981           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4982           if (val < 0)
4983             compiletimeSign = TRUE;
4984         }
4985       else
4986         /* signed but not literal */
4987         runtimeSign = TRUE;
4988     }
4989
4990   if (!rUnsigned)
4991     {
4992       if (AOP_TYPE(right) == AOP_LIT)
4993         {
4994           /* signed literal */
4995           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4996           if (val < 0)
4997             compiletimeSign ^= TRUE;
4998         }
4999       else
5000         /* signed but not literal */
5001         runtimeSign = TRUE;
5002     }
5003
5004   /* initialize F0, which stores the runtime sign */
5005   if (runtimeSign)
5006     {
5007       if (compiletimeSign)
5008         emitcode ("setb", "F0"); /* set sign flag */
5009       else
5010         emitcode ("clr", "F0"); /* reset sign flag */
5011     }
5012
5013   /* save the signs of the operands */
5014   if (AOP_TYPE(right) == AOP_LIT)
5015     {
5016       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5017
5018       if (!rUnsigned && val < 0)
5019         emitcode ("mov", "b,#0x%02x", -val);
5020       else
5021         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5022     }
5023   else /* ! literal */
5024     {
5025       if (rUnsigned)  /* emitcode (";", "signed"); */
5026         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5027       else
5028         {
5029           MOVA (aopGet (right, 0, FALSE, FALSE));
5030           lbl = newiTempLabel (NULL);
5031           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5032           emitcode ("cpl", "F0"); /* complement sign flag */
5033           emitcode ("cpl", "a");  /* 2's complement */
5034           emitcode ("inc", "a");
5035           emitLabel (lbl);
5036           emitcode ("mov", "b,a");
5037         }
5038     }
5039
5040   if (AOP_TYPE(left) == AOP_LIT)
5041     {
5042       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5043
5044       if (!lUnsigned && val < 0)
5045         emitcode ("mov", "a,#0x%02x", -val);
5046       else
5047         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5048     }
5049   else /* ! literal */
5050     {
5051       MOVA (aopGet (left, 0, FALSE, FALSE));
5052
5053       if (!lUnsigned)
5054         {
5055           lbl = newiTempLabel (NULL);
5056           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5057           emitcode ("cpl", "F0"); /* complement sign flag */
5058           emitcode ("cpl", "a"); /* 2's complement */
5059           emitcode ("inc", "a");
5060           emitLabel (lbl);
5061         }
5062     }
5063
5064   /* now the multiplication */
5065   emitcode ("mul", "ab");
5066   if (runtimeSign || compiletimeSign)
5067     {
5068       lbl = newiTempLabel (NULL);
5069       if (runtimeSign)
5070         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5071       emitcode ("cpl", "a"); /* lsb 2's complement */
5072       if (size != 2)
5073         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5074       else
5075         {
5076           emitcode ("add", "a,#1"); /* this sets carry flag */
5077           emitcode ("xch", "a,b");
5078           emitcode ("cpl", "a"); /* msb 2's complement */
5079           emitcode ("addc", "a,#0");
5080           emitcode ("xch", "a,b");
5081         }
5082       emitLabel (lbl);
5083     }
5084   aopPut (result, "a", 0);
5085   if (size == 2)
5086     aopPut (result, "b", 1);
5087
5088   popB (pushedB);
5089 }
5090
5091 /*-----------------------------------------------------------------*/
5092 /* genMult - generates code for multiplication                     */
5093 /*-----------------------------------------------------------------*/
5094 static void
5095 genMult (iCode * ic)
5096 {
5097   operand *left = IC_LEFT (ic);
5098   operand *right = IC_RIGHT (ic);
5099   operand *result = IC_RESULT (ic);
5100
5101   D (emitcode (";", "genMult"));
5102
5103   /* assign the asmops */
5104   aopOp (left, ic, FALSE);
5105   aopOp (right, ic, FALSE);
5106   aopOp (result, ic, TRUE);
5107
5108   /* special cases first */
5109   /* both are bits */
5110   if (AOP_TYPE (left) == AOP_CRY &&
5111       AOP_TYPE (right) == AOP_CRY)
5112     {
5113       genMultbits (left, right, result);
5114       goto release;
5115     }
5116
5117   /* if both are of size == 1 */
5118 #if 0 // one of them can be a sloc shared with the result
5119     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5120 #else
5121   if (getSize(operandType(left)) == 1 &&
5122       getSize(operandType(right)) == 1)
5123 #endif
5124     {
5125       genMultOneByte (left, right, result);
5126       goto release;
5127     }
5128
5129   /* should have been converted to function call */
5130     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5131              getSize(OP_SYMBOL(right)->type));
5132   assert (0);
5133
5134 release:
5135   freeAsmop (result, NULL, ic, TRUE);
5136   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5137   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5138 }
5139
5140 /*-----------------------------------------------------------------*/
5141 /* genDivbits :- division of bits                                  */
5142 /*-----------------------------------------------------------------*/
5143 static void
5144 genDivbits (operand * left,
5145             operand * right,
5146             operand * result)
5147 {
5148   char *l;
5149   bool pushedB;
5150
5151   D(emitcode (";     genDivbits",""));
5152
5153   pushedB = pushB ();
5154
5155   /* the result must be bit */
5156   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5157   l = aopGet (left, 0, FALSE, FALSE);
5158
5159   MOVA (l);
5160
5161   emitcode ("div", "ab");
5162   emitcode ("rrc", "a");
5163
5164   popB (pushedB);
5165
5166   aopPut (result, "c", 0);
5167 }
5168
5169 /*-----------------------------------------------------------------*/
5170 /* genDivOneByte : 8 bit division                                  */
5171 /*-----------------------------------------------------------------*/
5172 static void
5173 genDivOneByte (operand * left,
5174                operand * right,
5175                operand * result)
5176 {
5177   bool lUnsigned, rUnsigned, pushedB;
5178   bool runtimeSign, compiletimeSign;
5179   bool accuse = FALSE;
5180   bool pushedA = FALSE;
5181   symbol *lbl;
5182   int size, offset;
5183
5184   D(emitcode (";     genDivOneByte",""));
5185
5186   /* Why is it necessary that genDivOneByte() can return an int result?
5187      Have a look at:
5188
5189         volatile unsigned char uc;
5190         volatile signed char sc1, sc2;
5191         volatile int i;
5192
5193         uc  = 255;
5194         sc1 = -1;
5195         i = uc / sc1;
5196
5197      Or:
5198
5199         sc1 = -128;
5200         sc2 = -1;
5201         i = sc1 / sc2;
5202
5203      In all cases a one byte result would overflow, the following cast to int
5204      would return the wrong result.
5205
5206      Two possible solution:
5207         a) cast operands to int, if ((unsigned) / (signed)) or
5208            ((signed) / (signed))
5209         b) return an 16 bit signed int; this is what we're doing here!
5210   */
5211
5212   size = AOP_SIZE (result) - 1;
5213   offset = 1;
5214   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5215   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5216
5217   pushedB = pushB ();
5218
5219   /* signed or unsigned */
5220   if (lUnsigned && rUnsigned)
5221     {
5222       /* unsigned is easy */
5223       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5224       MOVA (aopGet (left, 0, FALSE, FALSE));
5225       emitcode ("div", "ab");
5226       aopPut (result, "a", 0);
5227       while (size--)
5228         aopPut (result, zero, offset++);
5229
5230       popB (pushedB);
5231       return;
5232     }
5233
5234   /* signed is a little bit more difficult */
5235
5236   /* now sign adjust for both left & right */
5237
5238   /* let's see what's needed: */
5239   /* apply negative sign during runtime */
5240   runtimeSign = FALSE;
5241   /* negative sign from literals */
5242   compiletimeSign = FALSE;
5243
5244   if (!lUnsigned)
5245     {
5246       if (AOP_TYPE(left) == AOP_LIT)
5247         {
5248           /* signed literal */
5249           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5250           if (val < 0)
5251             compiletimeSign = TRUE;
5252         }
5253       else
5254         /* signed but not literal */
5255         runtimeSign = TRUE;
5256     }
5257
5258   if (!rUnsigned)
5259     {
5260       if (AOP_TYPE(right) == AOP_LIT)
5261         {
5262           /* signed literal */
5263           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5264           if (val < 0)
5265             compiletimeSign ^= TRUE;
5266         }
5267       else
5268         /* signed but not literal */
5269         runtimeSign = TRUE;
5270     }
5271
5272   /* initialize F0, which stores the runtime sign */
5273   if (runtimeSign)
5274     {
5275       if (compiletimeSign)
5276         emitcode ("setb", "F0"); /* set sign flag */
5277       else
5278         emitcode ("clr", "F0"); /* reset sign flag */
5279     }
5280
5281   /* save the signs of the operands */
5282   if (AOP_TYPE(right) == AOP_LIT)
5283     {
5284       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5285
5286       if (!rUnsigned && val < 0)
5287         emitcode ("mov", "b,#0x%02x", -val);
5288       else
5289         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5290     }
5291   else /* ! literal */
5292     {
5293       if (rUnsigned)
5294         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5295       else
5296         {
5297           MOVA (aopGet (right, 0, FALSE, FALSE));
5298           lbl = newiTempLabel (NULL);
5299           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5300           emitcode ("cpl", "F0"); /* complement sign flag */
5301           emitcode ("cpl", "a");  /* 2's complement */
5302           emitcode ("inc", "a");
5303           emitLabel (lbl);
5304           emitcode ("mov", "b,a");
5305         }
5306     }
5307
5308   if (AOP_TYPE(left) == AOP_LIT)
5309     {
5310       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5311
5312       if (!lUnsigned && val < 0)
5313         emitcode ("mov", "a,#0x%02x", -val);
5314       else
5315         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5316     }
5317   else /* ! literal */
5318     {
5319       MOVA (aopGet (left, 0, FALSE, FALSE));
5320
5321       if (!lUnsigned)
5322         {
5323           lbl = newiTempLabel (NULL);
5324           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5325           emitcode ("cpl", "F0"); /* complement sign flag */
5326           emitcode ("cpl", "a");  /* 2's complement */
5327           emitcode ("inc", "a");
5328           emitLabel (lbl);
5329         }
5330     }
5331
5332   /* now the division */
5333   emitcode ("div", "ab");
5334
5335   if (runtimeSign || compiletimeSign)
5336     {
5337       lbl = newiTempLabel (NULL);
5338       if (runtimeSign)
5339         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5340       emitcode ("cpl", "a"); /* lsb 2's complement */
5341       emitcode ("inc", "a");
5342       emitLabel (lbl);
5343
5344       accuse = aopPut (result, "a", 0);
5345       if (size > 0)
5346         {
5347           /* msb is 0x00 or 0xff depending on the sign */
5348           if (runtimeSign)
5349             {
5350               if (accuse)
5351                 {
5352                   emitcode ("push", "acc");
5353                   pushedA = TRUE;
5354                 }
5355               emitcode ("mov", "c,F0");
5356               emitcode ("subb", "a,acc");
5357               while (size--)
5358                 aopPut (result, "a", offset++);
5359             }
5360           else /* compiletimeSign */
5361             {
5362               if (aopPutUsesAcc (result, "#0xFF", offset))
5363                 {
5364                   emitcode ("push", "acc");
5365                   pushedA = TRUE;
5366                 }
5367               while (size--)
5368                 aopPut (result, "#0xff", offset++);
5369             }
5370         }
5371     }
5372   else
5373     {
5374       aopPut (result, "a", 0);
5375       while (size--)
5376         aopPut (result, zero, offset++);
5377     }
5378
5379   if (pushedA)
5380     emitcode ("pop", "acc");
5381   popB (pushedB);
5382 }
5383
5384 /*-----------------------------------------------------------------*/
5385 /* genDiv - generates code for division                            */
5386 /*-----------------------------------------------------------------*/
5387 static void
5388 genDiv (iCode * ic)
5389 {
5390   operand *left = IC_LEFT (ic);
5391   operand *right = IC_RIGHT (ic);
5392   operand *result = IC_RESULT (ic);
5393
5394   D (emitcode (";", "genDiv"));
5395
5396   /* assign the amsops */
5397   aopOp (left, ic, FALSE);
5398   aopOp (right, ic, FALSE);
5399   aopOp (result, ic, TRUE);
5400
5401   /* special cases first */
5402   /* both are bits */
5403   if (AOP_TYPE (left) == AOP_CRY &&
5404       AOP_TYPE (right) == AOP_CRY)
5405     {
5406       genDivbits (left, right, result);
5407       goto release;
5408     }
5409
5410   /* if both are of size == 1 */
5411   if (AOP_SIZE (left) == 1 &&
5412       AOP_SIZE (right) == 1)
5413     {
5414       genDivOneByte (left, right, result);
5415       goto release;
5416     }
5417
5418   /* should have been converted to function call */
5419   assert (0);
5420 release:
5421   freeAsmop (result, NULL, ic, TRUE);
5422   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5424 }
5425
5426 /*-----------------------------------------------------------------*/
5427 /* genModbits :- modulus of bits                                   */
5428 /*-----------------------------------------------------------------*/
5429 static void
5430 genModbits (operand * left,
5431             operand * right,
5432             operand * result)
5433 {
5434   char *l;
5435   bool pushedB;
5436
5437   D (emitcode (";", "genModbits"));
5438
5439   pushedB = pushB ();
5440
5441   /* the result must be bit */
5442   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5443   l = aopGet (left, 0, FALSE, FALSE);
5444
5445   MOVA (l);
5446
5447   emitcode ("div", "ab");
5448   emitcode ("mov", "a,b");
5449   emitcode ("rrc", "a");
5450
5451   popB (pushedB);
5452
5453   aopPut (result, "c", 0);
5454 }
5455
5456 /*-----------------------------------------------------------------*/
5457 /* genModOneByte : 8 bit modulus                                   */
5458 /*-----------------------------------------------------------------*/
5459 static void
5460 genModOneByte (operand * left,
5461                operand * right,
5462                operand * result)
5463 {
5464   bool lUnsigned, rUnsigned, pushedB;
5465   bool runtimeSign, compiletimeSign;
5466   symbol *lbl;
5467   int size, offset;
5468
5469   D (emitcode (";", "genModOneByte"));
5470
5471   size = AOP_SIZE (result) - 1;
5472   offset = 1;
5473   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5474   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5475
5476   /* if right is a literal, check it for 2^n */
5477   if (AOP_TYPE(right) == AOP_LIT)
5478     {
5479       unsigned char val = abs((int) operandLitValue(right));
5480       symbol *lbl2 = NULL;
5481
5482       switch (val)
5483         {
5484           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5485           case 2:
5486           case 4:
5487           case 8:
5488           case 16:
5489           case 32:
5490           case 64:
5491           case 128:
5492             if (lUnsigned)
5493               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5494                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5495               /* because iCode should have been changed to genAnd  */
5496               /* see file "SDCCopt.c", function "convertToFcall()" */
5497
5498             MOVA (aopGet (left, 0, FALSE, FALSE));
5499             emitcode ("mov", "c,acc.7");
5500             emitcode ("anl", "a,#0x%02x", val - 1);
5501             lbl = newiTempLabel (NULL);
5502             emitcode ("jz", "%05d$", (lbl->key + 100));
5503             emitcode ("jnc", "%05d$", (lbl->key + 100));
5504             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5505             if (size)
5506               {
5507                 int size2 = size;
5508                 int offs2 = offset;
5509
5510                 aopPut (result, "a", 0);
5511                 while (size2--)
5512                   aopPut (result, "#0xff", offs2++);
5513                 lbl2 = newiTempLabel (NULL);
5514                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5515               }
5516             emitLabel (lbl);
5517             aopPut (result, "a", 0);
5518             while (size--)
5519               aopPut (result, zero, offset++);
5520             if (lbl2)
5521               {
5522                 emitLabel (lbl2);
5523               }
5524             return;
5525
5526           default:
5527             break;
5528         }
5529     }
5530
5531   pushedB = pushB ();
5532
5533   /* signed or unsigned */
5534   if (lUnsigned && rUnsigned)
5535     {
5536       /* unsigned is easy */
5537       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5538       MOVA (aopGet (left, 0, FALSE, FALSE));
5539       emitcode ("div", "ab");
5540       aopPut (result, "b", 0);
5541       while (size--)
5542         aopPut (result, zero, offset++);
5543
5544       popB (pushedB);
5545       return;
5546     }
5547
5548   /* signed is a little bit more difficult */
5549
5550   /* now sign adjust for both left & right */
5551
5552   /* modulus: sign of the right operand has no influence on the result! */
5553   if (AOP_TYPE(right) == AOP_LIT)
5554     {
5555       signed char val = (char) operandLitValue(right);
5556
5557       if (!rUnsigned && val < 0)
5558         emitcode ("mov", "b,#0x%02x", -val);
5559       else
5560         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5561     }
5562   else /* not literal */
5563     {
5564       if (rUnsigned)
5565         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5566       else
5567         {
5568           MOVA (aopGet (right, 0, FALSE, FALSE));
5569           lbl = newiTempLabel (NULL);
5570           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5571           emitcode ("cpl", "a"); /* 2's complement */
5572           emitcode ("inc", "a");
5573           emitLabel (lbl);
5574           emitcode ("mov", "b,a");
5575         }
5576     }
5577
5578   /* let's see what's needed: */
5579   /* apply negative sign during runtime */
5580   runtimeSign = FALSE;
5581   /* negative sign from literals */
5582   compiletimeSign = FALSE;
5583
5584   /* sign adjust left side */
5585   if (AOP_TYPE(left) == AOP_LIT)
5586     {
5587       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5588
5589       if (!lUnsigned && val < 0)
5590         {
5591           compiletimeSign = TRUE; /* set sign flag */
5592           emitcode ("mov", "a,#0x%02x", -val);
5593         }
5594       else
5595         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5596     }
5597   else /* ! literal */
5598     {
5599       MOVA (aopGet (left, 0, FALSE, FALSE));
5600
5601       if (!lUnsigned)
5602         {
5603           runtimeSign = TRUE;
5604           emitcode ("clr", "F0"); /* clear sign flag */
5605
5606           lbl = newiTempLabel (NULL);
5607           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5608           emitcode ("setb", "F0"); /* set sign flag */
5609           emitcode ("cpl", "a");   /* 2's complement */
5610           emitcode ("inc", "a");
5611           emitLabel (lbl);
5612         }
5613     }
5614
5615   /* now the modulus */
5616   emitcode ("div", "ab");
5617
5618   if (runtimeSign || compiletimeSign)
5619     {
5620       emitcode ("mov", "a,b");
5621       lbl = newiTempLabel (NULL);
5622       if (runtimeSign)
5623         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5624       emitcode ("cpl", "a"); /* 2's complement */
5625       emitcode ("inc", "a");
5626       emitLabel (lbl);
5627
5628       aopPut (result, "a", 0);
5629       if (size > 0)
5630         {
5631           /* msb is 0x00 or 0xff depending on the sign */
5632           if (runtimeSign)
5633             {
5634               emitcode ("mov", "c,F0");
5635               emitcode ("subb", "a,acc");
5636               while (size--)
5637                 aopPut (result, "a", offset++);
5638             }
5639           else /* compiletimeSign */
5640             while (size--)
5641               aopPut (result, "#0xff", offset++);
5642         }
5643     }
5644   else
5645     {
5646       aopPut (result, "b", 0);
5647       while (size--)
5648         aopPut (result, zero, offset++);
5649     }
5650
5651   popB (pushedB);
5652 }
5653
5654 /*-----------------------------------------------------------------*/
5655 /* genMod - generates code for division                            */
5656 /*-----------------------------------------------------------------*/
5657 static void
5658 genMod (iCode * ic)
5659 {
5660   operand *left = IC_LEFT (ic);
5661   operand *right = IC_RIGHT (ic);
5662   operand *result = IC_RESULT (ic);
5663
5664   D (emitcode (";", "genMod"));
5665
5666   /* assign the asmops */
5667   aopOp (left, ic, FALSE);
5668   aopOp (right, ic, FALSE);
5669   aopOp (result, ic, TRUE);
5670
5671   /* special cases first */
5672   /* both are bits */
5673   if (AOP_TYPE (left) == AOP_CRY &&
5674       AOP_TYPE (right) == AOP_CRY)
5675     {
5676       genModbits (left, right, result);
5677       goto release;
5678     }
5679
5680   /* if both are of size == 1 */
5681   if (AOP_SIZE (left) == 1 &&
5682       AOP_SIZE (right) == 1)
5683     {
5684       genModOneByte (left, right, result);
5685       goto release;
5686     }
5687
5688   /* should have been converted to function call */
5689   assert (0);
5690
5691 release:
5692   freeAsmop (result, NULL, ic, TRUE);
5693   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5694   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5695 }
5696
5697 /*-----------------------------------------------------------------*/
5698 /* genIfxJump :- will create a jump depending on the ifx           */
5699 /*-----------------------------------------------------------------*/
5700 static void
5701 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5702 {
5703   symbol *jlbl;
5704   symbol *tlbl = newiTempLabel (NULL);
5705   char *inst;
5706
5707   D (emitcode (";", "genIfxJump"));
5708
5709   /* if true label then we jump if condition
5710      supplied is true */
5711   if (IC_TRUE (ic))
5712     {
5713       jlbl = IC_TRUE (ic);
5714       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5715                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5716     }
5717   else
5718     {
5719       /* false label is present */
5720       jlbl = IC_FALSE (ic);
5721       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5722                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5723     }
5724   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5725     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5726   else
5727     emitcode (inst, "%05d$", tlbl->key + 100);
5728   freeForBranchAsmop (result);
5729   freeForBranchAsmop (right);
5730   freeForBranchAsmop (left);
5731   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5732   emitLabel (tlbl);
5733
5734   /* mark the icode as generated */
5735   ic->generated = 1;
5736 }
5737
5738 /*-----------------------------------------------------------------*/
5739 /* genCmp :- greater or less than comparison                       */
5740 /*-----------------------------------------------------------------*/
5741 static void
5742 genCmp (operand * left, operand * right,
5743         operand * result, iCode * ifx, int sign, iCode *ic)
5744 {
5745   int size, offset = 0;
5746   unsigned long lit = 0L;
5747   bool rightInB;
5748
5749   D (emitcode (";", "genCmp"));
5750
5751   /* if left & right are bit variables */
5752   if (AOP_TYPE (left) == AOP_CRY &&
5753       AOP_TYPE (right) == AOP_CRY)
5754     {
5755       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5756       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5757     }
5758   else
5759     {
5760       /* subtract right from left if at the
5761          end the carry flag is set then we know that
5762          left is greater than right */
5763       size = max (AOP_SIZE (left), AOP_SIZE (right));
5764
5765       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5766       if ((size == 1) && !sign &&
5767           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5768         {
5769           symbol *lbl = newiTempLabel (NULL);
5770           emitcode ("cjne", "%s,%s,%05d$",
5771                     aopGet (left, offset, FALSE, FALSE),
5772                     aopGet (right, offset, FALSE, FALSE),
5773                     lbl->key + 100);
5774           emitLabel (lbl);
5775         }
5776       else
5777         {
5778           if (AOP_TYPE (right) == AOP_LIT)
5779             {
5780               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5781               /* optimize if(x < 0) or if(x >= 0) */
5782               if (lit == 0L)
5783                 {
5784                   if (!sign)
5785                     {
5786                       CLRC;
5787                     }
5788                   else
5789                     {
5790                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5791                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5792                         {
5793                           genIfxJump (ifx, "acc.7", left, right, result);
5794                           freeAsmop (right, NULL, ic, TRUE);
5795                           freeAsmop (left, NULL, ic, TRUE);
5796
5797                           return;
5798                         }
5799                       else
5800                         {
5801                           emitcode ("rlc", "a");
5802                         }
5803                     }
5804                   goto release;
5805                 }
5806               else
5807                 {//nonzero literal
5808                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5809                   while (size && (bytelit == 0))
5810                     {
5811                       offset++;
5812                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5813                       size--;
5814                     }
5815                   CLRC;
5816                   while (size--)
5817                     {
5818                       MOVA (aopGet (left, offset, FALSE, FALSE));
5819                       if (sign && size == 0)
5820                         {
5821                           emitcode ("xrl", "a,#0x80");
5822                           emitcode ("subb", "a,#0x%02x",
5823                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5824                         }
5825                       else
5826                         {
5827                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5828                         }
5829                       offset++;
5830                     }
5831                   goto release;
5832                 }
5833             }
5834           CLRC;
5835           while (size--)
5836             {
5837               bool pushedB = FALSE;
5838               rightInB = aopGetUsesAcc(right, offset);
5839               if (rightInB)
5840                 {
5841                   pushedB = pushB ();
5842                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5843                 }
5844               MOVA (aopGet (left, offset, FALSE, FALSE));
5845               if (sign && size == 0)
5846                 {
5847                   emitcode ("xrl", "a,#0x80");
5848                   if (!rightInB)
5849                     {
5850                       pushedB = pushB ();
5851                       rightInB++;
5852                       MOVB (aopGet (right, offset, FALSE, FALSE));
5853                     }
5854                   emitcode ("xrl", "b,#0x80");
5855                   emitcode ("subb", "a,b");
5856                 }
5857               else
5858                 {
5859                   if (rightInB)
5860                     emitcode ("subb", "a,b");
5861                   else
5862                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5863                 }
5864               if (rightInB)
5865                 popB (pushedB);
5866               offset++;
5867             }
5868         }
5869     }
5870
5871 release:
5872   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5873   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5874   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5875     {
5876       outBitC (result);
5877     }
5878   else
5879     {
5880       /* if the result is used in the next
5881          ifx conditional branch then generate
5882          code a little differently */
5883       if (ifx)
5884         {
5885           genIfxJump (ifx, "c", NULL, NULL, result);
5886         }
5887       else
5888         {
5889           outBitC (result);
5890         }
5891       /* leave the result in acc */
5892     }
5893 }
5894
5895 /*-----------------------------------------------------------------*/
5896 /* genCmpGt :- greater than comparison                             */
5897 /*-----------------------------------------------------------------*/
5898 static void
5899 genCmpGt (iCode * ic, iCode * ifx)
5900 {
5901   operand *left, *right, *result;
5902   sym_link *letype, *retype;
5903   int sign;
5904
5905   D (emitcode (";", "genCmpGt"));
5906
5907   left = IC_LEFT (ic);
5908   right = IC_RIGHT (ic);
5909   result = IC_RESULT (ic);
5910
5911   letype = getSpec (operandType (left));
5912   retype = getSpec (operandType (right));
5913   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5914            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5915   /* assign the amsops */
5916   aopOp (result, ic, TRUE);
5917   aopOp (left, ic, FALSE);
5918   aopOp (right, ic, FALSE);
5919
5920   genCmp (right, left, result, ifx, sign, ic);
5921
5922   freeAsmop (result, NULL, ic, TRUE);
5923 }
5924
5925 /*-----------------------------------------------------------------*/
5926 /* genCmpLt - less than comparisons                                */
5927 /*-----------------------------------------------------------------*/
5928 static void
5929 genCmpLt (iCode * ic, iCode * ifx)
5930 {
5931   operand *left, *right, *result;
5932   sym_link *letype, *retype;
5933   int sign;
5934
5935   D (emitcode (";", "genCmpLt"));
5936
5937   left = IC_LEFT (ic);
5938   right = IC_RIGHT (ic);
5939   result = IC_RESULT (ic);
5940
5941   letype = getSpec (operandType (left));
5942   retype = getSpec (operandType (right));
5943   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5944            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5945   /* assign the amsops */
5946   aopOp (result, ic, TRUE);
5947   aopOp (left, ic, FALSE);
5948   aopOp (right, ic, FALSE);
5949
5950   genCmp (left, right, result, ifx, sign, ic);
5951
5952   freeAsmop (result, NULL, ic, TRUE);
5953 }
5954
5955 /*-----------------------------------------------------------------*/
5956 /* gencjneshort - compare and jump if not equal                    */
5957 /*-----------------------------------------------------------------*/
5958 static void
5959 gencjneshort (operand * left, operand * right, symbol * lbl)
5960 {
5961   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5962   int offset = 0;
5963   unsigned long lit = 0L;
5964
5965   D (emitcode (";", "gencjneshort"));
5966
5967   /* if the left side is a literal or
5968      if the right is in a pointer register and left
5969      is not */
5970   if ((AOP_TYPE (left) == AOP_LIT) ||
5971       (AOP_TYPE (left) == AOP_IMMD) ||
5972       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5973     {
5974       operand *t = right;
5975       right = left;
5976       left = t;
5977     }
5978
5979   if (AOP_TYPE (right) == AOP_LIT)
5980     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5981
5982   /* if the right side is a literal then anything goes */
5983   if (AOP_TYPE (right) == AOP_LIT &&
5984       AOP_TYPE (left) != AOP_DIR  &&
5985       AOP_TYPE (left) != AOP_IMMD)
5986     {
5987       while (size--)
5988         {
5989           emitcode ("cjne", "%s,%s,%05d$",
5990                     aopGet (left, offset, FALSE, FALSE),
5991                     aopGet (right, offset, FALSE, FALSE),
5992                     lbl->key + 100);
5993           offset++;
5994         }
5995     }
5996
5997   /* if the right side is in a register or in direct space or
5998      if the left is a pointer register & right is not */
5999   else if (AOP_TYPE (right) == AOP_REG ||
6000            AOP_TYPE (right) == AOP_DIR ||
6001            AOP_TYPE (right) == AOP_LIT ||
6002            AOP_TYPE (right) == AOP_IMMD ||
6003            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6004            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6005     {
6006       while (size--)
6007         {
6008           MOVA (aopGet (left, offset, FALSE, FALSE));
6009           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6010               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6011             emitcode ("jnz", "%05d$", lbl->key + 100);
6012           else
6013             emitcode ("cjne", "a,%s,%05d$",
6014                       aopGet (right, offset, FALSE, TRUE),
6015                       lbl->key + 100);
6016           offset++;
6017         }
6018     }
6019   else
6020     {
6021       /* right is a pointer reg need both a & b */
6022       while (size--)
6023         {
6024           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6025           wassertl(!BINUSE, "B was in use");
6026           MOVB (aopGet (left, offset, FALSE, FALSE));
6027           MOVA (aopGet (right, offset, FALSE, FALSE));
6028           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6029           offset++;
6030         }
6031     }
6032 }
6033
6034 /*-----------------------------------------------------------------*/
6035 /* gencjne - compare and jump if not equal                         */
6036 /*-----------------------------------------------------------------*/
6037 static void
6038 gencjne (operand * left, operand * right, symbol * lbl)
6039 {
6040   symbol *tlbl = newiTempLabel (NULL);
6041
6042   D (emitcode (";", "gencjne"));
6043
6044   gencjneshort (left, right, lbl);
6045
6046   emitcode ("mov", "a,%s", one);
6047   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6048   emitLabel (lbl);
6049   emitcode ("clr", "a");
6050   emitLabel (tlbl);
6051 }
6052
6053 /*-----------------------------------------------------------------*/
6054 /* genCmpEq - generates code for equal to                          */
6055 /*-----------------------------------------------------------------*/
6056 static void
6057 genCmpEq (iCode * ic, iCode * ifx)
6058 {
6059   bool swappedLR = FALSE;
6060   operand *left, *right, *result;
6061
6062   D (emitcode (";", "genCmpEq"));
6063
6064   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6065   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6066   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6067
6068   /* if literal, literal on the right or
6069      if the right is in a pointer register and left
6070      is not */
6071   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6072       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6073     {
6074       operand *t = IC_RIGHT (ic);
6075       IC_RIGHT (ic) = IC_LEFT (ic);
6076       IC_LEFT (ic) = t;
6077       swappedLR = TRUE;
6078     }
6079
6080   if (ifx && !AOP_SIZE (result))
6081     {
6082       symbol *tlbl;
6083       /* if they are both bit variables */
6084       if (AOP_TYPE (left) == AOP_CRY &&
6085           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6086         {
6087           if (AOP_TYPE (right) == AOP_LIT)
6088             {
6089               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6090               if (lit == 0L)
6091                 {
6092                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6093                   emitcode ("cpl", "c");
6094                 }
6095               else if (lit == 1L)
6096                 {
6097                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6098                 }
6099               else
6100                 {
6101                   emitcode ("clr", "c");
6102                 }
6103               /* AOP_TYPE(right) == AOP_CRY */
6104             }
6105           else
6106             {
6107               symbol *lbl = newiTempLabel (NULL);
6108               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6109               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6110               emitcode ("cpl", "c");
6111               emitLabel (lbl);
6112             }
6113           /* if true label then we jump if condition
6114              supplied is true */
6115           tlbl = newiTempLabel (NULL);
6116           if (IC_TRUE (ifx))
6117             {
6118               emitcode ("jnc", "%05d$", tlbl->key + 100);
6119               freeForBranchAsmop (result);
6120               freeForBranchAsmop (right);
6121               freeForBranchAsmop (left);
6122               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6123             }
6124           else
6125             {
6126               emitcode ("jc", "%05d$", tlbl->key + 100);
6127               freeForBranchAsmop (result);
6128               freeForBranchAsmop (right);
6129               freeForBranchAsmop (left);
6130               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6131             }
6132           emitLabel (tlbl);
6133         }
6134       else
6135         {
6136           tlbl = newiTempLabel (NULL);
6137           gencjneshort (left, right, tlbl);
6138           if (IC_TRUE (ifx))
6139             {
6140               freeForBranchAsmop (result);
6141               freeForBranchAsmop (right);
6142               freeForBranchAsmop (left);
6143               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6144               emitLabel (tlbl);
6145             }
6146           else
6147             {
6148               symbol *lbl = newiTempLabel (NULL);
6149               emitcode ("sjmp", "%05d$", lbl->key + 100);
6150               emitLabel (tlbl);
6151               freeForBranchAsmop (result);
6152               freeForBranchAsmop (right);
6153               freeForBranchAsmop (left);
6154               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6155               emitLabel (lbl);
6156             }
6157         }
6158       /* mark the icode as generated */
6159       ifx->generated = 1;
6160       goto release;
6161     }
6162
6163   /* if they are both bit variables */
6164   if (AOP_TYPE (left) == AOP_CRY &&
6165       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6166     {
6167       if (AOP_TYPE (right) == AOP_LIT)
6168         {
6169           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6170           if (lit == 0L)
6171             {
6172               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6173               emitcode ("cpl", "c");
6174             }
6175           else if (lit == 1L)
6176             {
6177               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6178             }
6179           else
6180             {
6181               emitcode ("clr", "c");
6182             }
6183           /* AOP_TYPE(right) == AOP_CRY */
6184         }
6185       else
6186         {
6187           symbol *lbl = newiTempLabel (NULL);
6188           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6189           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6190           emitcode ("cpl", "c");
6191           emitLabel (lbl);
6192         }
6193       /* c = 1 if egal */
6194       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6195         {
6196           outBitC (result);
6197           goto release;
6198         }
6199       if (ifx)
6200         {
6201           genIfxJump (ifx, "c", left, right, result);
6202           goto release;
6203         }
6204       /* if the result is used in an arithmetic operation
6205          then put the result in place */
6206       outBitC (result);
6207     }
6208   else
6209     {
6210       gencjne (left, right, newiTempLabel (NULL));
6211       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6212         {
6213           aopPut (result, "a", 0);
6214           goto release;
6215         }
6216       if (ifx)
6217         {
6218           genIfxJump (ifx, "a", left, right, result);
6219           goto release;
6220         }
6221       /* if the result is used in an arithmetic operation
6222          then put the result in place */
6223       if (AOP_TYPE (result) != AOP_CRY)
6224         outAcc (result);
6225       /* leave the result in acc */
6226     }
6227
6228 release:
6229   freeAsmop (result, NULL, ic, TRUE);
6230   if (!swappedLR)
6231     {
6232       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6234     }
6235   else
6236     {
6237       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6238       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6239     }
6240 }
6241
6242 /*-----------------------------------------------------------------*/
6243 /* ifxForOp - returns the icode containing the ifx for operand     */
6244 /*-----------------------------------------------------------------*/
6245 static iCode *
6246 ifxForOp (operand * op, iCode * ic)
6247 {
6248   /* if true symbol then needs to be assigned */
6249   if (IS_TRUE_SYMOP (op))
6250     return NULL;
6251
6252   /* if this has register type condition and
6253      the next instruction is ifx with the same operand
6254      and live to of the operand is upto the ifx only then */
6255   if (ic->next &&
6256       ic->next->op == IFX &&
6257       IC_COND (ic->next)->key == op->key &&
6258       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6259     return ic->next;
6260
6261   return NULL;
6262 }
6263
6264 /*-----------------------------------------------------------------*/
6265 /* hasInc - operand is incremented before any other use            */
6266 /*-----------------------------------------------------------------*/
6267 static iCode *
6268 hasInc (operand *op, iCode *ic, int osize)
6269 {
6270   sym_link *type = operandType(op);
6271   sym_link *retype = getSpec (type);
6272   iCode *lic = ic->next;
6273   int isize ;
6274
6275   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6276   if (!IS_SYMOP(op)) return NULL;
6277
6278   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6279   if (IS_AGGREGATE(type->next)) return NULL;
6280   if (osize != (isize = getSize(type->next))) return NULL;
6281
6282   while (lic) {
6283     /* if operand of the form op = op + <sizeof *op> */
6284     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6285         isOperandEqual(IC_RESULT(lic),op) &&
6286         isOperandLiteral(IC_RIGHT(lic)) &&
6287         operandLitValue(IC_RIGHT(lic)) == isize) {
6288       return lic;
6289     }
6290     /* if the operand used or deffed */
6291     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6292       return NULL;
6293     }
6294     /* if GOTO or IFX */
6295     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6296     lic = lic->next;
6297   }
6298   return NULL;
6299 }
6300
6301 /*-----------------------------------------------------------------*/
6302 /* genAndOp - for && operation                                     */
6303 /*-----------------------------------------------------------------*/
6304 static void
6305 genAndOp (iCode * ic)
6306 {
6307   operand *left, *right, *result;
6308   symbol *tlbl;
6309
6310   D (emitcode (";", "genAndOp"));
6311
6312   /* note here that && operations that are in an
6313      if statement are taken away by backPatchLabels
6314      only those used in arthmetic operations remain */
6315   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6316   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6317   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6318
6319   /* if both are bit variables */
6320   if (AOP_TYPE (left) == AOP_CRY &&
6321       AOP_TYPE (right) == AOP_CRY)
6322     {
6323       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6324       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6325       outBitC (result);
6326     }
6327   else
6328     {
6329       tlbl = newiTempLabel (NULL);
6330       toBoolean (left);
6331       emitcode ("jz", "%05d$", tlbl->key + 100);
6332       toBoolean (right);
6333       emitLabel (tlbl);
6334       outBitAcc (result);
6335     }
6336
6337   freeAsmop (result, NULL, ic, TRUE);
6338   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6339   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6340 }
6341
6342
6343 /*-----------------------------------------------------------------*/
6344 /* genOrOp - for || operation                                      */
6345 /*-----------------------------------------------------------------*/
6346 static void
6347 genOrOp (iCode * ic)
6348 {
6349   operand *left, *right, *result;
6350   symbol *tlbl;
6351
6352   D (emitcode (";", "genOrOp"));
6353
6354   /* note here that || operations that are in an
6355      if statement are taken away by backPatchLabels
6356      only those used in arthmetic operations remain */
6357   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6358   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6359   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6360
6361   /* if both are bit variables */
6362   if (AOP_TYPE (left) == AOP_CRY &&
6363       AOP_TYPE (right) == AOP_CRY)
6364     {
6365       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6366       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6367       outBitC (result);
6368     }
6369   else
6370     {
6371       tlbl = newiTempLabel (NULL);
6372       toBoolean (left);
6373       emitcode ("jnz", "%05d$", tlbl->key + 100);
6374       toBoolean (right);
6375       emitLabel (tlbl);
6376       outBitAcc (result);
6377     }
6378
6379   freeAsmop (result, NULL, ic, TRUE);
6380   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6381   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6382 }
6383
6384 /*-----------------------------------------------------------------*/
6385 /* isLiteralBit - test if lit == 2^n                               */
6386 /*-----------------------------------------------------------------*/
6387 static int
6388 isLiteralBit (unsigned long lit)
6389 {
6390   unsigned long pw[32] =
6391   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6392    0x100L, 0x200L, 0x400L, 0x800L,
6393    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6394    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6395    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6396    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6397    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6398   int idx;
6399
6400   for (idx = 0; idx < 32; idx++)
6401     if (lit == pw[idx])
6402       return idx + 1;
6403   return 0;
6404 }
6405
6406 /*-----------------------------------------------------------------*/
6407 /* continueIfTrue -                                                */
6408 /*-----------------------------------------------------------------*/
6409 static void
6410 continueIfTrue (iCode * ic)
6411 {
6412   if (IC_TRUE (ic))
6413     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6414   ic->generated = 1;
6415 }
6416
6417 /*-----------------------------------------------------------------*/
6418 /* jmpIfTrue -                                                     */
6419 /*-----------------------------------------------------------------*/
6420 static void
6421 jumpIfTrue (iCode * ic)
6422 {
6423   if (!IC_TRUE (ic))
6424     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6425   ic->generated = 1;
6426 }
6427
6428 /*-----------------------------------------------------------------*/
6429 /* jmpTrueOrFalse -                                                */
6430 /*-----------------------------------------------------------------*/
6431 static void
6432 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6433 {
6434   // ugly but optimized by peephole
6435   if (IC_TRUE (ic))
6436     {
6437       symbol *nlbl = newiTempLabel (NULL);
6438       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6439       emitLabel (tlbl);
6440       freeForBranchAsmop (result);
6441       freeForBranchAsmop (right);
6442       freeForBranchAsmop (left);
6443       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6444       emitLabel (nlbl);
6445     }
6446   else
6447     {
6448       freeForBranchAsmop (result);
6449       freeForBranchAsmop (right);
6450       freeForBranchAsmop (left);
6451       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6452       emitLabel (tlbl);
6453     }
6454   ic->generated = 1;
6455 }
6456
6457 /*-----------------------------------------------------------------*/
6458 /* genAnd  - code for and                                          */
6459 /*-----------------------------------------------------------------*/
6460 static void
6461 genAnd (iCode * ic, iCode * ifx)
6462 {
6463   operand *left, *right, *result;
6464   int size, offset = 0;
6465   unsigned long lit = 0L;
6466   int bytelit = 0;
6467   char buffer[10];
6468
6469   D (emitcode (";", "genAnd"));
6470
6471   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6472   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6473   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6474
6475 #ifdef DEBUG_TYPE
6476   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6477             AOP_TYPE (result),
6478             AOP_TYPE (left), AOP_TYPE (right));
6479   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6480             AOP_SIZE (result),
6481             AOP_SIZE (left), AOP_SIZE (right));
6482 #endif
6483
6484   /* if left is a literal & right is not then exchange them */
6485   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6486       AOP_NEEDSACC (left))
6487     {
6488       operand *tmp = right;
6489       right = left;
6490       left = tmp;
6491     }
6492
6493   /* if result = right then exchange left and right */
6494   if (sameRegs (AOP (result), AOP (right)))
6495     {
6496       operand *tmp = right;
6497       right = left;
6498       left = tmp;
6499     }
6500
6501   /* if right is bit then exchange them */
6502   if (AOP_TYPE (right) == AOP_CRY &&
6503       AOP_TYPE (left) != AOP_CRY)
6504     {
6505       operand *tmp = right;
6506       right = left;
6507       left = tmp;
6508     }
6509   if (AOP_TYPE (right) == AOP_LIT)
6510     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6511
6512   size = AOP_SIZE (result);
6513
6514   // if(bit & yy)
6515   // result = bit & yy;
6516   if (AOP_TYPE (left) == AOP_CRY)
6517     {
6518       // c = bit & literal;
6519       if (AOP_TYPE (right) == AOP_LIT)
6520         {
6521           if (lit & 1)
6522             {
6523               if (size && sameRegs (AOP (result), AOP (left)))
6524                 // no change
6525                 goto release;
6526               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6527             }
6528           else
6529             {
6530               // bit(result) = 0;
6531               if (size && (AOP_TYPE (result) == AOP_CRY))
6532                 {
6533                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6534                   goto release;
6535                 }
6536               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6537                 {
6538                   jumpIfTrue (ifx);
6539                   goto release;
6540                 }
6541               emitcode ("clr", "c");
6542             }
6543         }
6544       else
6545         {
6546           if (AOP_TYPE (right) == AOP_CRY)
6547             {
6548               // c = bit & bit;
6549               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6550               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6551             }
6552           else
6553             {
6554               // c = bit & val;
6555               MOVA (aopGet (right, 0, FALSE, FALSE));
6556               // c = lsb
6557               emitcode ("rrc", "a");
6558               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6559             }
6560         }
6561       // bit = c
6562       // val = c
6563       if (size)
6564         outBitC (result);
6565       // if(bit & ...)
6566       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6567         genIfxJump (ifx, "c", left, right, result);
6568       goto release;
6569     }
6570
6571   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6572   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6573   if ((AOP_TYPE (right) == AOP_LIT) &&
6574       (AOP_TYPE (result) == AOP_CRY) &&
6575       (AOP_TYPE (left) != AOP_CRY))
6576     {
6577       int posbit = isLiteralBit (lit);
6578       /* left &  2^n */
6579       if (posbit)
6580         {
6581           posbit--;
6582           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6583           // bit = left & 2^n
6584           if (size)
6585             {
6586               switch (posbit & 0x07)
6587                 {
6588                   case 0: emitcode ("rrc", "a");
6589                           break;
6590                   case 7: emitcode ("rlc", "a");
6591                           break;
6592                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6593                           break;
6594                 }
6595             }
6596           // if(left &  2^n)
6597           else
6598             {
6599               if (ifx)
6600                 {
6601                   SNPRINTF (buffer, sizeof(buffer),
6602                             "acc.%d", posbit & 0x07);
6603                   genIfxJump (ifx, buffer, left, right, result);
6604                 }
6605               else
6606                 {// what is this case? just found it in ds390/gen.c
6607                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6608                 }
6609               goto release;
6610             }
6611         }
6612       else
6613         {
6614           symbol *tlbl = newiTempLabel (NULL);
6615           int sizel = AOP_SIZE (left);
6616           if (size)
6617             emitcode ("setb", "c");
6618           while (sizel--)
6619             {
6620               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6621                 {
6622                   MOVA (aopGet (left, offset, FALSE, FALSE));
6623                   // byte ==  2^n ?
6624                   if ((posbit = isLiteralBit (bytelit)) != 0)
6625                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6626                   else
6627                     {
6628                       if (bytelit != 0x0FFL)
6629                         emitcode ("anl", "a,%s",
6630                                   aopGet (right, offset, FALSE, TRUE));
6631                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6632                     }
6633                 }
6634               offset++;
6635             }
6636           // bit = left & literal
6637           if (size)
6638             {
6639               emitcode ("clr", "c");
6640               emitLabel (tlbl);
6641             }
6642           // if(left & literal)
6643           else
6644             {
6645               if (ifx)
6646                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6647               else
6648                 emitLabel (tlbl);
6649               goto release;
6650             }
6651         }
6652       outBitC (result);
6653       goto release;
6654     }
6655
6656   /* if left is same as result */
6657   if (sameRegs (AOP (result), AOP (left)))
6658     {
6659       for (; size--; offset++)
6660         {
6661           if (AOP_TYPE (right) == AOP_LIT)
6662             {
6663               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6664               if (bytelit == 0x0FF)
6665                 {
6666                   /* dummy read of volatile operand */
6667                   if (isOperandVolatile (left, FALSE))
6668                     MOVA (aopGet (left, offset, FALSE, FALSE));
6669                   else
6670                     continue;
6671                 }
6672               else if (bytelit == 0)
6673                 {
6674                   aopPut (result, zero, offset);
6675                 }
6676               else if (IS_AOP_PREG (result))
6677                 {
6678                   MOVA (aopGet (left, offset, FALSE, TRUE));
6679                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6680                   aopPut (result, "a", offset);
6681                 }
6682               else
6683                 emitcode ("anl", "%s,%s",
6684                           aopGet (left, offset, FALSE, TRUE),
6685                           aopGet (right, offset, FALSE, FALSE));
6686             }
6687           else
6688             {
6689               if (AOP_TYPE (left) == AOP_ACC)
6690                 {
6691                   if (offset)
6692                     emitcode("mov", "a,b");
6693                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6694                 }
6695               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6696                 {
6697                   MOVB (aopGet (left, offset, FALSE, FALSE));
6698                   MOVA (aopGet (right, offset, FALSE, FALSE));
6699                   emitcode ("anl", "a,b");
6700                   aopPut (result, "a", offset);
6701                 }
6702               else if (aopGetUsesAcc (left, offset))
6703                 {
6704                   MOVA (aopGet (left, offset, FALSE, FALSE));
6705                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6706                   aopPut (result, "a", offset);
6707                 }
6708               else
6709                 {
6710                   MOVA (aopGet (right, offset, FALSE, FALSE));
6711                   if (IS_AOP_PREG (result))
6712                     {
6713                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6714                       aopPut (result, "a", offset);
6715                     }
6716                   else
6717                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6718                 }
6719             }
6720         }
6721     }
6722   else
6723     {
6724       // left & result in different registers
6725       if (AOP_TYPE (result) == AOP_CRY)
6726         {
6727           // result = bit
6728           // if(size), result in bit
6729           // if(!size && ifx), conditional oper: if(left & right)
6730           symbol *tlbl = newiTempLabel (NULL);
6731           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6732           if (size)
6733             emitcode ("setb", "c");
6734           while (sizer--)
6735             {
6736               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6737                   && AOP_TYPE(left)==AOP_ACC)
6738                 {
6739                   if (offset)
6740                     emitcode("mov", "a,b");
6741                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6742                 }
6743               else if (AOP_TYPE(left)==AOP_ACC)
6744                 {
6745                   if (!offset)
6746                     {
6747                       bool pushedB = pushB ();
6748                       emitcode("mov", "b,a");
6749                       MOVA (aopGet (right, offset, FALSE, FALSE));
6750                       emitcode("anl", "a,b");
6751                       popB (pushedB);
6752                     }
6753                   else
6754                     {
6755                       MOVA (aopGet (right, offset, FALSE, FALSE));
6756                       emitcode("anl", "a,b");
6757                     }
6758                 }
6759               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6760                 {
6761                   MOVB (aopGet (left, offset, FALSE, FALSE));
6762                   MOVA (aopGet (right, offset, FALSE, FALSE));
6763                   emitcode ("anl", "a,b");
6764                 }
6765               else if (aopGetUsesAcc (left, offset))
6766                 {
6767                   MOVA (aopGet (left, offset, FALSE, FALSE));
6768                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6769                     }
6770               else
6771                 {
6772                   MOVA (aopGet (right, offset, FALSE, FALSE));
6773                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6774                 }
6775
6776               emitcode ("jnz", "%05d$", tlbl->key + 100);
6777               offset++;
6778             }
6779           if (size)
6780             {
6781               CLRC;
6782               emitLabel (tlbl);
6783               outBitC (result);
6784             }
6785           else if (ifx)
6786             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6787           else
6788             emitLabel (tlbl);
6789         }
6790       else
6791         {
6792           for (; (size--); offset++)
6793             {
6794               // normal case
6795               // result = left & right
6796               if (AOP_TYPE (right) == AOP_LIT)
6797                 {
6798                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6799                   if (bytelit == 0x0FF)
6800                     {
6801                       aopPut (result,
6802                               aopGet (left, offset, FALSE, FALSE),
6803                               offset);
6804                       continue;
6805                     }
6806                   else if (bytelit == 0)
6807                     {
6808                       /* dummy read of volatile operand */
6809                       if (isOperandVolatile (left, FALSE))
6810                         MOVA (aopGet (left, offset, FALSE, FALSE));
6811                       aopPut (result, zero, offset);
6812                       continue;
6813                     }
6814                   else if (AOP_TYPE (left) == AOP_ACC)
6815                     {
6816                       if (!offset)
6817                         {
6818                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6819                           aopPut (result, "a", offset);
6820                           continue;
6821                         }
6822                       else
6823                         {
6824                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6825                           aopPut (result, "b", offset);
6826                           continue;
6827                         }
6828                     }
6829                 }
6830               // faster than result <- left, anl result,right
6831               // and better if result is SFR
6832               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6833                   && AOP_TYPE(left)==AOP_ACC)
6834                 {
6835                   if (offset)
6836                     emitcode("mov", "a,b");
6837                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6838                 }
6839               else if (AOP_TYPE(left)==AOP_ACC)
6840                 {
6841                   if (!offset)
6842                     {
6843                       bool pushedB = pushB ();
6844                       emitcode("mov", "b,a");
6845                       MOVA (aopGet (right, offset, FALSE, FALSE));
6846                       emitcode("anl", "a,b");
6847                       popB (pushedB);
6848                     }
6849                   else
6850                     {
6851                       MOVA (aopGet (right, offset, FALSE, FALSE));
6852                       emitcode("anl", "a,b");
6853                     }
6854                 }
6855               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6856                 {
6857                   MOVB (aopGet (left, offset, FALSE, FALSE));
6858                   MOVA (aopGet (right, offset, FALSE, FALSE));
6859                   emitcode ("anl", "a,b");
6860                 }
6861               else if (aopGetUsesAcc (left, offset))
6862                 {
6863                   MOVA (aopGet (left, offset, FALSE, FALSE));
6864                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6865                 }
6866               else
6867                 {
6868                   MOVA (aopGet (right, offset, FALSE, FALSE));
6869                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6870                 }
6871               aopPut (result, "a", offset);
6872             }
6873         }
6874     }
6875
6876 release:
6877   freeAsmop (result, NULL, ic, TRUE);
6878   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6879   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6880 }
6881
6882 /*-----------------------------------------------------------------*/
6883 /* genOr  - code for or                                            */
6884 /*-----------------------------------------------------------------*/
6885 static void
6886 genOr (iCode * ic, iCode * ifx)
6887 {
6888   operand *left, *right, *result;
6889   int size, offset = 0;
6890   unsigned long lit = 0L;
6891   int bytelit = 0;
6892
6893   D (emitcode (";", "genOr"));
6894
6895   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6896   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6897   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6898
6899 #ifdef DEBUG_TYPE
6900   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6901             AOP_TYPE (result),
6902             AOP_TYPE (left), AOP_TYPE (right));
6903   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6904             AOP_SIZE (result),
6905             AOP_SIZE (left), AOP_SIZE (right));
6906 #endif
6907
6908   /* if left is a literal & right is not then exchange them */
6909   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6910       AOP_NEEDSACC (left))
6911     {
6912       operand *tmp = right;
6913       right = left;
6914       left = tmp;
6915     }
6916
6917   /* if result = right then exchange them */
6918   if (sameRegs (AOP (result), AOP (right)))
6919     {
6920       operand *tmp = right;
6921       right = left;
6922       left = tmp;
6923     }
6924
6925   /* if right is bit then exchange them */
6926   if (AOP_TYPE (right) == AOP_CRY &&
6927       AOP_TYPE (left) != AOP_CRY)
6928     {
6929       operand *tmp = right;
6930       right = left;
6931       left = tmp;
6932     }
6933   if (AOP_TYPE (right) == AOP_LIT)
6934     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6935
6936   size = AOP_SIZE (result);
6937
6938   // if(bit | yy)
6939   // xx = bit | yy;
6940   if (AOP_TYPE (left) == AOP_CRY)
6941     {
6942       if (AOP_TYPE (right) == AOP_LIT)
6943         {
6944           // c = bit | literal;
6945           if (lit)
6946             {
6947               // lit != 0 => result = 1
6948               if (AOP_TYPE (result) == AOP_CRY)
6949                 {
6950                   if (size)
6951                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6952                   else if (ifx)
6953                     continueIfTrue (ifx);
6954                   goto release;
6955                 }
6956               emitcode ("setb", "c");
6957             }
6958           else
6959             {
6960               // lit == 0 => result = left
6961               if (size && sameRegs (AOP (result), AOP (left)))
6962                 goto release;
6963               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6964             }
6965         }
6966       else
6967         {
6968           if (AOP_TYPE (right) == AOP_CRY)
6969             {
6970               // c = bit | bit;
6971               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6972               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6973             }
6974           else
6975             {
6976               // c = bit | val;
6977               symbol *tlbl = newiTempLabel (NULL);
6978               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6979                 emitcode ("setb", "c");
6980               emitcode ("jb", "%s,%05d$",
6981                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6982               toBoolean (right);
6983               emitcode ("jnz", "%05d$", tlbl->key + 100);
6984               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6985                 {
6986                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6987                   goto release;
6988                 }
6989               else
6990                 {
6991                   CLRC;
6992                   emitLabel (tlbl);
6993                 }
6994             }
6995         }
6996       // bit = c
6997       // val = c
6998       if (size)
6999         outBitC (result);
7000       // if(bit | ...)
7001       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7002         genIfxJump (ifx, "c", left, right, result);
7003       goto release;
7004     }
7005
7006   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7007   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7008   if ((AOP_TYPE (right) == AOP_LIT) &&
7009       (AOP_TYPE (result) == AOP_CRY) &&
7010       (AOP_TYPE (left) != AOP_CRY))
7011     {
7012       if (lit)
7013         {
7014           // result = 1
7015           if (size)
7016             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7017           else
7018             continueIfTrue (ifx);
7019           goto release;
7020         }
7021       else
7022         {
7023           // lit = 0, result = boolean(left)
7024           if (size)
7025             emitcode ("setb", "c");
7026           toBoolean (right);
7027           if (size)
7028             {
7029               symbol *tlbl = newiTempLabel (NULL);
7030               emitcode ("jnz", "%05d$", tlbl->key + 100);
7031               CLRC;
7032               emitLabel (tlbl);
7033             }
7034           else
7035             {
7036               genIfxJump (ifx, "a", left, right, result);
7037               goto release;
7038             }
7039         }
7040       outBitC (result);
7041       goto release;
7042     }
7043
7044   /* if left is same as result */
7045   if (sameRegs (AOP (result), AOP (left)))
7046     {
7047       for (; size--; offset++)
7048         {
7049           if (AOP_TYPE (right) == AOP_LIT)
7050             {
7051               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7052               if (bytelit == 0)
7053                 {
7054                   /* dummy read of volatile operand */
7055                   if (isOperandVolatile (left, FALSE))
7056                     MOVA (aopGet (left, offset, FALSE, FALSE));
7057                   else
7058                     continue;
7059                 }
7060               else if (bytelit == 0x0FF)
7061                 {
7062                   aopPut (result, "#0xFF", offset);
7063                 }
7064               else if (IS_AOP_PREG (left))
7065                 {
7066                   MOVA (aopGet (left, offset, FALSE, TRUE));
7067                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7068                   aopPut (result, "a", offset);
7069                 }
7070               else
7071                 {
7072                   emitcode ("orl", "%s,%s",
7073                             aopGet (left, offset, FALSE, TRUE),
7074                             aopGet (right, offset, FALSE, FALSE));
7075                 }
7076             }
7077           else
7078             {
7079               if (AOP_TYPE (left) == AOP_ACC)
7080                 {
7081                   if (offset)
7082                     emitcode("mov", "a,b");
7083                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7084                 }
7085               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7086                 {
7087                   MOVB (aopGet (left, offset, FALSE, FALSE));
7088                   MOVA (aopGet (right, offset, FALSE, FALSE));
7089                   emitcode ("orl", "a,b");
7090                   aopPut (result, "a", offset);
7091                 }
7092               else if (aopGetUsesAcc (left, offset))
7093                 {
7094                   MOVA (aopGet (left, offset, FALSE, FALSE));
7095                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7096                   aopPut (result, "a", offset);
7097                 }
7098               else
7099                 {
7100                   MOVA (aopGet (right, offset, FALSE, FALSE));
7101                   if (IS_AOP_PREG (left))
7102                     {
7103                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7104                       aopPut (result, "a", offset);
7105                     }
7106                   else
7107                     {
7108                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7109                     }
7110                 }
7111             }
7112         }
7113     }
7114   else
7115     {
7116       // left & result in different registers
7117       if (AOP_TYPE (result) == AOP_CRY)
7118         {
7119           // result = bit
7120           // if(size), result in bit
7121           // if(!size && ifx), conditional oper: if(left | right)
7122           symbol *tlbl = newiTempLabel (NULL);
7123           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7124           if (size)
7125             emitcode ("setb", "c");
7126           while (sizer--)
7127             {
7128               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7129                   && AOP_TYPE(left)==AOP_ACC)
7130                 {
7131                   if (offset)
7132                     emitcode("mov", "a,b");
7133                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7134                 }
7135               else if (AOP_TYPE(left)==AOP_ACC)
7136                 {
7137                   if (!offset)
7138                     {
7139                       bool pushedB = pushB ();
7140                       emitcode("mov", "b,a");
7141                       MOVA (aopGet (right, offset, FALSE, FALSE));
7142                       emitcode("orl", "a,b");
7143                       popB (pushedB);
7144                     }
7145                   else
7146                     {
7147                       MOVA (aopGet (right, offset, FALSE, FALSE));
7148                       emitcode("orl", "a,b");
7149                     }
7150                 }
7151               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7152                 {
7153                   MOVB (aopGet (left, offset, FALSE, FALSE));
7154                   MOVA (aopGet (right, offset, FALSE, FALSE));
7155                   emitcode ("orl", "a,b");
7156                 }
7157               else if (aopGetUsesAcc (left, offset))
7158                 {
7159                   MOVA (aopGet (left, offset, FALSE, FALSE));
7160                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7161                 }
7162               else
7163                 {
7164                   MOVA (aopGet (right, offset, FALSE, FALSE));
7165                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7166               }
7167
7168               emitcode ("jnz", "%05d$", tlbl->key + 100);
7169               offset++;
7170             }
7171           if (size)
7172             {
7173               CLRC;
7174               emitLabel (tlbl);
7175               outBitC (result);
7176             }
7177           else if (ifx)
7178             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7179           else
7180             emitLabel (tlbl);
7181         }
7182       else
7183         {
7184           for (; (size--); offset++)
7185             {
7186               // normal case
7187               // result = left | right
7188               if (AOP_TYPE (right) == AOP_LIT)
7189                 {
7190                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7191                   if (bytelit == 0)
7192                     {
7193                       aopPut (result,
7194                               aopGet (left, offset, FALSE, FALSE),
7195                               offset);
7196                       continue;
7197                     }
7198                   else if (bytelit == 0x0FF)
7199                     {
7200                       /* dummy read of volatile operand */
7201                       if (isOperandVolatile (left, FALSE))
7202                         MOVA (aopGet (left, offset, FALSE, FALSE));
7203                       aopPut (result, "#0xFF", offset);
7204                       continue;
7205                     }
7206                 }
7207               // faster than result <- left, orl result,right
7208               // and better if result is SFR
7209               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7210                   && AOP_TYPE(left)==AOP_ACC)
7211                 {
7212                   if (offset)
7213                     emitcode("mov", "a,b");
7214                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7215                 }
7216               else if (AOP_TYPE(left)==AOP_ACC)
7217                 {
7218                   if (!offset)
7219                     {
7220                       bool pushedB = pushB ();
7221                       emitcode("mov", "b,a");
7222                       MOVA (aopGet (right, offset, FALSE, FALSE));
7223                       emitcode("orl", "a,b");
7224                       popB (pushedB);
7225                     }
7226                   else
7227                     {
7228                       MOVA (aopGet (right, offset, FALSE, FALSE));
7229                       emitcode("orl", "a,b");
7230                     }
7231                 }
7232               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7233                 {
7234                   MOVB (aopGet (left, offset, FALSE, FALSE));
7235                   MOVA (aopGet (right, offset, FALSE, FALSE));
7236                   emitcode ("orl", "a,b");
7237                 }
7238               else if (aopGetUsesAcc (left, offset))
7239                 {
7240                   MOVA (aopGet (left, offset, FALSE, FALSE));
7241                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7242                 }
7243               else
7244                 {
7245                   MOVA (aopGet (right, offset, FALSE, FALSE));
7246                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7247                 }
7248               aopPut (result, "a", offset);
7249             }
7250         }
7251     }
7252
7253 release:
7254   freeAsmop (result, NULL, ic, TRUE);
7255   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7256   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7257 }
7258
7259 /*-----------------------------------------------------------------*/
7260 /* genXor - code for xclusive or                                   */
7261 /*-----------------------------------------------------------------*/
7262 static void
7263 genXor (iCode * ic, iCode * ifx)
7264 {
7265   operand *left, *right, *result;
7266   int size, offset = 0;
7267   unsigned long lit = 0L;
7268   int bytelit = 0;
7269
7270   D (emitcode (";", "genXor"));
7271
7272   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7273   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7274   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7275
7276 #ifdef DEBUG_TYPE
7277   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7278             AOP_TYPE (result),
7279             AOP_TYPE (left), AOP_TYPE (right));
7280   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7281             AOP_SIZE (result),
7282             AOP_SIZE (left), AOP_SIZE (right));
7283 #endif
7284
7285   /* if left is a literal & right is not ||
7286      if left needs acc & right does not */
7287   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7288       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7289     {
7290       operand *tmp = right;
7291       right = left;
7292       left = tmp;
7293     }
7294
7295   /* if result = right then exchange them */
7296   if (sameRegs (AOP (result), AOP (right)))
7297     {
7298       operand *tmp = right;
7299       right = left;
7300       left = tmp;
7301     }
7302
7303   /* if right is bit then exchange them */
7304   if (AOP_TYPE (right) == AOP_CRY &&
7305       AOP_TYPE (left) != AOP_CRY)
7306     {
7307       operand *tmp = right;
7308       right = left;
7309       left = tmp;
7310     }
7311   if (AOP_TYPE (right) == AOP_LIT)
7312     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7313
7314   size = AOP_SIZE (result);
7315
7316   // if(bit ^ yy)
7317   // xx = bit ^ yy;
7318   if (AOP_TYPE (left) == AOP_CRY)
7319     {
7320       if (AOP_TYPE (right) == AOP_LIT)
7321         {
7322           // c = bit & literal;
7323           if (lit >> 1)
7324             {
7325               // lit>>1  != 0 => result = 1
7326               if (AOP_TYPE (result) == AOP_CRY)
7327                 {
7328                   if (size)
7329                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7330                   else if (ifx)
7331                     continueIfTrue (ifx);
7332                   goto release;
7333                 }
7334               emitcode ("setb", "c");
7335             }
7336           else
7337             {
7338               // lit == (0 or 1)
7339               if (lit == 0)
7340                 {
7341                   // lit == 0, result = left
7342                   if (size && sameRegs (AOP (result), AOP (left)))
7343                     goto release;
7344                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7345                 }
7346               else
7347                 {
7348                   // lit == 1, result = not(left)
7349                   if (size && sameRegs (AOP (result), AOP (left)))
7350                     {
7351                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7352                       goto release;
7353                     }
7354                   else
7355                     {
7356                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7357                       emitcode ("cpl", "c");
7358                     }
7359                 }
7360             }
7361         }
7362       else
7363         {
7364           // right != literal
7365           symbol *tlbl = newiTempLabel (NULL);
7366           if (AOP_TYPE (right) == AOP_CRY)
7367             {
7368               // c = bit ^ bit;
7369               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7370             }
7371           else
7372             {
7373               int sizer = AOP_SIZE (right);
7374               // c = bit ^ val
7375               // if val>>1 != 0, result = 1
7376               emitcode ("setb", "c");
7377               while (sizer)
7378                 {
7379                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7380                   if (sizer == 1)
7381                     // test the msb of the lsb
7382                     emitcode ("anl", "a,#0xfe");
7383                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7384                   sizer--;
7385                 }
7386               // val = (0,1)
7387               emitcode ("rrc", "a");
7388             }
7389           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7390           emitcode ("cpl", "c");
7391           emitLabel (tlbl);
7392         }
7393       // bit = c
7394       // val = c
7395       if (size)
7396         outBitC (result);
7397       // if(bit | ...)
7398       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7399         genIfxJump (ifx, "c", left, right, result);
7400       goto release;
7401     }
7402
7403   /* if left is same as result */
7404   if (sameRegs (AOP (result), AOP (left)))
7405     {
7406       for (; size--; offset++)
7407         {
7408           if (AOP_TYPE (right) == AOP_LIT)
7409             {
7410               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7411               if (bytelit == 0)
7412                 {
7413                   /* dummy read of volatile operand */
7414                   if (isOperandVolatile (left, FALSE))
7415                     MOVA (aopGet (left, offset, FALSE, FALSE));
7416                   else
7417                     continue;
7418                 }
7419               else if (IS_AOP_PREG (left))
7420                 {
7421                   MOVA (aopGet (left, offset, FALSE, TRUE));
7422                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7423                   aopPut (result, "a", offset);
7424                 }
7425               else
7426                 {
7427                   emitcode ("xrl", "%s,%s",
7428                             aopGet (left, offset, FALSE, TRUE),
7429                             aopGet (right, offset, FALSE, FALSE));
7430                 }
7431             }
7432           else
7433             {
7434               if (AOP_TYPE (left) == AOP_ACC)
7435                 {
7436                   if (offset)
7437                     emitcode("mov", "a,b");
7438                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7439                 }
7440               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7441                 {
7442                   MOVB (aopGet (left, offset, FALSE, FALSE));
7443                   MOVA (aopGet (right, offset, FALSE, FALSE));
7444                   emitcode ("xrl", "a,b");
7445                   aopPut (result, "a", offset);
7446                 }
7447               else if (aopGetUsesAcc (left, offset))
7448                 {
7449                   MOVA (aopGet (left, offset, FALSE, FALSE));
7450                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7451                   aopPut (result, "a", offset);
7452                 }
7453               else
7454                 {
7455                   MOVA (aopGet (right, offset, FALSE, FALSE));
7456                   if (IS_AOP_PREG (left))
7457                     {
7458                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7459                       aopPut (result, "a", offset);
7460                     }
7461                   else
7462                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7463                 }
7464             }
7465         }
7466     }
7467   else
7468     {
7469       // left & result in different registers
7470       if (AOP_TYPE (result) == AOP_CRY)
7471         {
7472           // result = bit
7473           // if(size), result in bit
7474           // if(!size && ifx), conditional oper: if(left ^ right)
7475           symbol *tlbl = newiTempLabel (NULL);
7476           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7477
7478           if (size)
7479             emitcode ("setb", "c");
7480           while (sizer--)
7481             {
7482               if ((AOP_TYPE (right) == AOP_LIT) &&
7483                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7484                 {
7485                   MOVA (aopGet (left, offset, FALSE, FALSE));
7486                 }
7487               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7488                   && AOP_TYPE(left)==AOP_ACC)
7489                 {
7490                   if (offset)
7491                     emitcode("mov", "a,b");
7492                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7493                 }
7494               else if (AOP_TYPE(left)==AOP_ACC)
7495                 {
7496                   if (!offset)
7497                     {
7498                       bool pushedB = pushB ();
7499                       emitcode("mov", "b,a");
7500                       MOVA (aopGet (right, offset, FALSE, FALSE));
7501                       emitcode("xrl", "a,b");
7502                       popB (pushedB);
7503                     }
7504                   else
7505                     {
7506                       MOVA (aopGet (right, offset, FALSE, FALSE));
7507                       emitcode("xrl", "a,b");
7508                     }
7509                 }
7510               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7511                 {
7512                   MOVB (aopGet (left, offset, FALSE, FALSE));
7513                   MOVA (aopGet (right, offset, FALSE, FALSE));
7514                   emitcode ("xrl", "a,b");
7515                 }
7516               else if (aopGetUsesAcc (left, offset))
7517                 {
7518                   MOVA (aopGet (left, offset, FALSE, FALSE));
7519                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7520                 }
7521               else
7522                 {
7523                   MOVA (aopGet (right, offset, FALSE, FALSE));
7524                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7525                 }
7526
7527               emitcode ("jnz", "%05d$", tlbl->key + 100);
7528               offset++;
7529             }
7530           if (size)
7531             {
7532               CLRC;
7533               emitLabel (tlbl);
7534               outBitC (result);
7535             }
7536           else if (ifx)
7537             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7538         }
7539       else
7540         {
7541           for (; (size--); offset++)
7542             {
7543               // normal case
7544               // result = left ^ right
7545               if (AOP_TYPE (right) == AOP_LIT)
7546                 {
7547                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7548                   if (bytelit == 0)
7549                     {
7550                       aopPut (result,
7551                               aopGet (left, offset, FALSE, FALSE),
7552                               offset);
7553                       continue;
7554                     }
7555                 }
7556               // faster than result <- left, xrl result,right
7557               // and better if result is SFR
7558               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7559                   && AOP_TYPE(left)==AOP_ACC)
7560                 {
7561                   if (offset)
7562                     emitcode("mov", "a,b");
7563                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7564                 }
7565               else if (AOP_TYPE(left)==AOP_ACC)
7566                 {
7567                   if (!offset)
7568                     {
7569                       bool pushedB = pushB ();
7570                       emitcode("mov", "b,a");
7571                       MOVA (aopGet (right, offset, FALSE, FALSE));
7572                       emitcode("xrl", "a,b");
7573                       popB (pushedB);
7574                     }
7575                   else
7576                     {
7577                       MOVA (aopGet (right, offset, FALSE, FALSE));
7578                       emitcode("xrl", "a,b");
7579                     }
7580                 }
7581               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7582                 {
7583                   MOVB (aopGet (left, offset, FALSE, FALSE));
7584                   MOVA (aopGet (right, offset, FALSE, FALSE));
7585                   emitcode ("xrl", "a,b");
7586                 }
7587               else if (aopGetUsesAcc (left, offset))
7588                 {
7589                   MOVA (aopGet (left, offset, FALSE, FALSE));
7590                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7591                 }
7592               else
7593                 {
7594                   MOVA (aopGet (right, offset, FALSE, FALSE));
7595                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7596                 }
7597               aopPut (result, "a", offset);
7598             }
7599         }
7600     }
7601
7602 release:
7603   freeAsmop (result, NULL, ic, TRUE);
7604   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7605   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7606 }
7607
7608 /*-----------------------------------------------------------------*/
7609 /* genInline - write the inline code out                           */
7610 /*-----------------------------------------------------------------*/
7611 static void
7612 genInline (iCode * ic)
7613 {
7614   char *buffer, *bp, *bp1;
7615
7616   D (emitcode (";", "genInline"));
7617
7618   _G.inLine += (!options.asmpeep);
7619
7620   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7621
7622   /* emit each line as a code */
7623   while (*bp)
7624     {
7625       if (*bp == '\n')
7626         {
7627           *bp++ = '\0';
7628           emitcode (bp1, "");
7629           bp1 = bp;
7630         }
7631       else
7632         {
7633           /* Add \n for labels, not dirs such as c:\mydir */
7634           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7635             {
7636               bp++;
7637               *bp = '\0';
7638               bp++;
7639               emitcode (bp1, "");
7640               bp1 = bp;
7641             }
7642           else
7643             bp++;
7644         }
7645     }
7646   if (bp1 != bp)
7647     emitcode (bp1, "");
7648   /*     emitcode("",buffer); */
7649   _G.inLine -= (!options.asmpeep);
7650 }
7651
7652 /*-----------------------------------------------------------------*/
7653 /* genRRC - rotate right with carry                                */
7654 /*-----------------------------------------------------------------*/
7655 static void
7656 genRRC (iCode * ic)
7657 {
7658   operand *left, *result;
7659   int size, offset;
7660   char *l;
7661
7662   D (emitcode (";", "genRRC"));
7663
7664   /* rotate right with carry */
7665   left = IC_LEFT (ic);
7666   result = IC_RESULT (ic);
7667   aopOp (left, ic, FALSE);
7668   aopOp (result, ic, FALSE);
7669
7670   /* move it to the result */
7671   size = AOP_SIZE (result);
7672   offset = size - 1;
7673   if (size == 1) { /* special case for 1 byte */
7674       l = aopGet (left, offset, FALSE, FALSE);
7675       MOVA (l);
7676       emitcode ("rr", "a");
7677       goto release;
7678   }
7679   /* no need to clear carry, bit7 will be written later */
7680   while (size--)
7681     {
7682       l = aopGet (left, offset, FALSE, FALSE);
7683       MOVA (l);
7684       emitcode ("rrc", "a");
7685       if (AOP_SIZE (result) > 1)
7686         aopPut (result, "a", offset--);
7687     }
7688   /* now we need to put the carry into the
7689      highest order byte of the result */
7690   if (AOP_SIZE (result) > 1)
7691     {
7692       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7693       MOVA (l);
7694     }
7695   emitcode ("mov", "acc.7,c");
7696  release:
7697   aopPut (result, "a", AOP_SIZE (result) - 1);
7698   freeAsmop (result, NULL, ic, TRUE);
7699   freeAsmop (left, NULL, ic, TRUE);
7700 }
7701
7702 /*-----------------------------------------------------------------*/
7703 /* genRLC - generate code for rotate left with carry               */
7704 /*-----------------------------------------------------------------*/
7705 static void
7706 genRLC (iCode * ic)
7707 {
7708   operand *left, *result;
7709   int size, offset;
7710   char *l;
7711
7712   D (emitcode (";", "genRLC"));
7713
7714   /* rotate right with carry */
7715   left = IC_LEFT (ic);
7716   result = IC_RESULT (ic);
7717   aopOp (left, ic, FALSE);
7718   aopOp (result, ic, FALSE);
7719
7720   /* move it to the result */
7721   size = AOP_SIZE (result);
7722   offset = 0;
7723   if (size--)
7724     {
7725       l = aopGet (left, offset, FALSE, FALSE);
7726       MOVA (l);
7727       if (size == 0) { /* special case for 1 byte */
7728               emitcode("rl","a");
7729               goto release;
7730       }
7731       emitcode("rlc","a"); /* bit0 will be written later */
7732       if (AOP_SIZE (result) > 1)
7733         {
7734           aopPut (result, "a", offset++);
7735         }
7736
7737       while (size--)
7738         {
7739           l = aopGet (left, offset, FALSE, FALSE);
7740           MOVA (l);
7741           emitcode ("rlc", "a");
7742           if (AOP_SIZE (result) > 1)
7743             aopPut (result, "a", offset++);
7744         }
7745     }
7746   /* now we need to put the carry into the
7747      highest order byte of the result */
7748   if (AOP_SIZE (result) > 1)
7749     {
7750       l = aopGet (result, 0, FALSE, FALSE);
7751       MOVA (l);
7752     }
7753   emitcode ("mov", "acc.0,c");
7754  release:
7755   aopPut (result, "a", 0);
7756   freeAsmop (result, NULL, ic, TRUE);
7757   freeAsmop (left, NULL, ic, TRUE);
7758 }
7759
7760 /*-----------------------------------------------------------------*/
7761 /* genGetHbit - generates code get highest order bit               */
7762 /*-----------------------------------------------------------------*/
7763 static void
7764 genGetHbit (iCode * ic)
7765 {
7766   operand *left, *result;
7767
7768   D (emitcode (";", "genGetHbit"));
7769
7770   left = IC_LEFT (ic);
7771   result = IC_RESULT (ic);
7772   aopOp (left, ic, FALSE);
7773   aopOp (result, ic, FALSE);
7774
7775   /* get the highest order byte into a */
7776   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7777   if (AOP_TYPE (result) == AOP_CRY)
7778     {
7779       emitcode ("rlc", "a");
7780       outBitC (result);
7781     }
7782   else
7783     {
7784       emitcode ("rl", "a");
7785       emitcode ("anl", "a,#0x01");
7786       outAcc (result);
7787     }
7788
7789   freeAsmop (result, NULL, ic, TRUE);
7790   freeAsmop (left, NULL, ic, TRUE);
7791 }
7792
7793 /*-----------------------------------------------------------------*/
7794 /* genGetAbit - generates code get a single bit                    */
7795 /*-----------------------------------------------------------------*/
7796 static void
7797 genGetAbit (iCode * ic)
7798 {
7799   operand *left, *right, *result;
7800   int shCount;
7801
7802   D (emitcode (";", "genGetAbit"));
7803
7804   left = IC_LEFT (ic);
7805   right = IC_RIGHT (ic);
7806   result = IC_RESULT (ic);
7807   aopOp (left, ic, FALSE);
7808   aopOp (right, ic, FALSE);
7809   aopOp (result, ic, FALSE);
7810
7811   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7812
7813   /* get the needed byte into a */
7814   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7815   shCount %= 8;
7816   if (AOP_TYPE (result) == AOP_CRY)
7817     {
7818       if ((shCount) == 7)
7819           emitcode ("rlc", "a");
7820       else if ((shCount) == 0)
7821           emitcode ("rrc", "a");
7822       else
7823           emitcode ("mov", "c,acc[%d]", shCount);
7824       outBitC (result);
7825     }
7826   else
7827     {
7828       switch (shCount)
7829         {
7830         case 2:
7831           emitcode ("rr", "a");
7832           //fallthrough
7833         case 1:
7834           emitcode ("rr", "a");
7835           //fallthrough
7836         case 0:
7837           emitcode ("anl", "a,#0x01");
7838           break;
7839         case 3:
7840         case 5:
7841           emitcode ("mov", "c,acc[%d]", shCount);
7842           emitcode ("clr", "a");
7843           emitcode ("rlc", "a");
7844           break;
7845         case 4:
7846           emitcode ("swap", "a");
7847           emitcode ("anl", "a,#0x01");
7848           break;
7849         case 6:
7850           emitcode ("rl", "a");
7851           //fallthrough
7852         case 7:
7853           emitcode ("rl", "a");
7854           emitcode ("anl", "a,#0x01");
7855           break;
7856         }
7857       outAcc (result);
7858     }
7859
7860   freeAsmop (result, NULL, ic, TRUE);
7861   freeAsmop (right, NULL, ic, TRUE);
7862   freeAsmop (left, NULL, ic, TRUE);
7863 }
7864
7865 /*-----------------------------------------------------------------*/
7866 /* genGetByte - generates code get a single byte                   */
7867 /*-----------------------------------------------------------------*/
7868 static void
7869 genGetByte (iCode * ic)
7870 {
7871   operand *left, *right, *result;
7872   int offset;
7873
7874   D (emitcode (";", "genGetByte"));
7875
7876   left = IC_LEFT (ic);
7877   right = IC_RIGHT (ic);
7878   result = IC_RESULT (ic);
7879   aopOp (left, ic, FALSE);
7880   aopOp (right, ic, FALSE);
7881   aopOp (result, ic, FALSE);
7882
7883   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7884   aopPut (result,
7885           aopGet (left, offset, FALSE, FALSE),
7886           0);
7887
7888   freeAsmop (result, NULL, ic, TRUE);
7889   freeAsmop (right, NULL, ic, TRUE);
7890   freeAsmop (left, NULL, ic, TRUE);
7891 }
7892
7893 /*-----------------------------------------------------------------*/
7894 /* genGetWord - generates code get two bytes                       */
7895 /*-----------------------------------------------------------------*/
7896 static void
7897 genGetWord (iCode * ic)
7898 {
7899   operand *left, *right, *result;
7900   int offset;
7901
7902   D (emitcode (";", "genGetWord"));
7903
7904   left = IC_LEFT (ic);
7905   right = IC_RIGHT (ic);
7906   result = IC_RESULT (ic);
7907   aopOp (left, ic, FALSE);
7908   aopOp (right, ic, FALSE);
7909   aopOp (result, ic, FALSE);
7910
7911   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7912   aopPut (result,
7913           aopGet (left, offset, FALSE, FALSE),
7914           0);
7915   aopPut (result,
7916           aopGet (left, offset+1, FALSE, FALSE),
7917           1);
7918
7919   freeAsmop (result, NULL, ic, TRUE);
7920   freeAsmop (right, NULL, ic, TRUE);
7921   freeAsmop (left, NULL, ic, TRUE);
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* genSwap - generates code to swap nibbles or bytes               */
7926 /*-----------------------------------------------------------------*/
7927 static void
7928 genSwap (iCode * ic)
7929 {
7930   operand *left, *result;
7931
7932   D(emitcode (";     genSwap",""));
7933
7934   left = IC_LEFT (ic);
7935   result = IC_RESULT (ic);
7936   aopOp (left, ic, FALSE);
7937   aopOp (result, ic, FALSE);
7938
7939   switch (AOP_SIZE (left))
7940     {
7941     case 1: /* swap nibbles in byte */
7942       MOVA (aopGet (left, 0, FALSE, FALSE));
7943       emitcode ("swap", "a");
7944       aopPut (result, "a", 0);
7945       break;
7946     case 2: /* swap bytes in word */
7947       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7948         {
7949           MOVA (aopGet (left, 0, FALSE, FALSE));
7950           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7951           aopPut (result, "a", 1);
7952         }
7953       else if (operandsEqu (left, result))
7954         {
7955           char * reg = "a";
7956           bool pushedB = FALSE, leftInB = FALSE;
7957
7958           MOVA (aopGet (left, 0, FALSE, FALSE));
7959           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7960             {
7961               pushedB = pushB ();
7962               emitcode ("mov", "b,a");
7963               reg = "b";
7964               leftInB = TRUE;
7965             }
7966           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7967           aopPut (result, reg, 1);
7968
7969           if (leftInB)
7970             popB (pushedB);
7971         }
7972       else
7973         {
7974           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7975           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7976         }
7977       break;
7978     default:
7979       wassertl(FALSE, "unsupported SWAP operand size");
7980     }
7981
7982   freeAsmop (result, NULL, ic, TRUE);
7983   freeAsmop (left, NULL, ic, TRUE);
7984 }
7985
7986 /*-----------------------------------------------------------------*/
7987 /* AccRol - rotate left accumulator by known count                 */
7988 /*-----------------------------------------------------------------*/
7989 static void
7990 AccRol (int shCount)
7991 {
7992   shCount &= 0x0007;            // shCount : 0..7
7993
7994   switch (shCount)
7995     {
7996     case 0:
7997       break;
7998     case 1:
7999       emitcode ("rl", "a");
8000       break;
8001     case 2:
8002       emitcode ("rl", "a");
8003       emitcode ("rl", "a");
8004       break;
8005     case 3:
8006       emitcode ("swap", "a");
8007       emitcode ("rr", "a");
8008       break;
8009     case 4:
8010       emitcode ("swap", "a");
8011       break;
8012     case 5:
8013       emitcode ("swap", "a");
8014       emitcode ("rl", "a");
8015       break;
8016     case 6:
8017       emitcode ("rr", "a");
8018       emitcode ("rr", "a");
8019       break;
8020     case 7:
8021       emitcode ("rr", "a");
8022       break;
8023     }
8024 }
8025
8026 /*-----------------------------------------------------------------*/
8027 /* AccLsh - left shift accumulator by known count                  */
8028 /*-----------------------------------------------------------------*/
8029 static void
8030 AccLsh (int shCount)
8031 {
8032   if (shCount != 0)
8033     {
8034       if (shCount == 1)
8035         emitcode ("add", "a,acc");
8036       else if (shCount == 2)
8037         {
8038           emitcode ("add", "a,acc");
8039           emitcode ("add", "a,acc");
8040         }
8041       else
8042         {
8043           /* rotate left accumulator */
8044           AccRol (shCount);
8045           /* and kill the lower order bits */
8046           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8047         }
8048     }
8049 }
8050
8051 /*-----------------------------------------------------------------*/
8052 /* AccRsh - right shift accumulator by known count                 */
8053 /*-----------------------------------------------------------------*/
8054 static void
8055 AccRsh (int shCount)
8056 {
8057   if (shCount != 0)
8058     {
8059       if (shCount == 1)
8060         {
8061           CLRC;
8062           emitcode ("rrc", "a");
8063         }
8064       else
8065         {
8066           /* rotate right accumulator */
8067           AccRol (8 - shCount);
8068           /* and kill the higher order bits */
8069           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8070         }
8071     }
8072 }
8073
8074 /*-----------------------------------------------------------------*/
8075 /* AccSRsh - signed right shift accumulator by known count                 */
8076 /*-----------------------------------------------------------------*/
8077 static void
8078 AccSRsh (int shCount)
8079 {
8080   symbol *tlbl;
8081   if (shCount != 0)
8082     {
8083       if (shCount == 1)
8084         {
8085           emitcode ("mov", "c,acc.7");
8086           emitcode ("rrc", "a");
8087         }
8088       else if (shCount == 2)
8089         {
8090           emitcode ("mov", "c,acc.7");
8091           emitcode ("rrc", "a");
8092           emitcode ("mov", "c,acc.7");
8093           emitcode ("rrc", "a");
8094         }
8095       else
8096         {
8097           tlbl = newiTempLabel (NULL);
8098           /* rotate right accumulator */
8099           AccRol (8 - shCount);
8100           /* and kill the higher order bits */
8101           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8102           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8103           emitcode ("orl", "a,#0x%02x",
8104                     (unsigned char) ~SRMask[shCount]);
8105           emitLabel (tlbl);
8106         }
8107     }
8108 }
8109
8110 /*-----------------------------------------------------------------*/
8111 /* shiftR1Left2Result - shift right one byte from left to result   */
8112 /*-----------------------------------------------------------------*/
8113 static void
8114 shiftR1Left2Result (operand * left, int offl,
8115                     operand * result, int offr,
8116                     int shCount, int sign)
8117 {
8118   MOVA (aopGet (left, offl, FALSE, FALSE));
8119   /* shift right accumulator */
8120   if (sign)
8121     AccSRsh (shCount);
8122   else
8123     AccRsh (shCount);
8124   aopPut (result, "a", offr);
8125 }
8126
8127 /*-----------------------------------------------------------------*/
8128 /* shiftL1Left2Result - shift left one byte from left to result    */
8129 /*-----------------------------------------------------------------*/
8130 static void
8131 shiftL1Left2Result (operand * left, int offl,
8132                     operand * result, int offr, int shCount)
8133 {
8134   char *l;
8135   l = aopGet (left, offl, FALSE, FALSE);
8136   MOVA (l);
8137   /* shift left accumulator */
8138   AccLsh (shCount);
8139   aopPut (result, "a", offr);
8140 }
8141
8142 /*-----------------------------------------------------------------*/
8143 /* movLeft2Result - move byte from left to result                  */
8144 /*-----------------------------------------------------------------*/
8145 static void
8146 movLeft2Result (operand * left, int offl,
8147                 operand * result, int offr, int sign)
8148 {
8149   char *l;
8150   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8151     {
8152       l = aopGet (left, offl, FALSE, FALSE);
8153
8154       if (*l == '@' && (IS_AOP_PREG (result)))
8155         {
8156           emitcode ("mov", "a,%s", l);
8157           aopPut (result, "a", offr);
8158         }
8159       else
8160         {
8161           if (!sign)
8162             {
8163               aopPut (result, l, offr);
8164             }
8165           else
8166             {
8167               /* MSB sign in acc.7 ! */
8168               if (getDataSize (left) == offl + 1)
8169                 {
8170                   MOVA (l);
8171                   aopPut (result, "a", offr);
8172                 }
8173             }
8174         }
8175     }
8176 }
8177
8178 /*-----------------------------------------------------------------*/
8179 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8180 /*-----------------------------------------------------------------*/
8181 static void
8182 AccAXRrl1 (char *x)
8183 {
8184   emitcode ("rrc", "a");
8185   emitcode ("xch", "a,%s", x);
8186   emitcode ("rrc", "a");
8187   emitcode ("xch", "a,%s", x);
8188 }
8189
8190 /*-----------------------------------------------------------------*/
8191 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8192 /*-----------------------------------------------------------------*/
8193 static void
8194 AccAXLrl1 (char *x)
8195 {
8196   emitcode ("xch", "a,%s", x);
8197   emitcode ("rlc", "a");
8198   emitcode ("xch", "a,%s", x);
8199   emitcode ("rlc", "a");
8200 }
8201
8202 /*-----------------------------------------------------------------*/
8203 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8204 /*-----------------------------------------------------------------*/
8205 static void
8206 AccAXLsh1 (char *x)
8207 {
8208   emitcode ("xch", "a,%s", x);
8209   emitcode ("add", "a,acc");
8210   emitcode ("xch", "a,%s", x);
8211   emitcode ("rlc", "a");
8212 }
8213
8214 /*-----------------------------------------------------------------*/
8215 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8216 /*-----------------------------------------------------------------*/
8217 static void
8218 AccAXLsh (char *x, int shCount)
8219 {
8220   switch (shCount)
8221     {
8222     case 0:
8223       break;
8224     case 1:
8225       AccAXLsh1 (x);
8226       break;
8227     case 2:
8228       AccAXLsh1 (x);
8229       AccAXLsh1 (x);
8230       break;
8231     case 3:
8232     case 4:
8233     case 5:                     // AAAAABBB:CCCCCDDD
8234
8235       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8236
8237       emitcode ("anl", "a,#0x%02x",
8238                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8239
8240       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8241
8242       AccRol (shCount);         // DDDCCCCC:BBB00000
8243
8244       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8245
8246       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8247
8248       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8249
8250       emitcode ("anl", "a,#0x%02x",
8251                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8252
8253       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8254
8255       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8256
8257       break;
8258     case 6:                     // AAAAAABB:CCCCCCDD
8259       emitcode ("anl", "a,#0x%02x",
8260                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8261       emitcode ("mov", "c,acc.0");      // c = B
8262       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8263 #if 0 // REMOVE ME
8264       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8265       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8266 #else
8267       emitcode("rrc","a");
8268       emitcode("xch","a,%s", x);
8269       emitcode("rrc","a");
8270       emitcode("mov","c,acc.0"); //<< get correct bit
8271       emitcode("xch","a,%s", x);
8272
8273       emitcode("rrc","a");
8274       emitcode("xch","a,%s", x);
8275       emitcode("rrc","a");
8276       emitcode("xch","a,%s", x);
8277 #endif
8278       break;
8279     case 7:                     // a:x <<= 7
8280
8281       emitcode ("anl", "a,#0x%02x",
8282                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8283
8284       emitcode ("mov", "c,acc.0");      // c = B
8285
8286       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8287
8288       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8289
8290       break;
8291     default:
8292       break;
8293     }
8294 }
8295
8296 /*-----------------------------------------------------------------*/
8297 /* AccAXRsh - right shift a:x known count (0..7)                   */
8298 /*-----------------------------------------------------------------*/
8299 static void
8300 AccAXRsh (char *x, int shCount)
8301 {
8302   switch (shCount)
8303     {
8304     case 0:
8305       break;
8306     case 1:
8307       CLRC;
8308       AccAXRrl1 (x);            // 0->a:x
8309
8310       break;
8311     case 2:
8312       CLRC;
8313       AccAXRrl1 (x);            // 0->a:x
8314
8315       CLRC;
8316       AccAXRrl1 (x);            // 0->a:x
8317
8318       break;
8319     case 3:
8320     case 4:
8321     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8322
8323       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8324
8325       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8326
8327       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8328
8329       emitcode ("anl", "a,#0x%02x",
8330                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8331
8332       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8333
8334       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8335
8336       emitcode ("anl", "a,#0x%02x",
8337                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8338
8339       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8340
8341       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8342
8343       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8344
8345       break;
8346     case 6:                     // AABBBBBB:CCDDDDDD
8347
8348       emitcode ("mov", "c,acc.7");
8349       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8350
8351       emitcode ("mov", "c,acc.7");
8352       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8353
8354       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8355
8356       emitcode ("anl", "a,#0x%02x",
8357                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8358
8359       break;
8360     case 7:                     // ABBBBBBB:CDDDDDDD
8361
8362       emitcode ("mov", "c,acc.7");      // c = A
8363
8364       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8365
8366       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8367
8368       emitcode ("anl", "a,#0x%02x",
8369                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8370
8371       break;
8372     default:
8373       break;
8374     }
8375 }
8376
8377 /*-----------------------------------------------------------------*/
8378 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8379 /*-----------------------------------------------------------------*/
8380 static void
8381 AccAXRshS (char *x, int shCount)
8382 {
8383   symbol *tlbl;
8384   switch (shCount)
8385     {
8386     case 0:
8387       break;
8388     case 1:
8389       emitcode ("mov", "c,acc.7");
8390       AccAXRrl1 (x);            // s->a:x
8391
8392       break;
8393     case 2:
8394       emitcode ("mov", "c,acc.7");
8395       AccAXRrl1 (x);            // s->a:x
8396
8397       emitcode ("mov", "c,acc.7");
8398       AccAXRrl1 (x);            // s->a:x
8399
8400       break;
8401     case 3:
8402     case 4:
8403     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8404
8405       tlbl = newiTempLabel (NULL);
8406       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8407
8408       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8409
8410       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8411
8412       emitcode ("anl", "a,#0x%02x",
8413                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8414
8415       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8416
8417       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8418
8419       emitcode ("anl", "a,#0x%02x",
8420                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8421
8422       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8423
8424       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8425
8426       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8427
8428       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8429       emitcode ("orl", "a,#0x%02x",
8430                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8431
8432       emitLabel (tlbl);
8433       break;                    // SSSSAAAA:BBBCCCCC
8434
8435     case 6:                     // AABBBBBB:CCDDDDDD
8436
8437       tlbl = newiTempLabel (NULL);
8438       emitcode ("mov", "c,acc.7");
8439       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8440
8441       emitcode ("mov", "c,acc.7");
8442       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8443
8444       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8445
8446       emitcode ("anl", "a,#0x%02x",
8447                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8448
8449       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8450       emitcode ("orl", "a,#0x%02x",
8451                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8452
8453       emitLabel (tlbl);
8454       break;
8455     case 7:                     // ABBBBBBB:CDDDDDDD
8456
8457       tlbl = newiTempLabel (NULL);
8458       emitcode ("mov", "c,acc.7");      // c = A
8459
8460       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8461
8462       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8463
8464       emitcode ("anl", "a,#0x%02x",
8465                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8466
8467       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8468       emitcode ("orl", "a,#0x%02x",
8469                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8470
8471       emitLabel (tlbl);
8472       break;
8473     default:
8474       break;
8475     }
8476 }
8477
8478 /*-----------------------------------------------------------------*/
8479 /* shiftL2Left2Result - shift left two bytes from left to result   */
8480 /*-----------------------------------------------------------------*/
8481 static void
8482 shiftL2Left2Result (operand * left, int offl,
8483                     operand * result, int offr, int shCount)
8484 {
8485   char * x;
8486   bool pushedB = FALSE;
8487   bool usedB = FALSE;
8488
8489   if (sameRegs (AOP (result), AOP (left)) &&
8490       ((offl + MSB16) == offr))
8491     {
8492       /* don't crash result[offr] */
8493       MOVA (aopGet (left, offl, FALSE, FALSE));
8494       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8495       usedB = !strncmp(x, "b", 1);
8496     }
8497   else if (aopGetUsesAcc (result, offr))
8498     {
8499       movLeft2Result (left, offl, result, offr, 0);
8500       pushedB = pushB ();
8501       usedB = TRUE;
8502       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8503       MOVA (aopGet (result, offr, FALSE, FALSE));
8504       emitcode ("xch", "a,b");
8505       x = "b";
8506     }
8507   else
8508     {
8509       movLeft2Result (left, offl, result, offr, 0);
8510       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8511       x = aopGet (result, offr, FALSE, FALSE);
8512     }
8513   /* ax << shCount (x = lsb(result)) */
8514   AccAXLsh (x, shCount);
8515   if (usedB)
8516     {
8517       emitcode ("xch", "a,b");
8518       aopPut (result, "a", offr);
8519       aopPut (result, "b", offr + MSB16);
8520       popB (pushedB);
8521     }
8522   else
8523     {
8524       aopPut (result, "a", offr + MSB16);
8525     }
8526 }
8527
8528
8529 /*-----------------------------------------------------------------*/
8530 /* shiftR2Left2Result - shift right two bytes from left to result  */
8531 /*-----------------------------------------------------------------*/
8532 static void
8533 shiftR2Left2Result (operand * left, int offl,
8534                     operand * result, int offr,
8535                     int shCount, int sign)
8536 {
8537   char * x;
8538   bool pushedB = FALSE;
8539   bool usedB = FALSE;
8540
8541   if (sameRegs (AOP (result), AOP (left)) &&
8542       ((offl + MSB16) == offr))
8543     {
8544       /* don't crash result[offr] */
8545       MOVA (aopGet (left, offl, FALSE, FALSE));
8546       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8547       usedB = !strncmp(x, "b", 1);
8548     }
8549   else if (aopGetUsesAcc (result, offr))
8550     {
8551       movLeft2Result (left, offl, result, offr, 0);
8552       pushedB = pushB ();
8553       usedB = TRUE;
8554       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8555       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8556       x = "b";
8557     }
8558   else
8559     {
8560       movLeft2Result (left, offl, result, offr, 0);
8561       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8562       x = aopGet (result, offr, FALSE, FALSE);
8563     }
8564   /* a:x >> shCount (x = lsb(result)) */
8565   if (sign)
8566     AccAXRshS (x, shCount);
8567   else
8568     AccAXRsh (x, shCount);
8569   if (usedB)
8570     {
8571       emitcode ("xch", "a,b");
8572       aopPut (result, "a", offr);
8573       emitcode ("xch", "a,b");
8574       popB (pushedB);
8575     }
8576   if (getDataSize (result) > 1)
8577     aopPut (result, "a", offr + MSB16);
8578 }
8579
8580 /*-----------------------------------------------------------------*/
8581 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8582 /*-----------------------------------------------------------------*/
8583 static void
8584 shiftLLeftOrResult (operand * left, int offl,
8585                     operand * result, int offr, int shCount)
8586 {
8587   MOVA (aopGet (left, offl, FALSE, FALSE));
8588   /* shift left accumulator */
8589   AccLsh (shCount);
8590   /* or with result */
8591   if (aopGetUsesAcc (result, offr))
8592     {
8593       emitcode ("xch", "a,b");
8594       MOVA (aopGet (result, offr, FALSE, FALSE));
8595       emitcode ("orl", "a,b");
8596     }
8597   else
8598     {
8599       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8600     }
8601   /* back to result */
8602   aopPut (result, "a", offr);
8603 }
8604
8605 /*-----------------------------------------------------------------*/
8606 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8607 /*-----------------------------------------------------------------*/
8608 static void
8609 shiftRLeftOrResult (operand * left, int offl,
8610                     operand * result, int offr, int shCount)
8611 {
8612   MOVA (aopGet (left, offl, FALSE, FALSE));
8613   /* shift right accumulator */
8614   AccRsh (shCount);
8615   /* or with result */
8616   if (aopGetUsesAcc(result, offr))
8617     {
8618       emitcode ("xch", "a,b");
8619       MOVA (aopGet (result, offr, FALSE, FALSE));
8620       emitcode ("orl", "a,b");
8621     }
8622   else
8623     {
8624       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8625     }
8626   /* back to result */
8627   aopPut (result, "a", offr);
8628 }
8629
8630 /*-----------------------------------------------------------------*/
8631 /* genlshOne - left shift a one byte quantity by known count       */
8632 /*-----------------------------------------------------------------*/
8633 static void
8634 genlshOne (operand * result, operand * left, int shCount)
8635 {
8636   D (emitcode (";", "genlshOne"));
8637
8638   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8639 }
8640
8641 /*-----------------------------------------------------------------*/
8642 /* genlshTwo - left shift two bytes by known amount != 0           */
8643 /*-----------------------------------------------------------------*/
8644 static void
8645 genlshTwo (operand * result, operand * left, int shCount)
8646 {
8647   int size;
8648
8649   D (emitcode (";", "genlshTwo"));
8650
8651   size = getDataSize (result);
8652
8653   /* if shCount >= 8 */
8654   if (shCount >= 8)
8655     {
8656       shCount -= 8;
8657
8658       if (size > 1)
8659         {
8660           if (shCount)
8661             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8662           else
8663             movLeft2Result (left, LSB, result, MSB16, 0);
8664         }
8665       aopPut (result, zero, LSB);
8666     }
8667
8668   /*  1 <= shCount <= 7 */
8669   else
8670     {
8671       if (size == 1)
8672         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8673       else
8674         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8675     }
8676 }
8677
8678 /*-----------------------------------------------------------------*/
8679 /* shiftLLong - shift left one long from left to result            */
8680 /* offl = LSB or MSB16                                             */
8681 /*-----------------------------------------------------------------*/
8682 static void
8683 shiftLLong (operand * left, operand * result, int offr)
8684 {
8685   char *l;
8686   int size = AOP_SIZE (result);
8687
8688   if (size >= LSB + offr)
8689     {
8690       l = aopGet (left, LSB, FALSE, FALSE);
8691       MOVA (l);
8692       emitcode ("add", "a,acc");
8693       if (sameRegs (AOP (left), AOP (result)) &&
8694           size >= MSB16 + offr && offr != LSB)
8695         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8696       else
8697         aopPut (result, "a", LSB + offr);
8698     }
8699
8700   if (size >= MSB16 + offr)
8701     {
8702       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8703         {
8704           l = aopGet (left, MSB16, FALSE, FALSE);
8705           MOVA (l);
8706         }
8707       emitcode ("rlc", "a");
8708       if (sameRegs (AOP (left), AOP (result)) &&
8709           size >= MSB24 + offr && offr != LSB)
8710         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8711       else
8712         aopPut (result, "a", MSB16 + offr);
8713     }
8714
8715   if (size >= MSB24 + offr)
8716     {
8717       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8718         {
8719           l = aopGet (left, MSB24, FALSE, FALSE);
8720           MOVA (l);
8721         }
8722       emitcode ("rlc", "a");
8723       if (sameRegs (AOP (left), AOP (result)) &&
8724           size >= MSB32 + offr && offr != LSB)
8725         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8726       else
8727         aopPut (result, "a", MSB24 + offr);
8728     }
8729
8730   if (size > MSB32 + offr)
8731     {
8732       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8733         {
8734           l = aopGet (left, MSB32, FALSE, FALSE);
8735           MOVA (l);
8736         }
8737       emitcode ("rlc", "a");
8738       aopPut (result, "a", MSB32 + offr);
8739     }
8740   if (offr != LSB)
8741     aopPut (result, zero, LSB);
8742 }
8743
8744 /*-----------------------------------------------------------------*/
8745 /* genlshFour - shift four byte by a known amount != 0             */
8746 /*-----------------------------------------------------------------*/
8747 static void
8748 genlshFour (operand * result, operand * left, int shCount)
8749 {
8750   int size;
8751
8752   D (emitcode (";", "genlshFour"));
8753
8754   size = AOP_SIZE (result);
8755
8756   /* if shifting more that 3 bytes */
8757   if (shCount >= 24)
8758     {
8759       shCount -= 24;
8760       if (shCount)
8761         /* lowest order of left goes to the highest
8762            order of the destination */
8763         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8764       else
8765         movLeft2Result (left, LSB, result, MSB32, 0);
8766       aopPut (result, zero, LSB);
8767       aopPut (result, zero, MSB16);
8768       aopPut (result, zero, MSB24);
8769       return;
8770     }
8771
8772   /* more than two bytes */
8773   else if (shCount >= 16)
8774     {
8775       /* lower order two bytes goes to higher order two bytes */
8776       shCount -= 16;
8777       /* if some more remaining */
8778       if (shCount)
8779         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8780       else
8781         {
8782           movLeft2Result (left, MSB16, result, MSB32, 0);
8783           movLeft2Result (left, LSB, result, MSB24, 0);
8784         }
8785       aopPut (result, zero, MSB16);
8786       aopPut (result, zero, LSB);
8787       return;
8788     }
8789
8790   /* if more than 1 byte */
8791   else if (shCount >= 8)
8792     {
8793       /* lower order three bytes goes to higher order  three bytes */
8794       shCount -= 8;
8795       if (size == 2)
8796         {
8797           if (shCount)
8798             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8799           else
8800             movLeft2Result (left, LSB, result, MSB16, 0);
8801         }
8802       else
8803         {                       /* size = 4 */
8804           if (shCount == 0)
8805             {
8806               movLeft2Result (left, MSB24, result, MSB32, 0);
8807               movLeft2Result (left, MSB16, result, MSB24, 0);
8808               movLeft2Result (left, LSB, result, MSB16, 0);
8809               aopPut (result, zero, LSB);
8810             }
8811           else if (shCount == 1)
8812             shiftLLong (left, result, MSB16);
8813           else
8814             {
8815               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8816               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8817               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8818               aopPut (result, zero, LSB);
8819             }
8820         }
8821     }
8822
8823   /* 1 <= shCount <= 7 */
8824   else if (shCount <= 2)
8825     {
8826       shiftLLong (left, result, LSB);
8827       if (shCount == 2)
8828         shiftLLong (result, result, LSB);
8829     }
8830   /* 3 <= shCount <= 7, optimize */
8831   else
8832     {
8833       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8834       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8835       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8836     }
8837 }
8838
8839 /*-----------------------------------------------------------------*/
8840 /* genLeftShiftLiteral - left shifting by known count              */
8841 /*-----------------------------------------------------------------*/
8842 static void
8843 genLeftShiftLiteral (operand * left,
8844                      operand * right,
8845                      operand * result,
8846                      iCode * ic)
8847 {
8848   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8849   int size;
8850
8851   D (emitcode (";", "genLeftShiftLiteral"));
8852
8853   freeAsmop (right, NULL, ic, TRUE);
8854
8855   aopOp (left, ic, FALSE);
8856   aopOp (result, ic, FALSE);
8857
8858   size = getSize (operandType (result));
8859
8860 #if VIEW_SIZE
8861   emitcode ("; shift left ", "result %d, left %d", size,
8862             AOP_SIZE (left));
8863 #endif
8864
8865   /* I suppose that the left size >= result size */
8866   if (shCount == 0)
8867     {
8868       while (size--)
8869         {
8870           movLeft2Result (left, size, result, size, 0);
8871         }
8872     }
8873   else if (shCount >= (size * 8))
8874     {
8875       while (size--)
8876         {
8877           aopPut (result, zero, size);
8878         }
8879     }
8880   else
8881     {
8882       switch (size)
8883         {
8884         case 1:
8885           genlshOne (result, left, shCount);
8886           break;
8887
8888         case 2:
8889           genlshTwo (result, left, shCount);
8890           break;
8891
8892         case 4:
8893           genlshFour (result, left, shCount);
8894           break;
8895         default:
8896           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8897                   "*** ack! mystery literal shift!\n");
8898           break;
8899         }
8900     }
8901   freeAsmop (result, NULL, ic, TRUE);
8902   freeAsmop (left, NULL, ic, TRUE);
8903 }
8904
8905 /*-----------------------------------------------------------------*/
8906 /* genLeftShift - generates code for left shifting                 */
8907 /*-----------------------------------------------------------------*/
8908 static void
8909 genLeftShift (iCode * ic)
8910 {
8911   operand *left, *right, *result;
8912   int size, offset;
8913   char *l;
8914   symbol *tlbl, *tlbl1;
8915   bool pushedB;
8916
8917   D (emitcode (";", "genLeftShift"));
8918
8919   right = IC_RIGHT (ic);
8920   left = IC_LEFT (ic);
8921   result = IC_RESULT (ic);
8922
8923   aopOp (right, ic, FALSE);
8924
8925   /* if the shift count is known then do it
8926      as efficiently as possible */
8927   if (AOP_TYPE (right) == AOP_LIT)
8928     {
8929       genLeftShiftLiteral (left, right, result, ic);
8930       return;
8931     }
8932
8933   /* shift count is unknown then we have to form
8934      a loop get the loop count in B : Note: we take
8935      only the lower order byte since shifting
8936      more that 32 bits make no sense anyway, ( the
8937      largest size of an object can be only 32 bits ) */
8938
8939   pushedB = pushB ();
8940   MOVB (aopGet (right, 0, FALSE, FALSE));
8941   emitcode ("inc", "b");
8942   freeAsmop (right, NULL, ic, TRUE);
8943   aopOp (left, ic, FALSE);
8944   aopOp (result, ic, FALSE);
8945
8946   /* now move the left to the result if they are not the same */
8947   if (!sameRegs (AOP (left), AOP (result)) &&
8948       AOP_SIZE (result) > 1)
8949     {
8950
8951       size = AOP_SIZE (result);
8952       offset = 0;
8953       while (size--)
8954         {
8955           l = aopGet (left, offset, FALSE, TRUE);
8956           if (*l == '@' && (IS_AOP_PREG (result)))
8957             {
8958
8959               emitcode ("mov", "a,%s", l);
8960               aopPut (result, "a", offset);
8961             }
8962           else
8963             aopPut (result, l, offset);
8964           offset++;
8965         }
8966     }
8967
8968   tlbl = newiTempLabel (NULL);
8969   size = AOP_SIZE (result);
8970   offset = 0;
8971   tlbl1 = newiTempLabel (NULL);
8972
8973   /* if it is only one byte then */
8974   if (size == 1)
8975     {
8976       symbol *tlbl1 = newiTempLabel (NULL);
8977
8978       l = aopGet (left, 0, FALSE, FALSE);
8979       MOVA (l);
8980       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8981       emitLabel (tlbl);
8982       emitcode ("add", "a,acc");
8983       emitLabel (tlbl1);
8984       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8985       popB (pushedB);
8986       aopPut (result, "a", 0);
8987       goto release;
8988     }
8989
8990   reAdjustPreg (AOP (result));
8991
8992   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8993   emitLabel (tlbl);
8994   l = aopGet (result, offset, FALSE, FALSE);
8995   MOVA (l);
8996   emitcode ("add", "a,acc");
8997   aopPut (result, "a", offset++);
8998   while (--size)
8999     {
9000       l = aopGet (result, offset, FALSE, FALSE);
9001       MOVA (l);
9002       emitcode ("rlc", "a");
9003       aopPut (result, "a", offset++);
9004     }
9005   reAdjustPreg (AOP (result));
9006
9007   emitLabel (tlbl1);
9008   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9009   popB (pushedB);
9010 release:
9011   freeAsmop (result, NULL, ic, TRUE);
9012   freeAsmop (left, NULL, ic, TRUE);
9013 }
9014
9015 /*-----------------------------------------------------------------*/
9016 /* genrshOne - right shift a one byte quantity by known count      */
9017 /*-----------------------------------------------------------------*/
9018 static void
9019 genrshOne (operand * result, operand * left,
9020            int shCount, int sign)
9021 {
9022   D (emitcode (";", "genrshOne"));
9023
9024   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9025 }
9026
9027 /*-----------------------------------------------------------------*/
9028 /* genrshTwo - right shift two bytes by known amount != 0          */
9029 /*-----------------------------------------------------------------*/
9030 static void
9031 genrshTwo (operand * result, operand * left,
9032            int shCount, int sign)
9033 {
9034   D (emitcode (";", "genrshTwo"));
9035
9036   /* if shCount >= 8 */
9037   if (shCount >= 8)
9038     {
9039       shCount -= 8;
9040       if (shCount)
9041         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9042       else
9043         movLeft2Result (left, MSB16, result, LSB, sign);
9044       addSign (result, MSB16, sign);
9045     }
9046
9047   /*  1 <= shCount <= 7 */
9048   else
9049     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9050 }
9051
9052 /*-----------------------------------------------------------------*/
9053 /* shiftRLong - shift right one long from left to result           */
9054 /* offl = LSB or MSB16                                             */
9055 /*-----------------------------------------------------------------*/
9056 static void
9057 shiftRLong (operand * left, int offl,
9058             operand * result, int sign)
9059 {
9060   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9061
9062   if (overlapping && offl>1)
9063     {
9064       // we are in big trouble, but this shouldn't happen
9065       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9066     }
9067
9068   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9069
9070   if (offl==MSB16)
9071     {
9072       // shift is > 8
9073       if (sign)
9074         {
9075           emitcode ("rlc", "a");
9076           emitcode ("subb", "a,acc");
9077           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9078             {
9079               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9080             }
9081           else
9082             {
9083               aopPut (result, "a", MSB32);
9084               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9085             }
9086         }
9087       else
9088         {
9089           if (aopPutUsesAcc (result, zero, MSB32))
9090             {
9091               emitcode("xch", "a,b");
9092               aopPut (result, zero, MSB32);
9093               emitcode("xch", "a,b");
9094             }
9095           else
9096             {
9097               aopPut (result, zero, MSB32);
9098             }
9099         }
9100     }
9101
9102   if (!sign)
9103     {
9104       emitcode ("clr", "c");
9105     }
9106   else
9107     {
9108       emitcode ("mov", "c,acc.7");
9109     }
9110
9111   emitcode ("rrc", "a");
9112
9113   if (overlapping && offl==MSB16 &&
9114       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9115     {
9116       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9117     }
9118   else
9119     {
9120       aopPut (result, "a", MSB32 - offl);
9121       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9122     }
9123
9124   emitcode ("rrc", "a");
9125   if (overlapping && offl==MSB16 &&
9126       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9127     {
9128       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9129     }
9130   else
9131     {
9132       aopPut (result, "a", MSB24 - offl);
9133       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9134     }
9135
9136   emitcode ("rrc", "a");
9137   if (offl != LSB)
9138     {
9139       aopPut (result, "a", MSB16 - offl);
9140     }
9141   else
9142     {
9143       if (overlapping &&
9144           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9145         {
9146           xch_a_aopGet (left, LSB, FALSE, FALSE);
9147         }
9148       else
9149         {
9150           aopPut (result, "a", MSB16 - offl);
9151           MOVA (aopGet (left, LSB, FALSE, FALSE));
9152         }
9153       emitcode ("rrc", "a");
9154       aopPut (result, "a", LSB);
9155     }
9156 }
9157
9158 /*-----------------------------------------------------------------*/
9159 /* genrshFour - shift four byte by a known amount != 0             */
9160 /*-----------------------------------------------------------------*/
9161 static void
9162 genrshFour (operand * result, operand * left,
9163             int shCount, int sign)
9164 {
9165   D (emitcode (";", "genrshFour"));
9166
9167   /* if shifting more that 3 bytes */
9168   if (shCount >= 24)
9169     {
9170       shCount -= 24;
9171       if (shCount)
9172         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9173       else
9174         movLeft2Result (left, MSB32, result, LSB, sign);
9175       addSign (result, MSB16, sign);
9176     }
9177   else if (shCount >= 16)
9178     {
9179       shCount -= 16;
9180       if (shCount)
9181         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9182       else
9183         {
9184           movLeft2Result (left, MSB24, result, LSB, 0);
9185           movLeft2Result (left, MSB32, result, MSB16, sign);
9186         }
9187       addSign (result, MSB24, sign);
9188     }
9189   else if (shCount >= 8)
9190     {
9191       shCount -= 8;
9192       if (shCount == 1)
9193         {
9194           shiftRLong (left, MSB16, result, sign);
9195         }
9196       else if (shCount == 0)
9197         {
9198           movLeft2Result (left, MSB16, result, LSB, 0);
9199           movLeft2Result (left, MSB24, result, MSB16, 0);
9200           movLeft2Result (left, MSB32, result, MSB24, sign);
9201           addSign (result, MSB32, sign);
9202         }
9203       else
9204         {
9205           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9206           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9207           /* the last shift is signed */
9208           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9209           addSign (result, MSB32, sign);
9210         }
9211     }
9212   else
9213     {
9214       /* 1 <= shCount <= 7 */
9215       if (shCount <= 2)
9216         {
9217           shiftRLong (left, LSB, result, sign);
9218           if (shCount == 2)
9219             shiftRLong (result, LSB, result, sign);
9220         }
9221       else
9222         {
9223           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9224           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9225           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9226         }
9227     }
9228 }
9229
9230 /*-----------------------------------------------------------------*/
9231 /* genRightShiftLiteral - right shifting by known count            */
9232 /*-----------------------------------------------------------------*/
9233 static void
9234 genRightShiftLiteral (operand * left,
9235                       operand * right,
9236                       operand * result,
9237                       iCode * ic,
9238                       int sign)
9239 {
9240   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9241   int size;
9242
9243   D (emitcode (";", "genRightShiftLiteral"));
9244
9245   freeAsmop (right, NULL, ic, TRUE);
9246
9247   aopOp (left, ic, FALSE);
9248   aopOp (result, ic, FALSE);
9249
9250 #if VIEW_SIZE
9251   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9252             AOP_SIZE (left));
9253 #endif
9254
9255   size = getDataSize (left);
9256   /* test the LEFT size !!! */
9257
9258   /* I suppose that the left size >= result size */
9259   if (shCount == 0)
9260     {
9261       size = getDataSize (result);
9262       while (size--)
9263         movLeft2Result (left, size, result, size, 0);
9264     }
9265
9266   else if (shCount >= (size * 8))
9267     {
9268       if (sign)
9269         {
9270           /* get sign in acc.7 */
9271           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9272         }
9273       addSign (result, LSB, sign);
9274     }
9275   else
9276     {
9277       switch (size)
9278         {
9279         case 1:
9280           genrshOne (result, left, shCount, sign);
9281           break;
9282
9283         case 2:
9284           genrshTwo (result, left, shCount, sign);
9285           break;
9286
9287         case 4:
9288           genrshFour (result, left, shCount, sign);
9289           break;
9290         default:
9291           break;
9292         }
9293     }
9294   freeAsmop (result, NULL, ic, TRUE);
9295   freeAsmop (left, NULL, ic, TRUE);
9296 }
9297
9298 /*-----------------------------------------------------------------*/
9299 /* genSignedRightShift - right shift of signed number              */
9300 /*-----------------------------------------------------------------*/
9301 static void
9302 genSignedRightShift (iCode * ic)
9303 {
9304   operand *right, *left, *result;
9305   int size, offset;
9306   char *l;
9307   symbol *tlbl, *tlbl1;
9308   bool pushedB;
9309
9310   D (emitcode (";", "genSignedRightShift"));
9311
9312   /* we do it the hard way put the shift count in b
9313      and loop thru preserving the sign */
9314
9315   right = IC_RIGHT (ic);
9316   left = IC_LEFT (ic);
9317   result = IC_RESULT (ic);
9318
9319   aopOp (right, ic, FALSE);
9320
9321
9322   if (AOP_TYPE (right) == AOP_LIT)
9323     {
9324       genRightShiftLiteral (left, right, result, ic, 1);
9325       return;
9326     }
9327   /* shift count is unknown then we have to form
9328      a loop get the loop count in B : Note: we take
9329      only the lower order byte since shifting
9330      more that 32 bits make no sense anyway, ( the
9331      largest size of an object can be only 32 bits ) */
9332
9333   pushedB = pushB ();
9334   MOVB (aopGet (right, 0, FALSE, FALSE));
9335   emitcode ("inc", "b");
9336   freeAsmop (right, NULL, ic, TRUE);
9337   aopOp (left, ic, FALSE);
9338   aopOp (result, ic, FALSE);
9339
9340   /* now move the left to the result if they are not the
9341      same */
9342   if (!sameRegs (AOP (left), AOP (result)) &&
9343       AOP_SIZE (result) > 1)
9344     {
9345
9346       size = AOP_SIZE (result);
9347       offset = 0;
9348       while (size--)
9349         {
9350           l = aopGet (left, offset, FALSE, TRUE);
9351           if (*l == '@' && IS_AOP_PREG (result))
9352             {
9353
9354               emitcode ("mov", "a,%s", l);
9355               aopPut (result, "a", offset);
9356             }
9357           else
9358             aopPut (result, l, offset);
9359           offset++;
9360         }
9361     }
9362
9363   /* mov the highest order bit to OVR */
9364   tlbl = newiTempLabel (NULL);
9365   tlbl1 = newiTempLabel (NULL);
9366
9367   size = AOP_SIZE (result);
9368   offset = size - 1;
9369   MOVA (aopGet (left, offset, FALSE, FALSE));
9370   emitcode ("rlc", "a");
9371   emitcode ("mov", "ov,c");
9372   /* if it is only one byte then */
9373   if (size == 1)
9374     {
9375       l = aopGet (left, 0, FALSE, FALSE);
9376       MOVA (l);
9377       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9378       emitLabel (tlbl);
9379       emitcode ("mov", "c,ov");
9380       emitcode ("rrc", "a");
9381       emitLabel (tlbl1);
9382       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9383       popB (pushedB);
9384       aopPut (result, "a", 0);
9385       goto release;
9386     }
9387
9388   reAdjustPreg (AOP (result));
9389   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9390   emitLabel (tlbl);
9391   emitcode ("mov", "c,ov");
9392   while (size--)
9393     {
9394       l = aopGet (result, offset, FALSE, FALSE);
9395       MOVA (l);
9396       emitcode ("rrc", "a");
9397       aopPut (result, "a", offset--);
9398     }
9399   reAdjustPreg (AOP (result));
9400   emitLabel (tlbl1);
9401   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9402   popB (pushedB);
9403
9404 release:
9405   freeAsmop (result, NULL, ic, TRUE);
9406   freeAsmop (left, NULL, ic, TRUE);
9407 }
9408
9409 /*-----------------------------------------------------------------*/
9410 /* genRightShift - generate code for right shifting                */
9411 /*-----------------------------------------------------------------*/
9412 static void
9413 genRightShift (iCode * ic)
9414 {
9415   operand *right, *left, *result;
9416   sym_link *letype;
9417   int size, offset;
9418   char *l;
9419   symbol *tlbl, *tlbl1;
9420   bool pushedB;
9421
9422   D (emitcode (";", "genRightShift"));
9423
9424   /* if signed then we do it the hard way preserve the
9425      sign bit moving it inwards */
9426   letype = getSpec (operandType (IC_LEFT (ic)));
9427
9428   if (!SPEC_USIGN (letype))
9429     {
9430       genSignedRightShift (ic);
9431       return;
9432     }
9433
9434   /* signed & unsigned types are treated the same : i.e. the
9435      signed is NOT propagated inwards : quoting from the
9436      ANSI - standard : "for E1 >> E2, is equivalent to division
9437      by 2**E2 if unsigned or if it has a non-negative value,
9438      otherwise the result is implementation defined ", MY definition
9439      is that the sign does not get propagated */
9440
9441   right = IC_RIGHT (ic);
9442   left = IC_LEFT (ic);
9443   result = IC_RESULT (ic);
9444
9445   aopOp (right, ic, FALSE);
9446
9447   /* if the shift count is known then do it
9448      as efficiently as possible */
9449   if (AOP_TYPE (right) == AOP_LIT)
9450     {
9451       genRightShiftLiteral (left, right, result, ic, 0);
9452       return;
9453     }
9454
9455   /* shift count is unknown then we have to form
9456      a loop get the loop count in B : Note: we take
9457      only the lower order byte since shifting
9458      more that 32 bits make no sense anyway, ( the
9459      largest size of an object can be only 32 bits ) */
9460
9461   pushedB = pushB ();
9462   MOVB (aopGet (right, 0, FALSE, FALSE));
9463   emitcode ("inc", "b");
9464   freeAsmop (right, NULL, ic, TRUE);
9465   aopOp (left, ic, FALSE);
9466   aopOp (result, ic, FALSE);
9467
9468   /* now move the left to the result if they are not the
9469      same */
9470   if (!sameRegs (AOP (left), AOP (result)) &&
9471       AOP_SIZE (result) > 1)
9472     {
9473       size = AOP_SIZE (result);
9474       offset = 0;
9475       while (size--)
9476         {
9477           l = aopGet (left, offset, FALSE, TRUE);
9478           if (*l == '@' && IS_AOP_PREG (result))
9479             {
9480
9481               emitcode ("mov", "a,%s", l);
9482               aopPut (result, "a", offset);
9483             }
9484           else
9485             aopPut (result, l, offset);
9486           offset++;
9487         }
9488     }
9489
9490   tlbl = newiTempLabel (NULL);
9491   tlbl1 = newiTempLabel (NULL);
9492   size = AOP_SIZE (result);
9493   offset = size - 1;
9494
9495   /* if it is only one byte then */
9496   if (size == 1)
9497     {
9498       l = aopGet (left, 0, FALSE, FALSE);
9499       MOVA (l);
9500       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9501       emitLabel (tlbl);
9502       CLRC;
9503       emitcode ("rrc", "a");
9504       emitLabel (tlbl1);
9505       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9506       popB (pushedB);
9507       aopPut (result, "a", 0);
9508       goto release;
9509     }
9510
9511   reAdjustPreg (AOP (result));
9512   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9513   emitLabel (tlbl);
9514   CLRC;
9515   while (size--)
9516     {
9517       l = aopGet (result, offset, FALSE, FALSE);
9518       MOVA (l);
9519       emitcode ("rrc", "a");
9520       aopPut (result, "a", offset--);
9521     }
9522   reAdjustPreg (AOP (result));
9523
9524   emitLabel (tlbl1);
9525   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9526   popB (pushedB);
9527
9528 release:
9529   freeAsmop (result, NULL, ic, TRUE);
9530   freeAsmop (left, NULL, ic, TRUE);
9531 }
9532
9533 /*-----------------------------------------------------------------*/
9534 /* emitPtrByteGet - emits code to get a byte into A through a      */
9535 /*                  pointer register (R0, R1, or DPTR). The        */
9536 /*                  original value of A can be preserved in B.     */
9537 /*-----------------------------------------------------------------*/
9538 static void
9539 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9540 {
9541   switch (p_type)
9542     {
9543     case IPOINTER:
9544     case POINTER:
9545       if (preserveAinB)
9546         emitcode ("mov", "b,a");
9547       emitcode ("mov", "a,@%s", rname);
9548       break;
9549
9550     case PPOINTER:
9551       if (preserveAinB)
9552         emitcode ("mov", "b,a");
9553       emitcode ("movx", "a,@%s", rname);
9554       break;
9555
9556     case FPOINTER:
9557       if (preserveAinB)
9558         emitcode ("mov", "b,a");
9559       emitcode ("movx", "a,@dptr");
9560       break;
9561
9562     case CPOINTER:
9563       if (preserveAinB)
9564         emitcode ("mov", "b,a");
9565       emitcode ("clr", "a");
9566       emitcode ("movc", "a,@a+dptr");
9567       break;
9568
9569     case GPOINTER:
9570       if (preserveAinB)
9571         {
9572           emitcode ("push", "b");
9573           emitcode ("push", "acc");
9574         }
9575       emitcode ("lcall", "__gptrget");
9576       if (preserveAinB)
9577         emitcode ("pop", "b");
9578       break;
9579     }
9580 }
9581
9582 /*-----------------------------------------------------------------*/
9583 /* emitPtrByteSet - emits code to set a byte from src through a    */
9584 /*                  pointer register (R0, R1, or DPTR).            */
9585 /*-----------------------------------------------------------------*/
9586 static void
9587 emitPtrByteSet (char *rname, int p_type, char *src)
9588 {
9589   switch (p_type)
9590     {
9591     case IPOINTER:
9592     case POINTER:
9593       if (*src=='@')
9594         {
9595           MOVA (src);
9596           emitcode ("mov", "@%s,a", rname);
9597         }
9598       else
9599         emitcode ("mov", "@%s,%s", rname, src);
9600       break;
9601
9602     case PPOINTER:
9603       MOVA (src);
9604       emitcode ("movx", "@%s,a", rname);
9605       break;
9606
9607     case FPOINTER:
9608       MOVA (src);
9609       emitcode ("movx", "@dptr,a");
9610       break;
9611
9612     case GPOINTER:
9613       MOVA (src);
9614       emitcode ("lcall", "__gptrput");
9615       break;
9616     }
9617 }
9618
9619 /*-----------------------------------------------------------------*/
9620 /* genUnpackBits - generates code for unpacking bits               */
9621 /*-----------------------------------------------------------------*/
9622 static void
9623 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9624 {
9625   int offset = 0;       /* result byte offset */
9626   int rsize;            /* result size */
9627   int rlen = 0;         /* remaining bitfield length */
9628   sym_link *etype;      /* bitfield type information */
9629   int blen;             /* bitfield length */
9630   int bstr;             /* bitfield starting bit within byte */
9631   char buffer[10];
9632
9633   D(emitcode (";     genUnpackBits",""));
9634
9635   etype = getSpec (operandType (result));
9636   rsize = getSize (operandType (result));
9637   blen = SPEC_BLEN (etype);
9638   bstr = SPEC_BSTR (etype);
9639
9640   if (ifx && blen <= 8)
9641     {
9642       emitPtrByteGet (rname, ptype, FALSE);
9643       if (blen == 1)
9644         {
9645           SNPRINTF (buffer, sizeof(buffer),
9646                     "acc.%d", bstr);
9647           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9648         }
9649       else
9650         {
9651           if (blen < 8)
9652             emitcode ("anl", "a,#0x%02x",
9653                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9654           genIfxJump (ifx, "a", NULL, NULL, NULL);
9655         }
9656       return;
9657     }
9658   wassert (!ifx);
9659
9660   /* If the bitfield length is less than a byte */
9661   if (blen < 8)
9662     {
9663       emitPtrByteGet (rname, ptype, FALSE);
9664       AccRol (8 - bstr);
9665       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9666       if (!SPEC_USIGN (etype))
9667         {
9668           /* signed bitfield */
9669           symbol *tlbl = newiTempLabel (NULL);
9670
9671           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9672           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9673           emitLabel (tlbl);
9674         }
9675       aopPut (result, "a", offset++);
9676       goto finish;
9677     }
9678
9679   /* Bit field did not fit in a byte. Copy all
9680      but the partial byte at the end.  */
9681   for (rlen=blen;rlen>=8;rlen-=8)
9682     {
9683       emitPtrByteGet (rname, ptype, FALSE);
9684       aopPut (result, "a", offset++);
9685       if (rlen>8)
9686         emitcode ("inc", "%s", rname);
9687     }
9688
9689   /* Handle the partial byte at the end */
9690   if (rlen)
9691     {
9692       emitPtrByteGet (rname, ptype, FALSE);
9693       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9694       if (!SPEC_USIGN (etype))
9695         {
9696           /* signed bitfield */
9697           symbol *tlbl = newiTempLabel (NULL);
9698
9699           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9700           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9701           emitLabel (tlbl);
9702         }
9703       aopPut (result, "a", offset++);
9704     }
9705
9706 finish:
9707   if (offset < rsize)
9708     {
9709       char *source;
9710
9711       if (SPEC_USIGN (etype))
9712         source = zero;
9713       else
9714         {
9715           /* signed bitfield: sign extension with 0x00 or 0xff */
9716           emitcode ("rlc", "a");
9717           emitcode ("subb", "a,acc");
9718
9719           source = "a";
9720         }
9721       rsize -= offset;
9722       while (rsize--)
9723         aopPut (result, source, offset++);
9724     }
9725 }
9726
9727
9728 /*-----------------------------------------------------------------*/
9729 /* genDataPointerGet - generates code when ptr offset is known     */
9730 /*-----------------------------------------------------------------*/
9731 static void
9732 genDataPointerGet (operand * left,
9733                    operand * result,
9734                    iCode * ic)
9735 {
9736   char *l;
9737   char buffer[256];
9738   int size, offset = 0;
9739
9740   D (emitcode (";", "genDataPointerGet"));
9741
9742   aopOp (result, ic, TRUE);
9743
9744   /* get the string representation of the name */
9745   l = aopGet (left, 0, FALSE, TRUE);
9746   l++; // remove #
9747   size = AOP_SIZE (result);
9748   while (size--)
9749     {
9750       if (offset)
9751         {
9752           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9753         }
9754       else
9755         {
9756           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9757         }
9758       aopPut (result, buffer, offset++);
9759     }
9760
9761   freeAsmop (result, NULL, ic, TRUE);
9762   freeAsmop (left, NULL, ic, TRUE);
9763 }
9764
9765 /*-----------------------------------------------------------------*/
9766 /* genNearPointerGet - emitcode for near pointer fetch             */
9767 /*-----------------------------------------------------------------*/
9768 static void
9769 genNearPointerGet (operand * left,
9770                    operand * result,
9771                    iCode * ic,
9772                    iCode * pi,
9773                    iCode * ifx)
9774 {
9775   asmop *aop = NULL;
9776   regs *preg = NULL;
9777   char *rname;
9778   sym_link *rtype, *retype;
9779   sym_link *ltype = operandType (left);
9780   char buffer[80];
9781
9782   D (emitcode (";", "genNearPointerGet"));
9783
9784   rtype = operandType (result);
9785   retype = getSpec (rtype);
9786
9787   aopOp (left, ic, FALSE);
9788
9789   /* if left is rematerialisable and
9790      result is not bitfield variable type and
9791      the left is pointer to data space i.e
9792      lower 128 bytes of space */
9793   if (AOP_TYPE (left) == AOP_IMMD &&
9794       !IS_BITFIELD (retype) &&
9795       DCL_TYPE (ltype) == POINTER)
9796     {
9797       genDataPointerGet (left, result, ic);
9798       return;
9799     }
9800
9801  /* if the value is already in a pointer register
9802      then don't need anything more */
9803   if (!AOP_INPREG (AOP (left)))
9804     {
9805       if (IS_AOP_PREG (left))
9806         {
9807           // Aha, it is a pointer, just in disguise.
9808           rname = aopGet (left, 0, FALSE, FALSE);
9809           if (*rname != '@')
9810             {
9811               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9812                       __FILE__, __LINE__);
9813             }
9814           else
9815             {
9816               // Expected case.
9817               emitcode ("mov", "a%s,%s", rname + 1, rname);
9818               rname++;  // skip the '@'.
9819             }
9820         }
9821       else
9822         {
9823           /* otherwise get a free pointer register */
9824           aop = newAsmop (0);
9825           preg = getFreePtr (ic, &aop, FALSE);
9826           emitcode ("mov", "%s,%s",
9827                     preg->name,
9828                     aopGet (left, 0, FALSE, TRUE));
9829           rname = preg->name;
9830         }
9831     }
9832   else
9833     rname = aopGet (left, 0, FALSE, FALSE);
9834
9835   //aopOp (result, ic, FALSE);
9836   aopOp (result, ic, result?TRUE:FALSE);
9837
9838   /* if bitfield then unpack the bits */
9839   if (IS_BITFIELD (retype))
9840     genUnpackBits (result, rname, POINTER, ifx);
9841   else
9842     {
9843       /* we have can just get the values */
9844       int size = AOP_SIZE (result);
9845       int offset = 0;
9846
9847       while (size--)
9848         {
9849           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9850             {
9851
9852               emitcode ("mov", "a,@%s", rname);
9853               if (!ifx)
9854                 aopPut (result, "a", offset);
9855             }
9856           else
9857             {
9858               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9859               aopPut (result, buffer, offset);
9860             }
9861           offset++;
9862           if (size || pi)
9863             emitcode ("inc", "%s", rname);
9864         }
9865     }
9866
9867   /* now some housekeeping stuff */
9868   if (aop)       /* we had to allocate for this iCode */
9869     {
9870       if (pi) { /* post increment present */
9871         aopPut (left, rname, 0);
9872       }
9873       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9874     }
9875   else
9876     {
9877       /* we did not allocate which means left
9878          already in a pointer register, then
9879          if size > 0 && this could be used again
9880          we have to point it back to where it
9881          belongs */
9882       if ((AOP_SIZE (result) > 1 &&
9883            !OP_SYMBOL (left)->remat &&
9884            (OP_SYMBOL (left)->liveTo > ic->seq ||
9885             ic->depth)) &&
9886           !pi)
9887         {
9888           int size = AOP_SIZE (result) - 1;
9889           while (size--)
9890             emitcode ("dec", "%s", rname);
9891         }
9892     }
9893
9894   if (ifx && !ifx->generated)
9895     {
9896       genIfxJump (ifx, "a", left, NULL, result);
9897     }
9898
9899   /* done */
9900   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9901   freeAsmop (left, NULL, ic, TRUE);
9902   if (pi) pi->generated = 1;
9903 }
9904
9905 /*-----------------------------------------------------------------*/
9906 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9907 /*-----------------------------------------------------------------*/
9908 static void
9909 genPagedPointerGet (operand * left,
9910                     operand * result,
9911                     iCode * ic,
9912                     iCode *pi,
9913                     iCode *ifx)
9914 {
9915   asmop *aop = NULL;
9916   regs *preg = NULL;
9917   char *rname;
9918   sym_link *rtype, *retype;
9919
9920   D (emitcode (";", "genPagedPointerGet"));
9921
9922   rtype = operandType (result);
9923   retype = getSpec (rtype);
9924
9925   aopOp (left, ic, FALSE);
9926
9927   /* if the value is already in a pointer register
9928      then don't need anything more */
9929   if (!AOP_INPREG (AOP (left)))
9930     {
9931       /* otherwise get a free pointer register */
9932       aop = newAsmop (0);
9933       preg = getFreePtr (ic, &aop, FALSE);
9934       emitcode ("mov", "%s,%s",
9935                 preg->name,
9936                 aopGet (left, 0, FALSE, TRUE));
9937       rname = preg->name;
9938     }
9939   else
9940     rname = aopGet (left, 0, FALSE, FALSE);
9941
9942   aopOp (result, ic, FALSE);
9943
9944   /* if bitfield then unpack the bits */
9945   if (IS_BITFIELD (retype))
9946     genUnpackBits (result, rname, PPOINTER, ifx);
9947   else
9948     {
9949       /* we have can just get the values */
9950       int size = AOP_SIZE (result);
9951       int offset = 0;
9952
9953       while (size--)
9954         {
9955
9956           emitcode ("movx", "a,@%s", rname);
9957           if (!ifx)
9958             aopPut (result, "a", offset);
9959
9960           offset++;
9961
9962           if (size || pi)
9963             emitcode ("inc", "%s", rname);
9964         }
9965     }
9966
9967   /* now some housekeeping stuff */
9968   if (aop) /* we had to allocate for this iCode */
9969     {
9970       if (pi)
9971         aopPut (left, rname, 0);
9972       freeAsmop (NULL, aop, ic, TRUE);
9973     }
9974   else
9975     {
9976       /* we did not allocate which means left
9977          already in a pointer register, then
9978          if size > 0 && this could be used again
9979          we have to point it back to where it
9980          belongs */
9981       if ((AOP_SIZE (result) > 1 &&
9982            !OP_SYMBOL (left)->remat &&
9983            (OP_SYMBOL (left)->liveTo > ic->seq ||
9984             ic->depth)) &&
9985           !pi)
9986         {
9987           int size = AOP_SIZE (result) - 1;
9988           while (size--)
9989             emitcode ("dec", "%s", rname);
9990         }
9991     }
9992
9993   if (ifx && !ifx->generated)
9994     {
9995       genIfxJump (ifx, "a", left, NULL, result);
9996     }
9997
9998   /* done */
9999   freeAsmop (result, NULL, ic, TRUE);
10000   freeAsmop (left, NULL, ic, TRUE);
10001   if (pi) pi->generated = 1;
10002 }
10003
10004 /*--------------------------------------------------------------------*/
10005 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10006 /*--------------------------------------------------------------------*/
10007 static void
10008 loadDptrFromOperand (operand *op, bool loadBToo)
10009 {
10010   if (AOP_TYPE (op) != AOP_STR)
10011     {
10012       /* if this is rematerializable */
10013       if (AOP_TYPE (op) == AOP_IMMD)
10014         {
10015           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10016           if (loadBToo)
10017             {
10018               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10019                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10020               else
10021                 {
10022                   wassertl(FALSE, "need pointerCode");
10023                   emitcode ("", "; mov b,???");
10024                   /* genPointerGet and genPointerSet originally did different
10025                   ** things for this case. Both seem wrong.
10026                   ** from genPointerGet:
10027                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10028                   ** from genPointerSet:
10029                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10030                   */
10031                 }
10032             }
10033         }
10034       else if (AOP_TYPE (op) == AOP_DPTR)
10035         {
10036           if (loadBToo)
10037             {
10038               MOVA (aopGet (op, 0, FALSE, FALSE));
10039               emitcode ("push", "acc");
10040               MOVA (aopGet (op, 1, FALSE, FALSE));
10041               emitcode ("push", "acc");
10042               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10043               emitcode ("pop", "dph");
10044               emitcode ("pop", "dpl");
10045             }
10046           else
10047             {
10048               MOVA (aopGet (op, 0, FALSE, FALSE));
10049               emitcode ("push", "acc");
10050               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10051               emitcode ("pop", "dpl");
10052             }
10053         }
10054       else
10055         {                       /* we need to get it byte by byte */
10056           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10057           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10058           if (loadBToo)
10059             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10060         }
10061     }
10062 }
10063
10064 /*-----------------------------------------------------------------*/
10065 /* genFarPointerGet - get value from far space                     */
10066 /*-----------------------------------------------------------------*/
10067 static void
10068 genFarPointerGet (operand * left,
10069                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10070 {
10071   int size, offset;
10072   sym_link *retype = getSpec (operandType (result));
10073
10074   D (emitcode (";", "genFarPointerGet"));
10075
10076   aopOp (left, ic, FALSE);
10077   loadDptrFromOperand (left, FALSE);
10078
10079   /* so dptr now contains the address */
10080   aopOp (result, ic, FALSE);
10081
10082   /* if bit then unpack */
10083   if (IS_BITFIELD (retype))
10084     genUnpackBits (result, "dptr", FPOINTER, ifx);
10085   else
10086     {
10087       size = AOP_SIZE (result);
10088       offset = 0;
10089
10090       while (size--)
10091         {
10092           emitcode ("movx", "a,@dptr");
10093           if (!ifx)
10094             aopPut (result, "a", offset++);
10095           if (size || pi)
10096             emitcode ("inc", "dptr");
10097         }
10098     }
10099
10100   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10101     {
10102       aopPut (left, "dpl", 0);
10103       aopPut (left, "dph", 1);
10104       pi->generated = 1;
10105     }
10106
10107   if (ifx && !ifx->generated)
10108     {
10109       genIfxJump (ifx, "a", left, NULL, result);
10110     }
10111
10112   freeAsmop (result, NULL, ic, TRUE);
10113   freeAsmop (left, NULL, ic, TRUE);
10114 }
10115
10116 /*-----------------------------------------------------------------*/
10117 /* genCodePointerGet - get value from code space                   */
10118 /*-----------------------------------------------------------------*/
10119 static void
10120 genCodePointerGet (operand * left,
10121                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10122 {
10123   int size, offset;
10124   sym_link *retype = getSpec (operandType (result));
10125
10126   D (emitcode (";", "genCodePointerGet"));
10127
10128   aopOp (left, ic, FALSE);
10129   loadDptrFromOperand (left, FALSE);
10130
10131   /* so dptr now contains the address */
10132   aopOp (result, ic, FALSE);
10133
10134   /* if bit then unpack */
10135   if (IS_BITFIELD (retype))
10136     genUnpackBits (result, "dptr", CPOINTER, ifx);
10137   else
10138     {
10139       size = AOP_SIZE (result);
10140       offset = 0;
10141
10142       while (size--)
10143         {
10144           emitcode ("clr", "a");
10145           emitcode ("movc", "a,@a+dptr");
10146           if (!ifx)
10147             aopPut (result, "a", offset++);
10148           if (size || pi)
10149             emitcode ("inc", "dptr");
10150         }
10151     }
10152
10153   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10154     {
10155       aopPut (left, "dpl", 0);
10156       aopPut (left, "dph", 1);
10157       pi->generated = 1;
10158     }
10159
10160   if (ifx && !ifx->generated)
10161     {
10162       genIfxJump (ifx, "a", left, NULL, result);
10163     }
10164
10165   freeAsmop (result, NULL, ic, TRUE);
10166   freeAsmop (left, NULL, ic, TRUE);
10167 }
10168
10169 /*-----------------------------------------------------------------*/
10170 /* genGenPointerGet - get value from generic pointer space         */
10171 /*-----------------------------------------------------------------*/
10172 static void
10173 genGenPointerGet (operand * left,
10174                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10175 {
10176   int size, offset;
10177   sym_link *retype = getSpec (operandType (result));
10178
10179   D (emitcode (";", "genGenPointerGet"));
10180
10181   aopOp (left, ic, FALSE);
10182   loadDptrFromOperand (left, TRUE);
10183
10184   /* so dptr now contains the address */
10185   aopOp (result, ic, FALSE);
10186
10187   /* if bit then unpack */
10188   if (IS_BITFIELD (retype))
10189     {
10190       genUnpackBits (result, "dptr", GPOINTER, ifx);
10191     }
10192   else
10193     {
10194       size = AOP_SIZE (result);
10195       offset = 0;
10196
10197       while (size--)
10198         {
10199           emitcode ("lcall", "__gptrget");
10200           if (!ifx)
10201             aopPut (result, "a", offset++);
10202           if (size || pi)
10203             emitcode ("inc", "dptr");
10204         }
10205     }
10206
10207   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10208     {
10209       aopPut (left, "dpl", 0);
10210       aopPut (left, "dph", 1);
10211       pi->generated = 1;
10212     }
10213
10214   if (ifx && !ifx->generated)
10215     {
10216       genIfxJump (ifx, "a", left, NULL, result);
10217     }
10218
10219   freeAsmop (result, NULL, ic, TRUE);
10220   freeAsmop (left, NULL, ic, TRUE);
10221 }
10222
10223 /*-----------------------------------------------------------------*/
10224 /* genPointerGet - generate code for pointer get                   */
10225 /*-----------------------------------------------------------------*/
10226 static void
10227 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10228 {
10229   operand *left, *result;
10230   sym_link *type, *etype;
10231   int p_type;
10232
10233   D (emitcode (";", "genPointerGet"));
10234
10235   left = IC_LEFT (ic);
10236   result = IC_RESULT (ic);
10237
10238   if (getSize (operandType (result))>1)
10239     ifx = NULL;
10240
10241   /* depending on the type of pointer we need to
10242      move it to the correct pointer register */
10243   type = operandType (left);
10244   etype = getSpec (type);
10245   /* if left is of type of pointer then it is simple */
10246   if (IS_PTR (type) && !IS_FUNC (type->next))
10247     p_type = DCL_TYPE (type);
10248   else
10249     {
10250       /* we have to go by the storage class */
10251       p_type = PTR_TYPE (SPEC_OCLS (etype));
10252     }
10253
10254   /* special case when cast remat */
10255   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10256       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10257     {
10258       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10259       type = operandType (left);
10260       p_type = DCL_TYPE (type);
10261     }
10262   /* now that we have the pointer type we assign
10263      the pointer values */
10264   switch (p_type)
10265     {
10266
10267     case POINTER:
10268     case IPOINTER:
10269       genNearPointerGet (left, result, ic, pi, ifx);
10270       break;
10271
10272     case PPOINTER:
10273       genPagedPointerGet (left, result, ic, pi, ifx);
10274       break;
10275
10276     case FPOINTER:
10277       genFarPointerGet (left, result, ic, pi, ifx);
10278       break;
10279
10280     case CPOINTER:
10281       genCodePointerGet (left, result, ic, pi, ifx);
10282       break;
10283
10284     case GPOINTER:
10285       genGenPointerGet (left, result, ic, pi, ifx);
10286       break;
10287     }
10288 }
10289
10290
10291 /*-----------------------------------------------------------------*/
10292 /* genPackBits - generates code for packed bit storage             */
10293 /*-----------------------------------------------------------------*/
10294 static void
10295 genPackBits (sym_link * etype,
10296              operand * right,
10297              char *rname, int p_type)
10298 {
10299   int offset = 0;       /* source byte offset */
10300   int rlen = 0;         /* remaining bitfield length */
10301   int blen;             /* bitfield length */
10302   int bstr;             /* bitfield starting bit within byte */
10303   int litval;           /* source literal value (if AOP_LIT) */
10304   unsigned char mask;   /* bitmask within current byte */
10305
10306   D(emitcode (";     genPackBits",""));
10307
10308   blen = SPEC_BLEN (etype);
10309   bstr = SPEC_BSTR (etype);
10310
10311   /* If the bitfield length is less than a byte */
10312   if (blen < 8)
10313     {
10314       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10315               (unsigned char) (0xFF >> (8 - bstr)));
10316
10317       if (AOP_TYPE (right) == AOP_LIT)
10318         {
10319           /* Case with a bitfield length <8 and literal source
10320           */
10321           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10322           litval <<= bstr;
10323           litval &= (~mask) & 0xff;
10324           emitPtrByteGet (rname, p_type, FALSE);
10325           if ((mask|litval)!=0xff)
10326             emitcode ("anl","a,#0x%02x", mask);
10327           if (litval)
10328             emitcode ("orl","a,#0x%02x", litval);
10329         }
10330       else
10331         {
10332           if ((blen==1) && (p_type!=GPOINTER))
10333             {
10334               /* Case with a bitfield length == 1 and no generic pointer
10335               */
10336               if (AOP_TYPE (right) == AOP_CRY)
10337                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10338               else
10339                 {
10340                   MOVA (aopGet (right, 0, FALSE, FALSE));
10341                   emitcode ("rrc","a");
10342                 }
10343               emitPtrByteGet (rname, p_type, FALSE);
10344               emitcode ("mov","acc.%d,c",bstr);
10345             }
10346           else
10347             {
10348               bool pushedB;
10349               /* Case with a bitfield length < 8 and arbitrary source
10350               */
10351               MOVA (aopGet (right, 0, FALSE, FALSE));
10352               /* shift and mask source value */
10353               AccLsh (bstr);
10354               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10355
10356               pushedB = pushB ();
10357               /* transfer A to B and get next byte */
10358               emitPtrByteGet (rname, p_type, TRUE);
10359
10360               emitcode ("anl", "a,#0x%02x", mask);
10361               emitcode ("orl", "a,b");
10362               if (p_type == GPOINTER)
10363                 emitcode ("pop", "b");
10364
10365               popB (pushedB);
10366            }
10367         }
10368
10369       emitPtrByteSet (rname, p_type, "a");
10370       return;
10371     }
10372
10373   /* Bit length is greater than 7 bits. In this case, copy  */
10374   /* all except the partial byte at the end                 */
10375   for (rlen=blen;rlen>=8;rlen-=8)
10376     {
10377       emitPtrByteSet (rname, p_type,
10378                       aopGet (right, offset++, FALSE, TRUE) );
10379       if (rlen>8)
10380         emitcode ("inc", "%s", rname);
10381     }
10382
10383   /* If there was a partial byte at the end */
10384   if (rlen)
10385     {
10386       mask = (((unsigned char) -1 << rlen) & 0xff);
10387
10388       if (AOP_TYPE (right) == AOP_LIT)
10389         {
10390           /* Case with partial byte and literal source
10391           */
10392           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10393           litval >>= (blen-rlen);
10394           litval &= (~mask) & 0xff;
10395           emitPtrByteGet (rname, p_type, FALSE);
10396           if ((mask|litval)!=0xff)
10397             emitcode ("anl","a,#0x%02x", mask);
10398           if (litval)
10399             emitcode ("orl","a,#0x%02x", litval);
10400         }
10401       else
10402         {
10403           bool pushedB;
10404           /* Case with partial byte and arbitrary source
10405           */
10406           MOVA (aopGet (right, offset++, FALSE, FALSE));
10407           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10408
10409           pushedB = pushB ();
10410           /* transfer A to B and get next byte */
10411           emitPtrByteGet (rname, p_type, TRUE);
10412
10413           emitcode ("anl", "a,#0x%02x", mask);
10414           emitcode ("orl", "a,b");
10415           if (p_type == GPOINTER)
10416             emitcode ("pop", "b");
10417
10418           popB (pushedB);
10419         }
10420       emitPtrByteSet (rname, p_type, "a");
10421     }
10422 }
10423
10424
10425 /*-----------------------------------------------------------------*/
10426 /* genDataPointerSet - remat pointer to data space                 */
10427 /*-----------------------------------------------------------------*/
10428 static void
10429 genDataPointerSet (operand * right,
10430                    operand * result,
10431                    iCode * ic)
10432 {
10433   int size, offset = 0;
10434   char *l, buffer[256];
10435
10436   D (emitcode (";", "genDataPointerSet"));
10437
10438   aopOp (right, ic, FALSE);
10439
10440   l = aopGet (result, 0, FALSE, TRUE);
10441   l++; //remove #
10442   size = AOP_SIZE (right);
10443   while (size--)
10444     {
10445       if (offset)
10446         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10447       else
10448         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10449       emitcode ("mov", "%s,%s", buffer,
10450                 aopGet (right, offset++, FALSE, FALSE));
10451     }
10452
10453   freeAsmop (result, NULL, ic, TRUE);
10454   freeAsmop (right, NULL, ic, TRUE);
10455 }
10456
10457 /*-----------------------------------------------------------------*/
10458 /* genNearPointerSet - emitcode for near pointer put                */
10459 /*-----------------------------------------------------------------*/
10460 static void
10461 genNearPointerSet (operand * right,
10462                    operand * result,
10463                    iCode * ic,
10464                    iCode * pi)
10465 {
10466   asmop *aop = NULL;
10467   regs *preg = NULL;
10468   char *rname, *l;
10469   sym_link *retype, *letype;
10470   sym_link *ptype = operandType (result);
10471
10472   D (emitcode (";", "genNearPointerSet"));
10473
10474   retype = getSpec (operandType (right));
10475   letype = getSpec (ptype);
10476
10477   aopOp (result, ic, FALSE);
10478
10479   /* if the result is rematerializable &
10480      in data space & not a bit variable */
10481   if (AOP_TYPE (result) == AOP_IMMD &&
10482       DCL_TYPE (ptype) == POINTER &&
10483       !IS_BITVAR (retype) &&
10484       !IS_BITVAR (letype))
10485     {
10486       genDataPointerSet (right, result, ic);
10487       return;
10488     }
10489
10490   /* if the value is already in a pointer register
10491      then don't need anything more */
10492   if (!AOP_INPREG (AOP (result)))
10493     {
10494         if (
10495             //AOP_TYPE (result) == AOP_STK
10496             IS_AOP_PREG(result)
10497             )
10498         {
10499             // Aha, it is a pointer, just in disguise.
10500             rname = aopGet (result, 0, FALSE, FALSE);
10501             if (*rname != '@')
10502             {
10503                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10504                         __FILE__, __LINE__);
10505             }
10506             else
10507             {
10508                 // Expected case.
10509                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10510                 rname++;  // skip the '@'.
10511             }
10512         }
10513         else
10514         {
10515             /* otherwise get a free pointer register */
10516             aop = newAsmop (0);
10517             preg = getFreePtr (ic, &aop, FALSE);
10518             emitcode ("mov", "%s,%s",
10519                       preg->name,
10520                       aopGet (result, 0, FALSE, TRUE));
10521             rname = preg->name;
10522         }
10523     }
10524     else
10525     {
10526         rname = aopGet (result, 0, FALSE, FALSE);
10527     }
10528
10529   aopOp (right, ic, FALSE);
10530
10531   /* if bitfield then unpack the bits */
10532   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10533     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10534   else
10535     {
10536       /* we can just get the values */
10537       int size = AOP_SIZE (right);
10538       int offset = 0;
10539
10540       while (size--)
10541         {
10542           l = aopGet (right, offset, FALSE, TRUE);
10543           if ((*l == '@') || (strcmp (l, "acc") == 0))
10544             {
10545               MOVA (l);
10546               emitcode ("mov", "@%s,a", rname);
10547             }
10548           else
10549             emitcode ("mov", "@%s,%s", rname, l);
10550           if (size || pi)
10551             emitcode ("inc", "%s", rname);
10552           offset++;
10553         }
10554     }
10555
10556   /* now some housekeeping stuff */
10557   if (aop) /* we had to allocate for this iCode */
10558     {
10559       if (pi)
10560         aopPut (result, rname, 0);
10561       freeAsmop (NULL, aop, ic, TRUE);
10562     }
10563   else
10564     {
10565       /* we did not allocate which means left
10566          already in a pointer register, then
10567          if size > 0 && this could be used again
10568          we have to point it back to where it
10569          belongs */
10570       if ((AOP_SIZE (right) > 1 &&
10571            !OP_SYMBOL (result)->remat &&
10572            (OP_SYMBOL (result)->liveTo > ic->seq ||
10573             ic->depth)) &&
10574           !pi)
10575         {
10576           int size = AOP_SIZE (right) - 1;
10577           while (size--)
10578             emitcode ("dec", "%s", rname);
10579         }
10580     }
10581
10582   /* done */
10583   if (pi) pi->generated = 1;
10584   freeAsmop (result, NULL, ic, TRUE);
10585   freeAsmop (right, NULL, ic, TRUE);
10586 }
10587
10588 /*-----------------------------------------------------------------*/
10589 /* genPagedPointerSet - emitcode for Paged pointer put             */
10590 /*-----------------------------------------------------------------*/
10591 static void
10592 genPagedPointerSet (operand * right,
10593                     operand * result,
10594                     iCode * ic,
10595                     iCode * pi)
10596 {
10597   asmop *aop = NULL;
10598   regs *preg = NULL;
10599   char *rname, *l;
10600   sym_link *retype, *letype;
10601
10602   D (emitcode (";", "genPagedPointerSet"));
10603
10604   retype = getSpec (operandType (right));
10605   letype = getSpec (operandType (result));
10606
10607   aopOp (result, ic, FALSE);
10608
10609   /* if the value is already in a pointer register
10610      then don't need anything more */
10611   if (!AOP_INPREG (AOP (result)))
10612     {
10613       /* otherwise get a free pointer register */
10614       aop = newAsmop (0);
10615       preg = getFreePtr (ic, &aop, FALSE);
10616       emitcode ("mov", "%s,%s",
10617                 preg->name,
10618                 aopGet (result, 0, FALSE, TRUE));
10619       rname = preg->name;
10620     }
10621   else
10622     rname = aopGet (result, 0, FALSE, FALSE);
10623
10624   aopOp (right, ic, FALSE);
10625
10626   /* if bitfield then unpack the bits */
10627   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10628     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10629   else
10630     {
10631       /* we have can just get the values */
10632       int size = AOP_SIZE (right);
10633       int offset = 0;
10634
10635       while (size--)
10636         {
10637           l = aopGet (right, offset, FALSE, TRUE);
10638           MOVA (l);
10639           emitcode ("movx", "@%s,a", rname);
10640
10641           if (size || pi)
10642             emitcode ("inc", "%s", rname);
10643
10644           offset++;
10645         }
10646     }
10647
10648   /* now some housekeeping stuff */
10649   if (aop) /* we had to allocate for this iCode */
10650     {
10651       if (pi)
10652         aopPut (result, rname, 0);
10653       freeAsmop (NULL, aop, ic, TRUE);
10654     }
10655   else
10656     {
10657       /* we did not allocate which means left
10658          already in a pointer register, then
10659          if size > 0 && this could be used again
10660          we have to point it back to where it
10661          belongs */
10662       if (AOP_SIZE (right) > 1 &&
10663           !OP_SYMBOL (result)->remat &&
10664           (OP_SYMBOL (result)->liveTo > ic->seq ||
10665            ic->depth))
10666         {
10667           int size = AOP_SIZE (right) - 1;
10668           while (size--)
10669             emitcode ("dec", "%s", rname);
10670         }
10671     }
10672
10673   /* done */
10674   if (pi) pi->generated = 1;
10675   freeAsmop (result, NULL, ic, TRUE);
10676   freeAsmop (right, NULL, ic, TRUE);
10677 }
10678
10679 /*-----------------------------------------------------------------*/
10680 /* genFarPointerSet - set value from far space                     */
10681 /*-----------------------------------------------------------------*/
10682 static void
10683 genFarPointerSet (operand * right,
10684                   operand * result, iCode * ic, iCode * pi)
10685 {
10686   int size, offset;
10687   sym_link *retype = getSpec (operandType (right));
10688   sym_link *letype = getSpec (operandType (result));
10689
10690   D(emitcode (";     genFarPointerSet",""));
10691
10692   aopOp (result, ic, FALSE);
10693   loadDptrFromOperand (result, FALSE);
10694
10695   /* so dptr now contains the address */
10696   aopOp (right, ic, FALSE);
10697
10698   /* if bit then unpack */
10699   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10700     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10701   else
10702     {
10703       size = AOP_SIZE (right);
10704       offset = 0;
10705
10706       while (size--)
10707         {
10708           char *l = aopGet (right, offset++, FALSE, FALSE);
10709           MOVA (l);
10710           emitcode ("movx", "@dptr,a");
10711           if (size || pi)
10712             emitcode ("inc", "dptr");
10713         }
10714     }
10715   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10716     aopPut (result, "dpl", 0);
10717     aopPut (result, "dph", 1);
10718     pi->generated=1;
10719   }
10720   freeAsmop (result, NULL, ic, TRUE);
10721   freeAsmop (right, NULL, ic, TRUE);
10722 }
10723
10724 /*-----------------------------------------------------------------*/
10725 /* genGenPointerSet - set value from generic pointer space         */
10726 /*-----------------------------------------------------------------*/
10727 static void
10728 genGenPointerSet (operand * right,
10729                   operand * result, iCode * ic, iCode * pi)
10730 {
10731   int size, offset;
10732   sym_link *retype = getSpec (operandType (right));
10733   sym_link *letype = getSpec (operandType (result));
10734
10735   D (emitcode (";", "genGenPointerSet"));
10736
10737   aopOp (result, ic, FALSE);
10738   loadDptrFromOperand (result, TRUE);
10739
10740   /* so dptr now contains the address */
10741   aopOp (right, ic, FALSE);
10742
10743   /* if bit then unpack */
10744   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10745     {
10746       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10747     }
10748   else
10749     {
10750       size = AOP_SIZE (right);
10751       offset = 0;
10752
10753       while (size--)
10754         {
10755           char *l = aopGet (right, offset++, FALSE, FALSE);
10756           MOVA (l);
10757           emitcode ("lcall", "__gptrput");
10758           if (size || pi)
10759             emitcode ("inc", "dptr");
10760         }
10761     }
10762
10763   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10764     aopPut (result, "dpl", 0);
10765     aopPut (result, "dph", 1);
10766     pi->generated=1;
10767   }
10768   freeAsmop (result, NULL, ic, TRUE);
10769   freeAsmop (right, NULL, ic, TRUE);
10770 }
10771
10772 /*-----------------------------------------------------------------*/
10773 /* genPointerSet - stores the value into a pointer location        */
10774 /*-----------------------------------------------------------------*/
10775 static void
10776 genPointerSet (iCode * ic, iCode *pi)
10777 {
10778   operand *right, *result;
10779   sym_link *type, *etype;
10780   int p_type;
10781
10782   D (emitcode (";", "genPointerSet"));
10783
10784   right = IC_RIGHT (ic);
10785   result = IC_RESULT (ic);
10786
10787   /* depending on the type of pointer we need to
10788      move it to the correct pointer register */
10789   type = operandType (result);
10790   etype = getSpec (type);
10791   /* if left is of type of pointer then it is simple */
10792   if (IS_PTR (type) && !IS_FUNC (type->next))
10793     {
10794       p_type = DCL_TYPE (type);
10795     }
10796   else
10797     {
10798       /* we have to go by the storage class */
10799       p_type = PTR_TYPE (SPEC_OCLS (etype));
10800     }
10801
10802   /* special case when cast remat */
10803   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10804       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10805           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10806           type = operandType (result);
10807           p_type = DCL_TYPE (type);
10808   }
10809
10810   /* now that we have the pointer type we assign
10811      the pointer values */
10812   switch (p_type)
10813     {
10814
10815     case POINTER:
10816     case IPOINTER:
10817       genNearPointerSet (right, result, ic, pi);
10818       break;
10819
10820     case PPOINTER:
10821       genPagedPointerSet (right, result, ic, pi);
10822       break;
10823
10824     case FPOINTER:
10825       genFarPointerSet (right, result, ic, pi);
10826       break;
10827
10828     case GPOINTER:
10829       genGenPointerSet (right, result, ic, pi);
10830       break;
10831
10832     default:
10833       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10834               "genPointerSet: illegal pointer type");
10835     }
10836 }
10837
10838 /*-----------------------------------------------------------------*/
10839 /* genIfx - generate code for Ifx statement                        */
10840 /*-----------------------------------------------------------------*/
10841 static void
10842 genIfx (iCode * ic, iCode * popIc)
10843 {
10844   operand *cond = IC_COND (ic);
10845   int isbit = 0;
10846   char *dup = NULL;
10847
10848   D (emitcode (";", "genIfx"));
10849
10850   aopOp (cond, ic, FALSE);
10851
10852   /* get the value into acc */
10853   if (AOP_TYPE (cond) != AOP_CRY)
10854     {
10855       toBoolean (cond);
10856     }
10857   else
10858     {
10859       isbit = 1;
10860       if (AOP(cond)->aopu.aop_dir)
10861         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10862     }
10863
10864   /* the result is now in the accumulator or a directly addressable bit */
10865   freeAsmop (cond, NULL, ic, TRUE);
10866
10867   /* if there was something to be popped then do it */
10868   if (popIc)
10869     genIpop (popIc);
10870
10871   /* if the condition is a bit variable */
10872   if (isbit && dup)
10873     genIfxJump(ic, dup, NULL, NULL, NULL);
10874   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10875     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10876   else if (isbit && !IS_ITEMP (cond))
10877     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10878   else
10879     genIfxJump (ic, "a", NULL, NULL, NULL);
10880
10881   ic->generated = 1;
10882 }
10883
10884 /*-----------------------------------------------------------------*/
10885 /* genAddrOf - generates code for address of                       */
10886 /*-----------------------------------------------------------------*/
10887 static void
10888 genAddrOf (iCode * ic)
10889 {
10890   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10891   int size, offset;
10892
10893   D (emitcode (";", "genAddrOf"));
10894
10895   aopOp (IC_RESULT (ic), ic, FALSE);
10896
10897   /* if the operand is on the stack then we
10898      need to get the stack offset of this
10899      variable */
10900   if (sym->onStack)
10901     {
10902       /* if it has an offset then we need to compute it */
10903       if (sym->stack)
10904         {
10905           int stack_offset = ((sym->stack < 0) ?
10906                               ((char) (sym->stack - _G.nRegsSaved)) :
10907                               ((char) sym->stack)) & 0xff;
10908           if ((abs(stack_offset) == 1) &&
10909               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10910               !isOperandVolatile (IC_RESULT (ic), FALSE))
10911             {
10912               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10913               if (stack_offset > 0)
10914                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10915               else
10916                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10917             }
10918           else
10919             {
10920               emitcode ("mov", "a,%s", SYM_BP (sym));
10921               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10922               aopPut (IC_RESULT (ic), "a", 0);
10923             }
10924         }
10925       else
10926         {
10927           /* we can just move _bp */
10928           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10929         }
10930       /* fill the result with zero */
10931       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10932
10933       offset = 1;
10934       while (size--)
10935         {
10936           aopPut (IC_RESULT (ic), zero, offset++);
10937         }
10938       goto release;
10939     }
10940
10941   /* object not on stack then we need the name */
10942   size = AOP_SIZE (IC_RESULT (ic));
10943   offset = 0;
10944
10945   while (size--)
10946     {
10947       char s[SDCC_NAME_MAX];
10948       if (offset)
10949         sprintf (s, "#(%s >> %d)",
10950                  sym->rname,
10951                  offset * 8);
10952       else
10953         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10954       aopPut (IC_RESULT (ic), s, offset++);
10955     }
10956
10957 release:
10958   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10959
10960 }
10961
10962 /*-----------------------------------------------------------------*/
10963 /* genFarFarAssign - assignment when both are in far space         */
10964 /*-----------------------------------------------------------------*/
10965 static void
10966 genFarFarAssign (operand * result, operand * right, iCode * ic)
10967 {
10968   int size = AOP_SIZE (right);
10969   int offset = 0;
10970   char *l;
10971
10972   D (emitcode (";", "genFarFarAssign"));
10973
10974   /* first push the right side on to the stack */
10975   while (size--)
10976     {
10977       l = aopGet (right, offset++, FALSE, FALSE);
10978       MOVA (l);
10979       emitcode ("push", "acc");
10980     }
10981
10982   freeAsmop (right, NULL, ic, FALSE);
10983   /* now assign DPTR to result */
10984   aopOp (result, ic, FALSE);
10985   size = AOP_SIZE (result);
10986   while (size--)
10987     {
10988       emitcode ("pop", "acc");
10989       aopPut (result, "a", --offset);
10990     }
10991   freeAsmop (result, NULL, ic, FALSE);
10992 }
10993
10994 /*-----------------------------------------------------------------*/
10995 /* genAssign - generate code for assignment                        */
10996 /*-----------------------------------------------------------------*/
10997 static void
10998 genAssign (iCode * ic)
10999 {
11000   operand *result, *right;
11001   int size, offset;
11002   unsigned long lit = 0L;
11003
11004   D (emitcode (";", "genAssign"));
11005
11006   result = IC_RESULT (ic);
11007   right = IC_RIGHT (ic);
11008
11009   /* if they are the same */
11010   if (operandsEqu (result, right) &&
11011       !isOperandVolatile (result, FALSE) &&
11012       !isOperandVolatile (right, FALSE))
11013     return;
11014
11015   aopOp (right, ic, FALSE);
11016
11017   /* special case both in far space */
11018   if (AOP_TYPE (right) == AOP_DPTR &&
11019       IS_TRUE_SYMOP (result) &&
11020       isOperandInFarSpace (result))
11021     {
11022       genFarFarAssign (result, right, ic);
11023       return;
11024     }
11025
11026   aopOp (result, ic, TRUE);
11027
11028   /* if they are the same registers */
11029   if (sameRegs (AOP (right), AOP (result)) &&
11030       !isOperandVolatile (result, FALSE) &&
11031       !isOperandVolatile (right, FALSE))
11032     goto release;
11033
11034   /* if the result is a bit */
11035   if (AOP_TYPE (result) == AOP_CRY)
11036     {
11037       /* if the right size is a literal then
11038          we know what the value is */
11039       if (AOP_TYPE (right) == AOP_LIT)
11040         {
11041           if (((int) operandLitValue (right)))
11042             aopPut (result, one, 0);
11043           else
11044             aopPut (result, zero, 0);
11045           goto release;
11046         }
11047
11048       /* the right is also a bit variable */
11049       if (AOP_TYPE (right) == AOP_CRY)
11050         {
11051           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11052           aopPut (result, "c", 0);
11053           goto release;
11054         }
11055
11056       /* we need to or */
11057       toBoolean (right);
11058       aopPut (result, "a", 0);
11059       goto release;
11060     }
11061
11062   /* bit variables done */
11063   /* general case */
11064   size = AOP_SIZE (result);
11065   offset = 0;
11066   if (AOP_TYPE (right) == AOP_LIT)
11067     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11068
11069   if ((size > 1) &&
11070       (AOP_TYPE (result) != AOP_REG) &&
11071       (AOP_TYPE (right) == AOP_LIT) &&
11072       !IS_FLOAT (operandType (right)) &&
11073       (lit < 256L))
11074     {
11075       while ((size) && (lit))
11076         {
11077           aopPut (result,
11078                   aopGet (right, offset, FALSE, FALSE),
11079                   offset);
11080           lit >>= 8;
11081           offset++;
11082           size--;
11083         }
11084       /* And now fill the rest with zeros. */
11085       if (size)
11086         {
11087           emitcode ("clr", "a");
11088         }
11089       while (size--)
11090         {
11091           aopPut (result, "a", offset);
11092           offset++;
11093         }
11094     }
11095   else
11096     {
11097       while (size--)
11098         {
11099           aopPut (result,
11100                   aopGet (right, offset, FALSE, FALSE),
11101                   offset);
11102           offset++;
11103         }
11104     }
11105
11106 release:
11107   freeAsmop (result, NULL, ic, TRUE);
11108   freeAsmop (right, NULL, ic, TRUE);
11109 }
11110
11111 /*-----------------------------------------------------------------*/
11112 /* genJumpTab - generates code for jump table                      */
11113 /*-----------------------------------------------------------------*/
11114 static void
11115 genJumpTab (iCode * ic)
11116 {
11117   symbol *jtab,*jtablo,*jtabhi;
11118   char *l;
11119   unsigned int count;
11120
11121   D (emitcode (";", "genJumpTab"));
11122
11123   count = elementsInSet( IC_JTLABELS (ic) );
11124
11125   if( count <= 16 )
11126     {
11127       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11128          if the switch argument is in a register.
11129          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11130       /* Peephole may not convert ljmp to sjmp or ret
11131          labelIsReturnOnly & labelInRange must check
11132          currPl->ic->op != JUMPTABLE */
11133       aopOp (IC_JTCOND (ic), ic, FALSE);
11134       /* get the condition into accumulator */
11135       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11136       MOVA (l);
11137       /* multiply by three */
11138       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11139         {
11140           emitcode ("mov", "b,#3");
11141           emitcode ("mul", "ab");
11142         }
11143       else
11144         {
11145           emitcode ("add", "a,acc");
11146           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11147         }
11148       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11149
11150       jtab = newiTempLabel (NULL);
11151       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11152       emitcode ("jmp", "@a+dptr");
11153       emitLabel (jtab);
11154       /* now generate the jump labels */
11155       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11156            jtab = setNextItem (IC_JTLABELS (ic)))
11157         emitcode ("ljmp", "%05d$", jtab->key + 100);
11158     }
11159   else
11160     {
11161       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11162          if the switch argument is in a register.
11163          For n>6 this algorithm may be more compact */
11164       jtablo = newiTempLabel (NULL);
11165       jtabhi = newiTempLabel (NULL);
11166
11167       /* get the condition into accumulator.
11168          Using b as temporary storage, if register push/pop is needed */
11169       aopOp (IC_JTCOND (ic), ic, FALSE);
11170       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11171       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11172           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11173         {
11174           // (MB) what if B is in use???
11175           wassertl(!BINUSE, "B was in use");
11176           emitcode ("mov", "b,%s", l);
11177           l = "b";
11178         }
11179       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11180       MOVA (l);
11181       if( count <= 112 )
11182         {
11183           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11184           emitcode ("movc", "a,@a+pc");
11185           emitcode ("push", "acc");
11186
11187           MOVA (l);
11188           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11189           emitcode ("movc", "a,@a+pc");
11190           emitcode ("push", "acc");
11191         }
11192       else
11193         {
11194           /* this scales up to n<=255, but needs two more bytes
11195              and changes dptr */
11196           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11197           emitcode ("movc", "a,@a+dptr");
11198           emitcode ("push", "acc");
11199
11200           MOVA (l);
11201           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11202           emitcode ("movc", "a,@a+dptr");
11203           emitcode ("push", "acc");
11204         }
11205
11206       emitcode ("ret", "");
11207
11208       /* now generate jump table, LSB */
11209       emitLabel (jtablo);
11210       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11211            jtab = setNextItem (IC_JTLABELS (ic)))
11212         emitcode (".db", "%05d$", jtab->key + 100);
11213
11214       /* now generate jump table, MSB */
11215       emitLabel (jtabhi);
11216       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11217            jtab = setNextItem (IC_JTLABELS (ic)))
11218          emitcode (".db", "%05d$>>8", jtab->key + 100);
11219     }
11220 }
11221
11222 /*-----------------------------------------------------------------*/
11223 /* genCast - gen code for casting                                  */
11224 /*-----------------------------------------------------------------*/
11225 static void
11226 genCast (iCode * ic)
11227 {
11228   operand *result = IC_RESULT (ic);
11229   sym_link *ctype = operandType (IC_LEFT (ic));
11230   sym_link *rtype = operandType (IC_RIGHT (ic));
11231   operand *right = IC_RIGHT (ic);
11232   int size, offset;
11233
11234   D (emitcode (";", "genCast"));
11235
11236   /* if they are equivalent then do nothing */
11237   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11238     return;
11239
11240   aopOp (right, ic, FALSE);
11241   aopOp (result, ic, FALSE);
11242
11243   /* if the result is a bit (and not a bitfield) */
11244   if (IS_BIT (OP_SYMBOL (result)->type))
11245     {
11246       /* if the right size is a literal then
11247          we know what the value is */
11248       if (AOP_TYPE (right) == AOP_LIT)
11249         {
11250           if (((int) operandLitValue (right)))
11251             aopPut (result, one, 0);
11252           else
11253             aopPut (result, zero, 0);
11254
11255           goto release;
11256         }
11257
11258       /* the right is also a bit variable */
11259       if (AOP_TYPE (right) == AOP_CRY)
11260         {
11261           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11262           aopPut (result, "c", 0);
11263           goto release;
11264         }
11265
11266       /* we need to or */
11267       toBoolean (right);
11268       aopPut (result, "a", 0);
11269       goto release;
11270     }
11271
11272   /* if they are the same size : or less */
11273   if (AOP_SIZE (result) <= AOP_SIZE (right))
11274     {
11275
11276       /* if they are in the same place */
11277       if (sameRegs (AOP (right), AOP (result)))
11278         goto release;
11279
11280       /* if they in different places then copy */
11281       size = AOP_SIZE (result);
11282       offset = 0;
11283       while (size--)
11284         {
11285           aopPut (result,
11286                   aopGet (right, offset, FALSE, FALSE),
11287                   offset);
11288           offset++;
11289         }
11290       goto release;
11291     }
11292
11293   /* if the result is of type pointer */
11294   if (IS_PTR (ctype))
11295     {
11296
11297       int p_type;
11298       sym_link *type = operandType (right);
11299       sym_link *etype = getSpec (type);
11300
11301       /* pointer to generic pointer */
11302       if (IS_GENPTR (ctype))
11303         {
11304           if (IS_PTR (type))
11305             {
11306               p_type = DCL_TYPE (type);
11307             }
11308           else
11309             {
11310               if (SPEC_SCLS(etype)==S_REGISTER) {
11311                 // let's assume it is a generic pointer
11312                 p_type=GPOINTER;
11313               } else {
11314                 /* we have to go by the storage class */
11315                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11316               }
11317             }
11318
11319           /* the first two bytes are known */
11320           size = GPTRSIZE - 1;
11321           offset = 0;
11322           while (size--)
11323             {
11324               aopPut (result,
11325                       aopGet (right, offset, FALSE, FALSE),
11326                       offset);
11327               offset++;
11328             }
11329           /* the last byte depending on type */
11330             {
11331                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11332                 char gpValStr[10];
11333
11334                 if (gpVal == -1)
11335                 {
11336                     // pointerTypeToGPByte will have bitched.
11337                     exit(1);
11338                 }
11339
11340                 sprintf(gpValStr, "#0x%x", gpVal);
11341                 aopPut (result, gpValStr, GPTRSIZE - 1);
11342             }
11343           goto release;
11344         }
11345
11346       /* just copy the pointers */
11347       size = AOP_SIZE (result);
11348       offset = 0;
11349       while (size--)
11350         {
11351           aopPut (result,
11352                   aopGet (right, offset, FALSE, FALSE),
11353                   offset);
11354           offset++;
11355         }
11356       goto release;
11357     }
11358
11359   /* so we now know that the size of destination is greater
11360      than the size of the source */
11361   /* we move to result for the size of source */
11362   size = AOP_SIZE (right);
11363   offset = 0;
11364   while (size--)
11365     {
11366       aopPut (result,
11367               aopGet (right, offset, FALSE, FALSE),
11368               offset);
11369       offset++;
11370     }
11371
11372   /* now depending on the sign of the source && destination */
11373   size = AOP_SIZE (result) - AOP_SIZE (right);
11374   /* if unsigned or not an integral type */
11375   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11376     {
11377       while (size--)
11378         aopPut (result, zero, offset++);
11379     }
11380   else
11381     {
11382       /* we need to extend the sign :{ */
11383       char *l = aopGet (right, AOP_SIZE (right) - 1,
11384                         FALSE, FALSE);
11385       MOVA (l);
11386       emitcode ("rlc", "a");
11387       emitcode ("subb", "a,acc");
11388       while (size--)
11389         aopPut (result, "a", offset++);
11390     }
11391
11392   /* we are done hurray !!!! */
11393
11394 release:
11395   freeAsmop (result, NULL, ic, TRUE);
11396   freeAsmop (right, NULL, ic, TRUE);
11397 }
11398
11399 /*-----------------------------------------------------------------*/
11400 /* genDjnz - generate decrement & jump if not zero instrucion      */
11401 /*-----------------------------------------------------------------*/
11402 static int
11403 genDjnz (iCode * ic, iCode * ifx)
11404 {
11405   symbol *lbl, *lbl1;
11406   if (!ifx)
11407     return 0;
11408
11409   /* if the if condition has a false label
11410      then we cannot save */
11411   if (IC_FALSE (ifx))
11412     return 0;
11413
11414   /* if the minus is not of the form a = a - 1 */
11415   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11416       !IS_OP_LITERAL (IC_RIGHT (ic)))
11417     return 0;
11418
11419   if (operandLitValue (IC_RIGHT (ic)) != 1)
11420     return 0;
11421
11422   /* if the size of this greater than one then no
11423      saving */
11424   if (getSize (operandType (IC_RESULT (ic))) > 1)
11425     return 0;
11426
11427   /* otherwise we can save BIG */
11428
11429   D (emitcode (";", "genDjnz"));
11430
11431   lbl = newiTempLabel (NULL);
11432   lbl1 = newiTempLabel (NULL);
11433
11434   aopOp (IC_RESULT (ic), ic, FALSE);
11435
11436   if (AOP_NEEDSACC(IC_RESULT(ic)))
11437   {
11438       /* If the result is accessed indirectly via
11439        * the accumulator, we must explicitly write
11440        * it back after the decrement.
11441        */
11442       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11443
11444       if (strcmp(rByte, "a"))
11445       {
11446            /* Something is hopelessly wrong */
11447            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11448                    __FILE__, __LINE__);
11449            /* We can just give up; the generated code will be inefficient,
11450             * but what the hey.
11451             */
11452            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11453            return 0;
11454       }
11455       emitcode ("dec", "%s", rByte);
11456       aopPut (IC_RESULT (ic), rByte, 0);
11457       emitcode ("jnz", "%05d$", lbl->key + 100);
11458   }
11459   else if (IS_AOP_PREG (IC_RESULT (ic)))
11460     {
11461       emitcode ("dec", "%s",
11462                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11463       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11464       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11465       ifx->generated = 1;
11466       emitcode ("jnz", "%05d$", lbl->key + 100);
11467     }
11468   else
11469     {
11470       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11471                 lbl->key + 100);
11472     }
11473   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11474   emitLabel (lbl);
11475   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11476   emitLabel (lbl1);
11477
11478   if (!ifx->generated)
11479       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11480   ifx->generated = 1;
11481   return 1;
11482 }
11483
11484 /*-----------------------------------------------------------------*/
11485 /* genReceive - generate code for a receive iCode                  */
11486 /*-----------------------------------------------------------------*/
11487 static void
11488 genReceive (iCode * ic)
11489 {
11490   int size = getSize (operandType (IC_RESULT (ic)));
11491   int offset = 0;
11492
11493   D (emitcode (";", "genReceive"));
11494
11495   if (ic->argreg == 1)
11496     { /* first parameter */
11497       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11498            isOperandInPagedSpace (IC_RESULT (ic))) &&
11499           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11500            IS_TRUE_SYMOP (IC_RESULT (ic))))
11501         {
11502           regs *tempRegs[4];
11503           int receivingA = 0;
11504           int roffset = 0;
11505
11506           for (offset = 0; offset<size; offset++)
11507             if (!strcmp (fReturn[offset], "a"))
11508               receivingA = 1;
11509
11510           if (!receivingA)
11511             {
11512               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11513                 {
11514                   for (offset = size-1; offset>0; offset--)
11515                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11516                   emitcode("mov","a,%s", fReturn[0]);
11517                   _G.accInUse++;
11518                   aopOp (IC_RESULT (ic), ic, FALSE);
11519                   _G.accInUse--;
11520                   aopPut (IC_RESULT (ic), "a", offset);
11521                   for (offset = 1; offset<size; offset++)
11522                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11523                   goto release;
11524                 }
11525             }
11526           else
11527             {
11528               if (getTempRegs(tempRegs, size, ic))
11529                 {
11530                   for (offset = 0; offset<size; offset++)
11531                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11532                   aopOp (IC_RESULT (ic), ic, FALSE);
11533                   for (offset = 0; offset<size; offset++)
11534                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11535                   goto release;
11536                 }
11537             }
11538
11539           offset = fReturnSizeMCS51 - size;
11540           while (size--)
11541             {
11542               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11543                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11544               offset++;
11545             }
11546           aopOp (IC_RESULT (ic), ic, FALSE);
11547           size = AOP_SIZE (IC_RESULT (ic));
11548           offset = 0;
11549           while (size--)
11550             {
11551               emitcode ("pop", "acc");
11552               aopPut (IC_RESULT (ic), "a", offset++);
11553             }
11554         }
11555       else
11556         {
11557           _G.accInUse++;
11558           aopOp (IC_RESULT (ic), ic, FALSE);
11559           _G.accInUse--;
11560           assignResultValue (IC_RESULT (ic), NULL);
11561         }
11562     }
11563   else if (ic->argreg > 12)
11564     { /* bit parameters */
11565       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11566         {
11567           aopOp (IC_RESULT (ic), ic, FALSE);
11568           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11569           outBitC(IC_RESULT (ic));
11570         }
11571     }
11572   else
11573     { /* other parameters */
11574       int rb1off ;
11575       aopOp (IC_RESULT (ic), ic, FALSE);
11576       rb1off = ic->argreg;
11577       while (size--)
11578         {
11579           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11580         }
11581     }
11582
11583 release:
11584   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11585 }
11586
11587 /*-----------------------------------------------------------------*/
11588 /* genDummyRead - generate code for dummy read of volatiles        */
11589 /*-----------------------------------------------------------------*/
11590 static void
11591 genDummyRead (iCode * ic)
11592 {
11593   operand *op;
11594   int size, offset;
11595
11596   D (emitcode(";", "genDummyRead"));
11597
11598   op = IC_RIGHT (ic);
11599   if (op && IS_SYMOP (op))
11600     {
11601       aopOp (op, ic, FALSE);
11602
11603       /* if the result is a bit */
11604       if (AOP_TYPE (op) == AOP_CRY)
11605         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11606       else
11607         {
11608           /* bit variables done */
11609           /* general case */
11610           size = AOP_SIZE (op);
11611           offset = 0;
11612           while (size--)
11613           {
11614             MOVA (aopGet (op, offset, FALSE, FALSE));
11615             offset++;
11616           }
11617         }
11618
11619       freeAsmop (op, NULL, ic, TRUE);
11620     }
11621
11622   op = IC_LEFT (ic);
11623   if (op && IS_SYMOP (op))
11624     {
11625       aopOp (op, ic, FALSE);
11626
11627       /* if the result is a bit */
11628       if (AOP_TYPE (op) == AOP_CRY)
11629         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11630       else
11631         {
11632           /* bit variables done */
11633           /* general case */
11634           size = AOP_SIZE (op);
11635           offset = 0;
11636           while (size--)
11637           {
11638             MOVA (aopGet (op, offset, FALSE, FALSE));
11639             offset++;
11640           }
11641         }
11642
11643       freeAsmop (op, NULL, ic, TRUE);
11644     }
11645 }
11646
11647 /*-----------------------------------------------------------------*/
11648 /* genCritical - generate code for start of a critical sequence    */
11649 /*-----------------------------------------------------------------*/
11650 static void
11651 genCritical (iCode *ic)
11652 {
11653   symbol *tlbl = newiTempLabel (NULL);
11654
11655   D (emitcode(";", "genCritical"));
11656
11657   if (IC_RESULT (ic))
11658     {
11659       aopOp (IC_RESULT (ic), ic, TRUE);
11660       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11661       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11662       aopPut (IC_RESULT (ic), zero, 0);
11663       emitLabel (tlbl);
11664       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11665     }
11666   else
11667     {
11668       emitcode ("setb", "c");
11669       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11670       emitcode ("clr", "c");
11671       emitLabel (tlbl);
11672       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11673     }
11674 }
11675
11676 /*-----------------------------------------------------------------*/
11677 /* genEndCritical - generate code for end of a critical sequence   */
11678 /*-----------------------------------------------------------------*/
11679 static void
11680 genEndCritical (iCode *ic)
11681 {
11682   D(emitcode(";     genEndCritical",""));
11683
11684   if (IC_RIGHT (ic))
11685     {
11686       aopOp (IC_RIGHT (ic), ic, FALSE);
11687       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11688         {
11689           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11690           emitcode ("mov", "ea,c");
11691         }
11692       else
11693         {
11694           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11695             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11696           emitcode ("rrc", "a");
11697           emitcode ("mov", "ea,c");
11698         }
11699       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11700     }
11701   else
11702     {
11703       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11704       emitcode ("mov", "ea,c");
11705     }
11706 }
11707
11708 /*-----------------------------------------------------------------*/
11709 /* gen51Code - generate code for 8051 based controllers            */
11710 /*-----------------------------------------------------------------*/
11711 void
11712 gen51Code (iCode * lic)
11713 {
11714   iCode *ic;
11715   int cln = 0;
11716   /* int cseq = 0; */
11717
11718   _G.currentFunc = NULL;
11719   lineHead = lineCurr = NULL;
11720
11721   /* print the allocation information */
11722   if (allocInfo && currFunc)
11723     printAllocInfo (currFunc, codeOutBuf);
11724   /* if debug information required */
11725   if (options.debug && currFunc)
11726     {
11727       debugFile->writeFunction (currFunc, lic);
11728     }
11729   /* stack pointer name */
11730   if (options.useXstack)
11731     spname = "_spx";
11732   else
11733     spname = "sp";
11734
11735
11736   for (ic = lic; ic; ic = ic->next)
11737     {
11738       _G.current_iCode = ic;
11739
11740       if (ic->lineno && cln != ic->lineno)
11741         {
11742           if (options.debug)
11743             {
11744               debugFile->writeCLine (ic);
11745             }
11746           if (!options.noCcodeInAsm) {
11747             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11748                       printCLine(ic->filename, ic->lineno));
11749           }
11750           cln = ic->lineno;
11751         }
11752       #if 0
11753       if (ic->seqPoint && ic->seqPoint != cseq)
11754         {
11755           emitcode ("", "; sequence point %d", ic->seqPoint);
11756           cseq = ic->seqPoint;
11757         }
11758       #endif
11759       if (options.iCodeInAsm) {
11760         char regsInUse[80];
11761         int i;
11762         char *iLine;
11763
11764         #if 0
11765         for (i=0; i<8; i++) {
11766           sprintf (&regsInUse[i],
11767                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11768         regsInUse[i]=0;
11769         #else
11770         strcpy (regsInUse, "--------");
11771         for (i=0; i < 8; i++) {
11772           if (bitVectBitValue (ic->rMask, i))
11773             {
11774               int offset = regs8051[i].offset;
11775               regsInUse[offset] = offset + '0'; /* show rMask */
11776             }
11777         #endif
11778         }
11779         iLine = printILine(ic);
11780         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11781         dbuf_free(iLine);
11782       }
11783       /* if the result is marked as
11784          spilt and rematerializable or code for
11785          this has already been generated then
11786          do nothing */
11787       if (resultRemat (ic) || ic->generated)
11788         continue;
11789
11790       /* depending on the operation */
11791       switch (ic->op)
11792         {
11793         case '!':
11794           genNot (ic);
11795           break;
11796
11797         case '~':
11798           genCpl (ic);
11799           break;
11800
11801         case UNARYMINUS:
11802           genUminus (ic);
11803           break;
11804
11805         case IPUSH:
11806           genIpush (ic);
11807           break;
11808
11809         case IPOP:
11810           /* IPOP happens only when trying to restore a
11811              spilt live range, if there is an ifx statement
11812              following this pop then the if statement might
11813              be using some of the registers being popped which
11814              would destory the contents of the register so
11815              we need to check for this condition and handle it */
11816           if (ic->next &&
11817               ic->next->op == IFX &&
11818               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11819             genIfx (ic->next, ic);
11820           else
11821             genIpop (ic);
11822           break;
11823
11824         case CALL:
11825           genCall (ic);
11826           break;
11827
11828         case PCALL:
11829           genPcall (ic);
11830           break;
11831
11832         case FUNCTION:
11833           genFunction (ic);
11834           break;
11835
11836         case ENDFUNCTION:
11837           genEndFunction (ic);
11838           break;
11839
11840         case RETURN:
11841           genRet (ic);
11842           break;
11843
11844         case LABEL:
11845           genLabel (ic);
11846           break;
11847
11848         case GOTO:
11849           genGoto (ic);
11850           break;
11851
11852         case '+':
11853           genPlus (ic);
11854           break;
11855
11856         case '-':
11857           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11858             genMinus (ic);
11859           break;
11860
11861         case '*':
11862           genMult (ic);
11863           break;
11864
11865         case '/':
11866           genDiv (ic);
11867           break;
11868
11869         case '%':
11870           genMod (ic);
11871           break;
11872
11873         case '>':
11874           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11875           break;
11876
11877         case '<':
11878           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11879           break;
11880
11881         case LE_OP:
11882         case GE_OP:
11883         case NE_OP:
11884
11885           /* note these two are xlated by algebraic equivalence
11886              in decorateType() in SDCCast.c */
11887           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11888                   "got '>=' or '<=' shouldn't have come here");
11889           break;
11890
11891         case EQ_OP:
11892           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11893           break;
11894
11895         case AND_OP:
11896           genAndOp (ic);
11897           break;
11898
11899         case OR_OP:
11900           genOrOp (ic);
11901           break;
11902
11903         case '^':
11904           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11905           break;
11906
11907         case '|':
11908           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11909           break;
11910
11911         case BITWISEAND:
11912           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11913           break;
11914
11915         case INLINEASM:
11916           genInline (ic);
11917           break;
11918
11919         case RRC:
11920           genRRC (ic);
11921           break;
11922
11923         case RLC:
11924           genRLC (ic);
11925           break;
11926
11927         case GETHBIT:
11928           genGetHbit (ic);
11929           break;
11930
11931         case GETABIT:
11932           genGetAbit (ic);
11933           break;
11934
11935         case GETBYTE:
11936           genGetByte (ic);
11937           break;
11938
11939         case GETWORD:
11940           genGetWord (ic);
11941           break;
11942
11943         case LEFT_OP:
11944           genLeftShift (ic);
11945           break;
11946
11947         case RIGHT_OP:
11948           genRightShift (ic);
11949           break;
11950
11951         case GET_VALUE_AT_ADDRESS:
11952           genPointerGet (ic,
11953                          hasInc (IC_LEFT (ic), ic,
11954                                  getSize (operandType (IC_RESULT (ic)))),
11955                          ifxForOp (IC_RESULT (ic), ic) );
11956           break;
11957
11958         case '=':
11959           if (POINTER_SET (ic))
11960             genPointerSet (ic,
11961                            hasInc (IC_RESULT (ic), ic,
11962                                    getSize (operandType (IC_RIGHT (ic)))));
11963           else
11964             genAssign (ic);
11965           break;
11966
11967         case IFX:
11968           genIfx (ic, NULL);
11969           break;
11970
11971         case ADDRESS_OF:
11972           genAddrOf (ic);
11973           break;
11974
11975         case JUMPTABLE:
11976           genJumpTab (ic);
11977           break;
11978
11979         case CAST:
11980           genCast (ic);
11981           break;
11982
11983         case RECEIVE:
11984           genReceive (ic);
11985           break;
11986
11987         case SEND:
11988           addSet (&_G.sendSet, ic);
11989           break;
11990
11991         case DUMMY_READ_VOLATILE:
11992           genDummyRead (ic);
11993           break;
11994
11995         case CRITICAL:
11996           genCritical (ic);
11997           break;
11998
11999         case ENDCRITICAL:
12000           genEndCritical (ic);
12001           break;
12002
12003         case SWAP:
12004           genSwap (ic);
12005           break;
12006
12007         default:
12008           ic = ic;
12009         }
12010     }
12011
12012   _G.current_iCode = NULL;
12013
12014   /* now we are ready to call the
12015      peep hole optimizer */
12016   if (!options.nopeep)
12017     peepHole (&lineHead);
12018
12019   /* now do the actual printing */
12020   printLine (lineHead, codeOutBuf);
12021   return;
12022 }