* debugger/mcs51/break.c,
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45
46 char *aopLiteral (value * val, int offset);
47 char *aopLiteralLong (value * val, int offset, int size);
48 extern int allocInfo;
49
50 /* this is the down and dirty file with all kinds of
51    kludgy & hacky stuff. This is what it is all about
52    CODE GENERATION for a specific MCU . some of the
53    routines may be reusable, will have to see */
54
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
57 static char *spname;
58
59 char *fReturn8051[] =
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
64 {"a", "b"};
65
66 static unsigned short rbank = -1;
67
68 #define AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72                        AOP_TYPE(x) == AOP_R0))
73
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
75                         AOP_TYPE(x) == AOP_DPTR || \
76                         AOP(x)->paged))
77
78 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
79                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
80                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
81
82 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
83
84 #define R0INB   _G.bu.bs.r0InB
85 #define R1INB   _G.bu.bs.r1InB
86 #define OPINB   _G.bu.bs.OpInB
87 #define BINUSE  _G.bu.BInUse
88
89 static struct
90   {
91     short r0Pushed;
92     short r1Pushed;
93     union
94       {
95         struct
96           {
97             short r0InB : 2;//2 so we can see it overflow
98             short r1InB : 2;//2 so we can see it overflow
99             short OpInB : 2;//2 so we can see it overflow
100           } bs;
101         short BInUse;
102       } bu;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108     iCode *current_iCode;
109     symbol *currentFunc;
110   }
111 _G;
112
113 static char *rb1regs[] = {
114     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
115     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
116 };
117
118 extern FILE *codeOutFile;
119 static void saveRBank (int, iCode *, bool);
120
121 #define RESULTONSTACK(x) \
122                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
123                          IC_RESULT(x)->aop->type == AOP_STK )
124
125 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
126 #define CLRC     emitcode("clr","c")
127 #define SETC     emitcode("setb","c")
128
129 static lineNode *lineHead = NULL;
130 static lineNode *lineCurr = NULL;
131
132 static unsigned char SLMask[] =
133 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
134  0xE0, 0xC0, 0x80, 0x00};
135 static unsigned char SRMask[] =
136 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
137  0x07, 0x03, 0x01, 0x00};
138
139 #define LSB     0
140 #define MSB16   1
141 #define MSB24   2
142 #define MSB32   3
143
144 /*-----------------------------------------------------------------*/
145 /* emitcode - writes the code into a file : for now it is simple    */
146 /*-----------------------------------------------------------------*/
147 static void
148 emitcode (char *inst, const char *fmt,...)
149 {
150   va_list ap;
151   char lb[INITIAL_INLINEASM];
152   char *lbp = lb;
153
154   va_start (ap, fmt);
155
156   if (inst && *inst)
157     {
158       if (fmt && *fmt)
159         {
160           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
161         }
162       else
163         {
164           SNPRINTF (lb, sizeof(lb), "%s", inst);
165         }
166
167       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
168     }
169   else
170     {
171       tvsprintf (lb, sizeof(lb), fmt, ap);
172     }
173
174   while (isspace ((unsigned char)*lbp))
175     {
176       lbp++;
177     }
178
179   if (lbp && *lbp)
180     {
181       lineCurr = (lineCurr ?
182                   connectLine (lineCurr, newLineNode (lb)) :
183                   (lineHead = newLineNode (lb)));
184     }
185
186   lineCurr->isInline = _G.inLine;
187   lineCurr->isDebug = _G.debugLine;
188   lineCurr->ic = _G.current_iCode;
189   lineCurr->isComment = (*lbp==';');
190   va_end (ap);
191 }
192
193 /*-----------------------------------------------------------------*/
194 /* mcs51_emitDebuggerSymbol - associate the current code location  */
195 /*   with a debugger symbol                                        */
196 /*-----------------------------------------------------------------*/
197 void
198 mcs51_emitDebuggerSymbol (char * debugSym)
199 {
200   _G.debugLine = 1;
201   emitcode ("", "%s ==.", debugSym);
202   _G.debugLine = 0;
203 }
204
205 /*-----------------------------------------------------------------*/
206 /* mova - moves specified value into accumulator                   */
207 /*-----------------------------------------------------------------*/
208 static void
209 mova (const char *x)
210 {
211   /* do some early peephole optimization */
212   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
213     return;
214
215   emitcode("mov", "a,%s", x);
216 }
217
218 /*-----------------------------------------------------------------*/
219 /* movc - moves specified value into the carry                     */
220 /*-----------------------------------------------------------------*/
221 static void
222 movc (const char *s)
223 {
224   if (s == zero)
225     CLRC;
226   else if (s == one)
227     SETC;
228   else if (strcmp (s, "c"))
229     {/* it's not in carry already */
230       MOVA (s);
231       /* set C, if a >= 1 */
232       emitcode ("add", "a,#0xff");
233     }
234 }
235
236 /*-----------------------------------------------------------------*/
237 /* pushB - saves register B if necessary                           */
238 /*-----------------------------------------------------------------*/
239 static bool
240 pushB (void)
241 {
242   bool pushedB = FALSE;
243
244   if (BINUSE)
245     {
246       emitcode ("push", "b");
247 //    printf("B was in use !\n");
248       pushedB = TRUE;
249     }
250   else
251     {
252       OPINB++;
253     }
254   return pushedB;
255 }
256
257 /*-----------------------------------------------------------------*/
258 /* popB - restores value of register B if necessary                */
259 /*-----------------------------------------------------------------*/
260 static void
261 popB (bool pushedB)
262 {
263   if (pushedB)
264     {
265       emitcode ("pop", "b");
266     }
267   else
268     {
269       OPINB--;
270     }
271 }
272
273 /*-----------------------------------------------------------------*/
274 /* pushReg - saves register                                        */
275 /*-----------------------------------------------------------------*/
276 static bool
277 pushReg (int index, bool bits_pushed)
278 {
279   regs * reg = mcs51_regWithIdx (index);
280   if (reg->type == REG_BIT)
281     {
282       if (!bits_pushed)
283         emitcode ("push", "%s", reg->base);
284       return TRUE;
285     }
286   else
287     emitcode ("push", "%s", reg->dname);
288   return bits_pushed;
289 }
290
291 /*-----------------------------------------------------------------*/
292 /* popReg - restores register                                      */
293 /*-----------------------------------------------------------------*/
294 static bool
295 popReg (int index, bool bits_popped)
296 {
297   regs * reg = mcs51_regWithIdx (index);
298   if (reg->type == REG_BIT)
299     {
300       if (!bits_popped)
301         emitcode ("pop", "%s", reg->base);
302       return TRUE;
303     }
304   else
305     emitcode ("pop", "%s", reg->dname);
306   return bits_popped;
307 }
308
309 /*-----------------------------------------------------------------*/
310 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
311 /*-----------------------------------------------------------------*/
312 static regs *
313 getFreePtr (iCode * ic, asmop ** aopp, bool result)
314 {
315   bool r0iu, r1iu;
316   bool r0ou, r1ou;
317
318   /* the logic: if r0 & r1 used in the instruction
319      then we are in trouble otherwise */
320
321   /* first check if r0 & r1 are used by this
322      instruction, in which case we are in trouble */
323   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
324   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
325   if (r0iu && r1iu) {
326       goto endOfWorld;
327     }
328
329   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
330   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
331
332   /* if no usage of r0 then return it */
333   if (!r0iu && !r0ou)
334     {
335       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
336       (*aopp)->type = AOP_R0;
337
338       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
339     }
340
341   /* if no usage of r1 then return it */
342   if (!r1iu && !r1ou)
343     {
344       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
345       (*aopp)->type = AOP_R1;
346
347       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
348     }
349
350   /* now we know they both have usage */
351   /* if r0 not used in this instruction */
352   if (!r0iu)
353     {
354       /* push it if not already pushed */
355       if (ic->op == IPUSH)
356         {
357           emitcode ("mov", "b,%s",
358                     mcs51_regWithIdx (R0_IDX)->dname);
359           R0INB++;
360         }
361       else if (!_G.r0Pushed)
362         {
363           emitcode ("push", "%s",
364                     mcs51_regWithIdx (R0_IDX)->dname);
365           _G.r0Pushed++;
366         }
367
368       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
369       (*aopp)->type = AOP_R0;
370
371       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
372     }
373
374   /* if r1 not used then */
375
376   if (!r1iu)
377     {
378       /* push it if not already pushed */
379       if (ic->op == IPUSH)
380         {
381           emitcode ("mov", "b,%s",
382                     mcs51_regWithIdx (R1_IDX)->dname);
383           R1INB++;
384         }
385       else if (!_G.r1Pushed)
386         {
387           emitcode ("push", "%s",
388                     mcs51_regWithIdx (R1_IDX)->dname);
389           _G.r1Pushed++;
390         }
391
392       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
393       (*aopp)->type = AOP_R1;
394       return mcs51_regWithIdx (R1_IDX);
395     }
396 endOfWorld:
397   /* I said end of world, but not quite end of world yet */
398   if (result) {
399     /* we can push it on the stack */
400     (*aopp)->type = AOP_STK;
401     return NULL;
402   } else {
403     /* in the case that result AND left AND right needs a pointer reg
404        we can safely use the result's */
405     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
406       (*aopp)->type = AOP_R0;
407       return mcs51_regWithIdx (R0_IDX);
408     }
409     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
410       (*aopp)->type = AOP_R1;
411       return mcs51_regWithIdx (R1_IDX);
412     }
413   }
414
415   /* now this is REALLY the end of the world */
416   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
417           "getFreePtr should never reach here");
418   exit (1);
419 }
420
421
422 /*-----------------------------------------------------------------*/
423 /* getTempRegs - initialize an array of pointers to GPR registers */
424 /*               that are not in use. Returns 1 if the requested   */
425 /*               number of registers were available, 0 otherwise.  */
426 /*-----------------------------------------------------------------*/
427 int
428 getTempRegs(regs **tempRegs, int size, iCode *ic)
429 {
430   bitVect * freeRegs;
431   int i;
432   int offset;
433
434   if (!ic)
435     ic = _G.current_iCode;
436   if (!ic)
437     return 0;
438   if (!_G.currentFunc)
439     return 0;
440
441   freeRegs = newBitVect(8);
442   bitVectSetBit (freeRegs, R2_IDX);
443   bitVectSetBit (freeRegs, R3_IDX);
444   bitVectSetBit (freeRegs, R4_IDX);
445   bitVectSetBit (freeRegs, R5_IDX);
446   bitVectSetBit (freeRegs, R6_IDX);
447   bitVectSetBit (freeRegs, R7_IDX);
448
449   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
450     {
451       bitVect * newfreeRegs;
452       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
453       freeBitVect(freeRegs);
454       freeRegs = newfreeRegs;
455     }
456   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
457
458   offset = 0;
459   for (i=0; i<freeRegs->size; i++)
460     {
461       if (bitVectBitValue(freeRegs,i))
462         tempRegs[offset++] = mcs51_regWithIdx(i);
463       if (offset>=size)
464         {
465           freeBitVect(freeRegs);
466           return 1;
467         }
468     }
469
470   freeBitVect(freeRegs);
471   return 0;
472 }
473
474
475 /*-----------------------------------------------------------------*/
476 /* newAsmop - creates a new asmOp                                  */
477 /*-----------------------------------------------------------------*/
478 static asmop *
479 newAsmop (short type)
480 {
481   asmop *aop;
482
483   aop = Safe_calloc (1, sizeof (asmop));
484   aop->type = type;
485   aop->allocated = 1;
486   return aop;
487 }
488
489 /*-----------------------------------------------------------------*/
490 /* pointerCode - returns the code for a pointer type               */
491 /*-----------------------------------------------------------------*/
492 static int
493 pointerCode (sym_link * etype)
494 {
495
496   return PTR_TYPE (SPEC_OCLS (etype));
497
498 }
499
500 /*-----------------------------------------------------------------*/
501 /* leftRightUseAcc - returns size of accumulator use by operands   */
502 /*-----------------------------------------------------------------*/
503 static int
504 leftRightUseAcc(iCode *ic)
505 {
506   operand *op;
507   int size;
508   int accuseSize = 0;
509   int accuse = 0;
510
511   if (!ic)
512     {
513       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
514               "null iCode pointer");
515       return 0;
516     }
517
518   if (ic->op == IFX)
519     {
520       op = IC_COND (ic);
521       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
522         {
523           accuse = 1;
524           size = getSize (OP_SYMBOL (op)->type);
525           if (size>accuseSize)
526             accuseSize = size;
527         }
528     }
529   else if (ic->op == JUMPTABLE)
530     {
531       op = IC_JTCOND (ic);
532       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
533         {
534           accuse = 1;
535           size = getSize (OP_SYMBOL (op)->type);
536           if (size>accuseSize)
537             accuseSize = size;
538         }
539     }
540   else
541     {
542       op = IC_LEFT (ic);
543       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
544         {
545           accuse = 1;
546           size = getSize (OP_SYMBOL (op)->type);
547           if (size>accuseSize)
548             accuseSize = size;
549         }
550       op = IC_RIGHT (ic);
551       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
552         {
553           accuse = 1;
554           size = getSize (OP_SYMBOL (op)->type);
555           if (size>accuseSize)
556             accuseSize = size;
557         }
558     }
559
560   if (accuseSize)
561     return accuseSize;
562   else
563     return accuse;
564 }
565
566 /*-----------------------------------------------------------------*/
567 /* aopForSym - for a true symbol                                   */
568 /*-----------------------------------------------------------------*/
569 static asmop *
570 aopForSym (iCode * ic, symbol * sym, bool result)
571 {
572   asmop *aop;
573   memmap *space;
574   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
575
576   wassertl (ic != NULL, "Got a null iCode");
577   wassertl (sym != NULL, "Got a null symbol");
578
579   space = SPEC_OCLS (sym->etype);
580
581   /* if already has one */
582   if (sym->aop)
583     {
584       sym->aop->allocated++;
585       return sym->aop;
586     }
587
588   /* assign depending on the storage class */
589   /* if it is on the stack or indirectly addressable */
590   /* space we need to assign either r0 or r1 to it   */
591   if (sym->onStack || sym->iaccess)
592     {
593       sym->aop = aop = newAsmop (0);
594       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
595       aop->size = getSize (sym->type);
596
597       /* now assign the address of the variable to
598          the pointer register */
599       if (aop->type != AOP_STK)
600         {
601           if (sym->onStack)
602             {
603               char offset = ((sym->stack < 0) ?
604                          ((char) (sym->stack - _G.nRegsSaved)) :
605                          ((char) sym->stack)) & 0xff;
606
607               if ((abs(offset) <= 3) ||
608                   (accuse && (abs(offset) <= 7)))
609                 {
610                   emitcode ("mov", "%s,%s",
611                             aop->aopu.aop_ptr->name, SYM_BP (sym));
612                   while (offset < 0)
613                     {
614                       emitcode ("dec", aop->aopu.aop_ptr->name);
615                       offset++;
616                     }
617                   while (offset > 0)
618                     {
619                       emitcode ("inc", aop->aopu.aop_ptr->name);
620                       offset--;
621                     }
622                 }
623               else
624                 {
625                   if (accuse)
626                     emitcode ("push", "acc");
627                   emitcode ("mov", "a,%s", SYM_BP (sym));
628                   emitcode ("add", "a,#0x%02x", offset);
629                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
630                   if (accuse)
631                     emitcode ("pop", "acc");
632                 }
633             }
634           else
635             {
636               emitcode ("mov", "%s,#%s",
637                         aop->aopu.aop_ptr->name,
638                         sym->rname);
639             }
640           aop->paged = space->paged;
641         }
642       else
643         aop->aopu.aop_stk = sym->stack;
644       return aop;
645     }
646
647   /* if in bit space */
648   if (IN_BITSPACE (space))
649     {
650       sym->aop = aop = newAsmop (AOP_CRY);
651       aop->aopu.aop_dir = sym->rname;
652       aop->size = getSize (sym->type);
653       return aop;
654     }
655   /* if it is in direct space */
656   if (IN_DIRSPACE (space))
657     {
658       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
659       //printTypeChainRaw(sym->type, NULL);
660       //printf("space = %s\n", space ? space->sname : "NULL");
661       sym->aop = aop = newAsmop (AOP_DIR);
662       aop->aopu.aop_dir = sym->rname;
663       aop->size = getSize (sym->type);
664       return aop;
665     }
666
667   /* special case for a function */
668   if (IS_FUNC (sym->type))
669     {
670       sym->aop = aop = newAsmop (AOP_IMMD);
671       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
672       aop->size = getSize (sym->type);
673       return aop;
674     }
675
676   /* only remaining is far space */
677   /* in which case DPTR gets the address */
678   sym->aop = aop = newAsmop (AOP_DPTR);
679   emitcode ("mov", "dptr,#%s", sym->rname);
680   aop->size = getSize (sym->type);
681
682   /* if it is in code space */
683   if (IN_CODESPACE (space))
684     aop->code = 1;
685
686   return aop;
687 }
688
689 /*-----------------------------------------------------------------*/
690 /* aopForRemat - rematerialzes an object                           */
691 /*-----------------------------------------------------------------*/
692 static asmop *
693 aopForRemat (symbol * sym)
694 {
695   iCode *ic = sym->rematiCode;
696   asmop *aop = newAsmop (AOP_IMMD);
697   int ptr_type = 0;
698   int val = 0;
699
700   for (;;)
701     {
702       if (ic->op == '+')
703         val += (int) operandLitValue (IC_RIGHT (ic));
704       else if (ic->op == '-')
705         val -= (int) operandLitValue (IC_RIGHT (ic));
706       else if (IS_CAST_ICODE(ic)) {
707               sym_link *from_type = operandType(IC_RIGHT(ic));
708               aop->aopu.aop_immd.from_cast_remat = 1;
709               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
710               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
711               continue;
712       } else break;
713
714       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
715     }
716
717   if (val)
718     {
719       SNPRINTF (buffer, sizeof(buffer),
720                 "(%s %c 0x%04x)",
721                 OP_SYMBOL (IC_LEFT (ic))->rname,
722                 val >= 0 ? '+' : '-',
723                 abs (val) & 0xffff);
724     }
725   else
726     {
727       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
728     }
729
730   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
731   /* set immd2 field if required */
732   if (aop->aopu.aop_immd.from_cast_remat)
733     {
734       sprintf(buffer,"#0x%02x",ptr_type);
735       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
736     }
737
738   return aop;
739 }
740
741 /*-----------------------------------------------------------------*/
742 /* regsInCommon - two operands have some registers in common       */
743 /*-----------------------------------------------------------------*/
744 static bool
745 regsInCommon (operand * op1, operand * op2)
746 {
747   symbol *sym1, *sym2;
748   int i;
749
750   /* if they have registers in common */
751   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
752     return FALSE;
753
754   sym1 = OP_SYMBOL (op1);
755   sym2 = OP_SYMBOL (op2);
756
757   if (sym1->nRegs == 0 || sym2->nRegs == 0)
758     return FALSE;
759
760   for (i = 0; i < sym1->nRegs; i++)
761     {
762       int j;
763       if (!sym1->regs[i])
764         continue;
765
766       for (j = 0; j < sym2->nRegs; j++)
767         {
768           if (!sym2->regs[j])
769             continue;
770
771           if (sym2->regs[j] == sym1->regs[i])
772             return TRUE;
773         }
774     }
775
776   return FALSE;
777 }
778
779 /*-----------------------------------------------------------------*/
780 /* operandsEqu - equivalent                                        */
781 /*-----------------------------------------------------------------*/
782 static bool
783 operandsEqu (operand * op1, operand * op2)
784 {
785   symbol *sym1, *sym2;
786
787   /* if they're not symbols */
788   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
789     return FALSE;
790
791   sym1 = OP_SYMBOL (op1);
792   sym2 = OP_SYMBOL (op2);
793
794   /* if both are itemps & one is spilt
795      and the other is not then false */
796   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
797       sym1->isspilt != sym2->isspilt)
798     return FALSE;
799
800   /* if they are the same */
801   if (sym1 == sym2)
802     return TRUE;
803
804   /* if they have the same rname */
805   if (sym1->rname[0] && sym2->rname[0] &&
806       strcmp (sym1->rname, sym2->rname) == 0 &&
807       !(IS_PARM (op2) && IS_ITEMP (op1)))
808     return TRUE;
809
810   /* if left is a tmp & right is not */
811   if (IS_ITEMP (op1) &&
812       !IS_ITEMP (op2) &&
813       sym1->isspilt &&
814       (sym1->usl.spillLoc == sym2))
815     return TRUE;
816
817   if (IS_ITEMP (op2) &&
818       !IS_ITEMP (op1) &&
819       sym2->isspilt &&
820       sym1->level > 0 &&
821       (sym2->usl.spillLoc == sym1))
822     return TRUE;
823
824   return FALSE;
825 }
826
827 /*-----------------------------------------------------------------*/
828 /* sameReg - two asmops have the same register at given offsets    */
829 /*-----------------------------------------------------------------*/
830 static bool
831 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
832 {
833   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
834     return FALSE;
835
836   if (aop1->type != aop2->type)
837     return FALSE;
838
839   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
840     return FALSE;
841
842   return TRUE;
843 }
844
845 /*-----------------------------------------------------------------*/
846 /* sameRegs - two asmops have the same registers                   */
847 /*-----------------------------------------------------------------*/
848 static bool
849 sameRegs (asmop * aop1, asmop * aop2)
850 {
851   int i;
852
853   if (aop1 == aop2)
854     return TRUE;
855
856   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
857     return FALSE;
858
859   if (aop1->type != aop2->type)
860     return FALSE;
861
862   if (aop1->size != aop2->size)
863     return FALSE;
864
865   for (i = 0; i < aop1->size; i++)
866     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
867       return FALSE;
868
869   return TRUE;
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* aopOp - allocates an asmop for an operand  :                    */
874 /*-----------------------------------------------------------------*/
875 static void
876 aopOp (operand * op, iCode * ic, bool result)
877 {
878   asmop *aop;
879   symbol *sym;
880   int i;
881
882   if (!op)
883     return;
884
885   /* if this a literal */
886   if (IS_OP_LITERAL (op))
887     {
888       op->aop = aop = newAsmop (AOP_LIT);
889       aop->aopu.aop_lit = op->operand.valOperand;
890       aop->size = getSize (operandType (op));
891       return;
892     }
893
894   /* if already has a asmop then continue */
895   if (op->aop)
896     {
897       op->aop->allocated++;
898       return;
899     }
900
901   /* if the underlying symbol has a aop */
902   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
903     {
904       op->aop = OP_SYMBOL (op)->aop;
905       op->aop->allocated++;
906       return;
907     }
908
909   /* if this is a true symbol */
910   if (IS_TRUE_SYMOP (op))
911     {
912       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
913       return;
914     }
915
916   /* this is a temporary : this has
917      only five choices :
918      a) register
919      b) spillocation
920      c) rematerialize
921      d) conditional
922      e) can be a return use only */
923
924   sym = OP_SYMBOL (op);
925
926   /* if the type is a conditional */
927   if (sym->regType == REG_CND)
928     {
929       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
930       aop->size = 0;
931       return;
932     }
933
934   /* if it is spilt then two situations
935      a) is rematerialize
936      b) has a spill location */
937   if (sym->isspilt || sym->nRegs == 0)
938     {
939
940       /* rematerialize it NOW */
941       if (sym->remat)
942         {
943           sym->aop = op->aop = aop =
944             aopForRemat (sym);
945           aop->size = getSize (sym->type);
946           return;
947         }
948
949       if (sym->accuse)
950         {
951           int i;
952           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
953           aop->size = getSize (sym->type);
954           for (i = 0; i < 2; i++)
955             aop->aopu.aop_str[i] = accUse[i];
956           return;
957         }
958
959       if (sym->ruonly)
960         {
961           unsigned i;
962
963           aop = op->aop = sym->aop = newAsmop (AOP_STR);
964           aop->size = getSize (sym->type);
965           for (i = 0; i < fReturnSizeMCS51; i++)
966             aop->aopu.aop_str[i] = fReturn[i];
967           return;
968         }
969
970       if (sym->usl.spillLoc)
971         {
972           asmop *oldAsmOp = NULL;
973
974           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
975             {
976               /* force a new aop if sizes differ */
977               oldAsmOp = sym->usl.spillLoc->aop;
978               sym->usl.spillLoc->aop = NULL;
979             }
980           sym->aop = op->aop = aop =
981                      aopForSym (ic, sym->usl.spillLoc, result);
982           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
983             {
984               /* Don't reuse the new aop, go with the last one */
985               sym->usl.spillLoc->aop = oldAsmOp;
986             }
987           aop->size = getSize (sym->type);
988           return;
989         }
990
991       /* else must be a dummy iTemp */
992       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
993       aop->size = getSize (sym->type);
994       return;
995     }
996
997   /* if the type is a bit register */
998   if (sym->regType == REG_BIT)
999     {
1000       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1001       aop->size = sym->nRegs;//1???
1002       aop->aopu.aop_reg[0] = sym->regs[0];
1003       aop->aopu.aop_dir = sym->regs[0]->name;
1004       return;
1005     }
1006
1007   /* must be in a register */
1008   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1009   aop->size = sym->nRegs;
1010   for (i = 0; i < sym->nRegs; i++)
1011     aop->aopu.aop_reg[i] = sym->regs[i];
1012 }
1013
1014 /*-----------------------------------------------------------------*/
1015 /* freeAsmop - free up the asmop given to an operand               */
1016 /*----------------------------------------------------------------*/
1017 static void
1018 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1019 {
1020   asmop *aop;
1021
1022   if (!op)
1023     aop = aaop;
1024   else
1025     aop = op->aop;
1026
1027   if (!aop)
1028     return;
1029
1030   aop->allocated--;
1031
1032   if (aop->allocated)
1033     goto dealloc;
1034
1035   /* depending on the asmop type only three cases need work
1036      AOP_R0, AOP_R1 & AOP_STK */
1037   switch (aop->type)
1038     {
1039     case AOP_R0:
1040       if (R0INB)
1041         {
1042           emitcode ("mov", "r0,b");
1043           R0INB--;
1044         }
1045       else if (_G.r0Pushed)
1046         {
1047           if (pop)
1048             {
1049               emitcode ("pop", "ar0");
1050               _G.r0Pushed--;
1051             }
1052         }
1053       bitVectUnSetBit (ic->rUsed, R0_IDX);
1054       break;
1055
1056     case AOP_R1:
1057       if (R1INB)
1058         {
1059           emitcode ("mov", "r1,b");
1060           R1INB--;
1061         }
1062       if (_G.r1Pushed)
1063         {
1064           if (pop)
1065             {
1066               emitcode ("pop", "ar1");
1067               _G.r1Pushed--;
1068             }
1069         }
1070       bitVectUnSetBit (ic->rUsed, R1_IDX);
1071       break;
1072
1073     case AOP_STK:
1074       {
1075         int sz = aop->size;
1076         int stk = aop->aopu.aop_stk + aop->size - 1;
1077         bitVectUnSetBit (ic->rUsed, R0_IDX);
1078         bitVectUnSetBit (ic->rUsed, R1_IDX);
1079
1080         getFreePtr (ic, &aop, FALSE);
1081
1082         if (stk)
1083           {
1084             emitcode ("mov", "a,_bp");
1085             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1086             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1087           }
1088         else
1089           {
1090             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1091           }
1092
1093         while (sz--)
1094           {
1095             emitcode ("pop", "acc");
1096             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1097             if (!sz)
1098               break;
1099             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1100           }
1101         op->aop = aop;
1102         freeAsmop (op, NULL, ic, TRUE);
1103         if (_G.r1Pushed)
1104           {
1105             emitcode ("pop", "ar1");
1106             _G.r1Pushed--;
1107           }
1108
1109         if (_G.r0Pushed)
1110           {
1111             emitcode ("pop", "ar0");
1112             _G.r0Pushed--;
1113           }
1114       }
1115       break;
1116     }
1117
1118 dealloc:
1119   /* all other cases just dealloc */
1120   if (op)
1121     {
1122       op->aop = NULL;
1123       if (IS_SYMOP (op))
1124         {
1125           OP_SYMBOL (op)->aop = NULL;
1126           /* if the symbol has a spill */
1127           if (SPIL_LOC (op))
1128             SPIL_LOC (op)->aop = NULL;
1129         }
1130     }
1131 }
1132
1133 /*------------------------------------------------------------------*/
1134 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1135 /*                      pop r0 or r1 off stack if pushed            */
1136 /*------------------------------------------------------------------*/
1137 static void
1138 freeForBranchAsmop (operand * op)
1139 {
1140   asmop *aop;
1141
1142   if (!op)
1143     return;
1144
1145   aop = op->aop;
1146
1147   if (!aop)
1148     return;
1149
1150   if (!aop->allocated)
1151     return;
1152
1153   switch (aop->type)
1154     {
1155     case AOP_R0:
1156       if (R0INB)
1157         {
1158           emitcode ("mov", "r0,b");
1159         }
1160       else if (_G.r0Pushed)
1161         {
1162           emitcode ("pop", "ar0");
1163         }
1164       break;
1165
1166     case AOP_R1:
1167       if (R1INB)
1168         {
1169           emitcode ("mov", "r1,b");
1170         }
1171       else if (_G.r1Pushed)
1172         {
1173           emitcode ("pop", "ar1");
1174         }
1175       break;
1176
1177     case AOP_STK:
1178       {
1179         int sz = aop->size;
1180         int stk = aop->aopu.aop_stk + aop->size - 1;
1181
1182         emitcode ("mov", "b,r0");
1183         if (stk)
1184           {
1185             emitcode ("mov", "a,_bp");
1186             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1187             emitcode ("mov", "r0,a");
1188           }
1189         else
1190           {
1191             emitcode ("mov", "r0,_bp");
1192           }
1193
1194         while (sz--)
1195           {
1196             emitcode ("pop", "acc");
1197             emitcode ("mov", "@r0,a");
1198             if (!sz)
1199               break;
1200             emitcode ("dec", "r0");
1201           }
1202         emitcode ("mov", "r0,b");
1203       }
1204     }
1205
1206 }
1207
1208 /*-----------------------------------------------------------------*/
1209 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1210 /*                 clobber the accumulator                         */
1211 /*-----------------------------------------------------------------*/
1212 static bool
1213 aopGetUsesAcc (operand * oper, int offset)
1214 {
1215   asmop * aop = AOP (oper);
1216
1217   if (offset > (aop->size - 1))
1218     return FALSE;
1219
1220   switch (aop->type)
1221     {
1222
1223     case AOP_R0:
1224     case AOP_R1:
1225       if (aop->paged)
1226         return TRUE;
1227       return FALSE;
1228     case AOP_DPTR:
1229       return TRUE;
1230     case AOP_IMMD:
1231       return FALSE;
1232     case AOP_DIR:
1233       return FALSE;
1234     case AOP_REG:
1235       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1236       return FALSE;
1237     case AOP_CRY:
1238       return TRUE;
1239     case AOP_ACC:
1240       if (offset)
1241         return FALSE;
1242       return TRUE;
1243     case AOP_LIT:
1244       return FALSE;
1245     case AOP_STR:
1246       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1247         return TRUE;
1248       return FALSE;
1249     case AOP_DUMMY:
1250       return FALSE;
1251     default:
1252       /* Error case --- will have been caught already */
1253       wassert(0);
1254       return FALSE;
1255     }
1256 }
1257
1258 /*-------------------------------------------------------------------*/
1259 /* aopGet - for fetching value of the aop                            */
1260 /*-------------------------------------------------------------------*/
1261 static char *
1262 aopGet (operand * oper, int offset, bool bit16, bool dname)
1263 {
1264   asmop * aop = AOP (oper);
1265
1266   /* offset is greater than
1267      size then zero */
1268   if (offset > (aop->size - 1) &&
1269       aop->type != AOP_LIT)
1270     return zero;
1271
1272   /* depending on type */
1273   switch (aop->type)
1274     {
1275     case AOP_DUMMY:
1276       return zero;
1277
1278     case AOP_R0:
1279     case AOP_R1:
1280       /* if we need to increment it */
1281       while (offset > aop->coff)
1282         {
1283           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1284           aop->coff++;
1285         }
1286
1287       while (offset < aop->coff)
1288         {
1289           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1290           aop->coff--;
1291         }
1292
1293       aop->coff = offset;
1294       if (aop->paged)
1295         {
1296           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1297           return (dname ? "acc" : "a");
1298         }
1299       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1300       return Safe_strdup(buffer);
1301
1302
1303     case AOP_DPTR:
1304       if (aop->code && aop->coff==0 && offset>=1) {
1305         emitcode ("mov", "a,#0x%02x", offset);
1306         emitcode ("movc", "a,@a+dptr");
1307         return (dname ? "acc" : "a");
1308       }
1309
1310       while (offset > aop->coff)
1311         {
1312           emitcode ("inc", "dptr");
1313           aop->coff++;
1314         }
1315
1316       while (offset < aop->coff)
1317         {
1318           emitcode ("lcall", "__decdptr");
1319           aop->coff--;
1320         }
1321
1322       aop->coff = offset;
1323       if (aop->code)
1324         {
1325           emitcode ("clr", "a");
1326           emitcode ("movc", "a,@a+dptr");
1327         }
1328       else
1329         {
1330           emitcode ("movx", "a,@dptr");
1331         }
1332       return (dname ? "acc" : "a");
1333
1334     case AOP_IMMD:
1335       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1336         {
1337           SNPRINTF(buffer, sizeof(buffer),
1338                    "%s",aop->aopu.aop_immd.aop_immd2);
1339         }
1340       else if (bit16)
1341         {
1342           SNPRINTF(buffer, sizeof(buffer),
1343                    "#%s", aop->aopu.aop_immd.aop_immd1);
1344         }
1345       else if (offset)
1346         {
1347           SNPRINTF (buffer, sizeof(buffer),
1348                     "#(%s >> %d)",
1349                     aop->aopu.aop_immd.aop_immd1,
1350                     offset * 8);
1351         }
1352       else
1353         {
1354           SNPRINTF (buffer, sizeof(buffer),
1355                     "#%s", aop->aopu.aop_immd.aop_immd1);
1356         }
1357       return Safe_strdup(buffer);
1358
1359     case AOP_DIR:
1360       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1361         {
1362           SNPRINTF (buffer, sizeof(buffer),
1363                     "(%s >> %d)",
1364                     aop->aopu.aop_dir, offset * 8);
1365         }
1366       else if (offset)
1367         {
1368           SNPRINTF (buffer, sizeof(buffer),
1369                     "(%s + %d)",
1370                    aop->aopu.aop_dir,
1371                    offset);
1372         }
1373       else
1374         {
1375           SNPRINTF (buffer, sizeof(buffer),
1376                    "%s", aop->aopu.aop_dir);
1377         }
1378
1379       return Safe_strdup(buffer);
1380
1381     case AOP_REG:
1382       if (dname)
1383         return aop->aopu.aop_reg[offset]->dname;
1384       else
1385         return aop->aopu.aop_reg[offset]->name;
1386
1387     case AOP_CRY:
1388       emitcode ("clr", "a");
1389       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1390       emitcode ("rlc", "a");
1391       return (dname ? "acc" : "a");
1392
1393     case AOP_ACC:
1394       if (!offset && dname)
1395         return "acc";
1396       return aop->aopu.aop_str[offset];
1397
1398     case AOP_LIT:
1399       return aopLiteral (aop->aopu.aop_lit, offset);
1400
1401     case AOP_STR:
1402       aop->coff = offset;
1403       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1404           dname)
1405         return "acc";
1406
1407       return aop->aopu.aop_str[offset];
1408
1409     }
1410
1411   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1412           "aopget got unsupported aop->type");
1413   exit (1);
1414 }
1415
1416 /*-----------------------------------------------------------------*/
1417 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1418 /*                 clobber the accumulator                         */
1419 /*-----------------------------------------------------------------*/
1420 static bool
1421 aopPutUsesAcc (operand * oper, const char *s, int offset)
1422 {
1423   asmop * aop = AOP (oper);
1424
1425   if (offset > (aop->size - 1))
1426     return FALSE;
1427
1428   switch (aop->type)
1429     {
1430     case AOP_DUMMY:
1431       return TRUE;
1432     case AOP_DIR:
1433       return FALSE;
1434     case AOP_REG:
1435       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1436       return FALSE;
1437     case AOP_DPTR:
1438       return TRUE;
1439     case AOP_R0:
1440     case AOP_R1:
1441       return ((aop->paged) || (*s == '@'));
1442     case AOP_STK:
1443       return (*s == '@');
1444     case AOP_CRY:
1445       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1446     case AOP_STR:
1447       return FALSE;
1448     case AOP_IMMD:
1449       return FALSE;
1450     case AOP_ACC:
1451       return FALSE;
1452     default:
1453       /* Error case --- will have been caught already */
1454       wassert(0);
1455       return FALSE;
1456     }
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /* aopPut - puts a string for a aop and indicates if acc is in use */
1461 /*-----------------------------------------------------------------*/
1462 static bool
1463 aopPut (operand * result, const char *s, int offset)
1464 {
1465   bool bvolatile = isOperandVolatile (result, FALSE);
1466   bool accuse = FALSE;
1467   asmop * aop = AOP (result);
1468
1469   if (aop->size && offset > (aop->size - 1))
1470     {
1471       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1472               "aopPut got offset > aop->size");
1473       exit (1);
1474     }
1475
1476   /* will assign value to value */
1477   /* depending on where it is ofcourse */
1478   switch (aop->type)
1479     {
1480     case AOP_DUMMY:
1481       MOVA (s);         /* read s in case it was volatile */
1482       accuse = TRUE;
1483       break;
1484
1485     case AOP_DIR:
1486       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1487         {
1488           SNPRINTF (buffer, sizeof(buffer),
1489                     "(%s >> %d)",
1490                     aop->aopu.aop_dir, offset * 8);
1491         }
1492       else if (offset)
1493         {
1494             SNPRINTF (buffer, sizeof(buffer),
1495                       "(%s + %d)",
1496                       aop->aopu.aop_dir, offset);
1497         }
1498       else
1499         {
1500             SNPRINTF (buffer, sizeof(buffer),
1501                      "%s", aop->aopu.aop_dir);
1502         }
1503
1504       if (strcmp (buffer, s) || bvolatile)
1505         {
1506             emitcode ("mov", "%s,%s", buffer, s);
1507         }
1508       if (!strcmp (buffer, "acc"))
1509         {
1510           accuse = TRUE;
1511         }
1512       break;
1513
1514     case AOP_REG:
1515       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1516           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1517         {
1518           if (*s == '@' ||
1519               strcmp (s, "r0") == 0 ||
1520               strcmp (s, "r1") == 0 ||
1521               strcmp (s, "r2") == 0 ||
1522               strcmp (s, "r3") == 0 ||
1523               strcmp (s, "r4") == 0 ||
1524               strcmp (s, "r5") == 0 ||
1525               strcmp (s, "r6") == 0 ||
1526               strcmp (s, "r7") == 0)
1527             {
1528               emitcode ("mov", "%s,%s",
1529                         aop->aopu.aop_reg[offset]->dname, s);
1530             }
1531           else
1532             {
1533               emitcode ("mov", "%s,%s",
1534                         aop->aopu.aop_reg[offset]->name, s);
1535             }
1536         }
1537       break;
1538
1539     case AOP_DPTR:
1540       if (aop->code)
1541         {
1542           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1543                   "aopPut writing to code space");
1544           exit (1);
1545         }
1546
1547       while (offset > aop->coff)
1548         {
1549           aop->coff++;
1550           emitcode ("inc", "dptr");
1551         }
1552
1553       while (offset < aop->coff)
1554         {
1555           aop->coff--;
1556           emitcode ("lcall", "__decdptr");
1557         }
1558
1559       aop->coff = offset;
1560
1561       /* if not in accumulator */
1562       MOVA (s);
1563
1564       emitcode ("movx", "@dptr,a");
1565       break;
1566
1567     case AOP_R0:
1568     case AOP_R1:
1569       while (offset > aop->coff)
1570         {
1571           aop->coff++;
1572           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1573         }
1574       while (offset < aop->coff)
1575         {
1576           aop->coff--;
1577           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1578         }
1579       aop->coff = offset;
1580
1581       if (aop->paged)
1582         {
1583           MOVA (s);
1584           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1585         }
1586       else if (*s == '@')
1587         {
1588           MOVA (s);
1589           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1590         }
1591       else if (strcmp (s, "r0") == 0 ||
1592                strcmp (s, "r1") == 0 ||
1593                strcmp (s, "r2") == 0 ||
1594                strcmp (s, "r3") == 0 ||
1595                strcmp (s, "r4") == 0 ||
1596                strcmp (s, "r5") == 0 ||
1597                strcmp (s, "r6") == 0 ||
1598                strcmp (s, "r7") == 0)
1599         {
1600           char buffer[10];
1601           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1602           emitcode ("mov", "@%s,%s",
1603                     aop->aopu.aop_ptr->name, buffer);
1604         }
1605       else
1606         {
1607           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1608         }
1609       break;
1610
1611     case AOP_STK:
1612       if (strcmp (s, "a") == 0)
1613         emitcode ("push", "acc");
1614       else
1615         if (*s=='@') {
1616           MOVA(s);
1617           emitcode ("push", "acc");
1618         } else {
1619           emitcode ("push", s);
1620         }
1621
1622       break;
1623
1624     case AOP_CRY:
1625       /* if not bit variable */
1626       if (!aop->aopu.aop_dir)
1627         {
1628           /* inefficient: move carry into A and use jz/jnz */
1629           emitcode ("clr", "a");
1630           emitcode ("rlc", "a");
1631           accuse = TRUE;
1632         }
1633       else
1634         {
1635           if (s == zero)
1636             emitcode ("clr", "%s", aop->aopu.aop_dir);
1637           else if (s == one)
1638             emitcode ("setb", "%s", aop->aopu.aop_dir);
1639           else if (!strcmp (s, "c"))
1640             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1641           else if (strcmp (s, aop->aopu.aop_dir))
1642             {
1643               MOVA (s);
1644               /* set C, if a >= 1 */
1645               emitcode ("add", "a,#0xff");
1646               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1647             }
1648         }
1649       break;
1650
1651     case AOP_STR:
1652       aop->coff = offset;
1653       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1654         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1655       break;
1656
1657     case AOP_ACC:
1658       accuse = TRUE;
1659       aop->coff = offset;
1660       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1661         break;
1662
1663       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1664         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1665       break;
1666
1667     default:
1668       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1669               "aopPut got unsupported aop->type");
1670       exit (1);
1671     }
1672
1673     return accuse;
1674 }
1675
1676
1677 #if 0
1678 /*-----------------------------------------------------------------*/
1679 /* pointToEnd :- points to the last byte of the operand            */
1680 /*-----------------------------------------------------------------*/
1681 static void
1682 pointToEnd (asmop * aop)
1683 {
1684   int count;
1685   if (!aop)
1686     return;
1687
1688   aop->coff = count = (aop->size - 1);
1689   switch (aop->type)
1690     {
1691     case AOP_R0:
1692     case AOP_R1:
1693       while (count--)
1694         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1695       break;
1696     case AOP_DPTR:
1697       while (count--)
1698         emitcode ("inc", "dptr");
1699       break;
1700     }
1701
1702 }
1703 #endif
1704
1705 /*-----------------------------------------------------------------*/
1706 /* reAdjustPreg - points a register back to where it should        */
1707 /*-----------------------------------------------------------------*/
1708 static void
1709 reAdjustPreg (asmop * aop)
1710 {
1711   if ((aop->coff==0) || (aop->size <= 1))
1712     return;
1713
1714   switch (aop->type)
1715     {
1716     case AOP_R0:
1717     case AOP_R1:
1718       while (aop->coff--)
1719         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1720       break;
1721     case AOP_DPTR:
1722       while (aop->coff--)
1723         {
1724           emitcode ("lcall", "__decdptr");
1725         }
1726       break;
1727     }
1728   aop->coff = 0;
1729 }
1730
1731 /*-----------------------------------------------------------------*/
1732 /* opIsGptr: returns non-zero if the passed operand is       */
1733 /* a generic pointer type.             */
1734 /*-----------------------------------------------------------------*/
1735 static int
1736 opIsGptr (operand * op)
1737 {
1738   sym_link *type = operandType (op);
1739
1740   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1741     {
1742       return 1;
1743     }
1744   return 0;
1745 }
1746
1747 /*-----------------------------------------------------------------*/
1748 /* getDataSize - get the operand data size                         */
1749 /*-----------------------------------------------------------------*/
1750 static int
1751 getDataSize (operand * op)
1752 {
1753   int size;
1754   size = AOP_SIZE (op);
1755   if (size == GPTRSIZE)
1756     {
1757       sym_link *type = operandType (op);
1758       if (IS_GENPTR (type))
1759         {
1760           /* generic pointer; arithmetic operations
1761            * should ignore the high byte (pointer type).
1762            */
1763           size--;
1764         }
1765     }
1766   return size;
1767 }
1768
1769 /*-----------------------------------------------------------------*/
1770 /* outAcc - output Acc                                             */
1771 /*-----------------------------------------------------------------*/
1772 static void
1773 outAcc (operand * result)
1774 {
1775   int size, offset;
1776   size = getDataSize (result);
1777   if (size)
1778     {
1779       aopPut (result, "a", 0);
1780       size--;
1781       offset = 1;
1782       /* unsigned or positive */
1783       while (size--)
1784         {
1785           aopPut (result, zero, offset++);
1786         }
1787     }
1788 }
1789
1790 /*-----------------------------------------------------------------*/
1791 /* outBitC - output a bit C                                        */
1792 /*-----------------------------------------------------------------*/
1793 static void
1794 outBitC (operand * result)
1795 {
1796   /* if the result is bit */
1797   if (AOP_TYPE (result) == AOP_CRY)
1798     {
1799       aopPut (result, "c", 0);
1800     }
1801   else
1802     {
1803       emitcode ("clr", "a");
1804       emitcode ("rlc", "a");
1805       outAcc (result);
1806     }
1807 }
1808
1809 /*-----------------------------------------------------------------*/
1810 /* toBoolean - emit code for orl a,operator(sizeop)                */
1811 /*-----------------------------------------------------------------*/
1812 static void
1813 toBoolean (operand * oper)
1814 {
1815   int size = AOP_SIZE (oper) - 1;
1816   int offset = 1;
1817   bool AccUsed = FALSE;
1818   bool pushedB;
1819
1820   while (!AccUsed && size--)
1821     {
1822       AccUsed |= aopGetUsesAcc(oper, offset++);
1823     }
1824
1825   size = AOP_SIZE (oper) - 1;
1826   offset = 1;
1827   MOVA (aopGet (oper, 0, FALSE, FALSE));
1828   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1829     {
1830       pushedB = pushB ();
1831       emitcode("mov", "b,a");
1832       while (--size)
1833         {
1834           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1835           emitcode ("orl", "b,a");
1836         }
1837       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1838       emitcode ("orl", "a,b");
1839       popB (pushedB);
1840     }
1841   else
1842     {
1843       while (size--)
1844         {
1845           emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1846         }
1847     }
1848 }
1849
1850
1851 /*-----------------------------------------------------------------*/
1852 /* genNot - generate code for ! operation                          */
1853 /*-----------------------------------------------------------------*/
1854 static void
1855 genNot (iCode * ic)
1856 {
1857   symbol *tlbl;
1858
1859   D (emitcode (";", "genNot"));
1860
1861   /* assign asmOps to operand & result */
1862   aopOp (IC_LEFT (ic), ic, FALSE);
1863   aopOp (IC_RESULT (ic), ic, TRUE);
1864
1865   /* if in bit space then a special case */
1866   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1867     {
1868       /* if left==result then cpl bit */
1869       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1870         {
1871           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1872         }
1873       else
1874         {
1875           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1876           emitcode ("cpl", "c");
1877           outBitC (IC_RESULT (ic));
1878         }
1879       goto release;
1880     }
1881
1882   toBoolean (IC_LEFT (ic));
1883
1884   /* set C, if a == 0 */
1885   tlbl = newiTempLabel (NULL);
1886   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1887   emitcode ("", "%05d$:", tlbl->key + 100);
1888   outBitC (IC_RESULT (ic));
1889
1890 release:
1891   /* release the aops */
1892   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1893   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1894 }
1895
1896
1897 /*-----------------------------------------------------------------*/
1898 /* genCpl - generate code for complement                           */
1899 /*-----------------------------------------------------------------*/
1900 static void
1901 genCpl (iCode * ic)
1902 {
1903   int offset = 0;
1904   int size;
1905   symbol *tlbl;
1906   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1907
1908   D(emitcode (";", "genCpl"));
1909
1910   /* assign asmOps to operand & result */
1911   aopOp (IC_LEFT (ic), ic, FALSE);
1912   aopOp (IC_RESULT (ic), ic, TRUE);
1913
1914   /* special case if in bit space */
1915   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1916     {
1917       char *l;
1918
1919       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1920           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1921         {
1922           /* promotion rules are responsible for this strange result:
1923              bit -> int -> ~int -> bit
1924              uchar -> int -> ~int -> bit
1925           */
1926           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1927           goto release;
1928         }
1929
1930       tlbl=newiTempLabel(NULL);
1931       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1932       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1933           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1934           IS_AOP_PREG (IC_LEFT (ic)))
1935         {
1936           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1937         }
1938       else
1939         {
1940           MOVA (l);
1941           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1942         }
1943       emitcode ("", "%05d$:", tlbl->key + 100);
1944       outBitC (IC_RESULT(ic));
1945       goto release;
1946     }
1947
1948   size = AOP_SIZE (IC_RESULT (ic));
1949   while (size--)
1950     {
1951       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1952       MOVA (l);
1953       emitcode ("cpl", "a");
1954       aopPut (IC_RESULT (ic), "a", offset++);
1955     }
1956
1957
1958 release:
1959   /* release the aops */
1960   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1961   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1962 }
1963
1964 /*-----------------------------------------------------------------*/
1965 /* genUminusFloat - unary minus for floating points                */
1966 /*-----------------------------------------------------------------*/
1967 static void
1968 genUminusFloat (operand * op, operand * result)
1969 {
1970   int size, offset = 0;
1971   char *l;
1972
1973   D (emitcode (";", "genUminusFloat"));
1974
1975   /* for this we just copy and then flip the bit */
1976
1977   size = AOP_SIZE (op) - 1;
1978
1979   while (size--)
1980     {
1981       aopPut (result,
1982               aopGet (op, offset, FALSE, FALSE),
1983               offset);
1984       offset++;
1985     }
1986
1987   l = aopGet (op, offset, FALSE, FALSE);
1988   MOVA (l);
1989
1990   emitcode ("cpl", "acc.7");
1991   aopPut (result, "a", offset);
1992 }
1993
1994 /*-----------------------------------------------------------------*/
1995 /* genUminus - unary minus code generation                         */
1996 /*-----------------------------------------------------------------*/
1997 static void
1998 genUminus (iCode * ic)
1999 {
2000   int offset, size;
2001   sym_link *optype;
2002
2003   D (emitcode (";", "genUminus"));
2004
2005   /* assign asmops */
2006   aopOp (IC_LEFT (ic), ic, FALSE);
2007   aopOp (IC_RESULT (ic), ic, TRUE);
2008
2009   /* if both in bit space then special
2010      case */
2011   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2012       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2013     {
2014
2015       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2016       emitcode ("cpl", "c");
2017       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2018       goto release;
2019     }
2020
2021   optype = operandType (IC_LEFT (ic));
2022
2023   /* if float then do float stuff */
2024   if (IS_FLOAT (optype))
2025     {
2026       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2027       goto release;
2028     }
2029
2030   /* otherwise subtract from zero */
2031   size = AOP_SIZE (IC_LEFT (ic));
2032   offset = 0;
2033   while (size--)
2034     {
2035       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2036       if (!strcmp (l, "a"))
2037         {
2038           if (offset == 0)
2039             SETC;
2040           emitcode ("cpl", "a");
2041           emitcode ("addc", "a,#0");
2042         }
2043       else
2044         {
2045           if (offset == 0)
2046             CLRC;
2047           emitcode ("clr", "a");
2048           emitcode ("subb", "a,%s", l);
2049         }
2050       aopPut (IC_RESULT (ic), "a", offset++);
2051     }
2052
2053   /* if any remaining bytes in the result */
2054   /* we just need to propagate the sign   */
2055   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2056     {
2057       emitcode ("rlc", "a");
2058       emitcode ("subb", "a,acc");
2059       while (size--)
2060         aopPut (IC_RESULT (ic), "a", offset++);
2061     }
2062
2063 release:
2064   /* release the aops */
2065   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2066   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2067 }
2068
2069 /*-----------------------------------------------------------------*/
2070 /* saveRegisters - will look for a call and save the registers     */
2071 /*-----------------------------------------------------------------*/
2072 static void
2073 saveRegisters (iCode * lic)
2074 {
2075   int i;
2076   iCode *ic;
2077   bitVect *rsave;
2078
2079   /* look for call */
2080   for (ic = lic; ic; ic = ic->next)
2081     if (ic->op == CALL || ic->op == PCALL)
2082       break;
2083
2084   if (!ic)
2085     {
2086       fprintf (stderr, "found parameter push with no function call\n");
2087       return;
2088     }
2089
2090   /* if the registers have been saved already or don't need to be then
2091      do nothing */
2092   if (ic->regsSaved)
2093     return;
2094   if (IS_SYMOP(IC_LEFT(ic)) &&
2095       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2096        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2097     return;
2098
2099   /* save the registers in use at this time but skip the
2100      ones for the result */
2101   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2102                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2103
2104   ic->regsSaved = 1;
2105   if (options.useXstack)
2106     {
2107       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2108       int nBits = bitVectnBitsOn (rsavebits);
2109       int count = bitVectnBitsOn (rsave);
2110
2111       if (nBits != 0)
2112         {
2113           count = count - nBits + 1;
2114           /* remove all but the first bits as they are pushed all at once */
2115           rsave = bitVectCplAnd (rsave, rsavebits);
2116           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2117         }
2118
2119       if (count == 1)
2120         {
2121           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2122           if (reg->type == REG_BIT)
2123             {
2124               emitcode ("mov", "a,%s", reg->base);
2125             }
2126           else
2127             {
2128               emitcode ("mov", "a,%s", reg->name);
2129             }
2130           emitcode ("mov", "r0,%s", spname);
2131           emitcode ("inc", "%s", spname);// allocate before use
2132           emitcode ("movx", "@r0,a");
2133           if (bitVectBitValue (rsave, R0_IDX))
2134             emitcode ("mov", "r0,a");
2135         }
2136       else if (count != 0)
2137         {
2138           if (bitVectBitValue (rsave, R0_IDX))
2139             {
2140               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2141             }
2142           emitcode ("mov", "r0,%s", spname);
2143           MOVA ("r0");
2144           emitcode ("add", "a,#%d", count);
2145           emitcode ("mov", "%s,a", spname);
2146           for (i = 0; i < mcs51_nRegs; i++)
2147             {
2148               if (bitVectBitValue (rsave, i))
2149                 {
2150                   regs * reg = mcs51_regWithIdx (i);
2151                   if (i == R0_IDX)
2152                     {
2153                       emitcode ("pop", "acc");
2154                       emitcode ("push", "acc");
2155                     }
2156                   else if (reg->type == REG_BIT)
2157                     {
2158                       emitcode ("mov", "a,%s", reg->base);
2159                     }
2160                   else
2161                     {
2162                       emitcode ("mov", "a,%s", reg->name);
2163                     }
2164                   emitcode ("movx", "@r0,a");
2165                   if (--count)
2166                     {
2167                       emitcode ("inc", "r0");
2168                     }
2169                 }
2170             }
2171           if (bitVectBitValue (rsave, R0_IDX))
2172             {
2173               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2174             }
2175         }
2176     }
2177   else
2178     {
2179       bool bits_pushed = FALSE;
2180       for (i = 0; i < mcs51_nRegs; i++)
2181         {
2182           if (bitVectBitValue (rsave, i))
2183             {
2184               bits_pushed = pushReg (i, bits_pushed);
2185             }
2186         }
2187     }
2188 }
2189
2190 /*-----------------------------------------------------------------*/
2191 /* unsaveRegisters - pop the pushed registers                      */
2192 /*-----------------------------------------------------------------*/
2193 static void
2194 unsaveRegisters (iCode * ic)
2195 {
2196   int i;
2197   bitVect *rsave;
2198
2199   /* restore the registers in use at this time but skip the
2200      ones for the result */
2201   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2202                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2203
2204   if (options.useXstack)
2205     {
2206       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2207       int nBits = bitVectnBitsOn (rsavebits);
2208       int count = bitVectnBitsOn (rsave);
2209
2210       if (nBits != 0)
2211         {
2212           count = count - nBits + 1;
2213           /* remove all but the first bits as they are popped all at once */
2214           rsave = bitVectCplAnd (rsave, rsavebits);
2215           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2216         }
2217
2218       if (count == 1)
2219         {
2220           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2221           emitcode ("mov", "r0,%s", spname);
2222           emitcode ("dec", "r0");
2223           emitcode ("movx", "a,@r0");
2224           if (reg->type == REG_BIT)
2225             {
2226               emitcode ("mov", "%s,a", reg->base);
2227             }
2228           else
2229             {
2230               emitcode ("mov", "%s,a", reg->name);
2231             }
2232           emitcode ("dec", "%s", spname);
2233         }
2234       else if (count != 0)
2235         {
2236           emitcode ("mov", "r0,%s", spname);
2237           for (i = mcs51_nRegs; i >= 0; i--)
2238             {
2239               if (bitVectBitValue (rsave, i))
2240                 {
2241                   regs * reg = mcs51_regWithIdx (i);
2242                   emitcode ("dec", "r0");
2243                   emitcode ("movx", "a,@r0");
2244                   if (i == R0_IDX)
2245                     {
2246                       emitcode ("push", "acc");
2247                     }
2248                   else if (reg->type == REG_BIT)
2249                     {
2250                       emitcode ("mov", "%s,a", reg->base);
2251                     }
2252                   else
2253                     {
2254                       emitcode ("mov", "%s,a", reg->name);
2255                     }
2256                 }
2257             }
2258           emitcode ("mov", "%s,r0", spname);
2259           if (bitVectBitValue (rsave, R0_IDX))
2260             {
2261               emitcode ("pop", "ar0");
2262             }
2263         }
2264     }
2265   else
2266     {
2267       bool bits_popped = FALSE;
2268       for (i = mcs51_nRegs; i >= 0; i--)
2269         {
2270           if (bitVectBitValue (rsave, i))
2271             {
2272               bits_popped = popReg (i, bits_popped);
2273             }
2274         }
2275     }
2276 }
2277
2278
2279 /*-----------------------------------------------------------------*/
2280 /* pushSide -                                                      */
2281 /*-----------------------------------------------------------------*/
2282 static void
2283 pushSide (operand * oper, int size)
2284 {
2285   int offset = 0;
2286   while (size--)
2287     {
2288       char *l = aopGet (oper, offset++, FALSE, TRUE);
2289       if (AOP_TYPE (oper) != AOP_REG &&
2290           AOP_TYPE (oper) != AOP_DIR &&
2291           strcmp (l, "a"))
2292         {
2293           MOVA (l);
2294           emitcode ("push", "acc");
2295         }
2296       else
2297         {
2298           emitcode ("push", "%s", l);
2299         }
2300     }
2301 }
2302
2303 /*-----------------------------------------------------------------*/
2304 /* assignResultValue - also indicates if acc is in use afterwards  */
2305 /*-----------------------------------------------------------------*/
2306 static bool
2307 assignResultValue (operand * oper, operand * func)
2308 {
2309   int offset = 0;
2310   int size = AOP_SIZE (oper);
2311   bool accuse = FALSE;
2312   bool pushedA = FALSE;
2313
2314   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2315     {
2316       outBitC (oper);
2317       return FALSE;
2318     }
2319
2320   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2321     {
2322       emitcode ("push", "acc");
2323       pushedA = TRUE;
2324     }
2325   while (size--)
2326     {
2327       if ((offset == 3) && pushedA)
2328         emitcode ("pop", "acc");
2329       accuse |= aopPut (oper, fReturn[offset], offset);
2330       offset++;
2331     }
2332   return accuse;
2333 }
2334
2335
2336 /*-----------------------------------------------------------------*/
2337 /* genXpush - pushes onto the external stack                       */
2338 /*-----------------------------------------------------------------*/
2339 static void
2340 genXpush (iCode * ic)
2341 {
2342   asmop *aop = newAsmop (0);
2343   regs *r;
2344   int size, offset = 0;
2345
2346   D (emitcode (";", "genXpush"));
2347
2348   aopOp (IC_LEFT (ic), ic, FALSE);
2349   r = getFreePtr (ic, &aop, FALSE);
2350
2351   size = AOP_SIZE (IC_LEFT (ic));
2352
2353   if (size == 1)
2354     {
2355       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2356       emitcode ("mov", "%s,%s", r->name, spname);
2357       emitcode ("inc", "%s", spname); // allocate space first
2358       emitcode ("movx", "@%s,a", r->name);
2359     }
2360   else
2361     {
2362       // allocate space first
2363       emitcode ("mov", "%s,%s", r->name, spname);
2364       MOVA (r->name);
2365       emitcode ("add", "a,#%d", size);
2366       emitcode ("mov", "%s,a", spname);
2367
2368       while (size--)
2369         {
2370           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2371           emitcode ("movx", "@%s,a", r->name);
2372           emitcode ("inc", "%s", r->name);
2373         }
2374     }
2375
2376   freeAsmop (NULL, aop, ic, TRUE);
2377   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2378 }
2379
2380 /*-----------------------------------------------------------------*/
2381 /* genIpush - generate code for pushing this gets a little complex */
2382 /*-----------------------------------------------------------------*/
2383 static void
2384 genIpush (iCode * ic)
2385 {
2386   int size, offset = 0;
2387   char *l;
2388   char *prev = "";
2389
2390   D (emitcode (";", "genIpush"));
2391
2392   /* if this is not a parm push : ie. it is spill push
2393      and spill push is always done on the local stack */
2394   if (!ic->parmPush)
2395     {
2396
2397       /* and the item is spilt then do nothing */
2398       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2399         return;
2400
2401       aopOp (IC_LEFT (ic), ic, FALSE);
2402       size = AOP_SIZE (IC_LEFT (ic));
2403       /* push it on the stack */
2404       while (size--)
2405         {
2406           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2407           if (*l == '#')
2408             {
2409               MOVA (l);
2410               l = "acc";
2411             }
2412           emitcode ("push", "%s", l);
2413         }
2414       return;
2415     }
2416
2417   /* this is a parameter push: in this case we call
2418      the routine to find the call and save those
2419      registers that need to be saved */
2420   saveRegisters (ic);
2421
2422   /* if use external stack then call the external
2423      stack pushing routine */
2424   if (options.useXstack)
2425     {
2426       genXpush (ic);
2427       return;
2428     }
2429
2430   /* then do the push */
2431   aopOp (IC_LEFT (ic), ic, FALSE);
2432
2433   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2434   size = AOP_SIZE (IC_LEFT (ic));
2435
2436   while (size--)
2437     {
2438       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2439       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2440           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2441         {
2442           if (strcmp (l, prev) || *l == '@')
2443             MOVA (l);
2444           emitcode ("push", "acc");
2445         }
2446       else
2447         {
2448           emitcode ("push", "%s", l);
2449         }
2450       prev = l;
2451     }
2452
2453   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2454 }
2455
2456 /*-----------------------------------------------------------------*/
2457 /* genIpop - recover the registers: can happen only for spilling   */
2458 /*-----------------------------------------------------------------*/
2459 static void
2460 genIpop (iCode * ic)
2461 {
2462   int size, offset;
2463
2464   D (emitcode (";", "genIpop"));
2465
2466   /* if the temp was not pushed then */
2467   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2468     return;
2469
2470   aopOp (IC_LEFT (ic), ic, FALSE);
2471   size = AOP_SIZE (IC_LEFT (ic));
2472   offset = (size - 1);
2473   while (size--)
2474     {
2475       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2476                                      FALSE, TRUE));
2477     }
2478
2479   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2480 }
2481
2482 /*-----------------------------------------------------------------*/
2483 /* saveRBank - saves an entire register bank on the stack          */
2484 /*-----------------------------------------------------------------*/
2485 static void
2486 saveRBank (int bank, iCode * ic, bool pushPsw)
2487 {
2488   int i;
2489   int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2490   asmop *aop = NULL;
2491   regs *r = NULL;
2492
2493   if (options.useXstack)
2494     {
2495       if (!ic)
2496       {
2497           /* Assume r0 is available for use. */
2498           r = mcs51_regWithIdx (R0_IDX);;
2499       }
2500       else
2501       {
2502           aop = newAsmop (0);
2503           r = getFreePtr (ic, &aop, FALSE);
2504       }
2505       // allocate space first
2506       emitcode ("mov", "%s,%s", r->name, spname);
2507       MOVA (r->name);
2508       emitcode ("add", "a,#%d", count);
2509       emitcode ("mov", "%s,a", spname);
2510     }
2511
2512   for (i = 0; i < 8; i++)
2513     {
2514       if (options.useXstack)
2515         {
2516           emitcode ("mov", "a,(%s+%d)",
2517                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2518           emitcode ("movx", "@%s,a", r->name);
2519           if (--count)
2520             emitcode ("inc", "%s", r->name);
2521         }
2522       else
2523         emitcode ("push", "(%s+%d)",
2524                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2525     }
2526
2527   if (mcs51_nRegs > 8)
2528     {
2529       if (options.useXstack)
2530         {
2531           emitcode ("mov", "a,bits");
2532           emitcode ("movx", "@%s,a", r->name);
2533           if (--count)
2534             emitcode ("inc", "%s", r->name);
2535         }
2536       else
2537         {
2538           emitcode ("push", "bits");
2539         }
2540       BitBankUsed = 1;
2541     }
2542
2543   if (pushPsw)
2544     {
2545       if (options.useXstack)
2546         {
2547           emitcode ("mov", "a,psw");
2548           emitcode ("movx", "@%s,a", r->name);
2549         }
2550       else
2551         {
2552           emitcode ("push", "psw");
2553         }
2554
2555       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2556     }
2557
2558   if (aop)
2559     {
2560       freeAsmop (NULL, aop, ic, TRUE);
2561     }
2562
2563   if (ic)
2564   {
2565     ic->bankSaved = 1;
2566   }
2567 }
2568
2569 /*-----------------------------------------------------------------*/
2570 /* unsaveRBank - restores the register bank from stack             */
2571 /*-----------------------------------------------------------------*/
2572 static void
2573 unsaveRBank (int bank, iCode * ic, bool popPsw)
2574 {
2575   int i;
2576   asmop *aop = NULL;
2577   regs *r = NULL;
2578
2579   if (options.useXstack)
2580     {
2581       if (!ic)
2582         {
2583           /* Assume r0 is available for use. */
2584           r = mcs51_regWithIdx (R0_IDX);;
2585         }
2586       else
2587         {
2588           aop = newAsmop (0);
2589           r = getFreePtr (ic, &aop, FALSE);
2590         }
2591       emitcode ("mov", "%s,%s", r->name, spname);
2592     }
2593
2594   if (popPsw)
2595     {
2596       if (options.useXstack)
2597         {
2598           emitcode ("dec", "%s", r->name);
2599           emitcode ("movx", "a,@%s", r->name);
2600           emitcode ("mov", "psw,a");
2601         }
2602       else
2603         {
2604           emitcode ("pop", "psw");
2605         }
2606     }
2607
2608   if (mcs51_nRegs > 8)
2609     {
2610       if (options.useXstack)
2611         {
2612           emitcode ("dec", "%s", r->name);
2613           emitcode ("movx", "a,@%s", r->name);
2614           emitcode ("mov", "bits,a");
2615         }
2616       else
2617         {
2618           emitcode ("pop", "bits");
2619         }
2620     }
2621
2622   for (i = 7; i >= 0; i--)
2623     {
2624       if (options.useXstack)
2625         {
2626           emitcode ("dec", "%s", r->name);
2627           emitcode ("movx", "a,@%s", r->name);
2628           emitcode ("mov", "(%s+%d),a",
2629                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2630         }
2631       else
2632         {
2633           emitcode ("pop", "(%s+%d)",
2634                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2635         }
2636     }
2637
2638   if (options.useXstack)
2639     {
2640       emitcode ("mov", "%s,%s", spname, r->name);
2641     }
2642
2643   if (aop)
2644     {
2645       freeAsmop (NULL, aop, ic, TRUE);
2646     }
2647 }
2648
2649 /*-----------------------------------------------------------------*/
2650 /* genSend - gen code for SEND                                     */
2651 /*-----------------------------------------------------------------*/
2652 static void genSend(set *sendSet)
2653 {
2654   iCode *sic;
2655   int bit_count = 0;
2656
2657   /* first we do all bit parameters */
2658   for (sic = setFirstItem (sendSet); sic;
2659        sic = setNextItem (sendSet))
2660     {
2661       if (sic->argreg > 12)
2662         {
2663           int bit = sic->argreg-13;
2664
2665           aopOp (IC_LEFT (sic), sic, FALSE);
2666
2667           /* if left is a literal then
2668              we know what the value is */
2669           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2670             {
2671               if (((int) operandLitValue (IC_LEFT (sic))))
2672                   emitcode ("setb", "b[%d]", bit);
2673               else
2674                   emitcode ("clr", "b[%d]", bit);
2675             }
2676           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2677             {
2678               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2679                 if (strcmp (l, "c"))
2680                     emitcode ("mov", "c,%s", l);
2681                 emitcode ("mov", "b[%d],c", bit);
2682             }
2683           else
2684             {
2685               /* we need to or */
2686               toBoolean (IC_LEFT (sic));
2687               /* set C, if a >= 1 */
2688               emitcode ("add", "a,#0xff");
2689               emitcode ("mov", "b[%d],c", bit);
2690             }
2691           bit_count++;
2692           BitBankUsed = 1;
2693
2694           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2695         }
2696     }
2697
2698   if (bit_count)
2699     {
2700       saveRegisters (setFirstItem (sendSet));
2701       emitcode ("mov", "bits,b");
2702     }
2703
2704   /* then we do all other parameters */
2705   for (sic = setFirstItem (sendSet); sic;
2706        sic = setNextItem (sendSet))
2707     {
2708       if (sic->argreg <= 12)
2709         {
2710           int size, offset = 0;
2711           aopOp (IC_LEFT (sic), sic, FALSE);
2712           size = AOP_SIZE (IC_LEFT (sic));
2713
2714           if (sic->argreg == 1)
2715             {
2716               while (size--)
2717                 {
2718                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2719                   if (strcmp (l, fReturn[offset]))
2720                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2721                   offset++;
2722                 }
2723             }
2724           else
2725             {
2726               while (size--)
2727                 {
2728                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2729                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2730                   offset++;
2731                 }
2732             }
2733           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2734         }
2735     }
2736 }
2737
2738 /*-----------------------------------------------------------------*/
2739 /* selectRegBank - emit code to select the register bank           */
2740 /*-----------------------------------------------------------------*/
2741 static void
2742 selectRegBank (short bank, bool keepFlags)
2743 {
2744   /* if f.e. result is in carry */
2745   if (keepFlags)
2746     {
2747       emitcode ("anl", "psw,#0xE7");
2748       if (bank)
2749         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2750     }
2751   else
2752     {
2753       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2754     }
2755 }
2756
2757 /*-----------------------------------------------------------------*/
2758 /* genCall - generates a call statement                            */
2759 /*-----------------------------------------------------------------*/
2760 static void
2761 genCall (iCode * ic)
2762 {
2763   sym_link *dtype;
2764   sym_link *etype;
2765 //  bool restoreBank = FALSE;
2766   bool swapBanks = FALSE;
2767   bool accuse = FALSE;
2768   bool accPushed = FALSE;
2769   bool resultInF0 = FALSE;
2770   bool assignResultGenerated = FALSE;
2771
2772   D (emitcode (";", "genCall"));
2773
2774   dtype = operandType (IC_LEFT (ic));
2775   etype = getSpec(dtype);
2776   /* if send set is not empty then assign */
2777   if (_G.sendSet)
2778     {
2779         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2780             genSend(reverseSet(_G.sendSet));
2781         } else {
2782             genSend(_G.sendSet);
2783         }
2784       _G.sendSet = NULL;
2785     }
2786
2787   /* if we are calling a not _naked function that is not using
2788      the same register bank then we need to save the
2789      destination registers on the stack */
2790   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2791       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2792        !IFFUNC_ISISR (dtype))
2793     {
2794       swapBanks = TRUE;
2795     }
2796
2797   /* if caller saves & we have not saved then */
2798   if (!ic->regsSaved)
2799       saveRegisters (ic);
2800
2801   if (swapBanks)
2802     {
2803         emitcode ("mov", "psw,#0x%02x",
2804            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2805     }
2806
2807   /* make the call */
2808   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2809     {
2810       if (IFFUNC_CALLEESAVES(dtype))
2811         {
2812           werror (E_BANKED_WITH_CALLEESAVES);
2813         }
2814       else
2815         {
2816           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2817                      OP_SYMBOL (IC_LEFT (ic))->rname :
2818                      OP_SYMBOL (IC_LEFT (ic))->name);
2819
2820           emitcode ("mov", "r0,#%s", l);
2821           emitcode ("mov", "r1,#(%s >> 8)", l);
2822           emitcode ("mov", "r2,#(%s >> 16)", l);
2823           emitcode ("lcall", "__sdcc_banked_call");
2824         }
2825     }
2826   else
2827     {
2828       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2829                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2830                                 OP_SYMBOL (IC_LEFT (ic))->name));
2831     }
2832
2833   if (swapBanks)
2834     {
2835       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2836     }
2837
2838   /* if we need assign a result value */
2839   if ((IS_ITEMP (IC_RESULT (ic)) &&
2840        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2841        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2842         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2843         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2844       IS_TRUE_SYMOP (IC_RESULT (ic)))
2845     {
2846
2847       _G.accInUse++;
2848       aopOp (IC_RESULT (ic), ic, FALSE);
2849       _G.accInUse--;
2850
2851       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2852       assignResultGenerated = TRUE;
2853
2854       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2855     }
2856
2857   /* adjust the stack for parameters if required */
2858   if (ic->parmBytes)
2859     {
2860       int i;
2861       if (ic->parmBytes > 3)
2862         {
2863           if (accuse)
2864             {
2865               emitcode ("push", "acc");
2866               accPushed = TRUE;
2867             }
2868           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2869               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2870               !assignResultGenerated)
2871             {
2872               emitcode ("mov", "F0,c");
2873               resultInF0 = TRUE;
2874             }
2875
2876           emitcode ("mov", "a,%s", spname);
2877           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2878           emitcode ("mov", "%s,a", spname);
2879
2880           /* unsaveRegisters from xstack needs acc, but */
2881           /* unsaveRegisters from stack needs this popped */
2882           if (accPushed && !options.useXstack)
2883             {
2884               emitcode ("pop", "acc");
2885               accPushed = FALSE;
2886             }
2887         }
2888       else
2889         for (i = 0; i < ic->parmBytes; i++)
2890           emitcode ("dec", "%s", spname);
2891     }
2892
2893   /* if we had saved some registers then unsave them */
2894   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2895     {
2896       if (accuse && !accPushed && options.useXstack)
2897         {
2898           /* xstack needs acc, but doesn't touch normal stack */
2899           emitcode ("push", "acc");
2900           accPushed = TRUE;
2901         }
2902       unsaveRegisters (ic);
2903     }
2904
2905 //  /* if register bank was saved then pop them */
2906 //  if (restoreBank)
2907 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2908
2909   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2910     {
2911       if (resultInF0)
2912           emitcode ("mov", "c,F0");
2913
2914       aopOp (IC_RESULT (ic), ic, FALSE);
2915       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2916       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2917     }
2918
2919   if (accPushed)
2920     emitcode ("pop", "acc");
2921 }
2922
2923 /*-----------------------------------------------------------------*/
2924 /* genPcall - generates a call by pointer statement                */
2925 /*-----------------------------------------------------------------*/
2926 static void
2927 genPcall (iCode * ic)
2928 {
2929   sym_link *dtype;
2930   sym_link *etype;
2931   symbol *rlbl = newiTempLabel (NULL);
2932 //  bool restoreBank=FALSE;
2933   bool swapBanks = FALSE;
2934   bool resultInF0 = FALSE;
2935
2936   D (emitcode (";", "genPcall"));
2937
2938   dtype = operandType (IC_LEFT (ic))->next;
2939   etype = getSpec(dtype);
2940   /* if caller saves & we have not saved then */
2941   if (!ic->regsSaved)
2942     saveRegisters (ic);
2943
2944   /* if we are calling a not _naked function that is not using
2945      the same register bank then we need to save the
2946      destination registers on the stack */
2947   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2948       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2949       !IFFUNC_ISISR (dtype))
2950     {
2951 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2952 //    restoreBank=TRUE;
2953       swapBanks = TRUE;
2954       // need caution message to user here
2955     }
2956
2957   if (IS_LITERAL(etype))
2958     {
2959       /* if send set is not empty then assign */
2960       if (_G.sendSet)
2961         {
2962           genSend(reverseSet(_G.sendSet));
2963           _G.sendSet = NULL;
2964         }
2965
2966       if (swapBanks)
2967         {
2968           emitcode ("mov", "psw,#0x%02x",
2969            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2970         }
2971
2972       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2973         {
2974           if (IFFUNC_CALLEESAVES(dtype))
2975             {
2976               werror (E_BANKED_WITH_CALLEESAVES);
2977             }
2978           else
2979             {
2980               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2981
2982               emitcode ("mov", "r0,#%s", l);
2983               emitcode ("mov", "r1,#(%s >> 8)", l);
2984               emitcode ("mov", "r2,#(%s >> 16)", l);
2985               emitcode ("lcall", "__sdcc_banked_call");
2986             }
2987         }
2988       else
2989         {
2990           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2991         }
2992     }
2993   else
2994     {
2995       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2996         {
2997           if (IFFUNC_CALLEESAVES(dtype))
2998             {
2999               werror (E_BANKED_WITH_CALLEESAVES);
3000             }
3001           else
3002             {
3003               aopOp (IC_LEFT (ic), ic, FALSE);
3004
3005               if (!swapBanks)
3006                 {
3007                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3008                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3009                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3010                 }
3011               else
3012                 {
3013                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3014                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3015                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3016                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3017                 }
3018
3019               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3020
3021               /* if send set is not empty then assign */
3022               if (_G.sendSet)
3023                 {
3024                   genSend(reverseSet(_G.sendSet));
3025                   _G.sendSet = NULL;
3026                 }
3027
3028               if (swapBanks)
3029                 {
3030                   emitcode ("mov", "psw,#0x%02x",
3031                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3032                 }
3033
3034               /* make the call */
3035               emitcode ("lcall", "__sdcc_banked_call");
3036             }
3037         }
3038       else
3039         {
3040           /* push the return address on to the stack */
3041           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3042           emitcode ("push", "acc");
3043           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3044           emitcode ("push", "acc");
3045
3046           /* now push the calling address */
3047           aopOp (IC_LEFT (ic), ic, FALSE);
3048
3049           pushSide (IC_LEFT (ic), FPTRSIZE);
3050
3051           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3052
3053           /* if send set is not empty the assign */
3054           if (_G.sendSet)
3055             {
3056               genSend(reverseSet(_G.sendSet));
3057               _G.sendSet = NULL;
3058             }
3059
3060           if (swapBanks)
3061             {
3062               emitcode ("mov", "psw,#0x%02x",
3063                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3064             }
3065
3066           /* make the call */
3067           emitcode ("ret", "");
3068           emitcode ("", "%05d$:", (rlbl->key + 100));
3069         }
3070     }
3071   if (swapBanks)
3072     {
3073       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3074     }
3075
3076   /* if we need assign a result value */
3077   if ((IS_ITEMP (IC_RESULT (ic)) &&
3078        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3079        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3080         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3081       IS_TRUE_SYMOP (IC_RESULT (ic)))
3082     {
3083
3084       _G.accInUse++;
3085       aopOp (IC_RESULT (ic), ic, FALSE);
3086       _G.accInUse--;
3087
3088       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3089
3090       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3091     }
3092
3093   /* adjust the stack for parameters if required */
3094   if (ic->parmBytes)
3095     {
3096       int i;
3097       if (ic->parmBytes > 3)
3098         {
3099           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3100               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3101             {
3102               emitcode ("mov", "F0,c");
3103               resultInF0 = TRUE;
3104             }
3105
3106           emitcode ("mov", "a,%s", spname);
3107           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3108           emitcode ("mov", "%s,a", spname);
3109         }
3110       else
3111         for (i = 0; i < ic->parmBytes; i++)
3112           emitcode ("dec", "%s", spname);
3113
3114     }
3115
3116 //  /* if register bank was saved then unsave them */
3117 //  if (restoreBank)
3118 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3119
3120   /* if we had saved some registers then unsave them */
3121   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3122     unsaveRegisters (ic);
3123
3124   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3125     {
3126       if (resultInF0)
3127           emitcode ("mov", "c,F0");
3128
3129       aopOp (IC_RESULT (ic), ic, FALSE);
3130       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3131       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3132     }
3133 }
3134
3135 /*-----------------------------------------------------------------*/
3136 /* resultRemat - result  is rematerializable                       */
3137 /*-----------------------------------------------------------------*/
3138 static int
3139 resultRemat (iCode * ic)
3140 {
3141   if (SKIP_IC (ic) || ic->op == IFX)
3142     return 0;
3143
3144   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3145     {
3146       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3147       if (sym->remat && !POINTER_SET (ic))
3148         return 1;
3149     }
3150
3151   return 0;
3152 }
3153
3154 #if defined(__BORLANDC__) || defined(_MSC_VER)
3155 #define STRCASECMP stricmp
3156 #else
3157 #define STRCASECMP strcasecmp
3158 #endif
3159
3160 /*-----------------------------------------------------------------*/
3161 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3162 /*-----------------------------------------------------------------*/
3163 static int
3164 regsCmp(void *p1, void *p2)
3165 {
3166   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3167 }
3168
3169 static bool
3170 inExcludeList (char *s)
3171 {
3172   const char *p = setFirstItem(options.excludeRegsSet);
3173
3174   if (p == NULL || STRCASECMP(p, "none") == 0)
3175     return FALSE;
3176
3177
3178   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3179 }
3180
3181 /*-----------------------------------------------------------------*/
3182 /* genFunction - generated code for function entry                 */
3183 /*-----------------------------------------------------------------*/
3184 static void
3185 genFunction (iCode * ic)
3186 {
3187   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3188   sym_link *ftype;
3189   bool     switchedPSW = FALSE;
3190   int      calleesaves_saved_register = -1;
3191   int      stackAdjust = sym->stack;
3192   int      accIsFree = sym->recvSize < 4;
3193   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3194   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3195
3196   _G.nRegsSaved = 0;
3197   /* create the function header */
3198   emitcode (";", "-----------------------------------------");
3199   emitcode (";", " function %s", sym->name);
3200   emitcode (";", "-----------------------------------------");
3201
3202   emitcode ("", "%s:", sym->rname);
3203   ftype = operandType (IC_LEFT (ic));
3204   _G.currentFunc = sym;
3205
3206   if (IFFUNC_ISNAKED(ftype))
3207   {
3208       emitcode(";", "naked function: no prologue.");
3209       return;
3210   }
3211
3212   /* here we need to generate the equates for the
3213      register bank if required */
3214   if (FUNC_REGBANK (ftype) != rbank)
3215     {
3216       int i;
3217
3218       rbank = FUNC_REGBANK (ftype);
3219       for (i = 0; i < mcs51_nRegs; i++)
3220         {
3221           if (regs8051[i].type != REG_BIT)
3222             {
3223               if (strcmp (regs8051[i].base, "0") == 0)
3224                 emitcode ("", "%s = 0x%02x",
3225                           regs8051[i].dname,
3226                           8 * rbank + regs8051[i].offset);
3227               else
3228                 emitcode ("", "%s = %s + 0x%02x",
3229                           regs8051[i].dname,
3230                           regs8051[i].base,
3231                           8 * rbank + regs8051[i].offset);
3232             }
3233         }
3234     }
3235
3236   /* if this is an interrupt service routine then
3237      save acc, b, dpl, dph  */
3238   if (IFFUNC_ISISR (sym->type))
3239     {
3240       if (!inExcludeList ("acc"))
3241         emitcode ("push", "acc");
3242       if (!inExcludeList ("b"))
3243         emitcode ("push", "b");
3244       if (!inExcludeList ("dpl"))
3245         emitcode ("push", "dpl");
3246       if (!inExcludeList ("dph"))
3247         emitcode ("push", "dph");
3248       /* if this isr has no bank i.e. is going to
3249          run with bank 0 , then we need to save more
3250          registers :-) */
3251       if (!FUNC_REGBANK (sym->type))
3252         {
3253           int i;
3254
3255           /* if this function does not call any other
3256              function then we can be economical and
3257              save only those registers that are used */
3258           if (!IFFUNC_HASFCALL(sym->type))
3259             {
3260               /* if any registers used */
3261               if (sym->regsUsed)
3262                 {
3263                   bool bits_pushed = FALSE;
3264                   /* save the registers used */
3265                   for (i = 0; i < sym->regsUsed->size; i++)
3266                     {
3267                       if (bitVectBitValue (sym->regsUsed, i))
3268                         bits_pushed = pushReg (i, bits_pushed);
3269                     }
3270                 }
3271             }
3272           else
3273             {
3274               /* this function has a function call. We cannot
3275                  determine register usage so we will have to push the
3276                  entire bank */
3277                 saveRBank (0, ic, FALSE);
3278                 if (options.parms_in_bank1) {
3279                     for (i=0; i < 8 ; i++ ) {
3280                         emitcode ("push","%s",rb1regs[i]);
3281                     }
3282                 }
3283             }
3284         }
3285         else
3286         {
3287             /* This ISR uses a non-zero bank.
3288              *
3289              * We assume that the bank is available for our
3290              * exclusive use.
3291              *
3292              * However, if this ISR calls a function which uses some
3293              * other bank, we must save that bank entirely.
3294              */
3295             unsigned long banksToSave = 0;
3296
3297             if (IFFUNC_HASFCALL(sym->type))
3298             {
3299
3300 #define MAX_REGISTER_BANKS 4
3301
3302                 iCode *i;
3303                 int ix;
3304
3305                 for (i = ic; i; i = i->next)
3306                 {
3307                     if (i->op == ENDFUNCTION)
3308                     {
3309                         /* we got to the end OK. */
3310                         break;
3311                     }
3312
3313                     if (i->op == CALL)
3314                     {
3315                         sym_link *dtype;
3316
3317                         dtype = operandType (IC_LEFT(i));
3318                         if (dtype
3319                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3320                         {
3321                              /* Mark this bank for saving. */
3322                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3323                              {
3324                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3325                              }
3326                              else
3327                              {
3328                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3329                              }
3330
3331                              /* And note that we don't need to do it in
3332                               * genCall.
3333                               */
3334                              i->bankSaved = 1;
3335                         }
3336                     }
3337                     if (i->op == PCALL)
3338                     {
3339                         /* This is a mess; we have no idea what
3340                          * register bank the called function might
3341                          * use.
3342                          *
3343                          * The only thing I can think of to do is
3344                          * throw a warning and hope.
3345                          */
3346                         werror(W_FUNCPTR_IN_USING_ISR);
3347                     }
3348                 }
3349
3350                 if (banksToSave && options.useXstack)
3351                 {
3352                     /* Since we aren't passing it an ic,
3353                      * saveRBank will assume r0 is available to abuse.
3354                      *
3355                      * So switch to our (trashable) bank now, so
3356                      * the caller's R0 isn't trashed.
3357                      */
3358                     emitcode ("push", "psw");
3359                     emitcode ("mov", "psw,#0x%02x",
3360                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3361                     switchedPSW = TRUE;
3362                 }
3363
3364                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3365                 {
3366                      if (banksToSave & (1 << ix))
3367                      {
3368                          saveRBank(ix, NULL, FALSE);
3369                      }
3370                 }
3371             }
3372             // TODO: this needs a closer look
3373             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3374         }
3375
3376       /* Set the register bank to the desired value if nothing else */
3377       /* has done so yet. */
3378       if (!switchedPSW)
3379         {
3380           emitcode ("push", "psw");
3381           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3382         }
3383     }
3384   else
3385     {
3386       /* This is a non-ISR function. The caller has already switched register */
3387       /* banks, if necessary, so just handle the callee-saves option. */
3388
3389       /* if callee-save to be used for this function
3390          then save the registers being used in this function */
3391       if (IFFUNC_CALLEESAVES(sym->type))
3392         {
3393           int i;
3394
3395           /* if any registers used */
3396           if (sym->regsUsed)
3397             {
3398               bool bits_pushed = FALSE;
3399               /* save the registers used */
3400               for (i = 0; i < sym->regsUsed->size; i++)
3401                 {
3402                   if (bitVectBitValue (sym->regsUsed, i))
3403                     {
3404                       /* remember one saved register for later usage */
3405                       if (calleesaves_saved_register < 0)
3406                         calleesaves_saved_register = i;
3407                       bits_pushed = pushReg (i, bits_pushed);
3408                       _G.nRegsSaved++;
3409                     }
3410                 }
3411             }
3412         }
3413     }
3414
3415
3416   if (fReentrant)
3417     {
3418       if (options.useXstack)
3419         {
3420           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3421             {
3422               emitcode ("mov", "r0,%s", spname);
3423               emitcode ("inc", "%s", spname);
3424               emitcode ("xch", "a,_bpx");
3425               emitcode ("movx", "@r0,a");
3426               emitcode ("inc", "r0");
3427               emitcode ("mov", "a,r0");
3428               emitcode ("xch", "a,_bpx");
3429             }
3430           if (sym->stack)
3431             {
3432               emitcode ("push", "_bp");     /* save the callers stack  */
3433               emitcode ("mov", "_bp,sp");
3434             }
3435         }
3436       else
3437         {
3438           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3439             {
3440               /* set up the stack */
3441               emitcode ("push", "_bp");     /* save the callers stack  */
3442               emitcode ("mov", "_bp,sp");
3443             }
3444         }
3445     }
3446
3447   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3448   /* before setting up the stack frame completely. */
3449   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3450     {
3451       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3452
3453       if (rsym->isitmp)
3454         {
3455           if (rsym && rsym->regType == REG_CND)
3456             rsym = NULL;
3457           if (rsym && (rsym->accuse || rsym->ruonly))
3458             rsym = NULL;
3459           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3460             rsym = rsym->usl.spillLoc;
3461         }
3462
3463       /* If the RECEIVE operand immediately spills to the first entry on the */
3464       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3465       /* rather than the usual @r0/r1 machinations. */
3466       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3467         {
3468           int ofs;
3469
3470           _G.current_iCode = ric;
3471           D(emitcode (";     genReceive",""));
3472           for (ofs=0; ofs < sym->recvSize; ofs++)
3473             {
3474               if (!strcmp (fReturn[ofs], "a"))
3475                 emitcode ("push", "acc");
3476               else
3477                 emitcode ("push", fReturn[ofs]);
3478             }
3479           stackAdjust -= sym->recvSize;
3480           if (stackAdjust<0)
3481             {
3482               assert (stackAdjust>=0);
3483               stackAdjust = 0;
3484             }
3485           _G.current_iCode = ic;
3486           ric->generated = 1;
3487           accIsFree = 1;
3488         }
3489       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3490       /* to free up the accumulator. */
3491       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3492         {
3493           int ofs;
3494
3495           _G.current_iCode = ric;
3496           D(emitcode (";     genReceive",""));
3497           for (ofs=0; ofs < sym->recvSize; ofs++)
3498             {
3499               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3500             }
3501           _G.current_iCode = ic;
3502           ric->generated = 1;
3503           accIsFree = 1;
3504         }
3505     }
3506
3507   /* adjust the stack for the function */
3508   if (stackAdjust)
3509     {
3510       int i = stackAdjust;
3511       if (i > 256)
3512         werror (W_STACK_OVERFLOW, sym->name);
3513
3514       if (i > 3 && accIsFree)
3515         {
3516           emitcode ("mov", "a,sp");
3517           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3518           emitcode ("mov", "sp,a");
3519         }
3520       else if (i > 5)
3521         {
3522           /* The accumulator is not free, so we will need another register */
3523           /* to clobber. No need to worry about a possible conflict with */
3524           /* the above early RECEIVE optimizations since they would have */
3525           /* freed the accumulator if they were generated. */
3526
3527           if (IFFUNC_CALLEESAVES(sym->type))
3528             {
3529               /* if it's a callee-saves function we need a saved register */
3530               if (calleesaves_saved_register >= 0)
3531                 {
3532                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3533                   emitcode ("mov", "a,sp");
3534                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3535                   emitcode ("mov", "sp,a");
3536                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3537                 }
3538               else
3539                 /* do it the hard way */
3540                 while (i--)
3541                   emitcode ("inc", "sp");
3542             }
3543           else
3544             {
3545               /* not callee-saves, we can clobber r0 */
3546               emitcode ("mov", "r0,a");
3547               emitcode ("mov", "a,sp");
3548               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3549               emitcode ("mov", "sp,a");
3550               emitcode ("mov", "a,r0");
3551             }
3552         }
3553       else
3554         while (i--)
3555           emitcode ("inc", "sp");
3556     }
3557
3558   if (sym->xstack)
3559     {
3560       char i = ((char) sym->xstack & 0xff);
3561
3562       if (i > 3 && accIsFree)
3563         {
3564           emitcode ("mov", "a,_spx");
3565           emitcode ("add", "a,#0x%02x", i);
3566           emitcode ("mov", "_spx,a");
3567         }
3568       else if (i > 5)
3569         {
3570           emitcode ("push", "acc");
3571           emitcode ("mov", "a,_spx");
3572           emitcode ("add", "a,#0x%02x", i);
3573           emitcode ("mov", "_spx,a");
3574           emitcode ("pop", "acc");
3575         }
3576       else
3577         {
3578           while (i--)
3579             emitcode ("inc", "_spx");
3580         }
3581     }
3582
3583   /* if critical function then turn interrupts off */
3584   if (IFFUNC_ISCRITICAL (ftype))
3585     {
3586       symbol *tlbl = newiTempLabel (NULL);
3587       emitcode ("setb", "c");
3588       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3589       emitcode ("clr", "c");
3590       emitcode ("", "%05d$:", (tlbl->key + 100));
3591       emitcode ("push", "psw"); /* save old ea via c in psw */
3592     }
3593 }
3594
3595 /*-----------------------------------------------------------------*/
3596 /* genEndFunction - generates epilogue for functions               */
3597 /*-----------------------------------------------------------------*/
3598 static void
3599 genEndFunction (iCode * ic)
3600 {
3601   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3602   lineNode *lnp = lineCurr;
3603   bitVect  *regsUsed;
3604   bitVect  *regsUsedPrologue;
3605   bitVect  *regsUnneeded;
3606   int      idx;
3607
3608   _G.currentFunc = NULL;
3609   if (IFFUNC_ISNAKED(sym->type))
3610   {
3611       emitcode(";", "naked function: no epilogue.");
3612       if (options.debug && currFunc)
3613         debugFile->writeEndFunction (currFunc, ic, 0);
3614       return;
3615   }
3616
3617   if (IFFUNC_ISCRITICAL (sym->type))
3618     {
3619       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3620         {
3621           emitcode ("rlc", "a");   /* save c in a */
3622           emitcode ("pop", "psw"); /* restore ea via c in psw */
3623           emitcode ("mov", "ea,c");
3624           emitcode ("rrc", "a");   /* restore c from a */
3625         }
3626       else
3627         {
3628           emitcode ("pop", "psw"); /* restore ea via c in psw */
3629           emitcode ("mov", "ea,c");
3630         }
3631     }
3632
3633   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3634     {
3635       if (options.useXstack)
3636         {
3637           if (sym->stack)
3638             {
3639               emitcode ("mov", "sp,_bp");
3640               emitcode ("pop", "_bp");
3641             }
3642           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3643             {
3644               emitcode ("xch", "a,_bpx");
3645               emitcode ("mov", "r0,a");
3646               emitcode ("dec", "r0");
3647               emitcode ("movx", "a,@r0");
3648               emitcode ("xch", "a,_bpx");
3649               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3650             }
3651         }
3652       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3653         {
3654           emitcode ("mov", "sp,_bp");
3655           emitcode ("pop", "_bp");
3656         }
3657     }
3658
3659   /* restore the register bank  */
3660   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3661   {
3662     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3663      || !options.useXstack)
3664     {
3665         /* Special case of ISR using non-zero bank with useXstack
3666          * is handled below.
3667          */
3668         emitcode ("pop", "psw");
3669     }
3670   }
3671
3672   if (IFFUNC_ISISR (sym->type))
3673     {
3674
3675       /* now we need to restore the registers */
3676       /* if this isr has no bank i.e. is going to
3677          run with bank 0 , then we need to save more
3678          registers :-) */
3679       if (!FUNC_REGBANK (sym->type))
3680         {
3681           int i;
3682           /* if this function does not call any other
3683              function then we can be economical and
3684              save only those registers that are used */
3685           if (!IFFUNC_HASFCALL(sym->type))
3686             {
3687               /* if any registers used */
3688               if (sym->regsUsed)
3689                 {
3690                   bool bits_popped = FALSE;
3691                   /* save the registers used */
3692                   for (i = sym->regsUsed->size; i >= 0; i--)
3693                     {
3694                       if (bitVectBitValue (sym->regsUsed, i))
3695                         bits_popped = popReg (i, bits_popped);
3696                     }
3697                 }
3698             }
3699           else
3700             {
3701               if (options.parms_in_bank1) {
3702                   for (i = 7 ; i >= 0 ; i-- ) {
3703                       emitcode ("pop","%s",rb1regs[i]);
3704                   }
3705               }
3706               /* this function has  a function call cannot
3707                  determines register usage so we will have to pop the
3708                  entire bank */
3709               unsaveRBank (0, ic, FALSE);
3710             }
3711         }
3712         else
3713         {
3714             /* This ISR uses a non-zero bank.
3715              *
3716              * Restore any register banks saved by genFunction
3717              * in reverse order.
3718              */
3719             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3720             int ix;
3721
3722             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3723             {
3724                 if (savedBanks & (1 << ix))
3725                 {
3726                     unsaveRBank(ix, NULL, FALSE);
3727                 }
3728             }
3729
3730             if (options.useXstack)
3731             {
3732                 /* Restore bank AFTER calling unsaveRBank,
3733                  * since it can trash r0.
3734                  */
3735                 emitcode ("pop", "psw");
3736             }
3737         }
3738
3739       if (!inExcludeList ("dph"))
3740         emitcode ("pop", "dph");
3741       if (!inExcludeList ("dpl"))
3742         emitcode ("pop", "dpl");
3743       if (!inExcludeList ("b"))
3744         emitcode ("pop", "b");
3745       if (!inExcludeList ("acc"))
3746         emitcode ("pop", "acc");
3747
3748       /* if debug then send end of function */
3749       if (options.debug && currFunc)
3750         {
3751           debugFile->writeEndFunction (currFunc, ic, 1);
3752         }
3753
3754       emitcode ("reti", "");
3755     }
3756   else
3757     {
3758       if (IFFUNC_CALLEESAVES(sym->type))
3759         {
3760           int i;
3761
3762           /* if any registers used */
3763           if (sym->regsUsed)
3764             {
3765               /* save the registers used */
3766               for (i = sym->regsUsed->size; i >= 0; i--)
3767                 {
3768                   if (bitVectBitValue (sym->regsUsed, i) ||
3769                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3770                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3771                 }
3772             }
3773           else if (mcs51_ptrRegReq)
3774             {
3775               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3776               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3777             }
3778
3779         }
3780
3781       /* if debug then send end of function */
3782       if (options.debug && currFunc)
3783         {
3784           debugFile->writeEndFunction (currFunc, ic, 1);
3785         }
3786
3787       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3788         {
3789           emitcode ("ljmp", "__sdcc_banked_ret");
3790         }
3791       else
3792         {
3793           emitcode ("ret", "");
3794         }
3795     }
3796
3797   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3798     return;
3799
3800   /* If this was an interrupt handler using bank 0 that called another */
3801   /* function, then all registers must be saved; nothing to optimized. */
3802   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3803       && !FUNC_REGBANK(sym->type))
3804     return;
3805
3806   /* There are no push/pops to optimize if not callee-saves or ISR */
3807   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3808     return;
3809
3810   /* If there were stack parameters, we cannot optimize without also    */
3811   /* fixing all of the stack offsets; this is too dificult to consider. */
3812   if (FUNC_HASSTACKPARM(sym->type))
3813     return;
3814
3815   /* Compute the registers actually used */
3816   regsUsed = newBitVect (mcs51_nRegs);
3817   regsUsedPrologue = newBitVect (mcs51_nRegs);
3818   while (lnp)
3819     {
3820       if (lnp->ic && lnp->ic->op == FUNCTION)
3821         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3822       else
3823         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3824
3825       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3826           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3827         break;
3828       if (!lnp->prev)
3829         break;
3830       lnp = lnp->prev;
3831     }
3832
3833   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3834       && !bitVectBitValue (regsUsed, CND_IDX))
3835     {
3836       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3837       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3838           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3839         bitVectUnSetBit (regsUsed, CND_IDX);
3840     }
3841   else
3842     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3843
3844   /* If this was an interrupt handler that called another function */
3845   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3846   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3847     {
3848       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3849       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3850       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3851       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3852       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3853     }
3854
3855   /* Remove the unneeded push/pops */
3856   regsUnneeded = newBitVect (mcs51_nRegs);
3857   while (lnp)
3858     {
3859       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3860         {
3861           if (!strncmp(lnp->line, "push", 4))
3862             {
3863               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3864               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3865                 {
3866                   connectLine (lnp->prev, lnp->next);
3867                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3868                 }
3869             }
3870           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3871             {
3872               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3873               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3874                 {
3875                   connectLine (lnp->prev, lnp->next);
3876                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3877                 }
3878             }
3879         }
3880       lnp = lnp->next;
3881     }
3882
3883   for (idx = 0; idx < regsUnneeded->size; idx++)
3884     if (bitVectBitValue (regsUnneeded, idx))
3885       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3886
3887   freeBitVect (regsUnneeded);
3888   freeBitVect (regsUsed);
3889   freeBitVect (regsUsedPrologue);
3890 }
3891
3892 /*-----------------------------------------------------------------*/
3893 /* genRet - generate code for return statement                     */
3894 /*-----------------------------------------------------------------*/
3895 static void
3896 genRet (iCode * ic)
3897 {
3898   int size, offset = 0, pushed = 0;
3899
3900   D (emitcode (";", "genRet"));
3901
3902   /* if we have no return value then
3903      just generate the "ret" */
3904   if (!IC_LEFT (ic))
3905     goto jumpret;
3906
3907   /* we have something to return then
3908      move the return value into place */
3909   aopOp (IC_LEFT (ic), ic, FALSE);
3910   size = AOP_SIZE (IC_LEFT (ic));
3911
3912   if (IS_BIT(_G.currentFunc->etype))
3913     {
3914       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3915       size = 0;
3916     }
3917
3918   while (size--)
3919     {
3920       char *l;
3921       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3922         {
3923           /* #NOCHANGE */
3924           l = aopGet (IC_LEFT (ic), offset++,
3925                       FALSE, TRUE);
3926           emitcode ("push", "%s", l);
3927           pushed++;
3928         }
3929       else
3930         {
3931           l = aopGet (IC_LEFT (ic), offset,
3932                       FALSE, FALSE);
3933           if (strcmp (fReturn[offset], l))
3934             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3935         }
3936     }
3937
3938   while (pushed)
3939     {
3940       pushed--;
3941       if (strcmp (fReturn[pushed], "a"))
3942         emitcode ("pop", fReturn[pushed]);
3943       else
3944         emitcode ("pop", "acc");
3945     }
3946   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3947
3948 jumpret:
3949   /* generate a jump to the return label
3950      if the next is not the return statement */
3951   if (!(ic->next && ic->next->op == LABEL &&
3952         IC_LABEL (ic->next) == returnLabel))
3953
3954     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3955
3956 }
3957
3958 /*-----------------------------------------------------------------*/
3959 /* genLabel - generates a label                                    */
3960 /*-----------------------------------------------------------------*/
3961 static void
3962 genLabel (iCode * ic)
3963 {
3964   /* special case never generate */
3965   if (IC_LABEL (ic) == entryLabel)
3966     return;
3967
3968   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3969 }
3970
3971 /*-----------------------------------------------------------------*/
3972 /* genGoto - generates a ljmp                                      */
3973 /*-----------------------------------------------------------------*/
3974 static void
3975 genGoto (iCode * ic)
3976 {
3977   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3978 }
3979
3980 /*-----------------------------------------------------------------*/
3981 /* findLabelBackwards: walks back through the iCode chain looking  */
3982 /* for the given label. Returns number of iCode instructions     */
3983 /* between that label and given ic.          */
3984 /* Returns zero if label not found.          */
3985 /*-----------------------------------------------------------------*/
3986 static int
3987 findLabelBackwards (iCode * ic, int key)
3988 {
3989   int count = 0;
3990
3991   while (ic->prev)
3992     {
3993       ic = ic->prev;
3994       count++;
3995
3996       /* If we have any pushes or pops, we cannot predict the distance.
3997          I don't like this at all, this should be dealt with in the
3998          back-end */
3999       if (ic->op == IPUSH || ic->op == IPOP) {
4000         return 0;
4001       }
4002
4003       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4004         {
4005           return count;
4006         }
4007     }
4008
4009   return 0;
4010 }
4011
4012 /*-----------------------------------------------------------------*/
4013 /* genPlusIncr :- does addition with increment if possible         */
4014 /*-----------------------------------------------------------------*/
4015 static bool
4016 genPlusIncr (iCode * ic)
4017 {
4018   unsigned int icount;
4019   unsigned int size = getDataSize (IC_RESULT (ic));
4020
4021   /* will try to generate an increment */
4022   /* if the right side is not a literal
4023      we cannot */
4024   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4025     return FALSE;
4026
4027   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4028
4029   D(emitcode (";     genPlusIncr",""));
4030
4031   /* if increment >=16 bits in register or direct space */
4032   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4033       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4034       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4035       (size > 1) &&
4036       (icount == 1))
4037     {
4038       symbol *tlbl;
4039       int emitTlbl;
4040       int labelRange;
4041
4042       /* If the next instruction is a goto and the goto target
4043        * is < 10 instructions previous to this, we can generate
4044        * jumps straight to that target.
4045        */
4046       if (ic->next && ic->next->op == GOTO
4047           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4048           && labelRange <= 10)
4049         {
4050           emitcode (";", "tail increment optimized");
4051           tlbl = IC_LABEL (ic->next);
4052           emitTlbl = 0;
4053         }
4054       else
4055         {
4056           tlbl = newiTempLabel (NULL);
4057           emitTlbl = 1;
4058         }
4059       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4060       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4061           IS_AOP_PREG (IC_RESULT (ic)))
4062         emitcode ("cjne", "%s,#0x00,%05d$",
4063                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4064                   tlbl->key + 100);
4065       else
4066         {
4067           emitcode ("clr", "a");
4068           emitcode ("cjne", "a,%s,%05d$",
4069                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4070                     tlbl->key + 100);
4071         }
4072
4073       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4074       if (size > 2)
4075         {
4076           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4077               IS_AOP_PREG (IC_RESULT (ic)))
4078             emitcode ("cjne", "%s,#0x00,%05d$",
4079                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4080                       tlbl->key + 100);
4081           else
4082             emitcode ("cjne", "a,%s,%05d$",
4083                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4084                       tlbl->key + 100);
4085
4086           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4087         }
4088       if (size > 3)
4089         {
4090           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4091               IS_AOP_PREG (IC_RESULT (ic)))
4092             emitcode ("cjne", "%s,#0x00,%05d$",
4093                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4094                       tlbl->key + 100);
4095           else
4096             {
4097               emitcode ("cjne", "a,%s,%05d$",
4098                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4099                         tlbl->key + 100);
4100             }
4101           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4102         }
4103
4104       if (emitTlbl)
4105         {
4106           emitcode ("", "%05d$:", tlbl->key + 100);
4107         }
4108       return TRUE;
4109     }
4110
4111   /* if result is dptr */
4112   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4113       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4114       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4115       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4116     {
4117       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4118         return FALSE;
4119
4120       if (icount > 9)
4121         return FALSE;
4122
4123       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4124         return FALSE;
4125
4126       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4127       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4128       while (icount--)
4129         emitcode ("inc", "dptr");
4130
4131       return TRUE;
4132     }
4133
4134   /* if the literal value of the right hand side
4135      is greater than 4 then it is not worth it */
4136   if (icount > 4)
4137     return FALSE;
4138
4139   /* if the sizes are greater than 1 then we cannot */
4140   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4141       AOP_SIZE (IC_LEFT (ic)) > 1)
4142     return FALSE;
4143
4144   /* we can if the aops of the left & result match or
4145      if they are in registers and the registers are the
4146      same */
4147   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4148     {
4149
4150       if (icount > 3)
4151         {
4152           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4153           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4154           aopPut (IC_RESULT (ic), "a", 0);
4155         }
4156       else
4157         {
4158
4159           while (icount--)
4160             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4161         }
4162
4163       return TRUE;
4164     }
4165
4166   return FALSE;
4167 }
4168
4169 /*-----------------------------------------------------------------*/
4170 /* outBitAcc - output a bit in acc                                 */
4171 /*-----------------------------------------------------------------*/
4172 static void
4173 outBitAcc (operand * result)
4174 {
4175   symbol *tlbl = newiTempLabel (NULL);
4176   /* if the result is a bit */
4177   if (AOP_TYPE (result) == AOP_CRY)
4178     {
4179       aopPut (result, "a", 0);
4180     }
4181   else
4182     {
4183       emitcode ("jz", "%05d$", tlbl->key + 100);
4184       emitcode ("mov", "a,%s", one);
4185       emitcode ("", "%05d$:", tlbl->key + 100);
4186       outAcc (result);
4187     }
4188 }
4189
4190 /*-----------------------------------------------------------------*/
4191 /* genPlusBits - generates code for addition of two bits           */
4192 /*-----------------------------------------------------------------*/
4193 static void
4194 genPlusBits (iCode * ic)
4195 {
4196   D(emitcode (";     genPlusBits",""));
4197
4198   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4199     {
4200       symbol *lbl = newiTempLabel (NULL);
4201       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4202       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4203       emitcode ("cpl", "c");
4204       emitcode ("", "%05d$:", (lbl->key + 100));
4205       outBitC (IC_RESULT (ic));
4206     }
4207   else
4208     {
4209       emitcode ("clr", "a");
4210       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4211       emitcode ("rlc", "a");
4212       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4213       emitcode ("addc", "a,#0x00");
4214       outAcc (IC_RESULT (ic));
4215     }
4216 }
4217
4218 #if 0
4219 /* This is the original version of this code.
4220
4221  * This is being kept around for reference,
4222  * because I am not entirely sure I got it right...
4223  */
4224 static void
4225 adjustArithmeticResult (iCode * ic)
4226 {
4227   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4228       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4229       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4230     aopPut (IC_RESULT (ic),
4231             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4232             2);
4233
4234   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4235       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4236       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4237     aopPut (IC_RESULT (ic),
4238             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4239             2);
4240
4241   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4242       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4243       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4244       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4245       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4246     {
4247       char buffer[5];
4248       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4249       aopPut (IC_RESULT (ic), buffer, 2);
4250     }
4251 }
4252 #else
4253 /* This is the pure and virtuous version of this code.
4254  * I'm pretty certain it's right, but not enough to toss the old
4255  * code just yet...
4256  */
4257 static void
4258 adjustArithmeticResult (iCode * ic)
4259 {
4260   if (opIsGptr (IC_RESULT (ic)) &&
4261       opIsGptr (IC_LEFT (ic)) &&
4262       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4263     {
4264       aopPut (IC_RESULT (ic),
4265               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4266               GPTRSIZE - 1);
4267     }
4268
4269   if (opIsGptr (IC_RESULT (ic)) &&
4270       opIsGptr (IC_RIGHT (ic)) &&
4271       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4272     {
4273       aopPut (IC_RESULT (ic),
4274               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4275               GPTRSIZE - 1);
4276     }
4277
4278   if (opIsGptr (IC_RESULT (ic)) &&
4279       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4280       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4281       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4282       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4283     {
4284       char buffer[5];
4285       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4286       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4287     }
4288 }
4289 #endif
4290
4291 /*-----------------------------------------------------------------*/
4292 /* genPlus - generates code for addition                           */
4293 /*-----------------------------------------------------------------*/
4294 static void
4295 genPlus (iCode * ic)
4296 {
4297   int size, offset = 0;
4298   int skip_bytes = 0;
4299   char *add = "add";
4300   bool swappedLR = FALSE;
4301   operand *leftOp, *rightOp;
4302   operand * op;
4303
4304   /* special cases :- */
4305
4306   D(emitcode (";     genPlus",""));
4307
4308   aopOp (IC_LEFT (ic), ic, FALSE);
4309   aopOp (IC_RIGHT (ic), ic, FALSE);
4310   aopOp (IC_RESULT (ic), ic, TRUE);
4311
4312   /* if literal, literal on the right or
4313      if left requires ACC or right is already
4314      in ACC */
4315   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4316       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4317       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4318     {
4319       operand *t = IC_RIGHT (ic);
4320       IC_RIGHT (ic) = IC_LEFT (ic);
4321       IC_LEFT (ic) = t;
4322       swappedLR = TRUE;
4323     }
4324
4325   /* if both left & right are in bit
4326      space */
4327   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4328       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4329     {
4330       genPlusBits (ic);
4331       goto release;
4332     }
4333
4334   /* if left in bit space & right literal */
4335   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4336       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4337     {
4338       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4339       /* if result in bit space */
4340       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4341         {
4342           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4343             emitcode ("cpl", "c");
4344           outBitC (IC_RESULT (ic));
4345         }
4346       else
4347         {
4348           size = getDataSize (IC_RESULT (ic));
4349           while (size--)
4350             {
4351               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4352               emitcode ("addc", "a,#00");
4353               aopPut (IC_RESULT (ic), "a", offset++);
4354             }
4355         }
4356       goto release;
4357     }
4358
4359   /* if I can do an increment instead
4360      of add then GOOD for ME */
4361   if (genPlusIncr (ic) == TRUE)
4362     goto release;
4363
4364   size = getDataSize (IC_RESULT (ic));
4365   leftOp = IC_LEFT(ic);
4366   rightOp = IC_RIGHT(ic);
4367   op = IC_LEFT(ic);
4368
4369   /* if this is an add for an array access
4370      at a 256 byte boundary */
4371   if ( 2 == size
4372        && AOP_TYPE (op) == AOP_IMMD
4373        && IS_SYMOP (op)
4374        && IS_SPEC (OP_SYM_ETYPE (op))
4375        && SPEC_ABSA (OP_SYM_ETYPE (op))
4376        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4377      )
4378     {
4379       D(emitcode (";     genPlus aligned array",""));
4380       aopPut (IC_RESULT (ic),
4381               aopGet (rightOp, 0, FALSE, FALSE),
4382               0);
4383
4384       if( 1 == getDataSize (IC_RIGHT (ic)) )
4385         {
4386           aopPut (IC_RESULT (ic),
4387                   aopGet (leftOp, 1, FALSE, FALSE),
4388                   1);
4389         }
4390       else
4391         {
4392           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4393           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4394           aopPut (IC_RESULT (ic), "a", 1);
4395         }
4396       goto release;
4397     }
4398
4399   /* if the lower bytes of a literal are zero skip the addition */
4400   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4401     {
4402        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4403               (skip_bytes+1 < size))
4404          {
4405            skip_bytes++;
4406          }
4407        if (skip_bytes)
4408          D(emitcode (";     genPlus shortcut",""));
4409     }
4410
4411   while (size--)
4412     {
4413       if( offset >= skip_bytes )
4414         {
4415           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4416             {
4417               bool pushedB;
4418               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4419               pushedB = pushB ();
4420               emitcode("xch", "a,b");
4421               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4422               emitcode (add, "a,b");
4423               popB (pushedB);
4424             }
4425           else if (aopGetUsesAcc (leftOp, offset))
4426             {
4427               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4428               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4429             }
4430           else
4431             {
4432               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4433               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4434             }
4435           aopPut (IC_RESULT (ic), "a", offset);
4436           add = "addc";  /* further adds must propagate carry */
4437         }
4438       else
4439         {
4440           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4441               isOperandVolatile (IC_RESULT (ic), FALSE))
4442             {
4443               /* just move */
4444               aopPut (IC_RESULT (ic),
4445                       aopGet (leftOp, offset, FALSE, FALSE),
4446                       offset);
4447             }
4448         }
4449       offset++;
4450     }
4451
4452   adjustArithmeticResult (ic);
4453
4454 release:
4455   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4456   if (!swappedLR)
4457     {
4458       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4459       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4460     }
4461   else
4462     {
4463       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4464       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4465     }
4466 }
4467
4468 /*-----------------------------------------------------------------*/
4469 /* genMinusDec :- does subtraction with decrement if possible      */
4470 /*-----------------------------------------------------------------*/
4471 static bool
4472 genMinusDec (iCode * ic)
4473 {
4474   unsigned int icount;
4475   unsigned int size = getDataSize (IC_RESULT (ic));
4476
4477   /* will try to generate an increment */
4478   /* if the right side is not a literal
4479      we cannot */
4480   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4481     return FALSE;
4482
4483   /* if the literal value of the right hand side
4484      is greater than 4 then it is not worth it */
4485   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4486     return FALSE;
4487
4488   D(emitcode (";     genMinusDec",""));
4489
4490   /* if decrement >=16 bits in register or direct space */
4491   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4492       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4493       (size > 1) &&
4494       (icount == 1))
4495     {
4496       symbol *tlbl;
4497       int emitTlbl;
4498       int labelRange;
4499
4500       /* If the next instruction is a goto and the goto target
4501        * is <= 10 instructions previous to this, we can generate
4502        * jumps straight to that target.
4503        */
4504       if (ic->next && ic->next->op == GOTO
4505           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4506           && labelRange <= 10)
4507         {
4508           emitcode (";", "tail decrement optimized");
4509           tlbl = IC_LABEL (ic->next);
4510           emitTlbl = 0;
4511         }
4512       else
4513         {
4514           tlbl = newiTempLabel (NULL);
4515           emitTlbl = 1;
4516         }
4517
4518       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4519       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4520           IS_AOP_PREG (IC_RESULT (ic)))
4521         emitcode ("cjne", "%s,#0xff,%05d$"
4522                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4523                   ,tlbl->key + 100);
4524       else
4525         {
4526           emitcode ("mov", "a,#0xff");
4527           emitcode ("cjne", "a,%s,%05d$"
4528                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4529                     ,tlbl->key + 100);
4530         }
4531       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4532       if (size > 2)
4533         {
4534           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4535               IS_AOP_PREG (IC_RESULT (ic)))
4536             emitcode ("cjne", "%s,#0xff,%05d$"
4537                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4538                       ,tlbl->key + 100);
4539           else
4540             {
4541               emitcode ("cjne", "a,%s,%05d$"
4542                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4543                         ,tlbl->key + 100);
4544             }
4545           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4546         }
4547       if (size > 3)
4548         {
4549           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4550               IS_AOP_PREG (IC_RESULT (ic)))
4551             emitcode ("cjne", "%s,#0xff,%05d$"
4552                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4553                       ,tlbl->key + 100);
4554           else
4555             {
4556               emitcode ("cjne", "a,%s,%05d$"
4557                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4558                         ,tlbl->key + 100);
4559             }
4560           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4561         }
4562       if (emitTlbl)
4563         {
4564           emitcode ("", "%05d$:", tlbl->key + 100);
4565         }
4566       return TRUE;
4567     }
4568
4569   /* if the sizes are greater than 1 then we cannot */
4570   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4571       AOP_SIZE (IC_LEFT (ic)) > 1)
4572     return FALSE;
4573
4574   /* we can if the aops of the left & result match or
4575      if they are in registers and the registers are the
4576      same */
4577   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4578     {
4579       char *l;
4580
4581       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4582         {
4583           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4584           l = "a";
4585         }
4586       else
4587         {
4588           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4589         }
4590
4591       while (icount--)
4592         emitcode ("dec", "%s", l);
4593
4594       if (AOP_NEEDSACC (IC_RESULT (ic)))
4595         aopPut (IC_RESULT (ic), "a", 0);
4596
4597       return TRUE;
4598     }
4599
4600   return FALSE;
4601 }
4602
4603 /*-----------------------------------------------------------------*/
4604 /* addSign - complete with sign                                    */
4605 /*-----------------------------------------------------------------*/
4606 static void
4607 addSign (operand * result, int offset, int sign)
4608 {
4609   int size = (getDataSize (result) - offset);
4610   if (size > 0)
4611     {
4612       if (sign)
4613         {
4614           emitcode ("rlc", "a");
4615           emitcode ("subb", "a,acc");
4616           while (size--)
4617             aopPut (result, "a", offset++);
4618         }
4619       else
4620         while (size--)
4621           aopPut (result, zero, offset++);
4622     }
4623 }
4624
4625 /*-----------------------------------------------------------------*/
4626 /* genMinusBits - generates code for subtraction  of two bits      */
4627 /*-----------------------------------------------------------------*/
4628 static void
4629 genMinusBits (iCode * ic)
4630 {
4631   symbol *lbl = newiTempLabel (NULL);
4632
4633   D(emitcode (";     genMinusBits",""));
4634
4635   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4636     {
4637       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4638       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4639       emitcode ("cpl", "c");
4640       emitcode ("", "%05d$:", (lbl->key + 100));
4641       outBitC (IC_RESULT (ic));
4642     }
4643   else
4644     {
4645       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4646       emitcode ("subb", "a,acc");
4647       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4648       emitcode ("inc", "a");
4649       emitcode ("", "%05d$:", (lbl->key + 100));
4650       aopPut (IC_RESULT (ic), "a", 0);
4651       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4652     }
4653 }
4654
4655 /*-----------------------------------------------------------------*/
4656 /* genMinus - generates code for subtraction                       */
4657 /*-----------------------------------------------------------------*/
4658 static void
4659 genMinus (iCode * ic)
4660 {
4661   int size, offset = 0;
4662
4663   D(emitcode (";     genMinus",""));
4664
4665   aopOp (IC_LEFT (ic), ic, FALSE);
4666   aopOp (IC_RIGHT (ic), ic, FALSE);
4667   aopOp (IC_RESULT (ic), ic, TRUE);
4668
4669   /* special cases :- */
4670   /* if both left & right are in bit space */
4671   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4672       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4673     {
4674       genMinusBits (ic);
4675       goto release;
4676     }
4677
4678   /* if I can do an decrement instead
4679      of subtract then GOOD for ME */
4680   if (genMinusDec (ic) == TRUE)
4681     goto release;
4682
4683   size = getDataSize (IC_RESULT (ic));
4684
4685   /* if literal, add a,#-lit, else normal subb */
4686   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4687     {
4688       unsigned long lit = 0L;
4689       bool useCarry = FALSE;
4690
4691       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4692       lit = -(long) lit;
4693
4694       while (size--)
4695         {
4696           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4697             {
4698             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4699               if (!offset && !size && lit== (unsigned long) -1)
4700                 {
4701                   emitcode ("dec", "a");
4702                 }
4703               else if (!useCarry)
4704                 {
4705                   /* first add without previous c */
4706                   emitcode ("add", "a,#0x%02x",
4707                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4708                   useCarry = TRUE;
4709                 }
4710               else
4711                 {
4712                   emitcode ("addc", "a,#0x%02x",
4713                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4714                 }
4715               aopPut (IC_RESULT (ic), "a", offset++);
4716             }
4717           else
4718             {
4719               /* no need to add zeroes */
4720               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4721                 {
4722                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4723                           offset);
4724                 }
4725               offset++;
4726             }
4727         }
4728     }
4729   else
4730     {
4731       operand *leftOp, *rightOp;
4732
4733       leftOp = IC_LEFT(ic);
4734       rightOp = IC_RIGHT(ic);
4735
4736       while (size--)
4737         {
4738           if (aopGetUsesAcc(rightOp, offset)) {
4739             if (aopGetUsesAcc(leftOp, offset)) {
4740               bool pushedB;
4741
4742               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4743               pushedB = pushB ();
4744               emitcode ("mov", "b,a");
4745               if (offset == 0)
4746                 CLRC;
4747               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4748               emitcode ("subb", "a,b");
4749               popB (pushedB);
4750             } else {
4751               /* reverse subtraction with 2's complement */
4752               if (offset == 0)
4753                 emitcode( "setb", "c");
4754                else
4755                 emitcode( "cpl", "c");
4756               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4757               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4758               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4759               emitcode("cpl", "a");
4760               if (size) /* skip if last byte */
4761                 emitcode( "cpl", "c");
4762             }
4763           } else {
4764             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4765             if (offset == 0)
4766               CLRC;
4767             emitcode ("subb", "a,%s",
4768                       aopGet(rightOp, offset, FALSE, TRUE));
4769           }
4770
4771           aopPut (IC_RESULT (ic), "a", offset++);
4772         }
4773     }
4774
4775   adjustArithmeticResult (ic);
4776
4777 release:
4778   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4779   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4780   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4781 }
4782
4783
4784 /*-----------------------------------------------------------------*/
4785 /* genMultbits :- multiplication of bits                           */
4786 /*-----------------------------------------------------------------*/
4787 static void
4788 genMultbits (operand * left,
4789              operand * right,
4790              operand * result)
4791 {
4792   D(emitcode (";     genMultbits",""));
4793
4794   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4795   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4796   outBitC (result);
4797 }
4798
4799 /*-----------------------------------------------------------------*/
4800 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4801 /*-----------------------------------------------------------------*/
4802 static void
4803 genMultOneByte (operand * left,
4804                 operand * right,
4805                 operand * result)
4806 {
4807   symbol *lbl;
4808   int size = AOP_SIZE (result);
4809   bool runtimeSign, compiletimeSign;
4810   bool lUnsigned, rUnsigned, pushedB;
4811
4812   D(emitcode (";     genMultOneByte",""));
4813
4814   if (size < 1 || size > 2)
4815     {
4816       /* this should never happen */
4817       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4818                AOP_SIZE(result), __FILE__, lineno);
4819       exit (1);
4820     }
4821
4822   /* (if two literals: the value is computed before) */
4823   /* if one literal, literal on the right */
4824   if (AOP_TYPE (left) == AOP_LIT)
4825     {
4826       operand *t = right;
4827       right = left;
4828       left = t;
4829       /* emitcode (";", "swapped left and right"); */
4830     }
4831   /* if no literal, unsigned on the right: shorter code */
4832   if (   AOP_TYPE (right) != AOP_LIT
4833       && SPEC_USIGN (getSpec (operandType (left))))
4834     {
4835       operand *t = right;
4836       right = left;
4837       left = t;
4838     }
4839
4840   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4841   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4842
4843   pushedB = pushB ();
4844
4845   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4846                    no need to take care about the signedness! */
4847       || (lUnsigned && rUnsigned))
4848     {
4849       /* just an unsigned 8 * 8 = 8 multiply
4850          or 8u * 8u = 16u */
4851       /* emitcode (";","unsigned"); */
4852       /* TODO: check for accumulator clash between left & right aops? */
4853
4854       if (AOP_TYPE (right) == AOP_LIT)
4855         {
4856           /* moving to accumulator first helps peepholes */
4857           MOVA (aopGet (left, 0, FALSE, FALSE));
4858           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4859         }
4860       else
4861         {
4862           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4863           MOVA (aopGet (left, 0, FALSE, FALSE));
4864         }
4865
4866       emitcode ("mul", "ab");
4867       aopPut (result, "a", 0);
4868       if (size == 2)
4869         aopPut (result, "b", 1);
4870
4871       popB (pushedB);
4872       return;
4873     }
4874
4875   /* we have to do a signed multiply */
4876   /* emitcode (";", "signed"); */
4877
4878   /* now sign adjust for both left & right */
4879
4880   /* let's see what's needed: */
4881   /* apply negative sign during runtime */
4882   runtimeSign = FALSE;
4883   /* negative sign from literals */
4884   compiletimeSign = FALSE;
4885
4886   if (!lUnsigned)
4887     {
4888       if (AOP_TYPE(left) == AOP_LIT)
4889         {
4890           /* signed literal */
4891           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4892           if (val < 0)
4893             compiletimeSign = TRUE;
4894         }
4895       else
4896         /* signed but not literal */
4897         runtimeSign = TRUE;
4898     }
4899
4900   if (!rUnsigned)
4901     {
4902       if (AOP_TYPE(right) == AOP_LIT)
4903         {
4904           /* signed literal */
4905           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4906           if (val < 0)
4907             compiletimeSign ^= TRUE;
4908         }
4909       else
4910         /* signed but not literal */
4911         runtimeSign = TRUE;
4912     }
4913
4914   /* initialize F0, which stores the runtime sign */
4915   if (runtimeSign)
4916     {
4917       if (compiletimeSign)
4918         emitcode ("setb", "F0"); /* set sign flag */
4919       else
4920         emitcode ("clr", "F0"); /* reset sign flag */
4921     }
4922
4923   /* save the signs of the operands */
4924   if (AOP_TYPE(right) == AOP_LIT)
4925     {
4926       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4927
4928       if (!rUnsigned && val < 0)
4929         emitcode ("mov", "b,#0x%02x", -val);
4930       else
4931         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4932     }
4933   else /* ! literal */
4934     {
4935       if (rUnsigned)  /* emitcode (";", "signed"); */
4936         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4937       else
4938         {
4939           MOVA (aopGet (right, 0, FALSE, FALSE));
4940           lbl = newiTempLabel (NULL);
4941           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4942           emitcode ("cpl", "F0"); /* complement sign flag */
4943           emitcode ("cpl", "a");  /* 2's complement */
4944           emitcode ("inc", "a");
4945           emitcode ("", "%05d$:", (lbl->key + 100));
4946           emitcode ("mov", "b,a");
4947         }
4948     }
4949
4950   if (AOP_TYPE(left) == AOP_LIT)
4951     {
4952       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4953
4954       if (!lUnsigned && val < 0)
4955         emitcode ("mov", "a,#0x%02x", -val);
4956       else
4957         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4958     }
4959   else /* ! literal */
4960     {
4961       MOVA (aopGet (left, 0, FALSE, FALSE));
4962
4963       if (!lUnsigned)
4964         {
4965           lbl = newiTempLabel (NULL);
4966           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4967           emitcode ("cpl", "F0"); /* complement sign flag */
4968           emitcode ("cpl", "a"); /* 2's complement */
4969           emitcode ("inc", "a");
4970           emitcode ("", "%05d$:", (lbl->key + 100));
4971         }
4972     }
4973
4974   /* now the multiplication */
4975   emitcode ("mul", "ab");
4976   if (runtimeSign || compiletimeSign)
4977     {
4978       lbl = newiTempLabel (NULL);
4979       if (runtimeSign)
4980         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4981       emitcode ("cpl", "a"); /* lsb 2's complement */
4982       if (size != 2)
4983         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4984       else
4985         {
4986           emitcode ("add", "a,#1"); /* this sets carry flag */
4987           emitcode ("xch", "a,b");
4988           emitcode ("cpl", "a"); /* msb 2's complement */
4989           emitcode ("addc", "a,#0");
4990           emitcode ("xch", "a,b");
4991         }
4992       emitcode ("", "%05d$:", (lbl->key + 100));
4993     }
4994   aopPut (result, "a", 0);
4995   if (size == 2)
4996     aopPut (result, "b", 1);
4997
4998   popB (pushedB);
4999 }
5000
5001 /*-----------------------------------------------------------------*/
5002 /* genMult - generates code for multiplication                     */
5003 /*-----------------------------------------------------------------*/
5004 static void
5005 genMult (iCode * ic)
5006 {
5007   operand *left = IC_LEFT (ic);
5008   operand *right = IC_RIGHT (ic);
5009   operand *result = IC_RESULT (ic);
5010
5011   D(emitcode (";     genMult",""));
5012
5013   /* assign the asmops */
5014   aopOp (left, ic, FALSE);
5015   aopOp (right, ic, FALSE);
5016   aopOp (result, ic, TRUE);
5017
5018   /* special cases first */
5019   /* both are bits */
5020   if (AOP_TYPE (left) == AOP_CRY &&
5021       AOP_TYPE (right) == AOP_CRY)
5022     {
5023       genMultbits (left, right, result);
5024       goto release;
5025     }
5026
5027   /* if both are of size == 1 */
5028 #if 0 // one of them can be a sloc shared with the result
5029     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5030 #else
5031   if (getSize(operandType(left)) == 1 &&
5032       getSize(operandType(right)) == 1)
5033 #endif
5034     {
5035       genMultOneByte (left, right, result);
5036       goto release;
5037     }
5038
5039   /* should have been converted to function call */
5040     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5041              getSize(OP_SYMBOL(right)->type));
5042   assert (0);
5043
5044 release:
5045   freeAsmop (result, NULL, ic, TRUE);
5046   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5047   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5048 }
5049
5050 /*-----------------------------------------------------------------*/
5051 /* genDivbits :- division of bits                                  */
5052 /*-----------------------------------------------------------------*/
5053 static void
5054 genDivbits (operand * left,
5055             operand * right,
5056             operand * result)
5057 {
5058   char *l;
5059   bool pushedB;
5060
5061   D(emitcode (";     genDivbits",""));
5062
5063   pushedB = pushB ();
5064
5065   /* the result must be bit */
5066   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5067   l = aopGet (left, 0, FALSE, FALSE);
5068
5069   MOVA (l);
5070
5071   emitcode ("div", "ab");
5072   emitcode ("rrc", "a");
5073
5074   popB (pushedB);
5075
5076   aopPut (result, "c", 0);
5077 }
5078
5079 /*-----------------------------------------------------------------*/
5080 /* genDivOneByte : 8 bit division                                  */
5081 /*-----------------------------------------------------------------*/
5082 static void
5083 genDivOneByte (operand * left,
5084                operand * right,
5085                operand * result)
5086 {
5087   bool lUnsigned, rUnsigned, pushedB;
5088   bool runtimeSign, compiletimeSign;
5089   bool accuse = FALSE;
5090   bool pushedA = FALSE;
5091   symbol *lbl;
5092   int size, offset;
5093
5094   D(emitcode (";     genDivOneByte",""));
5095
5096   /* Why is it necessary that genDivOneByte() can return an int result?
5097      Have a look at:
5098
5099         volatile unsigned char uc;
5100         volatile signed char sc1, sc2;
5101         volatile int i;
5102
5103         uc  = 255;
5104         sc1 = -1;
5105         i = uc / sc1;
5106
5107      Or:
5108
5109         sc1 = -128;
5110         sc2 = -1;
5111         i = sc1 / sc2;
5112
5113      In all cases a one byte result would overflow, the following cast to int
5114      would return the wrong result.
5115
5116      Two possible solution:
5117         a) cast operands to int, if ((unsigned) / (signed)) or
5118            ((signed) / (signed))
5119         b) return an 16 bit signed int; this is what we're doing here!
5120   */
5121
5122   size = AOP_SIZE (result) - 1;
5123   offset = 1;
5124   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5125   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5126
5127   pushedB = pushB ();
5128
5129   /* signed or unsigned */
5130   if (lUnsigned && rUnsigned)
5131     {
5132       /* unsigned is easy */
5133       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5134       MOVA (aopGet (left, 0, FALSE, FALSE));
5135       emitcode ("div", "ab");
5136       aopPut (result, "a", 0);
5137       while (size--)
5138         aopPut (result, zero, offset++);
5139
5140       popB (pushedB);
5141       return;
5142     }
5143
5144   /* signed is a little bit more difficult */
5145
5146   /* now sign adjust for both left & right */
5147
5148   /* let's see what's needed: */
5149   /* apply negative sign during runtime */
5150   runtimeSign = FALSE;
5151   /* negative sign from literals */
5152   compiletimeSign = FALSE;
5153
5154   if (!lUnsigned)
5155     {
5156       if (AOP_TYPE(left) == AOP_LIT)
5157         {
5158           /* signed literal */
5159           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5160           if (val < 0)
5161             compiletimeSign = TRUE;
5162         }
5163       else
5164         /* signed but not literal */
5165         runtimeSign = TRUE;
5166     }
5167
5168   if (!rUnsigned)
5169     {
5170       if (AOP_TYPE(right) == AOP_LIT)
5171         {
5172           /* signed literal */
5173           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5174           if (val < 0)
5175             compiletimeSign ^= TRUE;
5176         }
5177       else
5178         /* signed but not literal */
5179         runtimeSign = TRUE;
5180     }
5181
5182   /* initialize F0, which stores the runtime sign */
5183   if (runtimeSign)
5184     {
5185       if (compiletimeSign)
5186         emitcode ("setb", "F0"); /* set sign flag */
5187       else
5188         emitcode ("clr", "F0"); /* reset sign flag */
5189     }
5190
5191   /* save the signs of the operands */
5192   if (AOP_TYPE(right) == AOP_LIT)
5193     {
5194       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5195
5196       if (!rUnsigned && val < 0)
5197         emitcode ("mov", "b,#0x%02x", -val);
5198       else
5199         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5200     }
5201   else /* ! literal */
5202     {
5203       if (rUnsigned)
5204         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5205       else
5206         {
5207           MOVA (aopGet (right, 0, FALSE, FALSE));
5208           lbl = newiTempLabel (NULL);
5209           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5210           emitcode ("cpl", "F0"); /* complement sign flag */
5211           emitcode ("cpl", "a");  /* 2's complement */
5212           emitcode ("inc", "a");
5213           emitcode ("", "%05d$:", (lbl->key + 100));
5214           emitcode ("mov", "b,a");
5215         }
5216     }
5217
5218   if (AOP_TYPE(left) == AOP_LIT)
5219     {
5220       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5221
5222       if (!lUnsigned && val < 0)
5223         emitcode ("mov", "a,#0x%02x", -val);
5224       else
5225         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5226     }
5227   else /* ! literal */
5228     {
5229       MOVA (aopGet (left, 0, FALSE, FALSE));
5230
5231       if (!lUnsigned)
5232         {
5233           lbl = newiTempLabel (NULL);
5234           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5235           emitcode ("cpl", "F0"); /* complement sign flag */
5236           emitcode ("cpl", "a");  /* 2's complement */
5237           emitcode ("inc", "a");
5238           emitcode ("", "%05d$:", (lbl->key + 100));
5239         }
5240     }
5241
5242   /* now the division */
5243   emitcode ("div", "ab");
5244
5245   if (runtimeSign || compiletimeSign)
5246     {
5247       lbl = newiTempLabel (NULL);
5248       if (runtimeSign)
5249         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5250       emitcode ("cpl", "a"); /* lsb 2's complement */
5251       emitcode ("inc", "a");
5252       emitcode ("", "%05d$:", (lbl->key + 100));
5253
5254       accuse = aopPut (result, "a", 0);
5255       if (size > 0)
5256         {
5257           /* msb is 0x00 or 0xff depending on the sign */
5258           if (runtimeSign)
5259             {
5260               if (accuse)
5261                 {
5262                   emitcode ("push", "acc");
5263                   pushedA = TRUE;
5264                 }
5265               emitcode ("mov", "c,F0");
5266               emitcode ("subb", "a,acc");
5267               while (size--)
5268                 aopPut (result, "a", offset++);
5269             }
5270           else /* compiletimeSign */
5271             {
5272               if (aopPutUsesAcc (result, "#0xFF", offset))
5273                 {
5274                   emitcode ("push", "acc");
5275                   pushedA = TRUE;
5276                 }
5277               while (size--)
5278                 aopPut (result, "#0xff", offset++);
5279             }
5280         }
5281     }
5282   else
5283     {
5284       aopPut (result, "a", 0);
5285       while (size--)
5286         aopPut (result, zero, offset++);
5287     }
5288
5289   if (pushedA)
5290     emitcode ("pop", "acc");
5291   popB (pushedB);
5292 }
5293
5294 /*-----------------------------------------------------------------*/
5295 /* genDiv - generates code for division                            */
5296 /*-----------------------------------------------------------------*/
5297 static void
5298 genDiv (iCode * ic)
5299 {
5300   operand *left = IC_LEFT (ic);
5301   operand *right = IC_RIGHT (ic);
5302   operand *result = IC_RESULT (ic);
5303
5304   D(emitcode (";     genDiv",""));
5305
5306   /* assign the amsops */
5307   aopOp (left, ic, FALSE);
5308   aopOp (right, ic, FALSE);
5309   aopOp (result, ic, TRUE);
5310
5311   /* special cases first */
5312   /* both are bits */
5313   if (AOP_TYPE (left) == AOP_CRY &&
5314       AOP_TYPE (right) == AOP_CRY)
5315     {
5316       genDivbits (left, right, result);
5317       goto release;
5318     }
5319
5320   /* if both are of size == 1 */
5321   if (AOP_SIZE (left) == 1 &&
5322       AOP_SIZE (right) == 1)
5323     {
5324       genDivOneByte (left, right, result);
5325       goto release;
5326     }
5327
5328   /* should have been converted to function call */
5329   assert (0);
5330 release:
5331   freeAsmop (result, NULL, ic, TRUE);
5332   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5333   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5334 }
5335
5336 /*-----------------------------------------------------------------*/
5337 /* genModbits :- modulus of bits                                   */
5338 /*-----------------------------------------------------------------*/
5339 static void
5340 genModbits (operand * left,
5341             operand * right,
5342             operand * result)
5343 {
5344   char *l;
5345   bool pushedB;
5346
5347   D(emitcode (";     genModbits",""));
5348
5349   pushedB = pushB ();
5350
5351   /* the result must be bit */
5352   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5353   l = aopGet (left, 0, FALSE, FALSE);
5354
5355   MOVA (l);
5356
5357   emitcode ("div", "ab");
5358   emitcode ("mov", "a,b");
5359   emitcode ("rrc", "a");
5360
5361   popB (pushedB);
5362
5363   aopPut (result, "c", 0);
5364 }
5365
5366 /*-----------------------------------------------------------------*/
5367 /* genModOneByte : 8 bit modulus                                   */
5368 /*-----------------------------------------------------------------*/
5369 static void
5370 genModOneByte (operand * left,
5371                operand * right,
5372                operand * result)
5373 {
5374   bool lUnsigned, rUnsigned, pushedB;
5375   bool runtimeSign, compiletimeSign;
5376   symbol *lbl;
5377   int size, offset;
5378
5379   D(emitcode (";     genModOneByte",""));
5380
5381   size = AOP_SIZE (result) - 1;
5382   offset = 1;
5383   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5384   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5385
5386   /* if right is a literal, check it for 2^n */
5387   if (AOP_TYPE(right) == AOP_LIT)
5388     {
5389       unsigned char val = abs((int) operandLitValue(right));
5390       symbol *lbl2 = NULL;
5391
5392       switch (val)
5393         {
5394           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5395           case 2:
5396           case 4:
5397           case 8:
5398           case 16:
5399           case 32:
5400           case 64:
5401           case 128:
5402             if (lUnsigned)
5403               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5404                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5405               /* because iCode should have been changed to genAnd  */
5406               /* see file "SDCCopt.c", function "convertToFcall()" */
5407
5408             MOVA (aopGet (left, 0, FALSE, FALSE));
5409             emitcode ("mov", "c,acc.7");
5410             emitcode ("anl", "a,#0x%02x", val - 1);
5411             lbl = newiTempLabel (NULL);
5412             emitcode ("jz", "%05d$", (lbl->key + 100));
5413             emitcode ("jnc", "%05d$", (lbl->key + 100));
5414             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5415             if (size)
5416               {
5417                 int size2 = size;
5418                 int offs2 = offset;
5419
5420                 aopPut (result, "a", 0);
5421                 while (size2--)
5422                   aopPut (result, "#0xff", offs2++);
5423                 lbl2 = newiTempLabel (NULL);
5424                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5425               }
5426             emitcode ("", "%05d$:", (lbl->key + 100));
5427             aopPut (result, "a", 0);
5428             while (size--)
5429               aopPut (result, zero, offset++);
5430             if (lbl2)
5431               {
5432                 emitcode ("", "%05d$:", (lbl2->key + 100));
5433               }
5434             return;
5435
5436           default:
5437             break;
5438         }
5439     }
5440
5441   pushedB = pushB ();
5442
5443   /* signed or unsigned */
5444   if (lUnsigned && rUnsigned)
5445     {
5446       /* unsigned is easy */
5447       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5448       MOVA (aopGet (left, 0, FALSE, FALSE));
5449       emitcode ("div", "ab");
5450       aopPut (result, "b", 0);
5451       while (size--)
5452         aopPut (result, zero, offset++);
5453
5454       popB (pushedB);
5455       return;
5456     }
5457
5458   /* signed is a little bit more difficult */
5459
5460   /* now sign adjust for both left & right */
5461
5462   /* modulus: sign of the right operand has no influence on the result! */
5463   if (AOP_TYPE(right) == AOP_LIT)
5464     {
5465       signed char val = (char) operandLitValue(right);
5466
5467       if (!rUnsigned && val < 0)
5468         emitcode ("mov", "b,#0x%02x", -val);
5469       else
5470         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5471     }
5472   else /* not literal */
5473     {
5474       if (rUnsigned)
5475         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5476       else
5477         {
5478           MOVA (aopGet (right, 0, FALSE, FALSE));
5479           lbl = newiTempLabel (NULL);
5480           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5481           emitcode ("cpl", "a"); /* 2's complement */
5482           emitcode ("inc", "a");
5483           emitcode ("", "%05d$:", (lbl->key + 100));
5484           emitcode ("mov", "b,a");
5485         }
5486     }
5487
5488   /* let's see what's needed: */
5489   /* apply negative sign during runtime */
5490   runtimeSign = FALSE;
5491   /* negative sign from literals */
5492   compiletimeSign = FALSE;
5493
5494   /* sign adjust left side */
5495   if (AOP_TYPE(left) == AOP_LIT)
5496     {
5497       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5498
5499       if (!lUnsigned && val < 0)
5500         {
5501           compiletimeSign = TRUE; /* set sign flag */
5502           emitcode ("mov", "a,#0x%02x", -val);
5503         }
5504       else
5505         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5506     }
5507   else /* ! literal */
5508     {
5509       MOVA (aopGet (left, 0, FALSE, FALSE));
5510
5511       if (!lUnsigned)
5512         {
5513           runtimeSign = TRUE;
5514           emitcode ("clr", "F0"); /* clear sign flag */
5515
5516           lbl = newiTempLabel (NULL);
5517           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5518           emitcode ("setb", "F0"); /* set sign flag */
5519           emitcode ("cpl", "a");   /* 2's complement */
5520           emitcode ("inc", "a");
5521           emitcode ("", "%05d$:", (lbl->key + 100));
5522         }
5523     }
5524
5525   /* now the modulus */
5526   emitcode ("div", "ab");
5527
5528   if (runtimeSign || compiletimeSign)
5529     {
5530       emitcode ("mov", "a,b");
5531       lbl = newiTempLabel (NULL);
5532       if (runtimeSign)
5533         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5534       emitcode ("cpl", "a"); /* 2's complement */
5535       emitcode ("inc", "a");
5536       emitcode ("", "%05d$:", (lbl->key + 100));
5537
5538       aopPut (result, "a", 0);
5539       if (size > 0)
5540         {
5541           /* msb is 0x00 or 0xff depending on the sign */
5542           if (runtimeSign)
5543             {
5544               emitcode ("mov", "c,F0");
5545               emitcode ("subb", "a,acc");
5546               while (size--)
5547                 aopPut (result, "a", offset++);
5548             }
5549           else /* compiletimeSign */
5550             while (size--)
5551               aopPut (result, "#0xff", offset++);
5552         }
5553     }
5554   else
5555     {
5556       aopPut (result, "b", 0);
5557       while (size--)
5558         aopPut (result, zero, offset++);
5559     }
5560
5561   popB (pushedB);
5562 }
5563
5564 /*-----------------------------------------------------------------*/
5565 /* genMod - generates code for division                            */
5566 /*-----------------------------------------------------------------*/
5567 static void
5568 genMod (iCode * ic)
5569 {
5570   operand *left = IC_LEFT (ic);
5571   operand *right = IC_RIGHT (ic);
5572   operand *result = IC_RESULT (ic);
5573
5574   D(emitcode (";     genMod",""));
5575
5576   /* assign the asmops */
5577   aopOp (left, ic, FALSE);
5578   aopOp (right, ic, FALSE);
5579   aopOp (result, ic, TRUE);
5580
5581   /* special cases first */
5582   /* both are bits */
5583   if (AOP_TYPE (left) == AOP_CRY &&
5584       AOP_TYPE (right) == AOP_CRY)
5585     {
5586       genModbits (left, right, result);
5587       goto release;
5588     }
5589
5590   /* if both are of size == 1 */
5591   if (AOP_SIZE (left) == 1 &&
5592       AOP_SIZE (right) == 1)
5593     {
5594       genModOneByte (left, right, result);
5595       goto release;
5596     }
5597
5598   /* should have been converted to function call */
5599   assert (0);
5600
5601 release:
5602   freeAsmop (result, NULL, ic, TRUE);
5603   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5604   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5605 }
5606
5607 /*-----------------------------------------------------------------*/
5608 /* genIfxJump :- will create a jump depending on the ifx           */
5609 /*-----------------------------------------------------------------*/
5610 static void
5611 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5612 {
5613   symbol *jlbl;
5614   symbol *tlbl = newiTempLabel (NULL);
5615   char *inst;
5616
5617   D(emitcode (";     genIfxJump",""));
5618
5619   /* if true label then we jump if condition
5620      supplied is true */
5621   if (IC_TRUE (ic))
5622     {
5623       jlbl = IC_TRUE (ic);
5624       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5625                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5626     }
5627   else
5628     {
5629       /* false label is present */
5630       jlbl = IC_FALSE (ic);
5631       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5632                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5633     }
5634   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5635     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5636   else
5637     emitcode (inst, "%05d$", tlbl->key + 100);
5638   freeForBranchAsmop (result);
5639   freeForBranchAsmop (right);
5640   freeForBranchAsmop (left);
5641   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5642   emitcode ("", "%05d$:", tlbl->key + 100);
5643
5644   /* mark the icode as generated */
5645   ic->generated = 1;
5646 }
5647
5648 /*-----------------------------------------------------------------*/
5649 /* genCmp :- greater or less than comparison                       */
5650 /*-----------------------------------------------------------------*/
5651 static void
5652 genCmp (operand * left, operand * right,
5653         operand * result, iCode * ifx, int sign, iCode *ic)
5654 {
5655   int size, offset = 0;
5656   unsigned long lit = 0L;
5657   bool rightInB;
5658
5659   D(emitcode (";     genCmp",""));
5660
5661   /* if left & right are bit variables */
5662   if (AOP_TYPE (left) == AOP_CRY &&
5663       AOP_TYPE (right) == AOP_CRY)
5664     {
5665       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5666       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5667     }
5668   else
5669     {
5670       /* subtract right from left if at the
5671          end the carry flag is set then we know that
5672          left is greater than right */
5673       size = max (AOP_SIZE (left), AOP_SIZE (right));
5674
5675       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5676       if ((size == 1) && !sign &&
5677           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5678         {
5679           symbol *lbl = newiTempLabel (NULL);
5680           emitcode ("cjne", "%s,%s,%05d$",
5681                     aopGet (left, offset, FALSE, FALSE),
5682                     aopGet (right, offset, FALSE, FALSE),
5683                     lbl->key + 100);
5684           emitcode ("", "%05d$:", lbl->key + 100);
5685         }
5686       else
5687         {
5688           if (AOP_TYPE (right) == AOP_LIT)
5689             {
5690               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5691               /* optimize if(x < 0) or if(x >= 0) */
5692               if (lit == 0L)
5693                 {
5694                   if (!sign)
5695                     {
5696                       CLRC;
5697                     }
5698                   else
5699                     {
5700                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5701                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5702                         {
5703                           genIfxJump (ifx, "acc.7", left, right, result);
5704                           freeAsmop (right, NULL, ic, TRUE);
5705                           freeAsmop (left, NULL, ic, TRUE);
5706
5707                           return;
5708                         }
5709                       else
5710                         emitcode ("rlc", "a");
5711                     }
5712                   goto release;
5713                 }
5714             }
5715           CLRC;
5716           while (size--)
5717             {
5718               bool pushedB = FALSE;
5719               rightInB = aopGetUsesAcc(right, offset);
5720               if (rightInB)
5721                 {
5722                   pushedB = pushB ();
5723                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5724                 }
5725               MOVA (aopGet (left, offset, FALSE, FALSE));
5726               if (sign && size == 0)
5727                 {
5728                   emitcode ("xrl", "a,#0x80");
5729                   if (AOP_TYPE (right) == AOP_LIT)
5730                     {
5731                       unsigned long lit = (unsigned long)
5732                       floatFromVal (AOP (right)->aopu.aop_lit);
5733                       emitcode ("subb", "a,#0x%02x",
5734                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5735                     }
5736                   else
5737                     {
5738                       if (!rightInB)
5739                         {
5740                           pushedB = pushB ();
5741                           rightInB++;
5742                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5743                         }
5744                       emitcode ("xrl", "b,#0x80");
5745                       emitcode ("subb", "a,b");
5746                     }
5747                 }
5748               else
5749                 {
5750                   if (rightInB)
5751                     emitcode ("subb", "a,b");
5752                   else
5753                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5754                 }
5755               if (rightInB)
5756                 popB (pushedB);
5757               offset++;
5758             }
5759         }
5760     }
5761
5762 release:
5763   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5764   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5765   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5766     {
5767       outBitC (result);
5768     }
5769   else
5770     {
5771       /* if the result is used in the next
5772          ifx conditional branch then generate
5773          code a little differently */
5774       if (ifx)
5775         genIfxJump (ifx, "c", NULL, NULL, result);
5776       else
5777         outBitC (result);
5778       /* leave the result in acc */
5779     }
5780 }
5781
5782 /*-----------------------------------------------------------------*/
5783 /* genCmpGt :- greater than comparison                             */
5784 /*-----------------------------------------------------------------*/
5785 static void
5786 genCmpGt (iCode * ic, iCode * ifx)
5787 {
5788   operand *left, *right, *result;
5789   sym_link *letype, *retype;
5790   int sign;
5791
5792   D(emitcode (";     genCmpGt",""));
5793
5794   left = IC_LEFT (ic);
5795   right = IC_RIGHT (ic);
5796   result = IC_RESULT (ic);
5797
5798   letype = getSpec (operandType (left));
5799   retype = getSpec (operandType (right));
5800   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5801            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5802   /* assign the amsops */
5803   aopOp (result, ic, TRUE);
5804   aopOp (left, ic, FALSE);
5805   aopOp (right, ic, FALSE);
5806
5807   genCmp (right, left, result, ifx, sign, ic);
5808
5809   freeAsmop (result, NULL, ic, TRUE);
5810 }
5811
5812 /*-----------------------------------------------------------------*/
5813 /* genCmpLt - less than comparisons                                */
5814 /*-----------------------------------------------------------------*/
5815 static void
5816 genCmpLt (iCode * ic, iCode * ifx)
5817 {
5818   operand *left, *right, *result;
5819   sym_link *letype, *retype;
5820   int sign;
5821
5822   D(emitcode (";     genCmpLt",""));
5823
5824   left = IC_LEFT (ic);
5825   right = IC_RIGHT (ic);
5826   result = IC_RESULT (ic);
5827
5828   letype = getSpec (operandType (left));
5829   retype = getSpec (operandType (right));
5830   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5831            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5832   /* assign the amsops */
5833   aopOp (result, ic, TRUE);
5834   aopOp (left, ic, FALSE);
5835   aopOp (right, ic, FALSE);
5836
5837   genCmp (left, right, result, ifx, sign, ic);
5838
5839   freeAsmop (result, NULL, ic, TRUE);
5840 }
5841
5842 /*-----------------------------------------------------------------*/
5843 /* gencjneshort - compare and jump if not equal                    */
5844 /*-----------------------------------------------------------------*/
5845 static void
5846 gencjneshort (operand * left, operand * right, symbol * lbl)
5847 {
5848   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5849   int offset = 0;
5850   unsigned long lit = 0L;
5851
5852   /* if the left side is a literal or
5853      if the right is in a pointer register and left
5854      is not */
5855   if ((AOP_TYPE (left) == AOP_LIT) ||
5856       (AOP_TYPE (left) == AOP_IMMD) ||
5857       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5858     {
5859       operand *t = right;
5860       right = left;
5861       left = t;
5862     }
5863
5864   if (AOP_TYPE (right) == AOP_LIT)
5865     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5866
5867   /* if the right side is a literal then anything goes */
5868   if (AOP_TYPE (right) == AOP_LIT &&
5869       AOP_TYPE (left) != AOP_DIR  &&
5870       AOP_TYPE (left) != AOP_IMMD)
5871     {
5872       while (size--)
5873         {
5874           emitcode ("cjne", "%s,%s,%05d$",
5875                     aopGet (left, offset, FALSE, FALSE),
5876                     aopGet (right, offset, FALSE, FALSE),
5877                     lbl->key + 100);
5878           offset++;
5879         }
5880     }
5881
5882   /* if the right side is in a register or in direct space or
5883      if the left is a pointer register & right is not */
5884   else if (AOP_TYPE (right) == AOP_REG ||
5885            AOP_TYPE (right) == AOP_DIR ||
5886            AOP_TYPE (right) == AOP_LIT ||
5887            AOP_TYPE (right) == AOP_IMMD ||
5888            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5889            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5890     {
5891       while (size--)
5892         {
5893           MOVA (aopGet (left, offset, FALSE, FALSE));
5894           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5895               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5896             emitcode ("jnz", "%05d$", lbl->key + 100);
5897           else
5898             emitcode ("cjne", "a,%s,%05d$",
5899                       aopGet (right, offset, FALSE, TRUE),
5900                       lbl->key + 100);
5901           offset++;
5902         }
5903     }
5904   else
5905     {
5906       /* right is a pointer reg need both a & b */
5907       while (size--)
5908         {
5909           char *l;
5910           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5911           wassertl(!BINUSE, "B was in use");
5912           l = aopGet (left, offset, FALSE, FALSE);
5913           if (strcmp (l, "b"))
5914             emitcode ("mov", "b,%s", l);
5915           MOVA (aopGet (right, offset, FALSE, FALSE));
5916           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5917           offset++;
5918         }
5919     }
5920 }
5921
5922 /*-----------------------------------------------------------------*/
5923 /* gencjne - compare and jump if not equal                         */
5924 /*-----------------------------------------------------------------*/
5925 static void
5926 gencjne (operand * left, operand * right, symbol * lbl)
5927 {
5928   symbol *tlbl = newiTempLabel (NULL);
5929
5930   gencjneshort (left, right, lbl);
5931
5932   emitcode ("mov", "a,%s", one);
5933   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5934   emitcode ("", "%05d$:", lbl->key + 100);
5935   emitcode ("clr", "a");
5936   emitcode ("", "%05d$:", tlbl->key + 100);
5937 }
5938
5939 /*-----------------------------------------------------------------*/
5940 /* genCmpEq - generates code for equal to                          */
5941 /*-----------------------------------------------------------------*/
5942 static void
5943 genCmpEq (iCode * ic, iCode * ifx)
5944 {
5945   bool swappedLR = FALSE;
5946   operand *left, *right, *result;
5947
5948   D(emitcode (";     genCmpEq",""));
5949
5950   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5951   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5952   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5953
5954   /* if literal, literal on the right or
5955      if the right is in a pointer register and left
5956      is not */
5957   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5958       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5959     {
5960       operand *t = IC_RIGHT (ic);
5961       IC_RIGHT (ic) = IC_LEFT (ic);
5962       IC_LEFT (ic) = t;
5963       swappedLR = TRUE;
5964     }
5965
5966   if (ifx && !AOP_SIZE (result))
5967     {
5968       symbol *tlbl;
5969       /* if they are both bit variables */
5970       if (AOP_TYPE (left) == AOP_CRY &&
5971           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5972         {
5973           if (AOP_TYPE (right) == AOP_LIT)
5974             {
5975               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5976               if (lit == 0L)
5977                 {
5978                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5979                   emitcode ("cpl", "c");
5980                 }
5981               else if (lit == 1L)
5982                 {
5983                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5984                 }
5985               else
5986                 {
5987                   emitcode ("clr", "c");
5988                 }
5989               /* AOP_TYPE(right) == AOP_CRY */
5990             }
5991           else
5992             {
5993               symbol *lbl = newiTempLabel (NULL);
5994               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5995               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5996               emitcode ("cpl", "c");
5997               emitcode ("", "%05d$:", (lbl->key + 100));
5998             }
5999           /* if true label then we jump if condition
6000              supplied is true */
6001           tlbl = newiTempLabel (NULL);
6002           if (IC_TRUE (ifx))
6003             {
6004               emitcode ("jnc", "%05d$", tlbl->key + 100);
6005               freeForBranchAsmop (result);
6006               freeForBranchAsmop (right);
6007               freeForBranchAsmop (left);
6008               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6009             }
6010           else
6011             {
6012               emitcode ("jc", "%05d$", tlbl->key + 100);
6013               freeForBranchAsmop (result);
6014               freeForBranchAsmop (right);
6015               freeForBranchAsmop (left);
6016               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6017             }
6018           emitcode ("", "%05d$:", tlbl->key + 100);
6019         }
6020       else
6021         {
6022           tlbl = newiTempLabel (NULL);
6023           gencjneshort (left, right, tlbl);
6024           if (IC_TRUE (ifx))
6025             {
6026               freeForBranchAsmop (result);
6027               freeForBranchAsmop (right);
6028               freeForBranchAsmop (left);
6029               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6030               emitcode ("", "%05d$:", tlbl->key + 100);
6031             }
6032           else
6033             {
6034               symbol *lbl = newiTempLabel (NULL);
6035               emitcode ("sjmp", "%05d$", lbl->key + 100);
6036               emitcode ("", "%05d$:", tlbl->key + 100);
6037               freeForBranchAsmop (result);
6038               freeForBranchAsmop (right);
6039               freeForBranchAsmop (left);
6040               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6041               emitcode ("", "%05d$:", lbl->key + 100);
6042             }
6043         }
6044       /* mark the icode as generated */
6045       ifx->generated = 1;
6046       goto release;
6047     }
6048
6049   /* if they are both bit variables */
6050   if (AOP_TYPE (left) == AOP_CRY &&
6051       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6052     {
6053       if (AOP_TYPE (right) == AOP_LIT)
6054         {
6055           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6056           if (lit == 0L)
6057             {
6058               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6059               emitcode ("cpl", "c");
6060             }
6061           else if (lit == 1L)
6062             {
6063               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6064             }
6065           else
6066             {
6067               emitcode ("clr", "c");
6068             }
6069           /* AOP_TYPE(right) == AOP_CRY */
6070         }
6071       else
6072         {
6073           symbol *lbl = newiTempLabel (NULL);
6074           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6075           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6076           emitcode ("cpl", "c");
6077           emitcode ("", "%05d$:", (lbl->key + 100));
6078         }
6079       /* c = 1 if egal */
6080       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6081         {
6082           outBitC (result);
6083           goto release;
6084         }
6085       if (ifx)
6086         {
6087           genIfxJump (ifx, "c", left, right, result);
6088           goto release;
6089         }
6090       /* if the result is used in an arithmetic operation
6091          then put the result in place */
6092       outBitC (result);
6093     }
6094   else
6095     {
6096       gencjne (left, right, newiTempLabel (NULL));
6097       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6098         {
6099           aopPut (result, "a", 0);
6100           goto release;
6101         }
6102       if (ifx)
6103         {
6104           genIfxJump (ifx, "a", left, right, result);
6105           goto release;
6106         }
6107       /* if the result is used in an arithmetic operation
6108          then put the result in place */
6109       if (AOP_TYPE (result) != AOP_CRY)
6110         outAcc (result);
6111       /* leave the result in acc */
6112     }
6113
6114 release:
6115   freeAsmop (result, NULL, ic, TRUE);
6116   if (!swappedLR)
6117     {
6118       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6119       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6120     }
6121   else
6122     {
6123       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6124       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6125     }
6126 }
6127
6128 /*-----------------------------------------------------------------*/
6129 /* ifxForOp - returns the icode containing the ifx for operand     */
6130 /*-----------------------------------------------------------------*/
6131 static iCode *
6132 ifxForOp (operand * op, iCode * ic)
6133 {
6134   /* if true symbol then needs to be assigned */
6135   if (IS_TRUE_SYMOP (op))
6136     return NULL;
6137
6138   /* if this has register type condition and
6139      the next instruction is ifx with the same operand
6140      and live to of the operand is upto the ifx only then */
6141   if (ic->next &&
6142       ic->next->op == IFX &&
6143       IC_COND (ic->next)->key == op->key &&
6144       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6145     return ic->next;
6146
6147   return NULL;
6148 }
6149
6150 /*-----------------------------------------------------------------*/
6151 /* hasInc - operand is incremented before any other use            */
6152 /*-----------------------------------------------------------------*/
6153 static iCode *
6154 hasInc (operand *op, iCode *ic,int osize)
6155 {
6156   sym_link *type = operandType(op);
6157   sym_link *retype = getSpec (type);
6158   iCode *lic = ic->next;
6159   int isize ;
6160
6161   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6162   if (!IS_SYMOP(op)) return NULL;
6163
6164   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6165   if (IS_AGGREGATE(type->next)) return NULL;
6166   if (osize != (isize = getSize(type->next))) return NULL;
6167
6168   while (lic) {
6169     /* if operand of the form op = op + <sizeof *op> */
6170     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6171         isOperandEqual(IC_RESULT(lic),op) &&
6172         isOperandLiteral(IC_RIGHT(lic)) &&
6173         operandLitValue(IC_RIGHT(lic)) == isize) {
6174       return lic;
6175     }
6176     /* if the operand used or deffed */
6177     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6178       return NULL;
6179     }
6180     /* if GOTO or IFX */
6181     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6182     lic = lic->next;
6183   }
6184   return NULL;
6185 }
6186
6187 /*-----------------------------------------------------------------*/
6188 /* genAndOp - for && operation                                     */
6189 /*-----------------------------------------------------------------*/
6190 static void
6191 genAndOp (iCode * ic)
6192 {
6193   operand *left, *right, *result;
6194   symbol *tlbl;
6195
6196   D(emitcode (";     genAndOp",""));
6197
6198   /* note here that && operations that are in an
6199      if statement are taken away by backPatchLabels
6200      only those used in arthmetic operations remain */
6201   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6202   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6203   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6204
6205   /* if both are bit variables */
6206   if (AOP_TYPE (left) == AOP_CRY &&
6207       AOP_TYPE (right) == AOP_CRY)
6208     {
6209       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6210       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6211       outBitC (result);
6212     }
6213   else
6214     {
6215       tlbl = newiTempLabel (NULL);
6216       toBoolean (left);
6217       emitcode ("jz", "%05d$", tlbl->key + 100);
6218       toBoolean (right);
6219       emitcode ("", "%05d$:", tlbl->key + 100);
6220       outBitAcc (result);
6221     }
6222
6223   freeAsmop (result, NULL, ic, TRUE);
6224   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6225   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6226 }
6227
6228
6229 /*-----------------------------------------------------------------*/
6230 /* genOrOp - for || operation                                      */
6231 /*-----------------------------------------------------------------*/
6232 static void
6233 genOrOp (iCode * ic)
6234 {
6235   operand *left, *right, *result;
6236   symbol *tlbl;
6237
6238   D(emitcode (";     genOrOp",""));
6239
6240   /* note here that || operations that are in an
6241      if statement are taken away by backPatchLabels
6242      only those used in arthmetic operations remain */
6243   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6244   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6245   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6246
6247   /* if both are bit variables */
6248   if (AOP_TYPE (left) == AOP_CRY &&
6249       AOP_TYPE (right) == AOP_CRY)
6250     {
6251       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6252       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6253       outBitC (result);
6254     }
6255   else
6256     {
6257       tlbl = newiTempLabel (NULL);
6258       toBoolean (left);
6259       emitcode ("jnz", "%05d$", tlbl->key + 100);
6260       toBoolean (right);
6261       emitcode ("", "%05d$:", tlbl->key + 100);
6262       outBitAcc (result);
6263     }
6264
6265   freeAsmop (result, NULL, ic, TRUE);
6266   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6267   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6268 }
6269
6270 /*-----------------------------------------------------------------*/
6271 /* isLiteralBit - test if lit == 2^n                               */
6272 /*-----------------------------------------------------------------*/
6273 static int
6274 isLiteralBit (unsigned long lit)
6275 {
6276   unsigned long pw[32] =
6277   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6278    0x100L, 0x200L, 0x400L, 0x800L,
6279    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6280    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6281    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6282    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6283    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6284   int idx;
6285
6286   for (idx = 0; idx < 32; idx++)
6287     if (lit == pw[idx])
6288       return idx + 1;
6289   return 0;
6290 }
6291
6292 /*-----------------------------------------------------------------*/
6293 /* continueIfTrue -                                                */
6294 /*-----------------------------------------------------------------*/
6295 static void
6296 continueIfTrue (iCode * ic)
6297 {
6298   if (IC_TRUE (ic))
6299     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6300   ic->generated = 1;
6301 }
6302
6303 /*-----------------------------------------------------------------*/
6304 /* jmpIfTrue -                                                     */
6305 /*-----------------------------------------------------------------*/
6306 static void
6307 jumpIfTrue (iCode * ic)
6308 {
6309   if (!IC_TRUE (ic))
6310     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6311   ic->generated = 1;
6312 }
6313
6314 /*-----------------------------------------------------------------*/
6315 /* jmpTrueOrFalse -                                                */
6316 /*-----------------------------------------------------------------*/
6317 static void
6318 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6319 {
6320   // ugly but optimized by peephole
6321   if (IC_TRUE (ic))
6322     {
6323       symbol *nlbl = newiTempLabel (NULL);
6324       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6325       emitcode ("", "%05d$:", tlbl->key + 100);
6326       freeForBranchAsmop (result);
6327       freeForBranchAsmop (right);
6328       freeForBranchAsmop (left);
6329       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6330       emitcode ("", "%05d$:", nlbl->key + 100);
6331     }
6332   else
6333     {
6334       freeForBranchAsmop (result);
6335       freeForBranchAsmop (right);
6336       freeForBranchAsmop (left);
6337       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6338       emitcode ("", "%05d$:", tlbl->key + 100);
6339     }
6340   ic->generated = 1;
6341 }
6342
6343 /*-----------------------------------------------------------------*/
6344 /* genAnd  - code for and                                          */
6345 /*-----------------------------------------------------------------*/
6346 static void
6347 genAnd (iCode * ic, iCode * ifx)
6348 {
6349   operand *left, *right, *result;
6350   int size, offset = 0;
6351   unsigned long lit = 0L;
6352   int bytelit = 0;
6353   char buffer[10];
6354
6355   D(emitcode (";     genAnd",""));
6356
6357   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6358   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6359   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6360
6361 #ifdef DEBUG_TYPE
6362   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6363             AOP_TYPE (result),
6364             AOP_TYPE (left), AOP_TYPE (right));
6365   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6366             AOP_SIZE (result),
6367             AOP_SIZE (left), AOP_SIZE (right));
6368 #endif
6369
6370   /* if left is a literal & right is not then exchange them */
6371   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6372       AOP_NEEDSACC (left))
6373     {
6374       operand *tmp = right;
6375       right = left;
6376       left = tmp;
6377     }
6378
6379   /* if result = right then exchange left and right */
6380   if (sameRegs (AOP (result), AOP (right)))
6381     {
6382       operand *tmp = right;
6383       right = left;
6384       left = tmp;
6385     }
6386
6387   /* if right is bit then exchange them */
6388   if (AOP_TYPE (right) == AOP_CRY &&
6389       AOP_TYPE (left) != AOP_CRY)
6390     {
6391       operand *tmp = right;
6392       right = left;
6393       left = tmp;
6394     }
6395   if (AOP_TYPE (right) == AOP_LIT)
6396     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6397
6398   size = AOP_SIZE (result);
6399
6400   // if(bit & yy)
6401   // result = bit & yy;
6402   if (AOP_TYPE (left) == AOP_CRY)
6403     {
6404       // c = bit & literal;
6405       if (AOP_TYPE (right) == AOP_LIT)
6406         {
6407           if (lit & 1)
6408             {
6409               if (size && sameRegs (AOP (result), AOP (left)))
6410                 // no change
6411                 goto release;
6412               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6413             }
6414           else
6415             {
6416               // bit(result) = 0;
6417               if (size && (AOP_TYPE (result) == AOP_CRY))
6418                 {
6419                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6420                   goto release;
6421                 }
6422               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6423                 {
6424                   jumpIfTrue (ifx);
6425                   goto release;
6426                 }
6427               emitcode ("clr", "c");
6428             }
6429         }
6430       else
6431         {
6432           if (AOP_TYPE (right) == AOP_CRY)
6433             {
6434               // c = bit & bit;
6435               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6436               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6437             }
6438           else
6439             {
6440               // c = bit & val;
6441               MOVA (aopGet (right, 0, FALSE, FALSE));
6442               // c = lsb
6443               emitcode ("rrc", "a");
6444               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6445             }
6446         }
6447       // bit = c
6448       // val = c
6449       if (size)
6450         outBitC (result);
6451       // if(bit & ...)
6452       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6453         genIfxJump (ifx, "c", left, right, result);
6454       goto release;
6455     }
6456
6457   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6458   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6459   if ((AOP_TYPE (right) == AOP_LIT) &&
6460       (AOP_TYPE (result) == AOP_CRY) &&
6461       (AOP_TYPE (left) != AOP_CRY))
6462     {
6463       int posbit = isLiteralBit (lit);
6464       /* left &  2^n */
6465       if (posbit)
6466         {
6467           posbit--;
6468           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6469           // bit = left & 2^n
6470           if (size)
6471             {
6472               switch (posbit & 0x07)
6473                 {
6474                   case 0: emitcode ("rrc", "a");
6475                           break;
6476                   case 7: emitcode ("rlc", "a");
6477                           break;
6478                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6479                           break;
6480                 }
6481             }
6482           // if(left &  2^n)
6483           else
6484             {
6485               if (ifx)
6486                 {
6487                   SNPRINTF (buffer, sizeof(buffer),
6488                             "acc.%d", posbit & 0x07);
6489                   genIfxJump (ifx, buffer, left, right, result);
6490                 }
6491               else
6492                 {// what is this case? just found it in ds390/gen.c
6493                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6494                 }
6495               goto release;
6496             }
6497         }
6498       else
6499         {
6500           symbol *tlbl = newiTempLabel (NULL);
6501           int sizel = AOP_SIZE (left);
6502           if (size)
6503             emitcode ("setb", "c");
6504           while (sizel--)
6505             {
6506               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6507                 {
6508                   MOVA (aopGet (left, offset, FALSE, FALSE));
6509                   // byte ==  2^n ?
6510                   if ((posbit = isLiteralBit (bytelit)) != 0)
6511                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6512                   else
6513                     {
6514                       if (bytelit != 0x0FFL)
6515                         emitcode ("anl", "a,%s",
6516                                   aopGet (right, offset, FALSE, TRUE));
6517                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6518                     }
6519                 }
6520               offset++;
6521             }
6522           // bit = left & literal
6523           if (size)
6524             {
6525               emitcode ("clr", "c");
6526               emitcode ("", "%05d$:", tlbl->key + 100);
6527             }
6528           // if(left & literal)
6529           else
6530             {
6531               if (ifx)
6532                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6533               else
6534                 emitcode ("", "%05d$:", tlbl->key + 100);
6535               goto release;
6536             }
6537         }
6538       outBitC (result);
6539       goto release;
6540     }
6541
6542   /* if left is same as result */
6543   if (sameRegs (AOP (result), AOP (left)))
6544     {
6545       for (; size--; offset++)
6546         {
6547           if (AOP_TYPE (right) == AOP_LIT)
6548             {
6549               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6550               if (bytelit == 0x0FF)
6551                 {
6552                   /* dummy read of volatile operand */
6553                   if (isOperandVolatile (left, FALSE))
6554                     MOVA (aopGet (left, offset, FALSE, FALSE));
6555                   else
6556                     continue;
6557                 }
6558               else if (bytelit == 0)
6559                 {
6560                   aopPut (result, zero, offset);
6561                 }
6562               else if (IS_AOP_PREG (result))
6563                 {
6564                   MOVA (aopGet (left, offset, FALSE, TRUE));
6565                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6566                   aopPut (result, "a", offset);
6567                 }
6568               else
6569                 emitcode ("anl", "%s,%s",
6570                           aopGet (left, offset, FALSE, TRUE),
6571                           aopGet (right, offset, FALSE, FALSE));
6572             }
6573           else
6574             {
6575               if (AOP_TYPE (left) == AOP_ACC)
6576                 {
6577                   if (offset)
6578                     emitcode("mov", "a,b");
6579                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6580                 }
6581               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6582                 {
6583                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6584                   MOVA (aopGet (right, offset, FALSE, FALSE));
6585                   emitcode ("anl", "a,b");
6586                   aopPut (result, "a", offset);
6587                 }
6588               else if (aopGetUsesAcc (left, offset))
6589                 {
6590                   MOVA (aopGet (left, offset, FALSE, FALSE));
6591                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6592                   aopPut (result, "a", offset);
6593                 }
6594               else
6595                 {
6596                   MOVA (aopGet (right, offset, FALSE, FALSE));
6597                   if (IS_AOP_PREG (result))
6598                     {
6599                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6600                       aopPut (result, "a", offset);
6601                     }
6602                   else
6603                     emitcode ("anl", "%s,a",
6604                               aopGet (left, offset, FALSE, TRUE));
6605                 }
6606             }
6607         }
6608     }
6609   else
6610     {
6611       // left & result in different registers
6612       if (AOP_TYPE (result) == AOP_CRY)
6613         {
6614           // result = bit
6615           // if(size), result in bit
6616           // if(!size && ifx), conditional oper: if(left & right)
6617           symbol *tlbl = newiTempLabel (NULL);
6618           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6619           if (size)
6620             emitcode ("setb", "c");
6621           while (sizer--)
6622             {
6623               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6624                   && AOP_TYPE(left)==AOP_ACC)
6625                 {
6626                   if (offset)
6627                     emitcode("mov", "a,b");
6628                   emitcode ("anl", "a,%s",
6629                             aopGet (right, offset, FALSE, FALSE));
6630                 } else {
6631                   if (AOP_TYPE(left)==AOP_ACC)
6632                     {
6633                       if (!offset)
6634                         {
6635                           bool pushedB = pushB ();
6636                           emitcode("mov", "b,a");
6637                           MOVA (aopGet (right, offset, FALSE, FALSE));
6638                           emitcode("anl", "a,b");
6639                           popB (pushedB);
6640                         }
6641                       else
6642                         {
6643                           MOVA (aopGet (right, offset, FALSE, FALSE));
6644                           emitcode("anl", "a,b");
6645                         }
6646                     } else {
6647                       MOVA (aopGet (right, offset, FALSE, FALSE));
6648                       emitcode ("anl", "a,%s",
6649                                 aopGet (left, offset, FALSE, FALSE));
6650                     }
6651                 }
6652               emitcode ("jnz", "%05d$", tlbl->key + 100);
6653               offset++;
6654             }
6655           if (size)
6656             {
6657               CLRC;
6658               emitcode ("", "%05d$:", tlbl->key + 100);
6659               outBitC (result);
6660             }
6661           else if (ifx)
6662             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6663           else
6664             emitcode ("", "%05d$:", tlbl->key + 100);
6665         }
6666       else
6667         {
6668           for (; (size--); offset++)
6669             {
6670               // normal case
6671               // result = left & right
6672               if (AOP_TYPE (right) == AOP_LIT)
6673                 {
6674                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6675                   if (bytelit == 0x0FF)
6676                     {
6677                       aopPut (result,
6678                               aopGet (left, offset, FALSE, FALSE),
6679                               offset);
6680                       continue;
6681                     }
6682                   else if (bytelit == 0)
6683                     {
6684                       /* dummy read of volatile operand */
6685                       if (isOperandVolatile (left, FALSE))
6686                         MOVA (aopGet (left, offset, FALSE, FALSE));
6687                       aopPut (result, zero, offset);
6688                       continue;
6689                     }
6690                   else if (AOP_TYPE (left) == AOP_ACC)
6691                     {
6692                       if (!offset)
6693                         {
6694                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6695                           aopPut (result, "a", offset);
6696                           continue;
6697                         }
6698                       else
6699                         {
6700                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6701                           aopPut (result, "b", offset);
6702                           continue;
6703                         }
6704                     }
6705                 }
6706               // faster than result <- left, anl result,right
6707               // and better if result is SFR
6708               if (AOP_TYPE (left) == AOP_ACC)
6709                 {
6710                   if (offset)
6711                     emitcode("mov", "a,b");
6712                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6713                 }
6714               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6715                 {
6716                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6717                   MOVA (aopGet (right, offset, FALSE, FALSE));
6718                   emitcode ("anl", "a,b");
6719                 }
6720               else if (aopGetUsesAcc (left, offset))
6721                 {
6722                   MOVA (aopGet (left, offset, FALSE, FALSE));
6723                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6724                 }
6725               else
6726                 {
6727                   MOVA (aopGet (right, offset, FALSE, FALSE));
6728                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6729                 }
6730               aopPut (result, "a", offset);
6731             }
6732         }
6733     }
6734
6735 release:
6736   freeAsmop (result, NULL, ic, TRUE);
6737   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6738   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6739 }
6740
6741 /*-----------------------------------------------------------------*/
6742 /* genOr  - code for or                                            */
6743 /*-----------------------------------------------------------------*/
6744 static void
6745 genOr (iCode * ic, iCode * ifx)
6746 {
6747   operand *left, *right, *result;
6748   int size, offset = 0;
6749   unsigned long lit = 0L;
6750   int bytelit = 0;
6751
6752   D(emitcode (";     genOr",""));
6753
6754   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6755   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6756   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6757
6758 #ifdef DEBUG_TYPE
6759   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6760             AOP_TYPE (result),
6761             AOP_TYPE (left), AOP_TYPE (right));
6762   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6763             AOP_SIZE (result),
6764             AOP_SIZE (left), AOP_SIZE (right));
6765 #endif
6766
6767   /* if left is a literal & right is not then exchange them */
6768   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6769       AOP_NEEDSACC (left))
6770     {
6771       operand *tmp = right;
6772       right = left;
6773       left = tmp;
6774     }
6775
6776   /* if result = right then exchange them */
6777   if (sameRegs (AOP (result), AOP (right)))
6778     {
6779       operand *tmp = right;
6780       right = left;
6781       left = tmp;
6782     }
6783
6784   /* if right is bit then exchange them */
6785   if (AOP_TYPE (right) == AOP_CRY &&
6786       AOP_TYPE (left) != AOP_CRY)
6787     {
6788       operand *tmp = right;
6789       right = left;
6790       left = tmp;
6791     }
6792   if (AOP_TYPE (right) == AOP_LIT)
6793     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6794
6795   size = AOP_SIZE (result);
6796
6797   // if(bit | yy)
6798   // xx = bit | yy;
6799   if (AOP_TYPE (left) == AOP_CRY)
6800     {
6801       if (AOP_TYPE (right) == AOP_LIT)
6802         {
6803           // c = bit | literal;
6804           if (lit)
6805             {
6806               // lit != 0 => result = 1
6807               if (AOP_TYPE (result) == AOP_CRY)
6808                 {
6809                   if (size)
6810                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6811                   else if (ifx)
6812                     continueIfTrue (ifx);
6813                   goto release;
6814                 }
6815               emitcode ("setb", "c");
6816             }
6817           else
6818             {
6819               // lit == 0 => result = left
6820               if (size && sameRegs (AOP (result), AOP (left)))
6821                 goto release;
6822               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6823             }
6824         }
6825       else
6826         {
6827           if (AOP_TYPE (right) == AOP_CRY)
6828             {
6829               // c = bit | bit;
6830               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6831               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6832             }
6833           else
6834             {
6835               // c = bit | val;
6836               symbol *tlbl = newiTempLabel (NULL);
6837               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6838                 emitcode ("setb", "c");
6839               emitcode ("jb", "%s,%05d$",
6840                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6841               toBoolean (right);
6842               emitcode ("jnz", "%05d$", tlbl->key + 100);
6843               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6844                 {
6845                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6846                   goto release;
6847                 }
6848               else
6849                 {
6850                   CLRC;
6851                   emitcode ("", "%05d$:", tlbl->key + 100);
6852                 }
6853             }
6854         }
6855       // bit = c
6856       // val = c
6857       if (size)
6858         outBitC (result);
6859       // if(bit | ...)
6860       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6861         genIfxJump (ifx, "c", left, right, result);
6862       goto release;
6863     }
6864
6865   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6866   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6867   if ((AOP_TYPE (right) == AOP_LIT) &&
6868       (AOP_TYPE (result) == AOP_CRY) &&
6869       (AOP_TYPE (left) != AOP_CRY))
6870     {
6871       if (lit)
6872         {
6873           // result = 1
6874           if (size)
6875             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6876           else
6877             continueIfTrue (ifx);
6878           goto release;
6879         }
6880       else
6881         {
6882           // lit = 0, result = boolean(left)
6883           if (size)
6884             emitcode ("setb", "c");
6885           toBoolean (right);
6886           if (size)
6887             {
6888               symbol *tlbl = newiTempLabel (NULL);
6889               emitcode ("jnz", "%05d$", tlbl->key + 100);
6890               CLRC;
6891               emitcode ("", "%05d$:", tlbl->key + 100);
6892             }
6893           else
6894             {
6895               genIfxJump (ifx, "a", left, right, result);
6896               goto release;
6897             }
6898         }
6899       outBitC (result);
6900       goto release;
6901     }
6902
6903   /* if left is same as result */
6904   if (sameRegs (AOP (result), AOP (left)))
6905     {
6906       for (; size--; offset++)
6907         {
6908           if (AOP_TYPE (right) == AOP_LIT)
6909             {
6910               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6911               if (bytelit == 0)
6912                 {
6913                   /* dummy read of volatile operand */
6914                   if (isOperandVolatile (left, FALSE))
6915                     MOVA (aopGet (left, offset, FALSE, FALSE));
6916                   else
6917                     continue;
6918                 }
6919               else if (bytelit == 0x0FF)
6920                 {
6921                   aopPut (result, "#0xFF", offset);
6922                 }
6923               else if (IS_AOP_PREG (left))
6924                 {
6925                   MOVA (aopGet (left, offset, FALSE, TRUE));
6926                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6927                   aopPut (result, "a", offset);
6928                 }
6929               else
6930                 {
6931                   emitcode ("orl", "%s,%s",
6932                             aopGet (left, offset, FALSE, TRUE),
6933                             aopGet (right, offset, FALSE, FALSE));
6934                 }
6935             }
6936           else
6937             {
6938               if (AOP_TYPE (left) == AOP_ACC)
6939                 {
6940                   if (offset)
6941                     emitcode("mov", "a,b");
6942                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6943                 }
6944               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6945                 {
6946                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6947                   MOVA (aopGet (right, offset, FALSE, FALSE));
6948                   emitcode ("orl", "a,b");
6949                   aopPut (result, "a", offset);
6950                 }
6951               else if (aopGetUsesAcc (left, offset))
6952                 {
6953                   MOVA (aopGet (left, offset, FALSE, FALSE));
6954                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6955                   aopPut (result, "a", offset);
6956                 }
6957               else
6958                 {
6959                   MOVA (aopGet (right, offset, FALSE, FALSE));
6960                   if (IS_AOP_PREG (left))
6961                     {
6962                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6963                       aopPut (result, "a", offset);
6964                     }
6965                   else
6966                     {
6967                       emitcode ("orl", "%s,a",
6968                                 aopGet (left, offset, FALSE, TRUE));
6969                     }
6970                 }
6971             }
6972         }
6973     }
6974   else
6975     {
6976       // left & result in different registers
6977       if (AOP_TYPE (result) == AOP_CRY)
6978         {
6979           // result = bit
6980           // if(size), result in bit
6981           // if(!size && ifx), conditional oper: if(left | right)
6982           symbol *tlbl = newiTempLabel (NULL);
6983           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6984           if (size)
6985             emitcode ("setb", "c");
6986           while (sizer--)
6987             {
6988               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6989                 if (offset)
6990                   emitcode("mov", "a,b");
6991                 emitcode ("orl", "a,%s",
6992                           aopGet (right, offset, FALSE, FALSE));
6993               } else {
6994                 MOVA (aopGet (right, offset, FALSE, FALSE));
6995                 emitcode ("orl", "a,%s",
6996                           aopGet (left, offset, FALSE, FALSE));
6997               }
6998               emitcode ("jnz", "%05d$", tlbl->key + 100);
6999               offset++;
7000             }
7001           if (size)
7002             {
7003               CLRC;
7004               emitcode ("", "%05d$:", tlbl->key + 100);
7005               outBitC (result);
7006             }
7007           else if (ifx)
7008             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7009           else
7010             emitcode ("", "%05d$:", tlbl->key + 100);
7011         }
7012       else
7013         {
7014           for (; (size--); offset++)
7015             {
7016               // normal case
7017               // result = left | right
7018               if (AOP_TYPE (right) == AOP_LIT)
7019                 {
7020                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7021                   if (bytelit == 0)
7022                     {
7023                       aopPut (result,
7024                               aopGet (left, offset, FALSE, FALSE),
7025                               offset);
7026                       continue;
7027                     }
7028                   else if (bytelit == 0x0FF)
7029                     {
7030                       /* dummy read of volatile operand */
7031                       if (isOperandVolatile (left, FALSE))
7032                         MOVA (aopGet (left, offset, FALSE, FALSE));
7033                       aopPut (result, "#0xFF", offset);
7034                       continue;
7035                     }
7036                 }
7037               // faster than result <- left, anl result,right
7038               // and better if result is SFR
7039               if (AOP_TYPE (left) == AOP_ACC)
7040                 {
7041                   if (offset)
7042                     emitcode("mov", "a,b");
7043                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7044                 }
7045               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7046                 {
7047                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7048                   MOVA (aopGet (right, offset, FALSE, FALSE));
7049                   emitcode ("orl", "a,b");
7050                 }
7051               else if (aopGetUsesAcc (left, offset))
7052                 {
7053                   MOVA (aopGet (left, offset, FALSE, FALSE));
7054                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7055                 }
7056               else
7057                 {
7058                   MOVA (aopGet (right, offset, FALSE, FALSE));
7059                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7060                 }
7061               aopPut (result, "a", offset);
7062             }
7063         }
7064     }
7065
7066 release:
7067   freeAsmop (result, NULL, ic, TRUE);
7068   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7069   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7070 }
7071
7072 /*-----------------------------------------------------------------*/
7073 /* genXor - code for xclusive or                                   */
7074 /*-----------------------------------------------------------------*/
7075 static void
7076 genXor (iCode * ic, iCode * ifx)
7077 {
7078   operand *left, *right, *result;
7079   int size, offset = 0;
7080   unsigned long lit = 0L;
7081   int bytelit = 0;
7082
7083   D(emitcode (";     genXor",""));
7084
7085   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7086   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7087   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7088
7089 #ifdef DEBUG_TYPE
7090   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7091             AOP_TYPE (result),
7092             AOP_TYPE (left), AOP_TYPE (right));
7093   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7094             AOP_SIZE (result),
7095             AOP_SIZE (left), AOP_SIZE (right));
7096 #endif
7097
7098   /* if left is a literal & right is not ||
7099      if left needs acc & right does not */
7100   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7101       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7102     {
7103       operand *tmp = right;
7104       right = left;
7105       left = tmp;
7106     }
7107
7108   /* if result = right then exchange them */
7109   if (sameRegs (AOP (result), AOP (right)))
7110     {
7111       operand *tmp = right;
7112       right = left;
7113       left = tmp;
7114     }
7115
7116   /* if right is bit then exchange them */
7117   if (AOP_TYPE (right) == AOP_CRY &&
7118       AOP_TYPE (left) != AOP_CRY)
7119     {
7120       operand *tmp = right;
7121       right = left;
7122       left = tmp;
7123     }
7124   if (AOP_TYPE (right) == AOP_LIT)
7125     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7126
7127   size = AOP_SIZE (result);
7128
7129   // if(bit ^ yy)
7130   // xx = bit ^ yy;
7131   if (AOP_TYPE (left) == AOP_CRY)
7132     {
7133       if (AOP_TYPE (right) == AOP_LIT)
7134         {
7135           // c = bit & literal;
7136           if (lit >> 1)
7137             {
7138               // lit>>1  != 0 => result = 1
7139               if (AOP_TYPE (result) == AOP_CRY)
7140                 {
7141                   if (size)
7142                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7143                   else if (ifx)
7144                     continueIfTrue (ifx);
7145                   goto release;
7146                 }
7147               emitcode ("setb", "c");
7148             }
7149           else
7150             {
7151               // lit == (0 or 1)
7152               if (lit == 0)
7153                 {
7154                   // lit == 0, result = left
7155                   if (size && sameRegs (AOP (result), AOP (left)))
7156                     goto release;
7157                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7158                 }
7159               else
7160                 {
7161                   // lit == 1, result = not(left)
7162                   if (size && sameRegs (AOP (result), AOP (left)))
7163                     {
7164                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7165                       goto release;
7166                     }
7167                   else
7168                     {
7169                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7170                       emitcode ("cpl", "c");
7171                     }
7172                 }
7173             }
7174
7175         }
7176       else
7177         {
7178           // right != literal
7179           symbol *tlbl = newiTempLabel (NULL);
7180           if (AOP_TYPE (right) == AOP_CRY)
7181             {
7182               // c = bit ^ bit;
7183               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7184             }
7185           else
7186             {
7187               int sizer = AOP_SIZE (right);
7188               // c = bit ^ val
7189               // if val>>1 != 0, result = 1
7190               emitcode ("setb", "c");
7191               while (sizer)
7192                 {
7193                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7194                   if (sizer == 1)
7195                     // test the msb of the lsb
7196                     emitcode ("anl", "a,#0xfe");
7197                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7198                   sizer--;
7199                 }
7200               // val = (0,1)
7201               emitcode ("rrc", "a");
7202             }
7203           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7204           emitcode ("cpl", "c");
7205           emitcode ("", "%05d$:", (tlbl->key + 100));
7206         }
7207       // bit = c
7208       // val = c
7209       if (size)
7210         outBitC (result);
7211       // if(bit | ...)
7212       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7213         genIfxJump (ifx, "c", left, right, result);
7214       goto release;
7215     }
7216
7217   /* if left is same as result */
7218   if (sameRegs (AOP (result), AOP (left)))
7219     {
7220       for (; size--; offset++)
7221         {
7222           if (AOP_TYPE (right) == AOP_LIT)
7223             {
7224               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7225               if (bytelit == 0)
7226                 {
7227                   /* dummy read of volatile operand */
7228                   if (isOperandVolatile (left, FALSE))
7229                     MOVA (aopGet (left, offset, FALSE, FALSE));
7230                   else
7231                     continue;
7232                 }
7233               else if (IS_AOP_PREG (left))
7234                 {
7235                   MOVA (aopGet (left, offset, FALSE, TRUE));
7236                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7237                   aopPut (result, "a", offset);
7238                 }
7239               else
7240                 {
7241                   emitcode ("xrl", "%s,%s",
7242                             aopGet (left, offset, FALSE, TRUE),
7243                             aopGet (right, offset, FALSE, FALSE));
7244                 }
7245             }
7246           else
7247             {
7248               if (AOP_TYPE (left) == AOP_ACC)
7249                 {
7250                   if (offset)
7251                     emitcode("mov", "a,b");
7252                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7253                 }
7254               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7255                 {
7256                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7257                   MOVA (aopGet (right, offset, FALSE, FALSE));
7258                   emitcode ("xrl", "a,b");
7259                   aopPut (result, "a", offset);
7260                 }
7261               else if (aopGetUsesAcc (left, offset))
7262                 {
7263                   MOVA (aopGet (left, offset, FALSE, FALSE));
7264                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7265                   aopPut (result, "a", offset);
7266                 }
7267               else
7268                 {
7269                   MOVA (aopGet (right, offset, FALSE, FALSE));
7270                   if (IS_AOP_PREG (left))
7271                     {
7272                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7273                       aopPut (result, "a", offset);
7274                     }
7275                   else
7276                     emitcode ("xrl", "%s,a",
7277                               aopGet (left, offset, FALSE, TRUE));
7278                 }
7279             }
7280         }
7281     }
7282   else
7283     {
7284       // left & result in different registers
7285       if (AOP_TYPE (result) == AOP_CRY)
7286         {
7287           // result = bit
7288           // if(size), result in bit
7289           // if(!size && ifx), conditional oper: if(left ^ right)
7290           symbol *tlbl = newiTempLabel (NULL);
7291           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7292           if (size)
7293             emitcode ("setb", "c");
7294           while (sizer--)
7295             {
7296               if ((AOP_TYPE (right) == AOP_LIT) &&
7297                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7298                 {
7299                   MOVA (aopGet (left, offset, FALSE, FALSE));
7300                 }
7301               else
7302                 {
7303                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7304                     if (offset)
7305                       emitcode("mov", "a,b");
7306                     emitcode ("xrl", "a,%s",
7307                               aopGet (right, offset, FALSE, FALSE));
7308                   } else {
7309                     MOVA (aopGet (right, offset, FALSE, FALSE));
7310                     emitcode ("xrl", "a,%s",
7311                               aopGet (left, offset, FALSE, FALSE));
7312                   }
7313                 }
7314               emitcode ("jnz", "%05d$", tlbl->key + 100);
7315               offset++;
7316             }
7317           if (size)
7318             {
7319               CLRC;
7320               emitcode ("", "%05d$:", tlbl->key + 100);
7321               outBitC (result);
7322             }
7323           else if (ifx)
7324             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7325         }
7326       else
7327         {
7328           for (; (size--); offset++)
7329             {
7330               // normal case
7331               // result = left & right
7332               if (AOP_TYPE (right) == AOP_LIT)
7333                 {
7334                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7335                   if (bytelit == 0)
7336                     {
7337                       aopPut (result,
7338                               aopGet (left, offset, FALSE, FALSE),
7339                               offset);
7340                       continue;
7341                     }
7342                 }
7343               // faster than result <- left, anl result,right
7344               // and better if result is SFR
7345               if (AOP_TYPE (left) == AOP_ACC)
7346                 {
7347                   if (offset)
7348                     emitcode("mov", "a,b");
7349                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7350                 }
7351               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7352                 {
7353                   emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7354                   MOVA (aopGet (right, offset, FALSE, FALSE));
7355                   emitcode ("xrl", "a,b");
7356                 }
7357               else if (aopGetUsesAcc (left, offset))
7358                 {
7359                   MOVA (aopGet (left, offset, FALSE, FALSE));
7360                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7361                 }
7362               else
7363                 {
7364                   MOVA (aopGet (right, offset, FALSE, FALSE));
7365                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7366                 }
7367               aopPut (result, "a", offset);
7368             }
7369         }
7370     }
7371
7372 release:
7373   freeAsmop (result, NULL, ic, TRUE);
7374   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7375   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7376 }
7377
7378 /*-----------------------------------------------------------------*/
7379 /* genInline - write the inline code out                           */
7380 /*-----------------------------------------------------------------*/
7381 static void
7382 genInline (iCode * ic)
7383 {
7384   char *buffer, *bp, *bp1;
7385
7386   D (emitcode (";", "genInline"));
7387
7388   _G.inLine += (!options.asmpeep);
7389
7390   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7391
7392   /* emit each line as a code */
7393   while (*bp)
7394     {
7395       if (*bp == '\n')
7396         {
7397           *bp++ = '\0';
7398           emitcode (bp1, "");
7399           bp1 = bp;
7400         }
7401       else
7402         {
7403           /* Add \n for labels, not dirs such as c:\mydir */
7404           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7405             {
7406               bp++;
7407               *bp = '\0';
7408               bp++;
7409               emitcode (bp1, "");
7410               bp1 = bp;
7411             }
7412           else
7413             bp++;
7414         }
7415     }
7416   if (bp1 != bp)
7417     emitcode (bp1, "");
7418   /*     emitcode("",buffer); */
7419   _G.inLine -= (!options.asmpeep);
7420 }
7421
7422 /*-----------------------------------------------------------------*/
7423 /* genRRC - rotate right with carry                                */
7424 /*-----------------------------------------------------------------*/
7425 static void
7426 genRRC (iCode * ic)
7427 {
7428   operand *left, *result;
7429   int size, offset = 0;
7430   char *l;
7431
7432   D(emitcode (";     genRRC",""));
7433
7434   /* rotate right with carry */
7435   left = IC_LEFT (ic);
7436   result = IC_RESULT (ic);
7437   aopOp (left, ic, FALSE);
7438   aopOp (result, ic, FALSE);
7439
7440   /* move it to the result */
7441   size = AOP_SIZE (result);
7442   offset = size - 1;
7443   if (size == 1) { /* special case for 1 byte */
7444       l = aopGet (left, offset, FALSE, FALSE);
7445       MOVA (l);
7446       emitcode ("rr", "a");
7447       goto release;
7448   }
7449   /* no need to clear carry, bit7 will be written later */
7450   while (size--)
7451     {
7452       l = aopGet (left, offset, FALSE, FALSE);
7453       MOVA (l);
7454       emitcode ("rrc", "a");
7455       if (AOP_SIZE (result) > 1)
7456         aopPut (result, "a", offset--);
7457     }
7458   /* now we need to put the carry into the
7459      highest order byte of the result */
7460   if (AOP_SIZE (result) > 1)
7461     {
7462       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7463       MOVA (l);
7464     }
7465   emitcode ("mov", "acc.7,c");
7466  release:
7467   aopPut (result, "a", AOP_SIZE (result) - 1);
7468   freeAsmop (result, NULL, ic, TRUE);
7469   freeAsmop (left, NULL, ic, TRUE);
7470 }
7471
7472 /*-----------------------------------------------------------------*/
7473 /* genRLC - generate code for rotate left with carry               */
7474 /*-----------------------------------------------------------------*/
7475 static void
7476 genRLC (iCode * ic)
7477 {
7478   operand *left, *result;
7479   int size, offset = 0;
7480   char *l;
7481
7482   D(emitcode (";     genRLC",""));
7483
7484   /* rotate right with carry */
7485   left = IC_LEFT (ic);
7486   result = IC_RESULT (ic);
7487   aopOp (left, ic, FALSE);
7488   aopOp (result, ic, FALSE);
7489
7490   /* move it to the result */
7491   size = AOP_SIZE (result);
7492   offset = 0;
7493   if (size--)
7494     {
7495       l = aopGet (left, offset, FALSE, FALSE);
7496       MOVA (l);
7497       if (size == 0) { /* special case for 1 byte */
7498               emitcode("rl","a");
7499               goto release;
7500       }
7501       emitcode("rlc","a"); /* bit0 will be written later */
7502       if (AOP_SIZE (result) > 1)
7503         aopPut (result, "a", offset++);
7504       while (size--)
7505         {
7506           l = aopGet (left, offset, FALSE, FALSE);
7507           MOVA (l);
7508           emitcode ("rlc", "a");
7509           if (AOP_SIZE (result) > 1)
7510             aopPut (result, "a", offset++);
7511         }
7512     }
7513   /* now we need to put the carry into the
7514      highest order byte of the result */
7515   if (AOP_SIZE (result) > 1)
7516     {
7517       l = aopGet (result, 0, FALSE, FALSE);
7518       MOVA (l);
7519     }
7520   emitcode ("mov", "acc.0,c");
7521  release:
7522   aopPut (result, "a", 0);
7523   freeAsmop (result, NULL, ic, TRUE);
7524   freeAsmop (left, NULL, ic, TRUE);
7525 }
7526
7527 /*-----------------------------------------------------------------*/
7528 /* genGetHbit - generates code get highest order bit               */
7529 /*-----------------------------------------------------------------*/
7530 static void
7531 genGetHbit (iCode * ic)
7532 {
7533   operand *left, *result;
7534
7535   D(emitcode (";     genGetHbit",""));
7536
7537   left = IC_LEFT (ic);
7538   result = IC_RESULT (ic);
7539   aopOp (left, ic, FALSE);
7540   aopOp (result, ic, FALSE);
7541
7542   /* get the highest order byte into a */
7543   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7544   if (AOP_TYPE (result) == AOP_CRY)
7545     {
7546       emitcode ("rlc", "a");
7547       outBitC (result);
7548     }
7549   else
7550     {
7551       emitcode ("rl", "a");
7552       emitcode ("anl", "a,#0x01");
7553       outAcc (result);
7554     }
7555
7556   freeAsmop (result, NULL, ic, TRUE);
7557   freeAsmop (left, NULL, ic, TRUE);
7558 }
7559
7560 /*-----------------------------------------------------------------*/
7561 /* genGetAbit - generates code get a single bit                    */
7562 /*-----------------------------------------------------------------*/
7563 static void
7564 genGetAbit (iCode * ic)
7565 {
7566   operand *left, *right, *result;
7567   int shCount;
7568
7569   D(emitcode (";     genGetAbit",""));
7570
7571   left = IC_LEFT (ic);
7572   right = IC_RIGHT (ic);
7573   result = IC_RESULT (ic);
7574   aopOp (left, ic, FALSE);
7575   aopOp (right, ic, FALSE);
7576   aopOp (result, ic, FALSE);
7577
7578   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7579
7580   /* get the needed byte into a */
7581   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7582   shCount %= 8;
7583   if (AOP_TYPE (result) == AOP_CRY)
7584     {
7585       if ((shCount) == 7)
7586           emitcode ("rlc", "a");
7587       else if ((shCount) == 0)
7588           emitcode ("rrc", "a");
7589       else
7590           emitcode ("mov", "c,acc[%d]", shCount);
7591       outBitC (result);
7592     }
7593   else
7594     {
7595       switch (shCount)
7596         {
7597         case 2:
7598           emitcode ("rr", "a");
7599           //fallthrough
7600         case 1:
7601           emitcode ("rr", "a");
7602           //fallthrough
7603         case 0:
7604           emitcode ("anl", "a,#0x01");
7605           break;
7606         case 3:
7607         case 5:
7608           emitcode ("mov", "c,acc[%d]", shCount);
7609           emitcode ("clr", "a");
7610           emitcode ("rlc", "a");
7611           break;
7612         case 4:
7613           emitcode ("swap", "a");
7614           emitcode ("anl", "a,#0x01");
7615           break;
7616         case 6:
7617           emitcode ("rl", "a");
7618           //fallthrough
7619         case 7:
7620           emitcode ("rl", "a");
7621           emitcode ("anl", "a,#0x01");
7622           break;
7623         }
7624       outAcc (result);
7625     }
7626
7627   freeAsmop (result, NULL, ic, TRUE);
7628   freeAsmop (right, NULL, ic, TRUE);
7629   freeAsmop (left, NULL, ic, TRUE);
7630 }
7631
7632 /*-----------------------------------------------------------------*/
7633 /* genGetByte - generates code get a single byte                   */
7634 /*-----------------------------------------------------------------*/
7635 static void
7636 genGetByte (iCode * ic)
7637 {
7638   operand *left, *right, *result;
7639   int offset;
7640
7641   D(emitcode (";     genGetByte",""));
7642
7643   left = IC_LEFT (ic);
7644   right = IC_RIGHT (ic);
7645   result = IC_RESULT (ic);
7646   aopOp (left, ic, FALSE);
7647   aopOp (right, ic, FALSE);
7648   aopOp (result, ic, FALSE);
7649
7650   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7651   aopPut (result,
7652           aopGet (left, offset, FALSE, FALSE),
7653           0);
7654
7655   freeAsmop (result, NULL, ic, TRUE);
7656   freeAsmop (right, NULL, ic, TRUE);
7657   freeAsmop (left, NULL, ic, TRUE);
7658 }
7659
7660 /*-----------------------------------------------------------------*/
7661 /* genGetWord - generates code get two bytes                       */
7662 /*-----------------------------------------------------------------*/
7663 static void
7664 genGetWord (iCode * ic)
7665 {
7666   operand *left, *right, *result;
7667   int offset;
7668
7669   D(emitcode (";     genGetWord",""));
7670
7671   left = IC_LEFT (ic);
7672   right = IC_RIGHT (ic);
7673   result = IC_RESULT (ic);
7674   aopOp (left, ic, FALSE);
7675   aopOp (right, ic, FALSE);
7676   aopOp (result, ic, FALSE);
7677
7678   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7679   aopPut (result,
7680           aopGet (left, offset, FALSE, FALSE),
7681           0);
7682   aopPut (result,
7683           aopGet (left, offset+1, FALSE, FALSE),
7684           1);
7685
7686   freeAsmop (result, NULL, ic, TRUE);
7687   freeAsmop (right, NULL, ic, TRUE);
7688   freeAsmop (left, NULL, ic, TRUE);
7689 }
7690
7691 /*-----------------------------------------------------------------*/
7692 /* genSwap - generates code to swap nibbles or bytes               */
7693 /*-----------------------------------------------------------------*/
7694 static void
7695 genSwap (iCode * ic)
7696 {
7697   operand *left, *result;
7698
7699   D(emitcode (";     genSwap",""));
7700
7701   left = IC_LEFT (ic);
7702   result = IC_RESULT (ic);
7703   aopOp (left, ic, FALSE);
7704   aopOp (result, ic, FALSE);
7705
7706   switch (AOP_SIZE (left))
7707     {
7708     case 1: /* swap nibbles in byte */
7709       MOVA (aopGet (left, 0, FALSE, FALSE));
7710       emitcode ("swap", "a");
7711       aopPut (result, "a", 0);
7712       break;
7713     case 2: /* swap bytes in word */
7714       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7715         {
7716           MOVA (aopGet (left, 0, FALSE, FALSE));
7717           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7718           aopPut (result, "a", 1);
7719         }
7720       else if (operandsEqu (left, result))
7721         {
7722           char * reg = "a";
7723           bool pushedB = FALSE, leftInB = FALSE;
7724
7725           MOVA (aopGet (left, 0, FALSE, FALSE));
7726           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7727             {
7728               pushedB = pushB ();
7729               emitcode ("mov", "b,a");
7730               reg = "b";
7731               leftInB = TRUE;
7732             }
7733           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7734           aopPut (result, reg, 1);
7735
7736           if (leftInB)
7737             popB (pushedB);
7738         }
7739       else
7740         {
7741           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
7742           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
7743         }
7744       break;
7745     default:
7746       wassertl(FALSE, "unsupported SWAP operand size");
7747     }
7748
7749   freeAsmop (result, NULL, ic, TRUE);
7750   freeAsmop (left, NULL, ic, TRUE);
7751 }
7752
7753 /*-----------------------------------------------------------------*/
7754 /* AccRol - rotate left accumulator by known count                 */
7755 /*-----------------------------------------------------------------*/
7756 static void
7757 AccRol (int shCount)
7758 {
7759   shCount &= 0x0007;            // shCount : 0..7
7760
7761   switch (shCount)
7762     {
7763     case 0:
7764       break;
7765     case 1:
7766       emitcode ("rl", "a");
7767       break;
7768     case 2:
7769       emitcode ("rl", "a");
7770       emitcode ("rl", "a");
7771       break;
7772     case 3:
7773       emitcode ("swap", "a");
7774       emitcode ("rr", "a");
7775       break;
7776     case 4:
7777       emitcode ("swap", "a");
7778       break;
7779     case 5:
7780       emitcode ("swap", "a");
7781       emitcode ("rl", "a");
7782       break;
7783     case 6:
7784       emitcode ("rr", "a");
7785       emitcode ("rr", "a");
7786       break;
7787     case 7:
7788       emitcode ("rr", "a");
7789       break;
7790     }
7791 }
7792
7793 /*-----------------------------------------------------------------*/
7794 /* AccLsh - left shift accumulator by known count                  */
7795 /*-----------------------------------------------------------------*/
7796 static void
7797 AccLsh (int shCount)
7798 {
7799   if (shCount != 0)
7800     {
7801       if (shCount == 1)
7802         emitcode ("add", "a,acc");
7803       else if (shCount == 2)
7804         {
7805           emitcode ("add", "a,acc");
7806           emitcode ("add", "a,acc");
7807         }
7808       else
7809         {
7810           /* rotate left accumulator */
7811           AccRol (shCount);
7812           /* and kill the lower order bits */
7813           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7814         }
7815     }
7816 }
7817
7818 /*-----------------------------------------------------------------*/
7819 /* AccRsh - right shift accumulator by known count                 */
7820 /*-----------------------------------------------------------------*/
7821 static void
7822 AccRsh (int shCount)
7823 {
7824   if (shCount != 0)
7825     {
7826       if (shCount == 1)
7827         {
7828           CLRC;
7829           emitcode ("rrc", "a");
7830         }
7831       else
7832         {
7833           /* rotate right accumulator */
7834           AccRol (8 - shCount);
7835           /* and kill the higher order bits */
7836           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7837         }
7838     }
7839 }
7840
7841 /*-----------------------------------------------------------------*/
7842 /* AccSRsh - signed right shift accumulator by known count                 */
7843 /*-----------------------------------------------------------------*/
7844 static void
7845 AccSRsh (int shCount)
7846 {
7847   symbol *tlbl;
7848   if (shCount != 0)
7849     {
7850       if (shCount == 1)
7851         {
7852           emitcode ("mov", "c,acc.7");
7853           emitcode ("rrc", "a");
7854         }
7855       else if (shCount == 2)
7856         {
7857           emitcode ("mov", "c,acc.7");
7858           emitcode ("rrc", "a");
7859           emitcode ("mov", "c,acc.7");
7860           emitcode ("rrc", "a");
7861         }
7862       else
7863         {
7864           tlbl = newiTempLabel (NULL);
7865           /* rotate right accumulator */
7866           AccRol (8 - shCount);
7867           /* and kill the higher order bits */
7868           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7869           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7870           emitcode ("orl", "a,#0x%02x",
7871                     (unsigned char) ~SRMask[shCount]);
7872           emitcode ("", "%05d$:", tlbl->key + 100);
7873         }
7874     }
7875 }
7876
7877 /*-----------------------------------------------------------------*/
7878 /* shiftR1Left2Result - shift right one byte from left to result   */
7879 /*-----------------------------------------------------------------*/
7880 static void
7881 shiftR1Left2Result (operand * left, int offl,
7882                     operand * result, int offr,
7883                     int shCount, int sign)
7884 {
7885   MOVA (aopGet (left, offl, FALSE, FALSE));
7886   /* shift right accumulator */
7887   if (sign)
7888     AccSRsh (shCount);
7889   else
7890     AccRsh (shCount);
7891   aopPut (result, "a", offr);
7892 }
7893
7894 /*-----------------------------------------------------------------*/
7895 /* shiftL1Left2Result - shift left one byte from left to result    */
7896 /*-----------------------------------------------------------------*/
7897 static void
7898 shiftL1Left2Result (operand * left, int offl,
7899                     operand * result, int offr, int shCount)
7900 {
7901   char *l;
7902   l = aopGet (left, offl, FALSE, FALSE);
7903   MOVA (l);
7904   /* shift left accumulator */
7905   AccLsh (shCount);
7906   aopPut (result, "a", offr);
7907 }
7908
7909 /*-----------------------------------------------------------------*/
7910 /* movLeft2Result - move byte from left to result                  */
7911 /*-----------------------------------------------------------------*/
7912 static void
7913 movLeft2Result (operand * left, int offl,
7914                 operand * result, int offr, int sign)
7915 {
7916   char *l;
7917   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7918     {
7919       l = aopGet (left, offl, FALSE, FALSE);
7920
7921       if (*l == '@' && (IS_AOP_PREG (result)))
7922         {
7923           emitcode ("mov", "a,%s", l);
7924           aopPut (result, "a", offr);
7925         }
7926       else
7927         {
7928           if (!sign)
7929             aopPut (result, l, offr);
7930           else
7931             {
7932               /* MSB sign in acc.7 ! */
7933               if (getDataSize (left) == offl + 1)
7934                 {
7935                   MOVA (l);
7936                   aopPut (result, "a", offr);
7937                 }
7938             }
7939         }
7940     }
7941 }
7942
7943 /*-----------------------------------------------------------------*/
7944 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7945 /*-----------------------------------------------------------------*/
7946 static void
7947 AccAXRrl1 (char *x)
7948 {
7949   emitcode ("rrc", "a");
7950   emitcode ("xch", "a,%s", x);
7951   emitcode ("rrc", "a");
7952   emitcode ("xch", "a,%s", x);
7953 }
7954
7955 /*-----------------------------------------------------------------*/
7956 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7957 /*-----------------------------------------------------------------*/
7958 static void
7959 AccAXLrl1 (char *x)
7960 {
7961   emitcode ("xch", "a,%s", x);
7962   emitcode ("rlc", "a");
7963   emitcode ("xch", "a,%s", x);
7964   emitcode ("rlc", "a");
7965 }
7966
7967 /*-----------------------------------------------------------------*/
7968 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7969 /*-----------------------------------------------------------------*/
7970 static void
7971 AccAXLsh1 (char *x)
7972 {
7973   emitcode ("xch", "a,%s", x);
7974   emitcode ("add", "a,acc");
7975   emitcode ("xch", "a,%s", x);
7976   emitcode ("rlc", "a");
7977 }
7978
7979 /*-----------------------------------------------------------------*/
7980 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7981 /*-----------------------------------------------------------------*/
7982 static void
7983 AccAXLsh (char *x, int shCount)
7984 {
7985   switch (shCount)
7986     {
7987     case 0:
7988       break;
7989     case 1:
7990       AccAXLsh1 (x);
7991       break;
7992     case 2:
7993       AccAXLsh1 (x);
7994       AccAXLsh1 (x);
7995       break;
7996     case 3:
7997     case 4:
7998     case 5:                     // AAAAABBB:CCCCCDDD
7999
8000       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8001
8002       emitcode ("anl", "a,#0x%02x",
8003                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8004
8005       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8006
8007       AccRol (shCount);         // DDDCCCCC:BBB00000
8008
8009       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8010
8011       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8012
8013       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8014
8015       emitcode ("anl", "a,#0x%02x",
8016                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8017
8018       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8019
8020       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8021
8022       break;
8023     case 6:                     // AAAAAABB:CCCCCCDD
8024       emitcode ("anl", "a,#0x%02x",
8025                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8026       emitcode ("mov", "c,acc.0");      // c = B
8027       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8028 #if 0 // REMOVE ME
8029       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8030       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8031 #else
8032       emitcode("rrc","a");
8033       emitcode("xch","a,%s", x);
8034       emitcode("rrc","a");
8035       emitcode("mov","c,acc.0"); //<< get correct bit
8036       emitcode("xch","a,%s", x);
8037
8038       emitcode("rrc","a");
8039       emitcode("xch","a,%s", x);
8040       emitcode("rrc","a");
8041       emitcode("xch","a,%s", x);
8042 #endif
8043       break;
8044     case 7:                     // a:x <<= 7
8045
8046       emitcode ("anl", "a,#0x%02x",
8047                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8048
8049       emitcode ("mov", "c,acc.0");      // c = B
8050
8051       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8052
8053       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8054
8055       break;
8056     default:
8057       break;
8058     }
8059 }
8060
8061 /*-----------------------------------------------------------------*/
8062 /* AccAXRsh - right shift a:x known count (0..7)                   */
8063 /*-----------------------------------------------------------------*/
8064 static void
8065 AccAXRsh (char *x, int shCount)
8066 {
8067   switch (shCount)
8068     {
8069     case 0:
8070       break;
8071     case 1:
8072       CLRC;
8073       AccAXRrl1 (x);            // 0->a:x
8074
8075       break;
8076     case 2:
8077       CLRC;
8078       AccAXRrl1 (x);            // 0->a:x
8079
8080       CLRC;
8081       AccAXRrl1 (x);            // 0->a:x
8082
8083       break;
8084     case 3:
8085     case 4:
8086     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8087
8088       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8089
8090       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8091
8092       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8093
8094       emitcode ("anl", "a,#0x%02x",
8095                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8096
8097       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8098
8099       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8100
8101       emitcode ("anl", "a,#0x%02x",
8102                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8103
8104       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8105
8106       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8107
8108       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8109
8110       break;
8111     case 6:                     // AABBBBBB:CCDDDDDD
8112
8113       emitcode ("mov", "c,acc.7");
8114       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8115
8116       emitcode ("mov", "c,acc.7");
8117       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8118
8119       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8120
8121       emitcode ("anl", "a,#0x%02x",
8122                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8123
8124       break;
8125     case 7:                     // ABBBBBBB:CDDDDDDD
8126
8127       emitcode ("mov", "c,acc.7");      // c = A
8128
8129       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8130
8131       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8132
8133       emitcode ("anl", "a,#0x%02x",
8134                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8135
8136       break;
8137     default:
8138       break;
8139     }
8140 }
8141
8142 /*-----------------------------------------------------------------*/
8143 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8144 /*-----------------------------------------------------------------*/
8145 static void
8146 AccAXRshS (char *x, int shCount)
8147 {
8148   symbol *tlbl;
8149   switch (shCount)
8150     {
8151     case 0:
8152       break;
8153     case 1:
8154       emitcode ("mov", "c,acc.7");
8155       AccAXRrl1 (x);            // s->a:x
8156
8157       break;
8158     case 2:
8159       emitcode ("mov", "c,acc.7");
8160       AccAXRrl1 (x);            // s->a:x
8161
8162       emitcode ("mov", "c,acc.7");
8163       AccAXRrl1 (x);            // s->a:x
8164
8165       break;
8166     case 3:
8167     case 4:
8168     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8169
8170       tlbl = newiTempLabel (NULL);
8171       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8172
8173       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8174
8175       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8176
8177       emitcode ("anl", "a,#0x%02x",
8178                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8179
8180       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8181
8182       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8183
8184       emitcode ("anl", "a,#0x%02x",
8185                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8186
8187       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8188
8189       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8190
8191       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8192
8193       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8194       emitcode ("orl", "a,#0x%02x",
8195                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8196
8197       emitcode ("", "%05d$:", tlbl->key + 100);
8198       break;                    // SSSSAAAA:BBBCCCCC
8199
8200     case 6:                     // AABBBBBB:CCDDDDDD
8201
8202       tlbl = newiTempLabel (NULL);
8203       emitcode ("mov", "c,acc.7");
8204       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8205
8206       emitcode ("mov", "c,acc.7");
8207       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8208
8209       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8210
8211       emitcode ("anl", "a,#0x%02x",
8212                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8213
8214       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8215       emitcode ("orl", "a,#0x%02x",
8216                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8217
8218       emitcode ("", "%05d$:", tlbl->key + 100);
8219       break;
8220     case 7:                     // ABBBBBBB:CDDDDDDD
8221
8222       tlbl = newiTempLabel (NULL);
8223       emitcode ("mov", "c,acc.7");      // c = A
8224
8225       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8226
8227       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8228
8229       emitcode ("anl", "a,#0x%02x",
8230                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8231
8232       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8233       emitcode ("orl", "a,#0x%02x",
8234                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8235
8236       emitcode ("", "%05d$:", tlbl->key + 100);
8237       break;
8238     default:
8239       break;
8240     }
8241 }
8242
8243 /*-----------------------------------------------------------------*/
8244 /* shiftL2Left2Result - shift left two bytes from left to result   */
8245 /*-----------------------------------------------------------------*/
8246 static void
8247 shiftL2Left2Result (operand * left, int offl,
8248                     operand * result, int offr, int shCount)
8249 {
8250   char * x;
8251   bool pushedB = FALSE;
8252   bool usedB = FALSE;
8253
8254   if (sameRegs (AOP (result), AOP (left)) &&
8255       ((offl + MSB16) == offr))
8256     {
8257       /* don't crash result[offr] */
8258       MOVA (aopGet (left, offl, FALSE, FALSE));
8259       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8260       x = aopGet (result, offr, FALSE, FALSE);
8261     }
8262   else if (aopGetUsesAcc (result, offr))
8263     {
8264       movLeft2Result (left, offl, result, offr, 0);
8265       pushedB = pushB ();
8266       usedB = TRUE;
8267       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8268       MOVA (aopGet (result, offr, FALSE, FALSE));
8269       emitcode ("xch", "a,b");
8270       x = "b";
8271     }
8272   else
8273     {
8274       movLeft2Result (left, offl, result, offr, 0);
8275       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8276       x = aopGet (result, offr, FALSE, FALSE);
8277     }
8278   /* ax << shCount (x = lsb(result)) */
8279   AccAXLsh (x, shCount);
8280   if (usedB)
8281     {
8282       emitcode ("xch", "a,b");
8283       aopPut (result, "a", offr);
8284       aopPut (result, "b", offr + MSB16);
8285       popB (pushedB);
8286     }
8287   else
8288     {
8289       aopPut (result, "a", offr + MSB16);
8290     }
8291 }
8292
8293
8294 /*-----------------------------------------------------------------*/
8295 /* shiftR2Left2Result - shift right two bytes from left to result  */
8296 /*-----------------------------------------------------------------*/
8297 static void
8298 shiftR2Left2Result (operand * left, int offl,
8299                     operand * result, int offr,
8300                     int shCount, int sign)
8301 {
8302   char * x;
8303   bool pushedB = FALSE;
8304   bool usedB = FALSE;
8305
8306   if (sameRegs (AOP (result), AOP (left)) &&
8307       ((offl + MSB16) == offr))
8308     {
8309       /* don't crash result[offr] */
8310       MOVA (aopGet (left, offl, FALSE, FALSE));
8311       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8312       x = aopGet (result, offr, FALSE, FALSE);
8313     }
8314   else if (aopGetUsesAcc (result, offr))
8315     {
8316       movLeft2Result (left, offl, result, offr, 0);
8317       pushedB = pushB ();
8318       usedB = TRUE;
8319       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8320       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8321       x = "b";
8322     }
8323   else
8324     {
8325       movLeft2Result (left, offl, result, offr, 0);
8326       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8327       x = aopGet (result, offr, FALSE, FALSE);
8328     }
8329   /* a:x >> shCount (x = lsb(result)) */
8330   if (sign)
8331     AccAXRshS (x, shCount);
8332   else
8333     AccAXRsh (x, shCount);
8334   if (usedB)
8335     {
8336       emitcode ("xch", "a,b");
8337       aopPut (result, "a", offr);
8338       emitcode ("xch", "a,b");
8339       popB (pushedB);
8340     }
8341   if (getDataSize (result) > 1)
8342     aopPut (result, "a", offr + MSB16);
8343 }
8344
8345 /*-----------------------------------------------------------------*/
8346 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8347 /*-----------------------------------------------------------------*/
8348 static void
8349 shiftLLeftOrResult (operand * left, int offl,
8350                     operand * result, int offr, int shCount)
8351 {
8352   MOVA (aopGet (left, offl, FALSE, FALSE));
8353   /* shift left accumulator */
8354   AccLsh (shCount);
8355   /* or with result */
8356   if (aopGetUsesAcc (result, offr))
8357     {
8358       emitcode ("xch", "a,b");
8359       MOVA (aopGet (result, offr, FALSE, FALSE));
8360       emitcode ("orl", "a,b");
8361     }
8362   else
8363     {
8364       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8365     }
8366   /* back to result */
8367   aopPut (result, "a", offr);
8368 }
8369
8370 /*-----------------------------------------------------------------*/
8371 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8372 /*-----------------------------------------------------------------*/
8373 static void
8374 shiftRLeftOrResult (operand * left, int offl,
8375                     operand * result, int offr, int shCount)
8376 {
8377   MOVA (aopGet (left, offl, FALSE, FALSE));
8378   /* shift right accumulator */
8379   AccRsh (shCount);
8380   /* or with result */
8381   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8382   /* back to result */
8383   aopPut (result, "a", offr);
8384 }
8385
8386 /*-----------------------------------------------------------------*/
8387 /* genlshOne - left shift a one byte quantity by known count       */
8388 /*-----------------------------------------------------------------*/
8389 static void
8390 genlshOne (operand * result, operand * left, int shCount)
8391 {
8392   D(emitcode (";     genlshOne",""));
8393
8394   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8395 }
8396
8397 /*-----------------------------------------------------------------*/
8398 /* genlshTwo - left shift two bytes by known amount != 0           */
8399 /*-----------------------------------------------------------------*/
8400 static void
8401 genlshTwo (operand * result, operand * left, int shCount)
8402 {
8403   int size;
8404
8405   D(emitcode (";     genlshTwo",""));
8406
8407   size = getDataSize (result);
8408
8409   /* if shCount >= 8 */
8410   if (shCount >= 8)
8411     {
8412       shCount -= 8;
8413
8414       if (size > 1)
8415         {
8416           if (shCount)
8417             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8418           else
8419             movLeft2Result (left, LSB, result, MSB16, 0);
8420         }
8421       aopPut (result, zero, LSB);
8422     }
8423
8424   /*  1 <= shCount <= 7 */
8425   else
8426     {
8427       if (size == 1)
8428         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8429       else
8430         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8431     }
8432 }
8433
8434 /*-----------------------------------------------------------------*/
8435 /* shiftLLong - shift left one long from left to result            */
8436 /* offl = LSB or MSB16                                             */
8437 /*-----------------------------------------------------------------*/
8438 static void
8439 shiftLLong (operand * left, operand * result, int offr)
8440 {
8441   char *l;
8442   int size = AOP_SIZE (result);
8443
8444   if (size >= LSB + offr)
8445     {
8446       l = aopGet (left, LSB, FALSE, FALSE);
8447       MOVA (l);
8448       emitcode ("add", "a,acc");
8449       if (sameRegs (AOP (left), AOP (result)) &&
8450           size >= MSB16 + offr && offr != LSB)
8451         emitcode ("xch", "a,%s",
8452                   aopGet (left, LSB + offr, FALSE, FALSE));
8453       else
8454         aopPut (result, "a", LSB + offr);
8455     }
8456
8457   if (size >= MSB16 + offr)
8458     {
8459       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8460         {
8461           l = aopGet (left, MSB16, FALSE, FALSE);
8462           MOVA (l);
8463         }
8464       emitcode ("rlc", "a");
8465       if (sameRegs (AOP (left), AOP (result)) &&
8466           size >= MSB24 + offr && offr != LSB)
8467         emitcode ("xch", "a,%s",
8468                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8469       else
8470         aopPut (result, "a", MSB16 + offr);
8471     }
8472
8473   if (size >= MSB24 + offr)
8474     {
8475       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8476         {
8477           l = aopGet (left, MSB24, FALSE, FALSE);
8478           MOVA (l);
8479         }
8480       emitcode ("rlc", "a");
8481       if (sameRegs (AOP (left), AOP (result)) &&
8482           size >= MSB32 + offr && offr != LSB)
8483         emitcode ("xch", "a,%s",
8484                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8485       else
8486         aopPut (result, "a", MSB24 + offr);
8487     }
8488
8489   if (size > MSB32 + offr)
8490     {
8491       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8492         {
8493           l = aopGet (left, MSB32, FALSE, FALSE);
8494           MOVA (l);
8495         }
8496       emitcode ("rlc", "a");
8497       aopPut (result, "a", MSB32 + offr);
8498     }
8499   if (offr != LSB)
8500     aopPut (result, zero, LSB);
8501 }
8502
8503 /*-----------------------------------------------------------------*/
8504 /* genlshFour - shift four byte by a known amount != 0             */
8505 /*-----------------------------------------------------------------*/
8506 static void
8507 genlshFour (operand * result, operand * left, int shCount)
8508 {
8509   int size;
8510
8511   D(emitcode (";     genlshFour",""));
8512
8513   size = AOP_SIZE (result);
8514
8515   /* if shifting more that 3 bytes */
8516   if (shCount >= 24)
8517     {
8518       shCount -= 24;
8519       if (shCount)
8520         /* lowest order of left goes to the highest
8521            order of the destination */
8522         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8523       else
8524         movLeft2Result (left, LSB, result, MSB32, 0);
8525       aopPut (result, zero, LSB);
8526       aopPut (result, zero, MSB16);
8527       aopPut (result, zero, MSB24);
8528       return;
8529     }
8530
8531   /* more than two bytes */
8532   else if (shCount >= 16)
8533     {
8534       /* lower order two bytes goes to higher order two bytes */
8535       shCount -= 16;
8536       /* if some more remaining */
8537       if (shCount)
8538         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8539       else
8540         {
8541           movLeft2Result (left, MSB16, result, MSB32, 0);
8542           movLeft2Result (left, LSB, result, MSB24, 0);
8543         }
8544       aopPut (result, zero, MSB16);
8545       aopPut (result, zero, LSB);
8546       return;
8547     }
8548
8549   /* if more than 1 byte */
8550   else if (shCount >= 8)
8551     {
8552       /* lower order three bytes goes to higher order  three bytes */
8553       shCount -= 8;
8554       if (size == 2)
8555         {
8556           if (shCount)
8557             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8558           else
8559             movLeft2Result (left, LSB, result, MSB16, 0);
8560         }
8561       else
8562         {                       /* size = 4 */
8563           if (shCount == 0)
8564             {
8565               movLeft2Result (left, MSB24, result, MSB32, 0);
8566               movLeft2Result (left, MSB16, result, MSB24, 0);
8567               movLeft2Result (left, LSB, result, MSB16, 0);
8568               aopPut (result, zero, LSB);
8569             }
8570           else if (shCount == 1)
8571             shiftLLong (left, result, MSB16);
8572           else
8573             {
8574               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8575               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8576               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8577               aopPut (result, zero, LSB);
8578             }
8579         }
8580     }
8581
8582   /* 1 <= shCount <= 7 */
8583   else if (shCount <= 2)
8584     {
8585       shiftLLong (left, result, LSB);
8586       if (shCount == 2)
8587         shiftLLong (result, result, LSB);
8588     }
8589   /* 3 <= shCount <= 7, optimize */
8590   else
8591     {
8592       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8593       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8594       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8595     }
8596 }
8597
8598 /*-----------------------------------------------------------------*/
8599 /* genLeftShiftLiteral - left shifting by known count              */
8600 /*-----------------------------------------------------------------*/
8601 static void
8602 genLeftShiftLiteral (operand * left,
8603                      operand * right,
8604                      operand * result,
8605                      iCode * ic)
8606 {
8607   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8608   int size;
8609
8610   D(emitcode (";     genLeftShiftLiteral",""));
8611
8612   freeAsmop (right, NULL, ic, TRUE);
8613
8614   aopOp (left, ic, FALSE);
8615   aopOp (result, ic, FALSE);
8616
8617   size = getSize (operandType (result));
8618
8619 #if VIEW_SIZE
8620   emitcode ("; shift left ", "result %d, left %d", size,
8621             AOP_SIZE (left));
8622 #endif
8623
8624   /* I suppose that the left size >= result size */
8625   if (shCount == 0)
8626     {
8627       while (size--)
8628         {
8629           movLeft2Result (left, size, result, size, 0);
8630         }
8631     }
8632
8633   else if (shCount >= (size * 8))
8634     while (size--)
8635       aopPut (result, zero, size);
8636   else
8637     {
8638       switch (size)
8639         {
8640         case 1:
8641           genlshOne (result, left, shCount);
8642           break;
8643
8644         case 2:
8645           genlshTwo (result, left, shCount);
8646           break;
8647
8648         case 4:
8649           genlshFour (result, left, shCount);
8650           break;
8651         default:
8652           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8653                   "*** ack! mystery literal shift!\n");
8654           break;
8655         }
8656     }
8657   freeAsmop (result, NULL, ic, TRUE);
8658   freeAsmop (left, NULL, ic, TRUE);
8659 }
8660
8661 /*-----------------------------------------------------------------*/
8662 /* genLeftShift - generates code for left shifting                 */
8663 /*-----------------------------------------------------------------*/
8664 static void
8665 genLeftShift (iCode * ic)
8666 {
8667   operand *left, *right, *result;
8668   int size, offset;
8669   char *l;
8670   symbol *tlbl, *tlbl1;
8671   bool pushedB;
8672
8673   D(emitcode (";     genLeftShift",""));
8674
8675   right = IC_RIGHT (ic);
8676   left = IC_LEFT (ic);
8677   result = IC_RESULT (ic);
8678
8679   aopOp (right, ic, FALSE);
8680
8681   /* if the shift count is known then do it
8682      as efficiently as possible */
8683   if (AOP_TYPE (right) == AOP_LIT)
8684     {
8685       genLeftShiftLiteral (left, right, result, ic);
8686       return;
8687     }
8688
8689   /* shift count is unknown then we have to form
8690      a loop get the loop count in B : Note: we take
8691      only the lower order byte since shifting
8692      more that 32 bits make no sense anyway, ( the
8693      largest size of an object can be only 32 bits ) */
8694
8695   pushedB = pushB ();
8696   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8697   emitcode ("inc", "b");
8698   freeAsmop (right, NULL, ic, TRUE);
8699   aopOp (left, ic, FALSE);
8700   aopOp (result, ic, FALSE);
8701
8702   /* now move the left to the result if they are not the same */
8703   if (!sameRegs (AOP (left), AOP (result)) &&
8704       AOP_SIZE (result) > 1)
8705     {
8706
8707       size = AOP_SIZE (result);
8708       offset = 0;
8709       while (size--)
8710         {
8711           l = aopGet (left, offset, FALSE, TRUE);
8712           if (*l == '@' && (IS_AOP_PREG (result)))
8713             {
8714
8715               emitcode ("mov", "a,%s", l);
8716               aopPut (result, "a", offset);
8717             }
8718           else
8719             aopPut (result, l, offset);
8720           offset++;
8721         }
8722     }
8723
8724   tlbl = newiTempLabel (NULL);
8725   size = AOP_SIZE (result);
8726   offset = 0;
8727   tlbl1 = newiTempLabel (NULL);
8728
8729   /* if it is only one byte then */
8730   if (size == 1)
8731     {
8732       symbol *tlbl1 = newiTempLabel (NULL);
8733
8734       l = aopGet (left, 0, FALSE, FALSE);
8735       MOVA (l);
8736       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8737       emitcode ("", "%05d$:", tlbl->key + 100);
8738       emitcode ("add", "a,acc");
8739       emitcode ("", "%05d$:", tlbl1->key + 100);
8740       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8741       popB (pushedB);
8742       aopPut (result, "a", 0);
8743       goto release;
8744     }
8745
8746   reAdjustPreg (AOP (result));
8747
8748   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8749   emitcode ("", "%05d$:", tlbl->key + 100);
8750   l = aopGet (result, offset, FALSE, FALSE);
8751   MOVA (l);
8752   emitcode ("add", "a,acc");
8753   aopPut (result, "a", offset++);
8754   while (--size)
8755     {
8756       l = aopGet (result, offset, FALSE, FALSE);
8757       MOVA (l);
8758       emitcode ("rlc", "a");
8759       aopPut (result, "a", offset++);
8760     }
8761   reAdjustPreg (AOP (result));
8762
8763   emitcode ("", "%05d$:", tlbl1->key + 100);
8764   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8765   popB (pushedB);
8766 release:
8767   freeAsmop (result, NULL, ic, TRUE);
8768   freeAsmop (left, NULL, ic, TRUE);
8769 }
8770
8771 /*-----------------------------------------------------------------*/
8772 /* genrshOne - right shift a one byte quantity by known count      */
8773 /*-----------------------------------------------------------------*/
8774 static void
8775 genrshOne (operand * result, operand * left,
8776            int shCount, int sign)
8777 {
8778   D(emitcode (";     genrshOne",""));
8779
8780   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8781 }
8782
8783 /*-----------------------------------------------------------------*/
8784 /* genrshTwo - right shift two bytes by known amount != 0          */
8785 /*-----------------------------------------------------------------*/
8786 static void
8787 genrshTwo (operand * result, operand * left,
8788            int shCount, int sign)
8789 {
8790   D(emitcode (";     genrshTwo",""));
8791
8792   /* if shCount >= 8 */
8793   if (shCount >= 8)
8794     {
8795       shCount -= 8;
8796       if (shCount)
8797         shiftR1Left2Result (left, MSB16, result, LSB,
8798                             shCount, sign);
8799       else
8800         movLeft2Result (left, MSB16, result, LSB, sign);
8801       addSign (result, MSB16, sign);
8802     }
8803
8804   /*  1 <= shCount <= 7 */
8805   else
8806     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8807 }
8808
8809 /*-----------------------------------------------------------------*/
8810 /* shiftRLong - shift right one long from left to result           */
8811 /* offl = LSB or MSB16                                             */
8812 /*-----------------------------------------------------------------*/
8813 static void
8814 shiftRLong (operand * left, int offl,
8815             operand * result, int sign)
8816 {
8817   bool useSameRegs = regsInCommon (left, result);
8818
8819   if (useSameRegs && offl>1)
8820     {
8821       // we are in big trouble, but this shouldn't happen
8822       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8823     }
8824
8825   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8826
8827   if (offl==MSB16)
8828     {
8829       // shift is > 8
8830       if (sign)
8831         {
8832           emitcode ("rlc", "a");
8833           emitcode ("subb", "a,acc");
8834           if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8835             {
8836               emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8837             }
8838           else
8839             {
8840               aopPut (result, "a", MSB32);
8841               MOVA (aopGet (left, MSB32, FALSE, FALSE));
8842             }
8843         }
8844       else
8845         {
8846           aopPut (result, zero, MSB32);
8847         }
8848     }
8849
8850   if (!sign)
8851     {
8852       emitcode ("clr", "c");
8853     }
8854   else
8855     {
8856       emitcode ("mov", "c,acc.7");
8857     }
8858
8859   emitcode ("rrc", "a");
8860
8861   if (useSameRegs && offl==MSB16 &&
8862       sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8863     {
8864       emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8865     }
8866   else
8867     {
8868       aopPut (result, "a", MSB32-offl);
8869       MOVA (aopGet (left, MSB24, FALSE, FALSE));
8870     }
8871
8872   emitcode ("rrc", "a");
8873   if (useSameRegs && offl==1 &&
8874       sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8875     {
8876       emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8877     }
8878   else
8879     {
8880       aopPut (result, "a", MSB24-offl);
8881       MOVA (aopGet (left, MSB16, FALSE, FALSE));
8882     }
8883   emitcode ("rrc", "a");
8884   if (offl != LSB)
8885     {
8886       aopPut (result, "a", MSB16 - offl);
8887     }
8888   else
8889     {
8890       if (useSameRegs &&
8891           sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8892         {
8893           emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8894         }
8895       else
8896         {
8897           aopPut (result, "a", MSB16 - offl);
8898           MOVA (aopGet (left, LSB, FALSE, FALSE));
8899         }
8900       emitcode ("rrc", "a");
8901       aopPut (result, "a", LSB);
8902     }
8903 }
8904
8905 /*-----------------------------------------------------------------*/
8906 /* genrshFour - shift four byte by a known amount != 0             */
8907 /*-----------------------------------------------------------------*/
8908 static void
8909 genrshFour (operand * result, operand * left,
8910             int shCount, int sign)
8911 {
8912   D(emitcode (";     genrshFour",""));
8913
8914   /* if shifting more that 3 bytes */
8915   if (shCount >= 24)
8916     {
8917       shCount -= 24;
8918       if (shCount)
8919         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8920       else
8921         movLeft2Result (left, MSB32, result, LSB, sign);
8922       addSign (result, MSB16, sign);
8923     }
8924   else if (shCount >= 16)
8925     {
8926       shCount -= 16;
8927       if (shCount)
8928         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8929       else
8930         {
8931           movLeft2Result (left, MSB24, result, LSB, 0);
8932           movLeft2Result (left, MSB32, result, MSB16, sign);
8933         }
8934       addSign (result, MSB24, sign);
8935     }
8936   else if (shCount >= 8)
8937     {
8938       shCount -= 8;
8939       if (shCount == 1)
8940         shiftRLong (left, MSB16, result, sign);
8941       else if (shCount == 0)
8942         {
8943           movLeft2Result (left, MSB16, result, LSB, 0);
8944           movLeft2Result (left, MSB24, result, MSB16, 0);
8945           movLeft2Result (left, MSB32, result, MSB24, sign);
8946           addSign (result, MSB32, sign);
8947         }
8948       else
8949         {
8950           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8951           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8952           /* the last shift is signed */
8953           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8954           addSign (result, MSB32, sign);
8955         }
8956     }
8957   else
8958     {                           /* 1 <= shCount <= 7 */
8959       if (shCount <= 2)
8960         {
8961           shiftRLong (left, LSB, result, sign);
8962           if (shCount == 2)
8963             shiftRLong (result, LSB, result, sign);
8964         }
8965       else
8966         {
8967           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8968           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8969           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8970         }
8971     }
8972 }
8973
8974 /*-----------------------------------------------------------------*/
8975 /* genRightShiftLiteral - right shifting by known count            */
8976 /*-----------------------------------------------------------------*/
8977 static void
8978 genRightShiftLiteral (operand * left,
8979                       operand * right,
8980                       operand * result,
8981                       iCode * ic,
8982                       int sign)
8983 {
8984   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8985   int size;
8986
8987   D(emitcode (";     genRightShiftLiteral",""));
8988
8989   freeAsmop (right, NULL, ic, TRUE);
8990
8991   aopOp (left, ic, FALSE);
8992   aopOp (result, ic, FALSE);
8993
8994 #if VIEW_SIZE
8995   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8996             AOP_SIZE (left));
8997 #endif
8998
8999   size = getDataSize (left);
9000   /* test the LEFT size !!! */
9001
9002   /* I suppose that the left size >= result size */
9003   if (shCount == 0)
9004     {
9005       size = getDataSize (result);
9006       while (size--)
9007         movLeft2Result (left, size, result, size, 0);
9008     }
9009
9010   else if (shCount >= (size * 8))
9011     {
9012       if (sign) {
9013         /* get sign in acc.7 */
9014         MOVA (aopGet (left, size - 1, FALSE, FALSE));
9015       }
9016       addSign (result, LSB, sign);
9017     }
9018   else
9019     {
9020       switch (size)
9021         {
9022         case 1:
9023           genrshOne (result, left, shCount, sign);
9024           break;
9025
9026         case 2:
9027           genrshTwo (result, left, shCount, sign);
9028           break;
9029
9030         case 4:
9031           genrshFour (result, left, shCount, sign);
9032           break;
9033         default:
9034           break;
9035         }
9036     }
9037   freeAsmop (result, NULL, ic, TRUE);
9038   freeAsmop (left, NULL, ic, TRUE);
9039 }
9040
9041 /*-----------------------------------------------------------------*/
9042 /* genSignedRightShift - right shift of signed number              */
9043 /*-----------------------------------------------------------------*/
9044 static void
9045 genSignedRightShift (iCode * ic)
9046 {
9047   operand *right, *left, *result;
9048   int size, offset;
9049   char *l;
9050   symbol *tlbl, *tlbl1;
9051   bool pushedB;
9052
9053   D(emitcode (";     genSignedRightShift",""));
9054
9055   /* we do it the hard way put the shift count in b
9056      and loop thru preserving the sign */
9057
9058   right = IC_RIGHT (ic);
9059   left = IC_LEFT (ic);
9060   result = IC_RESULT (ic);
9061
9062   aopOp (right, ic, FALSE);
9063
9064
9065   if (AOP_TYPE (right) == AOP_LIT)
9066     {
9067       genRightShiftLiteral (left, right, result, ic, 1);
9068       return;
9069     }
9070   /* shift count is unknown then we have to form
9071      a loop get the loop count in B : Note: we take
9072      only the lower order byte since shifting
9073      more that 32 bits make no sense anyway, ( the
9074      largest size of an object can be only 32 bits ) */
9075
9076   pushedB = pushB ();
9077   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9078   emitcode ("inc", "b");
9079   freeAsmop (right, NULL, ic, TRUE);
9080   aopOp (left, ic, FALSE);
9081   aopOp (result, ic, FALSE);
9082
9083   /* now move the left to the result if they are not the
9084      same */
9085   if (!sameRegs (AOP (left), AOP (result)) &&
9086       AOP_SIZE (result) > 1)
9087     {
9088
9089       size = AOP_SIZE (result);
9090       offset = 0;
9091       while (size--)
9092         {
9093           l = aopGet (left, offset, FALSE, TRUE);
9094           if (*l == '@' && IS_AOP_PREG (result))
9095             {
9096
9097               emitcode ("mov", "a,%s", l);
9098               aopPut (result, "a", offset);
9099             }
9100           else
9101             aopPut (result, l, offset);
9102           offset++;
9103         }
9104     }
9105
9106   /* mov the highest order bit to OVR */
9107   tlbl = newiTempLabel (NULL);
9108   tlbl1 = newiTempLabel (NULL);
9109
9110   size = AOP_SIZE (result);
9111   offset = size - 1;
9112   MOVA (aopGet (left, offset, FALSE, FALSE));
9113   emitcode ("rlc", "a");
9114   emitcode ("mov", "ov,c");
9115   /* if it is only one byte then */
9116   if (size == 1)
9117     {
9118       l = aopGet (left, 0, FALSE, FALSE);
9119       MOVA (l);
9120       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9121       emitcode ("", "%05d$:", tlbl->key + 100);
9122       emitcode ("mov", "c,ov");
9123       emitcode ("rrc", "a");
9124       emitcode ("", "%05d$:", tlbl1->key + 100);
9125       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9126       popB (pushedB);
9127       aopPut (result, "a", 0);
9128       goto release;
9129     }
9130
9131   reAdjustPreg (AOP (result));
9132   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9133   emitcode ("", "%05d$:", tlbl->key + 100);
9134   emitcode ("mov", "c,ov");
9135   while (size--)
9136     {
9137       l = aopGet (result, offset, FALSE, FALSE);
9138       MOVA (l);
9139       emitcode ("rrc", "a");
9140       aopPut (result, "a", offset--);
9141     }
9142   reAdjustPreg (AOP (result));
9143   emitcode ("", "%05d$:", tlbl1->key + 100);
9144   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9145   popB (pushedB);
9146
9147 release:
9148   freeAsmop (result, NULL, ic, TRUE);
9149   freeAsmop (left, NULL, ic, TRUE);
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* genRightShift - generate code for right shifting                */
9154 /*-----------------------------------------------------------------*/
9155 static void
9156 genRightShift (iCode * ic)
9157 {
9158   operand *right, *left, *result;
9159   sym_link *letype;
9160   int size, offset;
9161   char *l;
9162   symbol *tlbl, *tlbl1;
9163   bool pushedB;
9164
9165   D(emitcode (";     genRightShift",""));
9166
9167   /* if signed then we do it the hard way preserve the
9168      sign bit moving it inwards */
9169   letype = getSpec (operandType (IC_LEFT (ic)));
9170
9171   if (!SPEC_USIGN (letype))
9172     {
9173       genSignedRightShift (ic);
9174       return;
9175     }
9176
9177   /* signed & unsigned types are treated the same : i.e. the
9178      signed is NOT propagated inwards : quoting from the
9179      ANSI - standard : "for E1 >> E2, is equivalent to division
9180      by 2**E2 if unsigned or if it has a non-negative value,
9181      otherwise the result is implementation defined ", MY definition
9182      is that the sign does not get propagated */
9183
9184   right = IC_RIGHT (ic);
9185   left = IC_LEFT (ic);
9186   result = IC_RESULT (ic);
9187
9188   aopOp (right, ic, FALSE);
9189
9190   /* if the shift count is known then do it
9191      as efficiently as possible */
9192   if (AOP_TYPE (right) == AOP_LIT)
9193     {
9194       genRightShiftLiteral (left, right, result, ic, 0);
9195       return;
9196     }
9197
9198   /* shift count is unknown then we have to form
9199      a loop get the loop count in B : Note: we take
9200      only the lower order byte since shifting
9201      more that 32 bits make no sense anyway, ( the
9202      largest size of an object can be only 32 bits ) */
9203
9204   pushedB = pushB ();
9205   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9206   emitcode ("inc", "b");
9207   freeAsmop (right, NULL, ic, TRUE);
9208   aopOp (left, ic, FALSE);
9209   aopOp (result, ic, FALSE);
9210
9211   /* now move the left to the result if they are not the
9212      same */
9213   if (!sameRegs (AOP (left), AOP (result)) &&
9214       AOP_SIZE (result) > 1)
9215     {
9216
9217       size = AOP_SIZE (result);
9218       offset = 0;
9219       while (size--)
9220         {
9221           l = aopGet (left, offset, FALSE, TRUE);
9222           if (*l == '@' && IS_AOP_PREG (result))
9223             {
9224
9225               emitcode ("mov", "a,%s", l);
9226               aopPut (result, "a", offset);
9227             }
9228           else
9229             aopPut (result, l, offset);
9230           offset++;
9231         }
9232     }
9233
9234   tlbl = newiTempLabel (NULL);
9235   tlbl1 = newiTempLabel (NULL);
9236   size = AOP_SIZE (result);
9237   offset = size - 1;
9238
9239   /* if it is only one byte then */
9240   if (size == 1)
9241     {
9242       l = aopGet (left, 0, FALSE, FALSE);
9243       MOVA (l);
9244       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9245       emitcode ("", "%05d$:", tlbl->key + 100);
9246       CLRC;
9247       emitcode ("rrc", "a");
9248       emitcode ("", "%05d$:", tlbl1->key + 100);
9249       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9250       popB (pushedB);
9251       aopPut (result, "a", 0);
9252       goto release;
9253     }
9254
9255   reAdjustPreg (AOP (result));
9256   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9257   emitcode ("", "%05d$:", tlbl->key + 100);
9258   CLRC;
9259   while (size--)
9260     {
9261       l = aopGet (result, offset, FALSE, FALSE);
9262       MOVA (l);
9263       emitcode ("rrc", "a");
9264       aopPut (result, "a", offset--);
9265     }
9266   reAdjustPreg (AOP (result));
9267
9268   emitcode ("", "%05d$:", tlbl1->key + 100);
9269   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9270   popB (pushedB);
9271
9272 release:
9273   freeAsmop (result, NULL, ic, TRUE);
9274   freeAsmop (left, NULL, ic, TRUE);
9275 }
9276
9277 /*-----------------------------------------------------------------*/
9278 /* emitPtrByteGet - emits code to get a byte into A through a      */
9279 /*                  pointer register (R0, R1, or DPTR). The        */
9280 /*                  original value of A can be preserved in B.     */
9281 /*-----------------------------------------------------------------*/
9282 static void
9283 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9284 {
9285   switch (p_type)
9286     {
9287     case IPOINTER:
9288     case POINTER:
9289       if (preserveAinB)
9290         emitcode ("mov", "b,a");
9291       emitcode ("mov", "a,@%s", rname);
9292       break;
9293
9294     case PPOINTER:
9295       if (preserveAinB)
9296         emitcode ("mov", "b,a");
9297       emitcode ("movx", "a,@%s", rname);
9298       break;
9299
9300     case FPOINTER:
9301       if (preserveAinB)
9302         emitcode ("mov", "b,a");
9303       emitcode ("movx", "a,@dptr");
9304       break;
9305
9306     case CPOINTER:
9307       if (preserveAinB)
9308         emitcode ("mov", "b,a");
9309       emitcode ("clr", "a");
9310       emitcode ("movc", "a,@a+dptr");
9311       break;
9312
9313     case GPOINTER:
9314       if (preserveAinB)
9315         {
9316           emitcode ("push", "b");
9317           emitcode ("push", "acc");
9318         }
9319       emitcode ("lcall", "__gptrget");
9320       if (preserveAinB)
9321         emitcode ("pop", "b");
9322       break;
9323     }
9324 }
9325
9326 /*-----------------------------------------------------------------*/
9327 /* emitPtrByteSet - emits code to set a byte from src through a    */
9328 /*                  pointer register (R0, R1, or DPTR).            */
9329 /*-----------------------------------------------------------------*/
9330 static void
9331 emitPtrByteSet (char *rname, int p_type, char *src)
9332 {
9333   switch (p_type)
9334     {
9335     case IPOINTER:
9336     case POINTER:
9337       if (*src=='@')
9338         {
9339           MOVA (src);
9340           emitcode ("mov", "@%s,a", rname);
9341         }
9342       else
9343         emitcode ("mov", "@%s,%s", rname, src);
9344       break;
9345
9346     case PPOINTER:
9347       MOVA (src);
9348       emitcode ("movx", "@%s,a", rname);
9349       break;
9350
9351     case FPOINTER:
9352       MOVA (src);
9353       emitcode ("movx", "@dptr,a");
9354       break;
9355
9356     case GPOINTER:
9357       MOVA (src);
9358       emitcode ("lcall", "__gptrput");
9359       break;
9360     }
9361 }
9362
9363 /*-----------------------------------------------------------------*/
9364 /* genUnpackBits - generates code for unpacking bits               */
9365 /*-----------------------------------------------------------------*/
9366 static void
9367 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9368 {
9369   int offset = 0;       /* result byte offset */
9370   int rsize;            /* result size */
9371   int rlen = 0;         /* remaining bitfield length */
9372   sym_link *etype;      /* bitfield type information */
9373   int blen;             /* bitfield length */
9374   int bstr;             /* bitfield starting bit within byte */
9375   char buffer[10];
9376
9377   D(emitcode (";     genUnpackBits",""));
9378
9379   etype = getSpec (operandType (result));
9380   rsize = getSize (operandType (result));
9381   blen = SPEC_BLEN (etype);
9382   bstr = SPEC_BSTR (etype);
9383
9384   if (ifx && blen <= 8)
9385     {
9386       emitPtrByteGet (rname, ptype, FALSE);
9387       if (blen == 1)
9388         {
9389           SNPRINTF (buffer, sizeof(buffer),
9390                     "acc.%d", bstr);
9391           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9392         }
9393       else
9394         {
9395           if (blen < 8)
9396             emitcode ("anl", "a,#0x%02x",
9397                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9398           genIfxJump (ifx, "a", NULL, NULL, NULL);
9399         }
9400       return;
9401     }
9402   wassert (!ifx);
9403
9404   /* If the bitfield length is less than a byte */
9405   if (blen < 8)
9406     {
9407       emitPtrByteGet (rname, ptype, FALSE);
9408       AccRol (8 - bstr);
9409       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9410       if (!SPEC_USIGN (etype))
9411         {
9412           /* signed bitfield */
9413           symbol *tlbl = newiTempLabel (NULL);
9414
9415           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9416           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9417           emitcode ("", "%05d$:", tlbl->key + 100);
9418         }
9419       aopPut (result, "a", offset++);
9420       goto finish;
9421     }
9422
9423   /* Bit field did not fit in a byte. Copy all
9424      but the partial byte at the end.  */
9425   for (rlen=blen;rlen>=8;rlen-=8)
9426     {
9427       emitPtrByteGet (rname, ptype, FALSE);
9428       aopPut (result, "a", offset++);
9429       if (rlen>8)
9430         emitcode ("inc", "%s", rname);
9431     }
9432
9433   /* Handle the partial byte at the end */
9434   if (rlen)
9435     {
9436       emitPtrByteGet (rname, ptype, FALSE);
9437       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9438       if (!SPEC_USIGN (etype))
9439         {
9440           /* signed bitfield */
9441           symbol *tlbl = newiTempLabel (NULL);
9442
9443           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9444           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9445           emitcode ("", "%05d$:", tlbl->key + 100);
9446         }
9447       aopPut (result, "a", offset++);
9448     }
9449
9450 finish:
9451   if (offset < rsize)
9452     {
9453       char *source;
9454
9455       if (SPEC_USIGN (etype))
9456         source = zero;
9457       else
9458         {
9459           /* signed bitfield: sign extension with 0x00 or 0xff */
9460           emitcode ("rlc", "a");
9461           emitcode ("subb", "a,acc");
9462
9463           source = "a";
9464         }
9465       rsize -= offset;
9466       while (rsize--)
9467         aopPut (result, source, offset++);
9468     }
9469 }
9470
9471
9472 /*-----------------------------------------------------------------*/
9473 /* genDataPointerGet - generates code when ptr offset is known     */
9474 /*-----------------------------------------------------------------*/
9475 static void
9476 genDataPointerGet (operand * left,
9477                    operand * result,
9478                    iCode * ic)
9479 {
9480   char *l;
9481   char buffer[256];
9482   int size, offset = 0;
9483
9484   D(emitcode (";     genDataPointerGet",""));
9485
9486   aopOp (result, ic, TRUE);
9487
9488   /* get the string representation of the name */
9489   l = aopGet (left, 0, FALSE, TRUE);
9490   size = AOP_SIZE (result);
9491   while (size--)
9492     {
9493       if (offset)
9494         sprintf (buffer, "(%s + %d)", l + 1, offset);
9495       else
9496         sprintf (buffer, "%s", l + 1);
9497       aopPut (result, buffer, offset++);
9498     }
9499
9500   freeAsmop (result, NULL, ic, TRUE);
9501   freeAsmop (left, NULL, ic, TRUE);
9502 }
9503
9504 /*-----------------------------------------------------------------*/
9505 /* genNearPointerGet - emitcode for near pointer fetch             */
9506 /*-----------------------------------------------------------------*/
9507 static void
9508 genNearPointerGet (operand * left,
9509                    operand * result,
9510                    iCode * ic,
9511                    iCode * pi,
9512                    iCode * ifx)
9513 {
9514   asmop *aop = NULL;
9515   regs *preg = NULL;
9516   char *rname;
9517   sym_link *rtype, *retype;
9518   sym_link *ltype = operandType (left);
9519   char buffer[80];
9520
9521   D(emitcode (";     genNearPointerGet",""));
9522
9523   rtype = operandType (result);
9524   retype = getSpec (rtype);
9525
9526   aopOp (left, ic, FALSE);
9527
9528   /* if left is rematerialisable and
9529      result is not bitfield variable type and
9530      the left is pointer to data space i.e
9531      lower 128 bytes of space */
9532   if (AOP_TYPE (left) == AOP_IMMD &&
9533       !IS_BITFIELD (retype) &&
9534       DCL_TYPE (ltype) == POINTER)
9535     {
9536       genDataPointerGet (left, result, ic);
9537       return;
9538     }
9539
9540  /* if the value is already in a pointer register
9541      then don't need anything more */
9542   if (!AOP_INPREG (AOP (left)))
9543     {
9544       if (IS_AOP_PREG (left))
9545         {
9546           // Aha, it is a pointer, just in disguise.
9547           rname = aopGet (left, 0, FALSE, FALSE);
9548           if (*rname != '@')
9549             {
9550               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9551                       __FILE__, __LINE__);
9552             }
9553           else
9554             {
9555               // Expected case.
9556               emitcode ("mov", "a%s,%s", rname + 1, rname);
9557               rname++;  // skip the '@'.
9558             }
9559         }
9560       else
9561         {
9562           /* otherwise get a free pointer register */
9563           aop = newAsmop (0);
9564           preg = getFreePtr (ic, &aop, FALSE);
9565           emitcode ("mov", "%s,%s",
9566                     preg->name,
9567                     aopGet (left, 0, FALSE, TRUE));
9568           rname = preg->name;
9569         }
9570     }
9571   else
9572     rname = aopGet (left, 0, FALSE, FALSE);
9573
9574   //aopOp (result, ic, FALSE);
9575   aopOp (result, ic, result?TRUE:FALSE);
9576
9577   /* if bitfield then unpack the bits */
9578   if (IS_BITFIELD (retype))
9579     genUnpackBits (result, rname, POINTER, ifx);
9580   else
9581     {
9582       /* we have can just get the values */
9583       int size = AOP_SIZE (result);
9584       int offset = 0;
9585
9586       while (size--)
9587         {
9588           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9589             {
9590
9591               emitcode ("mov", "a,@%s", rname);
9592               if (!ifx)
9593                 aopPut (result, "a", offset);
9594             }
9595           else
9596             {
9597               sprintf (buffer, "@%s", rname);
9598               aopPut (result, buffer, offset);
9599             }
9600           offset++;
9601           if (size || pi)
9602             emitcode ("inc", "%s", rname);
9603         }
9604     }
9605
9606   /* now some housekeeping stuff */
9607   if (aop)       /* we had to allocate for this iCode */
9608     {
9609       if (pi) { /* post increment present */
9610         aopPut (left, rname, 0);
9611       }
9612       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9613     }
9614   else
9615     {
9616       /* we did not allocate which means left
9617          already in a pointer register, then
9618          if size > 0 && this could be used again
9619          we have to point it back to where it
9620          belongs */
9621       if ((AOP_SIZE (result) > 1 &&
9622            !OP_SYMBOL (left)->remat &&
9623            (OP_SYMBOL (left)->liveTo > ic->seq ||
9624             ic->depth)) &&
9625           !pi)
9626         {
9627           int size = AOP_SIZE (result) - 1;
9628           while (size--)
9629             emitcode ("dec", "%s", rname);
9630         }
9631     }
9632
9633   if (ifx && !ifx->generated)
9634     {
9635       genIfxJump (ifx, "a", left, NULL, result);
9636     }
9637
9638   /* done */
9639   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9640   freeAsmop (left, NULL, ic, TRUE);
9641   if (pi) pi->generated = 1;
9642 }
9643
9644 /*-----------------------------------------------------------------*/
9645 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9646 /*-----------------------------------------------------------------*/
9647 static void
9648 genPagedPointerGet (operand * left,
9649                     operand * result,
9650                     iCode * ic,
9651                     iCode *pi,
9652                     iCode *ifx)
9653 {
9654   asmop *aop = NULL;
9655   regs *preg = NULL;
9656   char *rname;
9657   sym_link *rtype, *retype;
9658
9659   D(emitcode (";     genPagedPointerGet",""));
9660
9661   rtype = operandType (result);
9662   retype = getSpec (rtype);
9663
9664   aopOp (left, ic, FALSE);
9665
9666   /* if the value is already in a pointer register
9667      then don't need anything more */
9668   if (!AOP_INPREG (AOP (left)))
9669     {
9670       /* otherwise get a free pointer register */
9671       aop = newAsmop (0);
9672       preg = getFreePtr (ic, &aop, FALSE);
9673       emitcode ("mov", "%s,%s",
9674                 preg->name,
9675                 aopGet (left, 0, FALSE, TRUE));
9676       rname = preg->name;
9677     }
9678   else
9679     rname = aopGet (left, 0, FALSE, FALSE);
9680
9681   aopOp (result, ic, FALSE);
9682
9683   /* if bitfield then unpack the bits */
9684   if (IS_BITFIELD (retype))
9685     genUnpackBits (result, rname, PPOINTER, ifx);
9686   else
9687     {
9688       /* we have can just get the values */
9689       int size = AOP_SIZE (result);
9690       int offset = 0;
9691
9692       while (size--)
9693         {
9694
9695           emitcode ("movx", "a,@%s", rname);
9696           if (!ifx)
9697             aopPut (result, "a", offset);
9698
9699           offset++;
9700
9701           if (size || pi)
9702             emitcode ("inc", "%s", rname);
9703         }
9704     }
9705
9706   /* now some housekeeping stuff */
9707   if (aop) /* we had to allocate for this iCode */
9708     {
9709       if (pi)
9710         aopPut (left, rname, 0);
9711       freeAsmop (NULL, aop, ic, TRUE);
9712     }
9713   else
9714     {
9715       /* we did not allocate which means left
9716          already in a pointer register, then
9717          if size > 0 && this could be used again
9718          we have to point it back to where it
9719          belongs */
9720       if ((AOP_SIZE (result) > 1 &&
9721            !OP_SYMBOL (left)->remat &&
9722            (OP_SYMBOL (left)->liveTo > ic->seq ||
9723             ic->depth)) &&
9724           !pi)
9725         {
9726           int size = AOP_SIZE (result) - 1;
9727           while (size--)
9728             emitcode ("dec", "%s", rname);
9729         }
9730     }
9731
9732   if (ifx && !ifx->generated)
9733     {
9734       genIfxJump (ifx, "a", left, NULL, result);
9735     }
9736
9737   /* done */
9738   freeAsmop (result, NULL, ic, TRUE);
9739   freeAsmop (left, NULL, ic, TRUE);
9740   if (pi) pi->generated = 1;
9741 }
9742
9743 /*--------------------------------------------------------------------*/
9744 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9745 /*--------------------------------------------------------------------*/
9746 static void
9747 loadDptrFromOperand (operand *op, bool loadBToo)
9748 {
9749   if (AOP_TYPE (op) != AOP_STR)
9750     {
9751       /* if this is rematerializable */
9752       if (AOP_TYPE (op) == AOP_IMMD)
9753         {
9754           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9755           if (loadBToo)
9756             {
9757               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9758                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9759               else
9760                 {
9761                   wassertl(FALSE, "need pointerCode");
9762                   emitcode ("", "; mov b,???");
9763                   /* genPointerGet and genPointerSet originally did different
9764                   ** things for this case. Both seem wrong.
9765                   ** from genPointerGet:
9766                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9767                   ** from genPointerSet:
9768                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9769                   */
9770                 }
9771             }
9772         }
9773       else if (AOP_TYPE (op) == AOP_DPTR)
9774         {
9775           if (loadBToo)
9776             {
9777               MOVA (aopGet (op, 0, FALSE, FALSE));
9778               emitcode ("push", "acc");
9779               MOVA (aopGet (op, 1, FALSE, FALSE));
9780               emitcode ("push", "acc");
9781               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9782               emitcode ("pop", "dph");
9783               emitcode ("pop", "dpl");
9784             }
9785           else
9786             {
9787               MOVA (aopGet (op, 0, FALSE, FALSE));
9788               emitcode ("push", "acc");
9789               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9790               emitcode ("pop", "dpl");
9791             }
9792         }
9793       else
9794         {                       /* we need to get it byte by byte */
9795           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9796           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9797           if (loadBToo)
9798             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9799         }
9800     }
9801 }
9802
9803 /*-----------------------------------------------------------------*/
9804 /* genFarPointerGet - gget value from far space                    */
9805 /*-----------------------------------------------------------------*/
9806 static void
9807 genFarPointerGet (operand * left,
9808                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9809 {
9810   int size, offset;
9811   sym_link *retype = getSpec (operandType (result));
9812
9813   D(emitcode (";     genFarPointerGet",""));
9814
9815   aopOp (left, ic, FALSE);
9816   loadDptrFromOperand (left, FALSE);
9817
9818   /* so dptr now contains the address */
9819   aopOp (result, ic, FALSE);
9820
9821   /* if bit then unpack */
9822   if (IS_BITFIELD (retype))
9823     genUnpackBits (result, "dptr", FPOINTER, ifx);
9824   else
9825     {
9826       size = AOP_SIZE (result);
9827       offset = 0;
9828
9829       while (size--)
9830         {
9831           emitcode ("movx", "a,@dptr");
9832           if (!ifx)
9833             aopPut (result, "a", offset++);
9834           if (size || pi)
9835             emitcode ("inc", "dptr");
9836         }
9837     }
9838
9839   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9840     {
9841       aopPut (left, "dpl", 0);
9842       aopPut (left, "dph", 1);
9843       pi->generated = 1;
9844     }
9845
9846   if (ifx && !ifx->generated)
9847     {
9848       genIfxJump (ifx, "a", left, NULL, result);
9849     }
9850
9851   freeAsmop (result, NULL, ic, TRUE);
9852   freeAsmop (left, NULL, ic, TRUE);
9853 }
9854
9855 /*-----------------------------------------------------------------*/
9856 /* genCodePointerGet - get value from code space                   */
9857 /*-----------------------------------------------------------------*/
9858 static void
9859 genCodePointerGet (operand * left,
9860                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9861 {
9862   int size, offset;
9863   sym_link *retype = getSpec (operandType (result));
9864
9865   D(emitcode (";     genCodePointerGet",""));
9866
9867   aopOp (left, ic, FALSE);
9868   loadDptrFromOperand (left, FALSE);
9869
9870   /* so dptr now contains the address */
9871   aopOp (result, ic, FALSE);
9872
9873   /* if bit then unpack */
9874   if (IS_BITFIELD (retype))
9875     genUnpackBits (result, "dptr", CPOINTER, ifx);
9876   else
9877     {
9878       size = AOP_SIZE (result);
9879       offset = 0;
9880
9881       while (size--)
9882         {
9883           emitcode ("clr", "a");
9884           emitcode ("movc", "a,@a+dptr");
9885           if (!ifx)
9886             aopPut (result, "a", offset++);
9887           if (size || pi)
9888             emitcode ("inc", "dptr");
9889         }
9890     }
9891
9892   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9893     {
9894       aopPut (left, "dpl", 0);
9895       aopPut (left, "dph", 1);
9896       pi->generated = 1;
9897     }
9898
9899   if (ifx && !ifx->generated)
9900     {
9901       genIfxJump (ifx, "a", left, NULL, result);
9902     }
9903
9904   freeAsmop (result, NULL, ic, TRUE);
9905   freeAsmop (left, NULL, ic, TRUE);
9906 }
9907
9908 /*-----------------------------------------------------------------*/
9909 /* genGenPointerGet - get value from generic pointer space         */
9910 /*-----------------------------------------------------------------*/
9911 static void
9912 genGenPointerGet (operand * left,
9913                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9914 {
9915   int size, offset;
9916   sym_link *retype = getSpec (operandType (result));
9917
9918   D(emitcode (";     genGenPointerGet",""));
9919
9920   aopOp (left, ic, FALSE);
9921   loadDptrFromOperand (left, TRUE);
9922
9923   /* so dptr know contains the address */
9924   aopOp (result, ic, FALSE);
9925
9926   /* if bit then unpack */
9927   if (IS_BITFIELD (retype))
9928     genUnpackBits (result, "dptr", GPOINTER, ifx);
9929   else
9930     {
9931       size = AOP_SIZE (result);
9932       offset = 0;
9933
9934       while (size--)
9935         {
9936           emitcode ("lcall", "__gptrget");
9937           if (!ifx)
9938             aopPut (result, "a", offset++);
9939           if (size || pi)
9940             emitcode ("inc", "dptr");
9941         }
9942     }
9943
9944   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9945     {
9946       aopPut (left, "dpl", 0);
9947       aopPut (left, "dph", 1);
9948       pi->generated = 1;
9949     }
9950
9951   if (ifx && !ifx->generated)
9952     {
9953       genIfxJump (ifx, "a", left, NULL, result);
9954     }
9955
9956   freeAsmop (result, NULL, ic, TRUE);
9957   freeAsmop (left, NULL, ic, TRUE);
9958 }
9959
9960 /*-----------------------------------------------------------------*/
9961 /* genPointerGet - generate code for pointer get                   */
9962 /*-----------------------------------------------------------------*/
9963 static void
9964 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9965 {
9966   operand *left, *result;
9967   sym_link *type, *etype;
9968   int p_type;
9969
9970   D(emitcode (";     genPointerGet",""));
9971
9972   left = IC_LEFT (ic);
9973   result = IC_RESULT (ic);
9974
9975   if (getSize (operandType (result))>1)
9976     ifx = NULL;
9977
9978   /* depending on the type of pointer we need to
9979      move it to the correct pointer register */
9980   type = operandType (left);
9981   etype = getSpec (type);
9982   /* if left is of type of pointer then it is simple */
9983   if (IS_PTR (type) && !IS_FUNC (type->next))
9984     p_type = DCL_TYPE (type);
9985   else
9986     {
9987       /* we have to go by the storage class */
9988       p_type = PTR_TYPE (SPEC_OCLS (etype));
9989     }
9990
9991   /* special case when cast remat */
9992   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9993       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9994           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9995           type = operandType (left);
9996           p_type = DCL_TYPE (type);
9997   }
9998   /* now that we have the pointer type we assign
9999      the pointer values */
10000   switch (p_type)
10001     {
10002
10003     case POINTER:
10004     case IPOINTER:
10005       genNearPointerGet (left, result, ic, pi, ifx);
10006       break;
10007
10008     case PPOINTER:
10009       genPagedPointerGet (left, result, ic, pi, ifx);
10010       break;
10011
10012     case FPOINTER:
10013       genFarPointerGet (left, result, ic, pi, ifx);
10014       break;
10015
10016     case CPOINTER:
10017       genCodePointerGet (left, result, ic, pi, ifx);
10018       break;
10019
10020     case GPOINTER:
10021       genGenPointerGet (left, result, ic, pi, ifx);
10022       break;
10023     }
10024
10025 }
10026
10027
10028
10029 /*-----------------------------------------------------------------*/
10030 /* genPackBits - generates code for packed bit storage             */
10031 /*-----------------------------------------------------------------*/
10032 static void
10033 genPackBits (sym_link * etype,
10034              operand * right,
10035              char *rname, int p_type)
10036 {
10037   int offset = 0;       /* source byte offset */
10038   int rlen = 0;         /* remaining bitfield length */
10039   int blen;             /* bitfield length */
10040   int bstr;             /* bitfield starting bit within byte */
10041   int litval;           /* source literal value (if AOP_LIT) */
10042   unsigned char mask;   /* bitmask within current byte */
10043
10044   D(emitcode (";     genPackBits",""));
10045
10046   blen = SPEC_BLEN (etype);
10047   bstr = SPEC_BSTR (etype);
10048
10049   /* If the bitfield length is less than a byte */
10050   if (blen < 8)
10051     {
10052       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10053               (unsigned char) (0xFF >> (8 - bstr)));
10054
10055       if (AOP_TYPE (right) == AOP_LIT)
10056         {
10057           /* Case with a bitfield length <8 and literal source
10058           */
10059           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10060           litval <<= bstr;
10061           litval &= (~mask) & 0xff;
10062           emitPtrByteGet (rname, p_type, FALSE);
10063           if ((mask|litval)!=0xff)
10064             emitcode ("anl","a,#0x%02x", mask);
10065           if (litval)
10066             emitcode ("orl","a,#0x%02x", litval);
10067         }
10068       else
10069         {
10070           if ((blen==1) && (p_type!=GPOINTER))
10071             {
10072               /* Case with a bitfield length == 1 and no generic pointer
10073               */
10074               if (AOP_TYPE (right) == AOP_CRY)
10075                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10076               else
10077                 {
10078                   MOVA (aopGet (right, 0, FALSE, FALSE));
10079                   emitcode ("rrc","a");
10080                 }
10081               emitPtrByteGet (rname, p_type, FALSE);
10082               emitcode ("mov","acc.%d,c",bstr);
10083             }
10084           else
10085             {
10086               bool pushedB;
10087               /* Case with a bitfield length < 8 and arbitrary source
10088               */
10089               MOVA (aopGet (right, 0, FALSE, FALSE));
10090               /* shift and mask source value */
10091               AccLsh (bstr);
10092               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10093
10094               pushedB = pushB ();
10095               /* transfer A to B and get next byte */
10096               emitPtrByteGet (rname, p_type, TRUE);
10097
10098               emitcode ("anl", "a,#0x%02x", mask);
10099               emitcode ("orl", "a,b");
10100               if (p_type == GPOINTER)
10101                 emitcode ("pop", "b");
10102
10103               popB (pushedB);
10104            }
10105         }
10106
10107       emitPtrByteSet (rname, p_type, "a");
10108       return;
10109     }
10110
10111   /* Bit length is greater than 7 bits. In this case, copy  */
10112   /* all except the partial byte at the end                 */
10113   for (rlen=blen;rlen>=8;rlen-=8)
10114     {
10115       emitPtrByteSet (rname, p_type,
10116                       aopGet (right, offset++, FALSE, TRUE) );
10117       if (rlen>8)
10118         emitcode ("inc", "%s", rname);
10119     }
10120
10121   /* If there was a partial byte at the end */
10122   if (rlen)
10123     {
10124       mask = (((unsigned char) -1 << rlen) & 0xff);
10125
10126       if (AOP_TYPE (right) == AOP_LIT)
10127         {
10128           /* Case with partial byte and literal source
10129           */
10130           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10131           litval >>= (blen-rlen);
10132           litval &= (~mask) & 0xff;
10133           emitPtrByteGet (rname, p_type, FALSE);
10134           if ((mask|litval)!=0xff)
10135             emitcode ("anl","a,#0x%02x", mask);
10136           if (litval)
10137             emitcode ("orl","a,#0x%02x", litval);
10138         }
10139       else
10140         {
10141           bool pushedB;
10142           /* Case with partial byte and arbitrary source
10143           */
10144           MOVA (aopGet (right, offset++, FALSE, FALSE));
10145           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10146
10147           pushedB = pushB ();
10148           /* transfer A to B and get next byte */
10149           emitPtrByteGet (rname, p_type, TRUE);
10150
10151           emitcode ("anl", "a,#0x%02x", mask);
10152           emitcode ("orl", "a,b");
10153           if (p_type == GPOINTER)
10154             emitcode ("pop", "b");
10155
10156           popB (pushedB);
10157         }
10158       emitPtrByteSet (rname, p_type, "a");
10159     }
10160
10161 }
10162
10163
10164 /*-----------------------------------------------------------------*/
10165 /* genDataPointerSet - remat pointer to data space                 */
10166 /*-----------------------------------------------------------------*/
10167 static void
10168 genDataPointerSet (operand * right,
10169                    operand * result,
10170                    iCode * ic)
10171 {
10172   int size, offset = 0;
10173   char *l, buffer[256];
10174
10175   D(emitcode (";     genDataPointerSet",""));
10176
10177   aopOp (right, ic, FALSE);
10178
10179   l = aopGet (result, 0, FALSE, TRUE);
10180   size = AOP_SIZE (right);
10181   while (size--)
10182     {
10183       if (offset)
10184         sprintf (buffer, "(%s + %d)", l + 1, offset);
10185       else
10186         sprintf (buffer, "%s", l + 1);
10187       emitcode ("mov", "%s,%s", buffer,
10188                 aopGet (right, offset++, FALSE, FALSE));
10189     }
10190
10191   freeAsmop (result, NULL, ic, TRUE);
10192   freeAsmop (right, NULL, ic, TRUE);
10193 }
10194
10195 /*-----------------------------------------------------------------*/
10196 /* genNearPointerSet - emitcode for near pointer put                */
10197 /*-----------------------------------------------------------------*/
10198 static void
10199 genNearPointerSet (operand * right,
10200                    operand * result,
10201                    iCode * ic,
10202                    iCode * pi)
10203 {
10204   asmop *aop = NULL;
10205   regs *preg = NULL;
10206   char *rname, *l;
10207   sym_link *retype, *letype;
10208   sym_link *ptype = operandType (result);
10209
10210   D(emitcode (";     genNearPointerSet",""));
10211
10212   retype = getSpec (operandType (right));
10213   letype = getSpec (ptype);
10214   aopOp (result, ic, FALSE);
10215
10216   /* if the result is rematerializable &
10217      in data space & not a bit variable */
10218   if (AOP_TYPE (result) == AOP_IMMD &&
10219       DCL_TYPE (ptype) == POINTER &&
10220       !IS_BITVAR (retype) &&
10221       !IS_BITVAR (letype))
10222     {
10223       genDataPointerSet (right, result, ic);
10224       return;
10225     }
10226
10227   /* if the value is already in a pointer register
10228      then don't need anything more */
10229   if (!AOP_INPREG (AOP (result)))
10230     {
10231         if (
10232             //AOP_TYPE (result) == AOP_STK
10233             IS_AOP_PREG(result)
10234             )
10235         {
10236             // Aha, it is a pointer, just in disguise.
10237             rname = aopGet (result, 0, FALSE, FALSE);
10238             if (*rname != '@')
10239             {
10240                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10241                         __FILE__, __LINE__);
10242             }
10243             else
10244             {
10245                 // Expected case.
10246                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10247                 rname++;  // skip the '@'.
10248             }
10249         }
10250         else
10251         {
10252             /* otherwise get a free pointer register */
10253             aop = newAsmop (0);
10254             preg = getFreePtr (ic, &aop, FALSE);
10255             emitcode ("mov", "%s,%s",
10256                       preg->name,
10257                       aopGet (result, 0, FALSE, TRUE));
10258             rname = preg->name;
10259         }
10260     }
10261     else
10262     {
10263         rname = aopGet (result, 0, FALSE, FALSE);
10264     }
10265
10266   aopOp (right, ic, FALSE);
10267
10268   /* if bitfield then unpack the bits */
10269   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10270     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10271   else
10272     {
10273       /* we have can just get the values */
10274       int size = AOP_SIZE (right);
10275       int offset = 0;
10276
10277       while (size--)
10278         {
10279           l = aopGet (right, offset, FALSE, TRUE);
10280           if (*l == '@')
10281             {
10282               MOVA (l);
10283               emitcode ("mov", "@%s,a", rname);
10284             }
10285           else
10286             emitcode ("mov", "@%s,%s", rname, l);
10287           if (size || pi)
10288             emitcode ("inc", "%s", rname);
10289           offset++;
10290         }
10291     }
10292
10293   /* now some housekeeping stuff */
10294   if (aop) /* we had to allocate for this iCode */
10295     {
10296       if (pi)
10297         aopPut (result, rname, 0);
10298       freeAsmop (NULL, aop, ic, TRUE);
10299     }
10300   else
10301     {
10302       /* we did not allocate which means left
10303          already in a pointer register, then
10304          if size > 0 && this could be used again
10305          we have to point it back to where it
10306          belongs */
10307       if ((AOP_SIZE (right) > 1 &&
10308            !OP_SYMBOL (result)->remat &&
10309            (OP_SYMBOL (result)->liveTo > ic->seq ||
10310             ic->depth)) &&
10311           !pi)
10312         {
10313           int size = AOP_SIZE (right) - 1;
10314           while (size--)
10315             emitcode ("dec", "%s", rname);
10316         }
10317     }
10318
10319   /* done */
10320   if (pi) pi->generated = 1;
10321   freeAsmop (result, NULL, ic, TRUE);
10322   freeAsmop (right, NULL, ic, TRUE);
10323 }
10324
10325 /*-----------------------------------------------------------------*/
10326 /* genPagedPointerSet - emitcode for Paged pointer put             */
10327 /*-----------------------------------------------------------------*/
10328 static void
10329 genPagedPointerSet (operand * right,
10330                     operand * result,
10331                     iCode * ic,
10332                     iCode * pi)
10333 {
10334   asmop *aop = NULL;
10335   regs *preg = NULL;
10336   char *rname, *l;
10337   sym_link *retype, *letype;
10338
10339   D(emitcode (";     genPagedPointerSet",""));
10340
10341   retype = getSpec (operandType (right));
10342   letype = getSpec (operandType (result));
10343
10344   aopOp (result, ic, FALSE);
10345
10346   /* if the value is already in a pointer register
10347      then don't need anything more */
10348   if (!AOP_INPREG (AOP (result)))
10349     {
10350       /* otherwise get a free pointer register */
10351       aop = newAsmop (0);
10352       preg = getFreePtr (ic, &aop, FALSE);
10353       emitcode ("mov", "%s,%s",
10354                 preg->name,
10355                 aopGet (result, 0, FALSE, TRUE));
10356       rname = preg->name;
10357     }
10358   else
10359     rname = aopGet (result, 0, FALSE, FALSE);
10360
10361   aopOp (right, ic, FALSE);
10362
10363   /* if bitfield then unpack the bits */
10364   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10365     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10366   else
10367     {
10368       /* we have can just get the values */
10369       int size = AOP_SIZE (right);
10370       int offset = 0;
10371
10372       while (size--)
10373         {
10374           l = aopGet (right, offset, FALSE, TRUE);
10375
10376           MOVA (l);
10377           emitcode ("movx", "@%s,a", rname);
10378
10379           if (size || pi)
10380             emitcode ("inc", "%s", rname);
10381
10382           offset++;
10383         }
10384     }
10385
10386   /* now some housekeeping stuff */
10387   if (aop) /* we had to allocate for this iCode */
10388     {
10389       if (pi)
10390         aopPut (result, rname, 0);
10391       freeAsmop (NULL, aop, ic, TRUE);
10392     }
10393   else
10394     {
10395       /* we did not allocate which means left
10396          already in a pointer register, then
10397          if size > 0 && this could be used again
10398          we have to point it back to where it
10399          belongs */
10400       if (AOP_SIZE (right) > 1 &&
10401           !OP_SYMBOL (result)->remat &&
10402           (OP_SYMBOL (result)->liveTo > ic->seq ||
10403            ic->depth))
10404         {
10405           int size = AOP_SIZE (right) - 1;
10406           while (size--)
10407             emitcode ("dec", "%s", rname);
10408         }
10409     }
10410
10411   /* done */
10412   if (pi) pi->generated = 1;
10413   freeAsmop (result, NULL, ic, TRUE);
10414   freeAsmop (right, NULL, ic, TRUE);
10415 }
10416
10417 /*-----------------------------------------------------------------*/
10418 /* genFarPointerSet - set value from far space                     */
10419 /*-----------------------------------------------------------------*/
10420 static void
10421 genFarPointerSet (operand * right,
10422                   operand * result, iCode * ic, iCode * pi)
10423 {
10424   int size, offset;
10425   sym_link *retype = getSpec (operandType (right));
10426   sym_link *letype = getSpec (operandType (result));
10427
10428   D(emitcode (";     genFarPointerSet",""));
10429
10430   aopOp (result, ic, FALSE);
10431   loadDptrFromOperand (result, FALSE);
10432
10433   /* so dptr know contains the address */
10434   aopOp (right, ic, FALSE);
10435
10436   /* if bit then unpack */
10437   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10438     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10439   else
10440     {
10441       size = AOP_SIZE (right);
10442       offset = 0;
10443
10444       while (size--)
10445         {
10446           char *l = aopGet (right, offset++, FALSE, FALSE);
10447           MOVA (l);
10448           emitcode ("movx", "@dptr,a");
10449           if (size || pi)
10450             emitcode ("inc", "dptr");
10451         }
10452     }
10453   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10454     aopPut (result, "dpl", 0);
10455     aopPut (result, "dph", 1);
10456     pi->generated=1;
10457   }
10458   freeAsmop (result, NULL, ic, TRUE);
10459   freeAsmop (right, NULL, ic, TRUE);
10460 }
10461
10462 /*-----------------------------------------------------------------*/
10463 /* genGenPointerSet - set value from generic pointer space         */
10464 /*-----------------------------------------------------------------*/
10465 static void
10466 genGenPointerSet (operand * right,
10467                   operand * result, iCode * ic, iCode * pi)
10468 {
10469   int size, offset;
10470   sym_link *retype = getSpec (operandType (right));
10471   sym_link *letype = getSpec (operandType (result));
10472
10473   D(emitcode (";     genGenPointerSet",""));
10474
10475   aopOp (result, ic, FALSE);
10476   loadDptrFromOperand (result, TRUE);
10477
10478   /* so dptr know contains the address */
10479   aopOp (right, ic, FALSE);
10480
10481   /* if bit then unpack */
10482   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10483     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10484   else
10485     {
10486       size = AOP_SIZE (right);
10487       offset = 0;
10488
10489       while (size--)
10490         {
10491           char *l = aopGet (right, offset++, FALSE, FALSE);
10492           MOVA (l);
10493           emitcode ("lcall", "__gptrput");
10494           if (size || pi)
10495             emitcode ("inc", "dptr");
10496         }
10497     }
10498
10499   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10500     aopPut (result, "dpl", 0);
10501     aopPut (result, "dph", 1);
10502     pi->generated=1;
10503   }
10504   freeAsmop (result, NULL, ic, TRUE);
10505   freeAsmop (right, NULL, ic, TRUE);
10506 }
10507
10508 /*-----------------------------------------------------------------*/
10509 /* genPointerSet - stores the value into a pointer location        */
10510 /*-----------------------------------------------------------------*/
10511 static void
10512 genPointerSet (iCode * ic, iCode *pi)
10513 {
10514   operand *right, *result;
10515   sym_link *type, *etype;
10516   int p_type;
10517
10518   D(emitcode (";     genPointerSet",""));
10519
10520   right = IC_RIGHT (ic);
10521   result = IC_RESULT (ic);
10522
10523   /* depending on the type of pointer we need to
10524      move it to the correct pointer register */
10525   type = operandType (result);
10526   etype = getSpec (type);
10527   /* if left is of type of pointer then it is simple */
10528   if (IS_PTR (type) && !IS_FUNC (type->next))
10529     {
10530       p_type = DCL_TYPE (type);
10531     }
10532   else
10533     {
10534       /* we have to go by the storage class */
10535       p_type = PTR_TYPE (SPEC_OCLS (etype));
10536     }
10537
10538   /* special case when cast remat */
10539   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10540       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10541           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10542           type = operandType (result);
10543           p_type = DCL_TYPE (type);
10544   }
10545   /* now that we have the pointer type we assign
10546      the pointer values */
10547   switch (p_type)
10548     {
10549
10550     case POINTER:
10551     case IPOINTER:
10552       genNearPointerSet (right, result, ic, pi);
10553       break;
10554
10555     case PPOINTER:
10556       genPagedPointerSet (right, result, ic, pi);
10557       break;
10558
10559     case FPOINTER:
10560       genFarPointerSet (right, result, ic, pi);
10561       break;
10562
10563     case GPOINTER:
10564       genGenPointerSet (right, result, ic, pi);
10565       break;
10566
10567     default:
10568       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10569               "genPointerSet: illegal pointer type");
10570     }
10571
10572 }
10573
10574 /*-----------------------------------------------------------------*/
10575 /* genIfx - generate code for Ifx statement                        */
10576 /*-----------------------------------------------------------------*/
10577 static void
10578 genIfx (iCode * ic, iCode * popIc)
10579 {
10580   operand *cond = IC_COND (ic);
10581   int isbit = 0;
10582   char *dup = NULL;
10583
10584   D(emitcode (";     genIfx",""));
10585
10586   aopOp (cond, ic, FALSE);
10587
10588   /* get the value into acc */
10589   if (AOP_TYPE (cond) != AOP_CRY)
10590     toBoolean (cond);
10591   else
10592     {
10593       isbit = 1;
10594       if (AOP(cond)->aopu.aop_dir)
10595         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10596     }
10597   /* the result is now in the accumulator or a directly addressable bit */
10598   freeAsmop (cond, NULL, ic, TRUE);
10599
10600   /* if there was something to be popped then do it */
10601   if (popIc)
10602     genIpop (popIc);
10603
10604   /* if the condition is a bit variable */
10605   if (isbit && dup)
10606     genIfxJump(ic, dup, NULL, NULL, NULL);
10607   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10608     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10609   else if (isbit && !IS_ITEMP (cond))
10610     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10611   else
10612     genIfxJump (ic, "a", NULL, NULL, NULL);
10613
10614   ic->generated = 1;
10615 }
10616
10617 /*-----------------------------------------------------------------*/
10618 /* genAddrOf - generates code for address of                       */
10619 /*-----------------------------------------------------------------*/
10620 static void
10621 genAddrOf (iCode * ic)
10622 {
10623   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10624   int size, offset;
10625
10626   D(emitcode (";     genAddrOf",""));
10627
10628   aopOp (IC_RESULT (ic), ic, FALSE);
10629
10630   /* if the operand is on the stack then we
10631      need to get the stack offset of this
10632      variable */
10633   if (sym->onStack)
10634     {
10635       /* if it has an offset then we need to compute
10636          it */
10637       if (sym->stack)
10638         {
10639           emitcode ("mov", "a,%s", SYM_BP (sym));
10640           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10641                                          ((char) (sym->stack - _G.nRegsSaved)) :
10642                                          ((char) sym->stack)) & 0xff);
10643           aopPut (IC_RESULT (ic), "a", 0);
10644         }
10645       else
10646         {
10647           /* we can just move _bp */
10648           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10649         }
10650       /* fill the result with zero */
10651       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10652
10653       offset = 1;
10654       while (size--)
10655         {
10656           aopPut (IC_RESULT (ic), zero, offset++);
10657         }
10658
10659       goto release;
10660     }
10661
10662   /* object not on stack then we need the name */
10663   size = AOP_SIZE (IC_RESULT (ic));
10664   offset = 0;
10665
10666   while (size--)
10667     {
10668       char s[SDCC_NAME_MAX];
10669       if (offset)
10670         sprintf (s, "#(%s >> %d)",
10671                  sym->rname,
10672                  offset * 8);
10673       else
10674         sprintf (s, "#%s", sym->rname);
10675       aopPut (IC_RESULT (ic), s, offset++);
10676     }
10677
10678 release:
10679   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10680
10681 }
10682
10683 /*-----------------------------------------------------------------*/
10684 /* genFarFarAssign - assignment when both are in far space         */
10685 /*-----------------------------------------------------------------*/
10686 static void
10687 genFarFarAssign (operand * result, operand * right, iCode * ic)
10688 {
10689   int size = AOP_SIZE (right);
10690   int offset = 0;
10691   char *l;
10692
10693   D(emitcode (";     genFarFarAssign",""));
10694
10695   /* first push the right side on to the stack */
10696   while (size--)
10697     {
10698       l = aopGet (right, offset++, FALSE, FALSE);
10699       MOVA (l);
10700       emitcode ("push", "acc");
10701     }
10702
10703   freeAsmop (right, NULL, ic, FALSE);
10704   /* now assign DPTR to result */
10705   aopOp (result, ic, FALSE);
10706   size = AOP_SIZE (result);
10707   while (size--)
10708     {
10709       emitcode ("pop", "acc");
10710       aopPut (result, "a", --offset);
10711     }
10712   freeAsmop (result, NULL, ic, FALSE);
10713 }
10714
10715 /*-----------------------------------------------------------------*/
10716 /* genAssign - generate code for assignment                        */
10717 /*-----------------------------------------------------------------*/
10718 static void
10719 genAssign (iCode * ic)
10720 {
10721   operand *result, *right;
10722   int size, offset;
10723   unsigned long lit = 0L;
10724
10725   D(emitcode(";     genAssign",""));
10726
10727   result = IC_RESULT (ic);
10728   right = IC_RIGHT (ic);
10729
10730   /* if they are the same */
10731   if (operandsEqu (result, right) &&
10732       !isOperandVolatile (result, FALSE) &&
10733       !isOperandVolatile (right, FALSE))
10734     return;
10735
10736   aopOp (right, ic, FALSE);
10737
10738   /* special case both in far space */
10739   if (AOP_TYPE (right) == AOP_DPTR &&
10740       IS_TRUE_SYMOP (result) &&
10741       isOperandInFarSpace (result))
10742     {
10743
10744       genFarFarAssign (result, right, ic);
10745       return;
10746     }
10747
10748   aopOp (result, ic, TRUE);
10749
10750   /* if they are the same registers */
10751   if (sameRegs (AOP (right), AOP (result)) &&
10752       !isOperandVolatile (result, FALSE) &&
10753       !isOperandVolatile (right, FALSE))
10754     goto release;
10755
10756   /* if the result is a bit */
10757   if (AOP_TYPE (result) == AOP_CRY)
10758     {
10759
10760       /* if the right size is a literal then
10761          we know what the value is */
10762       if (AOP_TYPE (right) == AOP_LIT)
10763         {
10764           if (((int) operandLitValue (right)))
10765             aopPut (result, one, 0);
10766           else
10767             aopPut (result, zero, 0);
10768           goto release;
10769         }
10770
10771       /* the right is also a bit variable */
10772       if (AOP_TYPE (right) == AOP_CRY)
10773         {
10774           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10775           aopPut (result, "c", 0);
10776           goto release;
10777         }
10778
10779       /* we need to or */
10780       toBoolean (right);
10781       aopPut (result, "a", 0);
10782       goto release;
10783     }
10784
10785   /* bit variables done */
10786   /* general case */
10787   size = AOP_SIZE (result);
10788   offset = 0;
10789   if (AOP_TYPE (right) == AOP_LIT)
10790     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10791   if ((size > 1) &&
10792       (AOP_TYPE (result) != AOP_REG) &&
10793       (AOP_TYPE (right) == AOP_LIT) &&
10794       !IS_FLOAT (operandType (right)) &&
10795       (lit < 256L))
10796     {
10797       while ((size) && (lit))
10798         {
10799           aopPut (result,
10800                   aopGet (right, offset, FALSE, FALSE),
10801                   offset);
10802           lit >>= 8;
10803           offset++;
10804           size--;
10805         }
10806       emitcode ("clr", "a");
10807       while (size--)
10808         {
10809           aopPut (result, "a", offset);
10810           offset++;
10811         }
10812     }
10813   else
10814     {
10815       while (size--)
10816         {
10817           aopPut (result,
10818                   aopGet (right, offset, FALSE, FALSE),
10819                   offset);
10820           offset++;
10821         }
10822     }
10823
10824 release:
10825   freeAsmop (result, NULL, ic, TRUE);
10826   freeAsmop (right, NULL, ic, TRUE);
10827 }
10828
10829 /*-----------------------------------------------------------------*/
10830 /* genJumpTab - generates code for jump table                      */
10831 /*-----------------------------------------------------------------*/
10832 static void
10833 genJumpTab (iCode * ic)
10834 {
10835   symbol *jtab,*jtablo,*jtabhi;
10836   char *l;
10837   unsigned int count;
10838
10839   D(emitcode (";     genJumpTab",""));
10840
10841   count = elementsInSet( IC_JTLABELS (ic) );
10842
10843   if( count <= 16 )
10844     {
10845       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10846          if the switch argument is in a register.
10847          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10848       /* Peephole may not convert ljmp to sjmp or ret
10849          labelIsReturnOnly & labelInRange must check
10850          currPl->ic->op != JUMPTABLE */
10851       aopOp (IC_JTCOND (ic), ic, FALSE);
10852       /* get the condition into accumulator */
10853       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10854       MOVA (l);
10855       /* multiply by three */
10856       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10857         {
10858           emitcode ("mov", "b,#3");
10859           emitcode ("mul", "ab");
10860         }
10861       else
10862         {
10863           emitcode ("add", "a,acc");
10864           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10865         }
10866       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10867
10868       jtab = newiTempLabel (NULL);
10869       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10870       emitcode ("jmp", "@a+dptr");
10871       emitcode ("", "%05d$:", jtab->key + 100);
10872       /* now generate the jump labels */
10873       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10874            jtab = setNextItem (IC_JTLABELS (ic)))
10875         emitcode ("ljmp", "%05d$", jtab->key + 100);
10876     }
10877   else
10878     {
10879       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10880          if the switch argument is in a register.
10881          For n>6 this algorithm may be more compact */
10882       jtablo = newiTempLabel (NULL);
10883       jtabhi = newiTempLabel (NULL);
10884
10885       /* get the condition into accumulator.
10886          Using b as temporary storage, if register push/pop is needed */
10887       aopOp (IC_JTCOND (ic), ic, FALSE);
10888       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10889       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10890           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10891         {
10892           // (MB) what if B is in use???
10893           wassertl(!BINUSE, "B was in use");
10894           emitcode ("mov", "b,%s", l);
10895           l = "b";
10896         }
10897       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10898       MOVA (l);
10899       if( count <= 112 )
10900         {
10901           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10902           emitcode ("movc", "a,@a+pc");
10903           emitcode ("push", "acc");
10904
10905           MOVA (l);
10906           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10907           emitcode ("movc", "a,@a+pc");
10908           emitcode ("push", "acc");
10909         }
10910       else
10911         {
10912           /* this scales up to n<=255, but needs two more bytes
10913              and changes dptr */
10914           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10915           emitcode ("movc", "a,@a+dptr");
10916           emitcode ("push", "acc");
10917
10918           MOVA (l);
10919           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10920           emitcode ("movc", "a,@a+dptr");
10921           emitcode ("push", "acc");
10922         }
10923
10924       emitcode ("ret", "");
10925
10926       /* now generate jump table, LSB */
10927       emitcode ("", "%05d$:", jtablo->key + 100);
10928       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10929            jtab = setNextItem (IC_JTLABELS (ic)))
10930         emitcode (".db", "%05d$", jtab->key + 100);
10931
10932       /* now generate jump table, MSB */
10933       emitcode ("", "%05d$:", jtabhi->key + 100);
10934       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10935            jtab = setNextItem (IC_JTLABELS (ic)))
10936          emitcode (".db", "%05d$>>8", jtab->key + 100);
10937     }
10938 }
10939
10940 /*-----------------------------------------------------------------*/
10941 /* genCast - gen code for casting                                  */
10942 /*-----------------------------------------------------------------*/
10943 static void
10944 genCast (iCode * ic)
10945 {
10946   operand *result = IC_RESULT (ic);
10947   sym_link *ctype = operandType (IC_LEFT (ic));
10948   sym_link *rtype = operandType (IC_RIGHT (ic));
10949   operand *right = IC_RIGHT (ic);
10950   int size, offset;
10951
10952   D(emitcode(";     genCast",""));
10953
10954   /* if they are equivalent then do nothing */
10955   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10956     return;
10957
10958   aopOp (right, ic, FALSE);
10959   aopOp (result, ic, FALSE);
10960
10961   /* if the result is a bit (and not a bitfield) */
10962   // if (AOP_TYPE (result) == AOP_CRY)
10963   if (IS_BIT (OP_SYMBOL (result)->type))
10964     /* not for bitfields */
10965     {
10966       /* if the right size is a literal then
10967          we know what the value is */
10968       if (AOP_TYPE (right) == AOP_LIT)
10969         {
10970           if (((int) operandLitValue (right)))
10971             aopPut (result, one, 0);
10972           else
10973             aopPut (result, zero, 0);
10974
10975           goto release;
10976         }
10977
10978       /* the right is also a bit variable */
10979       if (AOP_TYPE (right) == AOP_CRY)
10980         {
10981           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10982           aopPut (result, "c", 0);
10983           goto release;
10984         }
10985
10986       /* we need to or */
10987       toBoolean (right);
10988       aopPut (result, "a", 0);
10989       goto release;
10990     }
10991
10992   /* if they are the same size : or less */
10993   if (AOP_SIZE (result) <= AOP_SIZE (right))
10994     {
10995
10996       /* if they are in the same place */
10997       if (sameRegs (AOP (right), AOP (result)))
10998         goto release;
10999
11000       /* if they in different places then copy */
11001       size = AOP_SIZE (result);
11002       offset = 0;
11003       while (size--)
11004         {
11005           aopPut (result,
11006                   aopGet (right, offset, FALSE, FALSE),
11007                   offset);
11008           offset++;
11009         }
11010       goto release;
11011     }
11012
11013   /* if the result is of type pointer */
11014   if (IS_PTR (ctype))
11015     {
11016
11017       int p_type;
11018       sym_link *type = operandType (right);
11019       sym_link *etype = getSpec (type);
11020
11021       /* pointer to generic pointer */
11022       if (IS_GENPTR (ctype))
11023         {
11024           if (IS_PTR (type))
11025             p_type = DCL_TYPE (type);
11026           else
11027             {
11028               if (SPEC_SCLS(etype)==S_REGISTER) {
11029                 // let's assume it is a generic pointer
11030                 p_type=GPOINTER;
11031               } else {
11032                 /* we have to go by the storage class */
11033                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11034               }
11035             }
11036
11037           /* the first two bytes are known */
11038           size = GPTRSIZE - 1;
11039           offset = 0;
11040           while (size--)
11041             {
11042               aopPut (result,
11043                       aopGet (right, offset, FALSE, FALSE),
11044                       offset);
11045               offset++;
11046             }
11047           /* the last byte depending on type */
11048             {
11049                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11050                 char gpValStr[10];
11051
11052                 if (gpVal == -1)
11053                 {
11054                     // pointerTypeToGPByte will have bitched.
11055                     exit(1);
11056                 }
11057
11058                 sprintf(gpValStr, "#0x%x", gpVal);
11059                 aopPut (result, gpValStr, GPTRSIZE - 1);
11060             }
11061           goto release;
11062         }
11063
11064       /* just copy the pointers */
11065       size = AOP_SIZE (result);
11066       offset = 0;
11067       while (size--)
11068         {
11069           aopPut (result,
11070                   aopGet (right, offset, FALSE, FALSE),
11071                   offset);
11072           offset++;
11073         }
11074       goto release;
11075     }
11076
11077   /* so we now know that the size of destination is greater
11078      than the size of the source */
11079   /* we move to result for the size of source */
11080   size = AOP_SIZE (right);
11081   offset = 0;
11082   while (size--)
11083     {
11084       aopPut (result,
11085               aopGet (right, offset, FALSE, FALSE),
11086               offset);
11087       offset++;
11088     }
11089
11090   /* now depending on the sign of the source && destination */
11091   size = AOP_SIZE (result) - AOP_SIZE (right);
11092   /* if unsigned or not an integral type */
11093   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11094     {
11095       while (size--)
11096         aopPut (result, zero, offset++);
11097     }
11098   else
11099     {
11100       /* we need to extend the sign :{ */
11101       char *l = aopGet (right, AOP_SIZE (right) - 1,
11102                         FALSE, FALSE);
11103       MOVA (l);
11104       emitcode ("rlc", "a");
11105       emitcode ("subb", "a,acc");
11106       while (size--)
11107         aopPut (result, "a", offset++);
11108     }
11109
11110   /* we are done hurray !!!! */
11111
11112 release:
11113   freeAsmop (result, NULL, ic, TRUE);
11114   freeAsmop (right, NULL, ic, TRUE);
11115 }
11116
11117 /*-----------------------------------------------------------------*/
11118 /* genDjnz - generate decrement & jump if not zero instrucion      */
11119 /*-----------------------------------------------------------------*/
11120 static int
11121 genDjnz (iCode * ic, iCode * ifx)
11122 {
11123   symbol *lbl, *lbl1;
11124   if (!ifx)
11125     return 0;
11126
11127   D(emitcode (";     genDjnz",""));
11128
11129   /* if the if condition has a false label
11130      then we cannot save */
11131   if (IC_FALSE (ifx))
11132     return 0;
11133
11134   /* if the minus is not of the form
11135      a = a - 1 */
11136   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11137       !IS_OP_LITERAL (IC_RIGHT (ic)))
11138     return 0;
11139
11140   if (operandLitValue (IC_RIGHT (ic)) != 1)
11141     return 0;
11142
11143   /* if the size of this greater than one then no
11144      saving */
11145   if (getSize (operandType (IC_RESULT (ic))) > 1)
11146     return 0;
11147
11148   /* otherwise we can save BIG */
11149   lbl = newiTempLabel (NULL);
11150   lbl1 = newiTempLabel (NULL);
11151
11152   aopOp (IC_RESULT (ic), ic, FALSE);
11153
11154   if (AOP_NEEDSACC(IC_RESULT(ic)))
11155   {
11156       /* If the result is accessed indirectly via
11157        * the accumulator, we must explicitly write
11158        * it back after the decrement.
11159        */
11160       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11161
11162       if (strcmp(rByte, "a"))
11163       {
11164            /* Something is hopelessly wrong */
11165            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11166                    __FILE__, __LINE__);
11167            /* We can just give up; the generated code will be inefficient,
11168             * but what the hey.
11169             */
11170            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11171            return 0;
11172       }
11173       emitcode ("dec", "%s", rByte);
11174       aopPut (IC_RESULT (ic), rByte, 0);
11175       emitcode ("jnz", "%05d$", lbl->key + 100);
11176   }
11177   else if (IS_AOP_PREG (IC_RESULT (ic)))
11178     {
11179       emitcode ("dec", "%s",
11180                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11181       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11182       emitcode ("jnz", "%05d$", lbl->key + 100);
11183     }
11184   else
11185     {
11186       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11187                 lbl->key + 100);
11188     }
11189   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11190   emitcode ("", "%05d$:", lbl->key + 100);
11191   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11192   emitcode ("", "%05d$:", lbl1->key + 100);
11193
11194   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11195   ifx->generated = 1;
11196   return 1;
11197 }
11198
11199 /*-----------------------------------------------------------------*/
11200 /* genReceive - generate code for a receive iCode                  */
11201 /*-----------------------------------------------------------------*/
11202 static void
11203 genReceive (iCode * ic)
11204 {
11205   int size = getSize (operandType (IC_RESULT (ic)));
11206   int offset = 0;
11207
11208   D(emitcode (";     genReceive",""));
11209
11210   if (ic->argreg == 1)
11211     { /* first parameter */
11212       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11213            isOperandInPagedSpace (IC_RESULT (ic))) &&
11214           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11215            IS_TRUE_SYMOP (IC_RESULT (ic))))
11216         {
11217           regs *tempRegs[4];
11218           int receivingA = 0;
11219           int roffset = 0;
11220
11221           for (offset = 0; offset<size; offset++)
11222             if (!strcmp (fReturn[offset], "a"))
11223               receivingA = 1;
11224
11225           if (!receivingA)
11226             {
11227               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11228                 {
11229                   for (offset = size-1; offset>0; offset--)
11230                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11231                   emitcode("mov","a,%s", fReturn[0]);
11232                   _G.accInUse++;
11233                   aopOp (IC_RESULT (ic), ic, FALSE);
11234                   _G.accInUse--;
11235                   aopPut (IC_RESULT (ic), "a", offset);
11236                   for (offset = 1; offset<size; offset++)
11237                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11238                   goto release;
11239                 }
11240             }
11241           else
11242             {
11243               if (getTempRegs(tempRegs, size, ic))
11244                 {
11245                   for (offset = 0; offset<size; offset++)
11246                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11247                   aopOp (IC_RESULT (ic), ic, FALSE);
11248                   for (offset = 0; offset<size; offset++)
11249                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11250                   goto release;
11251                 }
11252             }
11253
11254           offset = fReturnSizeMCS51 - size;
11255           while (size--)
11256             {
11257               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11258                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11259               offset++;
11260             }
11261           aopOp (IC_RESULT (ic), ic, FALSE);
11262           size = AOP_SIZE (IC_RESULT (ic));
11263           offset = 0;
11264           while (size--)
11265             {
11266               emitcode ("pop", "acc");
11267               aopPut (IC_RESULT (ic), "a", offset++);
11268             }
11269         }
11270       else
11271         {
11272           _G.accInUse++;
11273           aopOp (IC_RESULT (ic), ic, FALSE);
11274           _G.accInUse--;
11275           assignResultValue (IC_RESULT (ic), NULL);
11276         }
11277     }
11278   else if (ic->argreg > 12)
11279     { /* bit parameters */
11280       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11281         {
11282           aopOp (IC_RESULT (ic), ic, FALSE);
11283           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11284           outBitC(IC_RESULT (ic));
11285         }
11286     }
11287   else
11288     { /* other parameters */
11289       int rb1off ;
11290       aopOp (IC_RESULT (ic), ic, FALSE);
11291       rb1off = ic->argreg;
11292       while (size--)
11293         {
11294           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11295         }
11296     }
11297
11298 release:
11299   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11300 }
11301
11302 /*-----------------------------------------------------------------*/
11303 /* genDummyRead - generate code for dummy read of volatiles        */
11304 /*-----------------------------------------------------------------*/
11305 static void
11306 genDummyRead (iCode * ic)
11307 {
11308   operand *op;
11309   int size, offset;
11310
11311   D(emitcode(";     genDummyRead",""));
11312
11313   op = IC_RIGHT (ic);
11314   if (op && IS_SYMOP (op))
11315     {
11316       aopOp (op, ic, FALSE);
11317
11318       /* if the result is a bit */
11319       if (AOP_TYPE (op) == AOP_CRY)
11320         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11321       else
11322         {
11323           /* bit variables done */
11324           /* general case */
11325           size = AOP_SIZE (op);
11326           offset = 0;
11327           while (size--)
11328           {
11329             MOVA (aopGet (op, offset, FALSE, FALSE));
11330             offset++;
11331           }
11332         }
11333
11334       freeAsmop (op, NULL, ic, TRUE);
11335     }
11336
11337   op = IC_LEFT (ic);
11338   if (op && IS_SYMOP (op))
11339     {
11340       aopOp (op, ic, FALSE);
11341
11342       /* if the result is a bit */
11343       if (AOP_TYPE (op) == AOP_CRY)
11344         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11345       else
11346         {
11347           /* bit variables done */
11348           /* general case */
11349           size = AOP_SIZE (op);
11350           offset = 0;
11351           while (size--)
11352           {
11353             MOVA (aopGet (op, offset, FALSE, FALSE));
11354             offset++;
11355           }
11356         }
11357
11358       freeAsmop (op, NULL, ic, TRUE);
11359     }
11360 }
11361
11362 /*-----------------------------------------------------------------*/
11363 /* genCritical - generate code for start of a critical sequence    */
11364 /*-----------------------------------------------------------------*/
11365 static void
11366 genCritical (iCode *ic)
11367 {
11368   symbol *tlbl = newiTempLabel (NULL);
11369
11370   D(emitcode(";     genCritical",""));
11371
11372   if (IC_RESULT (ic))
11373     {
11374       aopOp (IC_RESULT (ic), ic, TRUE);
11375       aopPut (IC_RESULT (ic), one, 0);
11376       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11377       aopPut (IC_RESULT (ic), zero, 0);
11378       emitcode ("", "%05d$:", (tlbl->key + 100));
11379       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11380     }
11381   else
11382     {
11383       emitcode ("setb", "c");
11384       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11385       emitcode ("clr", "c");
11386       emitcode ("", "%05d$:", (tlbl->key + 100));
11387       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11388     }
11389 }
11390
11391 /*-----------------------------------------------------------------*/
11392 /* genEndCritical - generate code for end of a critical sequence   */
11393 /*-----------------------------------------------------------------*/
11394 static void
11395 genEndCritical (iCode *ic)
11396 {
11397   D(emitcode(";     genEndCritical",""));
11398
11399   if (IC_RIGHT (ic))
11400     {
11401       aopOp (IC_RIGHT (ic), ic, FALSE);
11402       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11403         {
11404           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11405           emitcode ("mov", "ea,c");
11406         }
11407       else
11408         {
11409           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11410             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11411           emitcode ("rrc", "a");
11412           emitcode ("mov", "ea,c");
11413         }
11414       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11415     }
11416   else
11417     {
11418       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11419       emitcode ("mov", "ea,c");
11420     }
11421 }
11422
11423 /*-----------------------------------------------------------------*/
11424 /* gen51Code - generate code for 8051 based controllers            */
11425 /*-----------------------------------------------------------------*/
11426 void
11427 gen51Code (iCode * lic)
11428 {
11429   iCode *ic;
11430   int cln = 0;
11431   /* int cseq = 0; */
11432
11433   _G.currentFunc = NULL;
11434   lineHead = lineCurr = NULL;
11435
11436   /* print the allocation information */
11437   if (allocInfo && currFunc)
11438     printAllocInfo (currFunc, codeOutFile);
11439   /* if debug information required */
11440   if (options.debug && currFunc)
11441     {
11442       debugFile->writeFunction (currFunc, lic);
11443     }
11444   /* stack pointer name */
11445   if (options.useXstack)
11446     spname = "_spx";
11447   else
11448     spname = "sp";
11449
11450
11451   for (ic = lic; ic; ic = ic->next)
11452     {
11453       _G.current_iCode = ic;
11454
11455       if (ic->lineno && cln != ic->lineno)
11456         {
11457           if (options.debug)
11458             {
11459               debugFile->writeCLine (ic);
11460             }
11461           if (!options.noCcodeInAsm) {
11462             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11463                       printCLine(ic->filename, ic->lineno));
11464           }
11465           cln = ic->lineno;
11466         }
11467       #if 0
11468       if (ic->seqPoint && ic->seqPoint != cseq)
11469         {
11470           emitcode ("", "; sequence point %d", ic->seqPoint);
11471           cseq = ic->seqPoint;
11472         }
11473       #endif
11474       if (options.iCodeInAsm) {
11475         char regsInUse[80];
11476         int i;
11477
11478         #if 0
11479         for (i=0; i<8; i++) {
11480           sprintf (&regsInUse[i],
11481                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11482         regsInUse[i]=0;
11483         #else
11484         strcpy (regsInUse, "--------");
11485         for (i=0; i < 8; i++) {
11486           if (bitVectBitValue (ic->rMask, i))
11487             {
11488               int offset = regs8051[i].offset;
11489               regsInUse[offset] = offset + '0'; /* show rMask */
11490             }
11491         #endif
11492         }
11493         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11494       }
11495       /* if the result is marked as
11496          spilt and rematerializable or code for
11497          this has already been generated then
11498          do nothing */
11499       if (resultRemat (ic) || ic->generated)
11500         continue;
11501
11502       /* depending on the operation */
11503       switch (ic->op)
11504         {
11505         case '!':
11506           genNot (ic);
11507           break;
11508
11509         case '~':
11510           genCpl (ic);
11511           break;
11512
11513         case UNARYMINUS:
11514           genUminus (ic);
11515           break;
11516
11517         case IPUSH:
11518           genIpush (ic);
11519           break;
11520
11521         case IPOP:
11522           /* IPOP happens only when trying to restore a
11523              spilt live range, if there is an ifx statement
11524              following this pop then the if statement might
11525              be using some of the registers being popped which
11526              would destory the contents of the register so
11527              we need to check for this condition and handle it */
11528           if (ic->next &&
11529               ic->next->op == IFX &&
11530               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11531             genIfx (ic->next, ic);
11532           else
11533             genIpop (ic);
11534           break;
11535
11536         case CALL:
11537           genCall (ic);
11538           break;
11539
11540         case PCALL:
11541           genPcall (ic);
11542           break;
11543
11544         case FUNCTION:
11545           genFunction (ic);
11546           break;
11547
11548         case ENDFUNCTION:
11549           genEndFunction (ic);
11550           break;
11551
11552         case RETURN:
11553           genRet (ic);
11554           break;
11555
11556         case LABEL:
11557           genLabel (ic);
11558           break;
11559
11560         case GOTO:
11561           genGoto (ic);
11562           break;
11563
11564         case '+':
11565           genPlus (ic);
11566           break;
11567
11568         case '-':
11569           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11570             genMinus (ic);
11571           break;
11572
11573         case '*':
11574           genMult (ic);
11575           break;
11576
11577         case '/':
11578           genDiv (ic);
11579           break;
11580
11581         case '%':
11582           genMod (ic);
11583           break;
11584
11585         case '>':
11586           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11587           break;
11588
11589         case '<':
11590           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11591           break;
11592
11593         case LE_OP:
11594         case GE_OP:
11595         case NE_OP:
11596
11597           /* note these two are xlated by algebraic equivalence
11598              during parsing SDCC.y */
11599           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11600                   "got '>=' or '<=' shouldn't have come here");
11601           break;
11602
11603         case EQ_OP:
11604           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11605           break;
11606
11607         case AND_OP:
11608           genAndOp (ic);
11609           break;
11610
11611         case OR_OP:
11612           genOrOp (ic);
11613           break;
11614
11615         case '^':
11616           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11617           break;
11618
11619         case '|':
11620           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11621           break;
11622
11623         case BITWISEAND:
11624           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11625           break;
11626
11627         case INLINEASM:
11628           genInline (ic);
11629           break;
11630
11631         case RRC:
11632           genRRC (ic);
11633           break;
11634
11635         case RLC:
11636           genRLC (ic);
11637           break;
11638
11639         case GETHBIT:
11640           genGetHbit (ic);
11641           break;
11642
11643         case GETABIT:
11644           genGetAbit (ic);
11645           break;
11646
11647         case GETBYTE:
11648           genGetByte (ic);
11649           break;
11650
11651         case GETWORD:
11652           genGetWord (ic);
11653           break;
11654
11655         case LEFT_OP:
11656           genLeftShift (ic);
11657           break;
11658
11659         case RIGHT_OP:
11660           genRightShift (ic);
11661           break;
11662
11663         case GET_VALUE_AT_ADDRESS:
11664           genPointerGet (ic,
11665                          hasInc (IC_LEFT (ic), ic,
11666                                  getSize (operandType (IC_RESULT (ic)))),
11667                          ifxForOp (IC_RESULT (ic), ic) );
11668           break;
11669
11670         case '=':
11671           if (POINTER_SET (ic))
11672             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11673           else
11674             genAssign (ic);
11675           break;
11676
11677         case IFX:
11678           genIfx (ic, NULL);
11679           break;
11680
11681         case ADDRESS_OF:
11682           genAddrOf (ic);
11683           break;
11684
11685         case JUMPTABLE:
11686           genJumpTab (ic);
11687           break;
11688
11689         case CAST:
11690           genCast (ic);
11691           break;
11692
11693         case RECEIVE:
11694           genReceive (ic);
11695           break;
11696
11697         case SEND:
11698           addSet (&_G.sendSet, ic);
11699           break;
11700
11701         case DUMMY_READ_VOLATILE:
11702           genDummyRead (ic);
11703           break;
11704
11705         case CRITICAL:
11706           genCritical (ic);
11707           break;
11708
11709         case ENDCRITICAL:
11710           genEndCritical (ic);
11711           break;
11712
11713         case SWAP:
11714           genSwap (ic);
11715           break;
11716
11717         default:
11718           ic = ic;
11719         }
11720     }
11721
11722   _G.current_iCode = NULL;
11723
11724   /* now we are ready to call the
11725      peep hole optimizer */
11726   if (!options.nopeep)
11727     peepHole (&lineHead);
11728
11729   /* now do the actual printing */
11730   printLine (lineHead, codeOutFile);
11731   return;
11732 }