* src/SDCC.y: added tokens GETABIT, GETBYTE, GETWORD
[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 || AOP(x)->paged))
76
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
78                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
80
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 int mcs51_ptrRegReq;
119 extern int mcs51_nRegs;
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define CLRC     emitcode("clr","c")
129 #define SETC     emitcode("setb","c")
130
131 static lineNode *lineHead = NULL;
132 static lineNode *lineCurr = NULL;
133
134 static unsigned char SLMask[] =
135 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
136  0xE0, 0xC0, 0x80, 0x00};
137 static unsigned char SRMask[] =
138 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
139  0x07, 0x03, 0x01, 0x00};
140
141 #define LSB     0
142 #define MSB16   1
143 #define MSB24   2
144 #define MSB32   3
145
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple    */
148 /*-----------------------------------------------------------------*/
149 static void
150 emitcode (char *inst, const char *fmt,...)
151 {
152   va_list ap;
153   char lb[INITIAL_INLINEASM];
154   char *lbp = lb;
155
156   va_start (ap, fmt);
157
158   if (inst && *inst)
159     {
160       if (fmt && *fmt)
161           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
162       else
163           SNPRINTF (lb, sizeof(lb), "%s", inst);
164       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
165     }
166   else
167       tvsprintf (lb, sizeof(lb), fmt, ap);
168
169   while (isspace ((unsigned char)*lbp))
170       lbp++;
171
172   if (lbp && *lbp)
173       lineCurr = (lineCurr ?
174                   connectLine (lineCurr, newLineNode (lb)) :
175                   (lineHead = newLineNode (lb)));
176   lineCurr->isInline = _G.inLine;
177   lineCurr->isDebug = _G.debugLine;
178   lineCurr->ic = _G.current_iCode;
179   lineCurr->isComment = (*lbp==';');
180   va_end (ap);
181 }
182
183 /*-----------------------------------------------------------------*/
184 /* mcs51_emitDebuggerSymbol - associate the current code location  */
185 /*   with a debugger symbol                                        */
186 /*-----------------------------------------------------------------*/
187 void
188 mcs51_emitDebuggerSymbol (char * debugSym)
189 {
190   _G.debugLine = 1;
191   emitcode ("", "%s ==.", debugSym);
192   _G.debugLine = 0;
193 }
194
195 /*-----------------------------------------------------------------*/
196 /* mova - moves specified value into accumulator                   */
197 /*-----------------------------------------------------------------*/
198 static void
199 mova (const char *x)
200 {
201   /* do some early peephole optimization */
202   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
203     return;
204
205   emitcode("mov","a,%s", x);
206 }
207
208 /*-----------------------------------------------------------------*/
209 /* movc - moves specified value into the carry                     */
210 /*-----------------------------------------------------------------*/
211 static void
212 movc (const char *s)
213 {
214   if (s == zero)
215     CLRC;
216   else if (s == one)
217     SETC;
218   else if (strcmp (s, "c"))
219     {/* it's not in carry already */
220       MOVA (s);
221       /* set C, if a >= 1 */
222       emitcode ("add", "a,#0xff");
223     }
224 }
225
226 /*-----------------------------------------------------------------*/
227 /* pushB - saves register B if necessary                           */
228 /*-----------------------------------------------------------------*/
229 static bool
230 pushB (void)
231 {
232   bool pushedB = FALSE;
233
234   if (BINUSE)
235     {
236       emitcode ("push", "b");
237 //    printf("B was in use !\n");
238       pushedB = TRUE;
239     }
240   else
241     {
242       OPINB++;
243     }
244   return pushedB;
245 }
246
247 /*-----------------------------------------------------------------*/
248 /* popB - restores value of register B if necessary                */
249 /*-----------------------------------------------------------------*/
250 static void
251 popB (bool pushedB)
252 {
253   if (pushedB)
254     {
255       emitcode ("pop", "b");
256     }
257   else
258     {
259       OPINB--;
260     }
261 }
262
263 /*-----------------------------------------------------------------*/
264 /* pushReg - saves register                                        */
265 /*-----------------------------------------------------------------*/
266 static bool
267 pushReg (int index, bool bits_pushed)
268 {
269   regs * reg = mcs51_regWithIdx (index);
270   if (reg->type == REG_BIT)
271     {
272       if (!bits_pushed)
273         emitcode ("push", "%s", reg->base);
274       return TRUE;
275     }
276   else
277     emitcode ("push", "%s", reg->dname);
278   return bits_pushed;
279 }
280
281 /*-----------------------------------------------------------------*/
282 /* popReg - restores register                                      */
283 /*-----------------------------------------------------------------*/
284 static bool
285 popReg (int index, bool bits_popped)
286 {
287   regs * reg = mcs51_regWithIdx (index);
288   if (reg->type == REG_BIT)
289     {
290       if (!bits_popped)
291         emitcode ("pop", "%s", reg->base);
292       return TRUE;
293     }
294   else
295     emitcode ("pop", "%s", reg->dname);
296   return bits_popped;
297 }
298
299 /*-----------------------------------------------------------------*/
300 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
301 /*-----------------------------------------------------------------*/
302 static regs *
303 getFreePtr (iCode * ic, asmop ** aopp, bool result)
304 {
305   bool r0iu, r1iu;
306   bool r0ou, r1ou;
307
308   /* the logic: if r0 & r1 used in the instruction
309      then we are in trouble otherwise */
310
311   /* first check if r0 & r1 are used by this
312      instruction, in which case we are in trouble */
313   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
314   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
315   if (r0iu && r1iu) {
316       goto endOfWorld;
317     }
318
319   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
320   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
321
322   /* if no usage of r0 then return it */
323   if (!r0iu && !r0ou)
324     {
325       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
326       (*aopp)->type = AOP_R0;
327
328       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
329     }
330
331   /* if no usage of r1 then return it */
332   if (!r1iu && !r1ou)
333     {
334       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
335       (*aopp)->type = AOP_R1;
336
337       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
338     }
339
340   /* now we know they both have usage */
341   /* if r0 not used in this instruction */
342   if (!r0iu)
343     {
344       /* push it if not already pushed */
345       if (ic->op == IPUSH)
346         {
347           emitcode ("mov", "b,%s",
348                     mcs51_regWithIdx (R0_IDX)->dname);
349           R0INB++;
350         }
351       else if (!_G.r0Pushed)
352         {
353           emitcode ("push", "%s",
354                     mcs51_regWithIdx (R0_IDX)->dname);
355           _G.r0Pushed++;
356         }
357
358       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359       (*aopp)->type = AOP_R0;
360
361       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
362     }
363
364   /* if r1 not used then */
365
366   if (!r1iu)
367     {
368       /* push it if not already pushed */
369       if (ic->op == IPUSH)
370         {
371           emitcode ("mov", "b,%s",
372                     mcs51_regWithIdx (R1_IDX)->dname);
373           R1INB++;
374         }
375       else if (!_G.r1Pushed)
376         {
377           emitcode ("push", "%s",
378                     mcs51_regWithIdx (R1_IDX)->dname);
379           _G.r1Pushed++;
380         }
381
382       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
383       (*aopp)->type = AOP_R1;
384       return mcs51_regWithIdx (R1_IDX);
385     }
386 endOfWorld:
387   /* I said end of world, but not quite end of world yet */
388   if (result) {
389     /* we can push it on the stack */
390     (*aopp)->type = AOP_STK;
391     return NULL;
392   } else {
393     /* in the case that result AND left AND right needs a pointer reg
394        we can safely use the result's */
395     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
396       (*aopp)->type = AOP_R0;
397       return mcs51_regWithIdx (R0_IDX);
398     }
399     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
400       (*aopp)->type = AOP_R1;
401       return mcs51_regWithIdx (R1_IDX);
402     }
403   }
404
405   /* now this is REALLY the end of the world */
406   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
407           "getFreePtr should never reach here");
408   exit (1);
409 }
410
411
412 /*-----------------------------------------------------------------*/
413 /* getTempRegs - initialize an array of pointers to GPR registers */
414 /*               that are not in use. Returns 1 if the requested   */
415 /*               number of registers were available, 0 otherwise.  */
416 /*-----------------------------------------------------------------*/
417 int
418 getTempRegs(regs **tempRegs, int size, iCode *ic)
419 {
420   bitVect * freeRegs;
421   int i;
422   int offset;
423
424   if (!ic)
425     ic = _G.current_iCode;
426   if (!ic)
427     return 0;
428   if (!_G.currentFunc)
429     return 0;
430
431   freeRegs = newBitVect(8);
432   bitVectSetBit (freeRegs, R2_IDX);
433   bitVectSetBit (freeRegs, R3_IDX);
434   bitVectSetBit (freeRegs, R4_IDX);
435   bitVectSetBit (freeRegs, R5_IDX);
436   bitVectSetBit (freeRegs, R6_IDX);
437   bitVectSetBit (freeRegs, R7_IDX);
438
439   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
440     {
441       bitVect * newfreeRegs;
442       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
443       freeBitVect(freeRegs);
444       freeRegs = newfreeRegs;
445     }
446   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
447
448   offset = 0;
449   for (i=0; i<freeRegs->size; i++)
450     {
451       if (bitVectBitValue(freeRegs,i))
452         tempRegs[offset++] = mcs51_regWithIdx(i);
453       if (offset>=size)
454         {
455           freeBitVect(freeRegs);
456           return 1;
457         }
458     }
459
460   freeBitVect(freeRegs);
461   return 1;
462 }
463
464
465 /*-----------------------------------------------------------------*/
466 /* newAsmop - creates a new asmOp                                  */
467 /*-----------------------------------------------------------------*/
468 static asmop *
469 newAsmop (short type)
470 {
471   asmop *aop;
472
473   aop = Safe_calloc (1, sizeof (asmop));
474   aop->type = type;
475   return aop;
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* pointerCode - returns the code for a pointer type               */
480 /*-----------------------------------------------------------------*/
481 static int
482 pointerCode (sym_link * etype)
483 {
484
485   return PTR_TYPE (SPEC_OCLS (etype));
486
487 }
488
489 /*-----------------------------------------------------------------*/
490 /* leftRightUseAcc - returns size of accumulator use by operands   */
491 /*-----------------------------------------------------------------*/
492 static int
493 leftRightUseAcc(iCode *ic)
494 {
495   operand *op;
496   int size;
497   int accuseSize = 0;
498   int accuse = 0;
499
500   if (!ic)
501     {
502       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
503               "null iCode pointer");
504       return 0;
505     }
506
507   if (ic->op == IFX)
508     {
509       op = IC_COND (ic);
510       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
511         {
512           accuse = 1;
513           size = getSize (OP_SYMBOL (op)->type);
514           if (size>accuseSize)
515             accuseSize = size;
516         }
517     }
518   else if (ic->op == JUMPTABLE)
519     {
520       op = IC_JTCOND (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
530     {
531       op = IC_LEFT (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       op = IC_RIGHT (ic);
540       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
541         {
542           accuse = 1;
543           size = getSize (OP_SYMBOL (op)->type);
544           if (size>accuseSize)
545             accuseSize = size;
546         }
547     }
548
549   if (accuseSize)
550     return accuseSize;
551   else
552     return accuse;
553 }
554
555 /*-----------------------------------------------------------------*/
556 /* aopForSym - for a true symbol                                   */
557 /*-----------------------------------------------------------------*/
558 static asmop *
559 aopForSym (iCode * ic, symbol * sym, bool result)
560 {
561   asmop *aop;
562   memmap *space;
563
564   wassertl (ic != NULL, "Got a null iCode");
565   wassertl (sym != NULL, "Got a null symbol");
566
567   space = SPEC_OCLS (sym->etype);
568
569   /* if already has one */
570   if (sym->aop)
571     return sym->aop;
572
573   /* assign depending on the storage class */
574   /* if it is on the stack or indirectly addressable */
575   /* space we need to assign either r0 or r1 to it   */
576   if (sym->onStack || sym->iaccess)
577     {
578       sym->aop = aop = newAsmop (0);
579       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
580       aop->size = getSize (sym->type);
581
582       /* now assign the address of the variable to
583          the pointer register */
584       if (aop->type != AOP_STK)
585         {
586
587           if (sym->onStack)
588             {
589               char offset = ((sym->stack < 0) ?
590                          ((char) (sym->stack - _G.nRegsSaved)) :
591                          ((char) sym->stack)) & 0xff;
592
593               if ((offset >= -3) && (offset <= 3))
594                 {
595                   emitcode ("mov", "%s,%s",
596                             aop->aopu.aop_ptr->name, SYM_BP (sym));
597                   while (offset < 0)
598                     {
599                       emitcode ("dec", aop->aopu.aop_ptr->name);
600                       offset++;
601                     }
602                   while (offset > 0)
603                     {
604                       emitcode ("inc", aop->aopu.aop_ptr->name);
605                       offset--;
606                     }
607                 }
608               else
609                 {
610                   if (_G.accInUse || leftRightUseAcc (ic))
611                     emitcode ("push", "acc");
612                   emitcode ("mov", "a,%s", SYM_BP (sym));
613                   emitcode ("add", "a,#0x%02x", offset);
614                   emitcode ("mov", "%s,a",
615                             aop->aopu.aop_ptr->name);
616                   if (_G.accInUse || leftRightUseAcc (ic))
617                     emitcode ("pop", "acc");
618                 }
619             }
620           else
621             emitcode ("mov", "%s,#%s",
622                       aop->aopu.aop_ptr->name,
623                       sym->rname);
624           aop->paged = space->paged;
625         }
626       else
627         aop->aopu.aop_stk = sym->stack;
628       return aop;
629     }
630
631   /* if in bit space */
632   if (IN_BITSPACE (space))
633     {
634       sym->aop = aop = newAsmop (AOP_CRY);
635       aop->aopu.aop_dir = sym->rname;
636       aop->size = getSize (sym->type);
637       return aop;
638     }
639   /* if it is in direct space */
640   if (IN_DIRSPACE (space))
641     {
642       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
643       //printTypeChainRaw(sym->type, NULL);
644       //printf("space = %s\n", space ? space->sname : "NULL");
645       sym->aop = aop = newAsmop (AOP_DIR);
646       aop->aopu.aop_dir = sym->rname;
647       aop->size = getSize (sym->type);
648       return aop;
649     }
650
651   /* special case for a function */
652   if (IS_FUNC (sym->type))
653     {
654       sym->aop = aop = newAsmop (AOP_IMMD);
655       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
656       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
657       aop->size = getSize (sym->type);
658       return aop;
659     }
660
661   /* only remaining is far space */
662   /* in which case DPTR gets the address */
663   sym->aop = aop = newAsmop (AOP_DPTR);
664   emitcode ("mov", "dptr,#%s", sym->rname);
665   aop->size = getSize (sym->type);
666
667   /* if it is in code space */
668   if (IN_CODESPACE (space))
669     aop->code = 1;
670
671   return aop;
672 }
673
674 /*-----------------------------------------------------------------*/
675 /* aopForRemat - rematerialzes an object                           */
676 /*-----------------------------------------------------------------*/
677 static asmop *
678 aopForRemat (symbol * sym)
679 {
680   iCode *ic = sym->rematiCode;
681   asmop *aop = newAsmop (AOP_IMMD);
682   int ptr_type = 0;
683   int val = 0;
684
685   for (;;)
686     {
687       if (ic->op == '+')
688         val += (int) operandLitValue (IC_RIGHT (ic));
689       else if (ic->op == '-')
690         val -= (int) operandLitValue (IC_RIGHT (ic));
691       else if (IS_CAST_ICODE(ic)) {
692               sym_link *from_type = operandType(IC_RIGHT(ic));
693               aop->aopu.aop_immd.from_cast_remat = 1;
694               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
695               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
696               continue;
697       } else break;
698
699       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
700     }
701
702   if (val)
703     sprintf (buffer, "(%s %c 0x%04x)",
704              OP_SYMBOL (IC_LEFT (ic))->rname,
705              val >= 0 ? '+' : '-',
706              abs (val) & 0xffff);
707   else
708     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
709
710   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
711   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
712   /* set immd2 field if required */
713   if (aop->aopu.aop_immd.from_cast_remat) {
714           sprintf(buffer,"#0x%02x",ptr_type);
715           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
716           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
717   }
718
719   return aop;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common       */
724 /*-----------------------------------------------------------------*/
725 static bool
726 regsInCommon (operand * op1, operand * op2)
727 {
728   symbol *sym1, *sym2;
729   int i;
730
731   /* if they have registers in common */
732   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
733     return FALSE;
734
735   sym1 = OP_SYMBOL (op1);
736   sym2 = OP_SYMBOL (op2);
737
738   if (sym1->nRegs == 0 || sym2->nRegs == 0)
739     return FALSE;
740
741   for (i = 0; i < sym1->nRegs; i++)
742     {
743       int j;
744       if (!sym1->regs[i])
745         continue;
746
747       for (j = 0; j < sym2->nRegs; j++)
748         {
749           if (!sym2->regs[j])
750             continue;
751
752           if (sym2->regs[j] == sym1->regs[i])
753             return TRUE;
754         }
755     }
756
757   return FALSE;
758 }
759
760 /*-----------------------------------------------------------------*/
761 /* operandsEqu - equivalent                                        */
762 /*-----------------------------------------------------------------*/
763 static bool
764 operandsEqu (operand * op1, operand * op2)
765 {
766   symbol *sym1, *sym2;
767
768   /* if they're not symbols */
769   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
770     return FALSE;
771
772   sym1 = OP_SYMBOL (op1);
773   sym2 = OP_SYMBOL (op2);
774
775   /* if both are itemps & one is spilt
776      and the other is not then false */
777   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
778       sym1->isspilt != sym2->isspilt)
779     return FALSE;
780
781   /* if they are the same */
782   if (sym1 == sym2)
783     return TRUE;
784
785   /* if they have the same rname */
786   if (sym1->rname[0] && sym2->rname[0] &&
787       strcmp (sym1->rname, sym2->rname) == 0 &&
788       !(IS_PARM (op2) && IS_ITEMP (op1)))
789     return TRUE;
790
791   /* if left is a tmp & right is not */
792   if (IS_ITEMP (op1) &&
793       !IS_ITEMP (op2) &&
794       sym1->isspilt &&
795       (sym1->usl.spillLoc == sym2))
796     return TRUE;
797
798   if (IS_ITEMP (op2) &&
799       !IS_ITEMP (op1) &&
800       sym2->isspilt &&
801       sym1->level > 0 &&
802       (sym2->usl.spillLoc == sym1))
803     return TRUE;
804
805   return FALSE;
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* sameRegs - two asmops have the same registers                   */
810 /*-----------------------------------------------------------------*/
811 static bool
812 sameRegs (asmop * aop1, asmop * aop2)
813 {
814   int i;
815
816   if (aop1 == aop2)
817     return TRUE;
818
819   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
820     return FALSE;
821
822   if (aop1->type != aop2->type)
823     return FALSE;
824
825   if (aop1->size != aop2->size)
826     return FALSE;
827
828   for (i = 0; i < aop1->size; i++)
829     if (aop1->aopu.aop_reg[i] !=
830         aop2->aopu.aop_reg[i])
831       return FALSE;
832
833   return TRUE;
834 }
835
836 /*-----------------------------------------------------------------*/
837 /* aopOp - allocates an asmop for an operand  :                    */
838 /*-----------------------------------------------------------------*/
839 static void
840 aopOp (operand * op, iCode * ic, bool result)
841 {
842   asmop *aop;
843   symbol *sym;
844   int i;
845
846   if (!op)
847     return;
848
849   /* if this a literal */
850   if (IS_OP_LITERAL (op))
851     {
852       op->aop = aop = newAsmop (AOP_LIT);
853       aop->aopu.aop_lit = op->operand.valOperand;
854       aop->size = getSize (operandType (op));
855       return;
856     }
857
858   /* if already has a asmop then continue */
859   if (op->aop )
860     return;
861
862   /* if the underlying symbol has a aop */
863   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
864     {
865       op->aop = OP_SYMBOL (op)->aop;
866       return;
867     }
868
869   /* if this is a true symbol */
870   if (IS_TRUE_SYMOP (op))
871     {
872       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
873       return;
874     }
875
876   /* this is a temporary : this has
877      only five choices :
878      a) register
879      b) spillocation
880      c) rematerialize
881      d) conditional
882      e) can be a return use only */
883
884   sym = OP_SYMBOL (op);
885
886   /* if the type is a conditional */
887   if (sym->regType == REG_CND)
888     {
889       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
890       aop->size = 0;
891       return;
892     }
893
894   /* if it is spilt then two situations
895      a) is rematerialize
896      b) has a spill location */
897   if (sym->isspilt || sym->nRegs == 0)
898     {
899
900       /* rematerialize it NOW */
901       if (sym->remat)
902         {
903           sym->aop = op->aop = aop =
904             aopForRemat (sym);
905           aop->size = getSize (sym->type);
906           return;
907         }
908
909       if (sym->accuse)
910         {
911           int i;
912           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
913           aop->size = getSize (sym->type);
914           for (i = 0; i < 2; i++)
915             aop->aopu.aop_str[i] = accUse[i];
916           return;
917         }
918
919       if (sym->ruonly)
920         {
921           unsigned i;
922
923           aop = op->aop = sym->aop = newAsmop (AOP_STR);
924           aop->size = getSize (sym->type);
925           for (i = 0; i < fReturnSizeMCS51; i++)
926             aop->aopu.aop_str[i] = fReturn[i];
927           return;
928         }
929
930       if (sym->usl.spillLoc)
931         {
932           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
933             {
934               /* force a new aop if sizes differ */
935               sym->usl.spillLoc->aop = NULL;
936             }
937           sym->aop = op->aop = aop =
938                      aopForSym (ic, sym->usl.spillLoc, result);
939           aop->size = getSize (sym->type);
940           return;
941         }
942
943       /* else must be a dummy iTemp */
944       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
945       aop->size = getSize (sym->type);
946       return;
947     }
948
949   /* if the type is a bit register */
950   if (sym->regType == REG_BIT)
951     {
952       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
953       aop->size = sym->nRegs;//1???
954       aop->aopu.aop_reg[0] = sym->regs[0];
955       aop->aopu.aop_dir = sym->regs[0]->name;
956       return;
957     }
958
959   /* must be in a register */
960   sym->aop = op->aop = aop = newAsmop (AOP_REG);
961   aop->size = sym->nRegs;
962   for (i = 0; i < sym->nRegs; i++)
963     aop->aopu.aop_reg[i] = sym->regs[i];
964 }
965
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand               */
968 /*----------------------------------------------------------------*/
969 static void
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
971 {
972   asmop *aop;
973
974   if (!op)
975     aop = aaop;
976   else
977     aop = op->aop;
978
979   if (!aop)
980     return;
981
982   if (aop->freed)
983     goto dealloc;
984
985   aop->freed = 1;
986
987   /* depending on the asmop type only three cases need work AOP_RO
988      , AOP_R1 && AOP_STK */
989   switch (aop->type)
990     {
991     case AOP_R0:
992       if (R0INB)
993         {
994           emitcode ("mov", "r0,b");
995           R0INB--;
996         }
997       else if (_G.r0Pushed)
998         {
999           if (pop)
1000             {
1001               emitcode ("pop", "ar0");
1002               _G.r0Pushed--;
1003             }
1004         }
1005       bitVectUnSetBit (ic->rUsed, R0_IDX);
1006       break;
1007
1008     case AOP_R1:
1009       if (R1INB)
1010         {
1011           emitcode ("mov", "r1,b");
1012           R1INB--;
1013         }
1014       if (_G.r1Pushed)
1015         {
1016           if (pop)
1017             {
1018               emitcode ("pop", "ar1");
1019               _G.r1Pushed--;
1020             }
1021         }
1022       bitVectUnSetBit (ic->rUsed, R1_IDX);
1023       break;
1024
1025     case AOP_STK:
1026       {
1027         int sz = aop->size;
1028         int stk = aop->aopu.aop_stk + aop->size - 1;
1029         bitVectUnSetBit (ic->rUsed, R0_IDX);
1030         bitVectUnSetBit (ic->rUsed, R1_IDX);
1031
1032         getFreePtr (ic, &aop, FALSE);
1033
1034         if (stk)
1035           {
1036             emitcode ("mov", "a,_bp");
1037             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1038             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1039           }
1040         else
1041           {
1042             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1043           }
1044
1045         while (sz--)
1046           {
1047             emitcode ("pop", "acc");
1048             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1049             if (!sz)
1050               break;
1051             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1052           }
1053         op->aop = aop;
1054         freeAsmop (op, NULL, ic, TRUE);
1055         if (_G.r1Pushed)
1056           {
1057             emitcode ("pop", "ar1");
1058             _G.r1Pushed--;
1059           }
1060
1061         if (_G.r0Pushed)
1062           {
1063             emitcode ("pop", "ar0");
1064             _G.r0Pushed--;
1065           }
1066       }
1067     }
1068
1069 dealloc:
1070   /* all other cases just dealloc */
1071   if (op)
1072     {
1073       op->aop = NULL;
1074       if (IS_SYMOP (op))
1075         {
1076           OP_SYMBOL (op)->aop = NULL;
1077           /* if the symbol has a spill */
1078           if (SPIL_LOC (op))
1079             SPIL_LOC (op)->aop = NULL;
1080         }
1081     }
1082 }
1083
1084 /*------------------------------------------------------------------*/
1085 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1086 /*                      pop r0 or r1 off stack if pushed            */
1087 /*------------------------------------------------------------------*/
1088 static void
1089 freeForBranchAsmop (operand * op)
1090 {
1091   asmop *aop;
1092
1093   if (!op)
1094     return;
1095
1096   aop = op->aop;
1097
1098   if (!aop)
1099     return;
1100
1101   if (aop->freed)
1102     return;
1103
1104   switch (aop->type)
1105     {
1106     case AOP_R0:
1107       if (R0INB)
1108         {
1109           emitcode ("mov", "r0,b");
1110         }
1111       else if (_G.r0Pushed)
1112         {
1113           emitcode ("pop", "ar0");
1114         }
1115       break;
1116
1117     case AOP_R1:
1118       if (R1INB)
1119         {
1120           emitcode ("mov", "r1,b");
1121         }
1122       else if (_G.r1Pushed)
1123         {
1124           emitcode ("pop", "ar1");
1125         }
1126       break;
1127
1128     case AOP_STK:
1129       {
1130         int sz = aop->size;
1131         int stk = aop->aopu.aop_stk + aop->size - 1;
1132
1133         emitcode ("mov", "b,r0");
1134         if (stk)
1135           {
1136             emitcode ("mov", "a,_bp");
1137             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1138             emitcode ("mov", "r0,a");
1139           }
1140         else
1141           {
1142             emitcode ("mov", "r0,_bp");
1143           }
1144
1145         while (sz--)
1146           {
1147             emitcode ("pop", "acc");
1148             emitcode ("mov", "@r0,a");
1149             if (!sz)
1150               break;
1151             emitcode ("dec", "r0");
1152           }
1153         emitcode ("mov", "r0,b");
1154       }
1155     }
1156
1157 }
1158
1159 /*-----------------------------------------------------------------*/
1160 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1161 /*                 clobber the accumulator                         */
1162 /*-----------------------------------------------------------------*/
1163 static bool
1164 aopGetUsesAcc (operand * oper, int offset)
1165 {
1166   asmop * aop = AOP (oper);
1167
1168   if (offset > (aop->size - 1))
1169     return FALSE;
1170
1171   switch (aop->type)
1172     {
1173
1174     case AOP_R0:
1175     case AOP_R1:
1176       if (aop->paged)
1177         return TRUE;
1178       return FALSE;
1179     case AOP_DPTR:
1180       return TRUE;
1181     case AOP_IMMD:
1182       return FALSE;
1183     case AOP_DIR:
1184       return FALSE;
1185     case AOP_REG:
1186       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1187       return FALSE;
1188     case AOP_CRY:
1189       return TRUE;
1190     case AOP_ACC:
1191       if (offset)
1192         return FALSE;
1193       return TRUE;
1194     case AOP_LIT:
1195       return FALSE;
1196     case AOP_STR:
1197       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1198         return TRUE;
1199       return FALSE;
1200     case AOP_DUMMY:
1201       return FALSE;
1202     default:
1203       /* Error case --- will have been caught already */
1204       wassert(0);
1205       return FALSE;
1206     }
1207 }
1208
1209 /*-----------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop                          */
1211 /*-----------------------------------------------------------------*/
1212 static char *
1213 aopGet (operand * oper, int offset, bool bit16, bool dname)
1214 {
1215   char *s = buffer;
1216   char *rs;
1217   asmop * aop = AOP (oper);
1218
1219   /* offset is greater than
1220      size then zero */
1221   if (offset > (aop->size - 1) &&
1222       aop->type != AOP_LIT)
1223     return zero;
1224
1225   /* depending on type */
1226   switch (aop->type)
1227     {
1228     case AOP_DUMMY:
1229       return zero;
1230
1231     case AOP_R0:
1232     case AOP_R1:
1233       /* if we need to increment it */
1234       while (offset > aop->coff)
1235         {
1236           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1237           aop->coff++;
1238         }
1239
1240       while (offset < aop->coff)
1241         {
1242           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1243           aop->coff--;
1244         }
1245
1246       aop->coff = offset;
1247       if (aop->paged)
1248         {
1249           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1250           return (dname ? "acc" : "a");
1251         }
1252       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1253       rs = Safe_calloc (1, strlen (s) + 1);
1254       strcpy (rs, s);
1255       return rs;
1256
1257     case AOP_DPTR:
1258       if (aop->code && aop->coff==0 && offset>=1) {
1259         emitcode ("mov", "a,#0x%02x", offset);
1260         emitcode ("movc", "a,@a+dptr");
1261         return (dname ? "acc" : "a");
1262       }
1263
1264       while (offset > aop->coff)
1265         {
1266           emitcode ("inc", "dptr");
1267           aop->coff++;
1268         }
1269
1270       while (offset < aop->coff)
1271         {
1272           emitcode ("lcall", "__decdptr");
1273           aop->coff--;
1274         }
1275
1276       aop->coff = offset;
1277       if (aop->code)
1278         {
1279           emitcode ("clr", "a");
1280           emitcode ("movc", "a,@a+dptr");
1281         }
1282       else
1283         {
1284           emitcode ("movx", "a,@dptr");
1285         }
1286       return (dname ? "acc" : "a");
1287
1288
1289     case AOP_IMMD:
1290       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1291               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1292       } else if (bit16)
1293         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1294       else if (offset)
1295         sprintf (s, "#(%s >> %d)",
1296                  aop->aopu.aop_immd.aop_immd1,
1297                  offset * 8);
1298       else
1299         sprintf (s, "#%s",
1300                  aop->aopu.aop_immd.aop_immd1);
1301       rs = Safe_calloc (1, strlen (s) + 1);
1302       strcpy (rs, s);
1303       return rs;
1304
1305     case AOP_DIR:
1306       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1307         sprintf (s, "(%s >> %d)",
1308                  aop->aopu.aop_dir, offset * 8);
1309       else if (offset)
1310         sprintf (s, "(%s + %d)",
1311                  aop->aopu.aop_dir,
1312                  offset);
1313       else
1314         sprintf (s, "%s", aop->aopu.aop_dir);
1315       rs = Safe_calloc (1, strlen (s) + 1);
1316       strcpy (rs, s);
1317       return rs;
1318
1319     case AOP_REG:
1320       if (dname)
1321         return aop->aopu.aop_reg[offset]->dname;
1322       else
1323         return aop->aopu.aop_reg[offset]->name;
1324
1325     case AOP_CRY:
1326       emitcode ("clr", "a");
1327       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1328       emitcode ("rlc", "a");
1329       return (dname ? "acc" : "a");
1330
1331     case AOP_ACC:
1332       if (!offset && dname)
1333         return "acc";
1334       return aop->aopu.aop_str[offset];
1335
1336     case AOP_LIT:
1337       return aopLiteral (aop->aopu.aop_lit, offset);
1338
1339     case AOP_STR:
1340       aop->coff = offset;
1341       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1342           dname)
1343         return "acc";
1344
1345       return aop->aopu.aop_str[offset];
1346
1347     }
1348
1349   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1350           "aopget got unsupported aop->type");
1351   exit (1);
1352 }
1353 /*-----------------------------------------------------------------*/
1354 /* aopPut - puts a string for a aop and indicates if acc is in use */
1355 /*-----------------------------------------------------------------*/
1356 static bool
1357 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1358 {
1359   char *d = buffer;
1360   bool accuse = FALSE;
1361   asmop * aop = AOP (result);
1362
1363   if (aop->size && offset > (aop->size - 1))
1364     {
1365       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1366               "aopPut got offset > aop->size");
1367       exit (1);
1368     }
1369
1370   /* will assign value to value */
1371   /* depending on where it is ofcourse */
1372   switch (aop->type)
1373     {
1374     case AOP_DUMMY:
1375       MOVA (s);         /* read s in case it was volatile */
1376       accuse = TRUE;
1377       break;
1378
1379     case AOP_DIR:
1380       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1381         sprintf (d, "(%s >> %d)",
1382                  aop->aopu.aop_dir, offset * 8);
1383       else if (offset)
1384         sprintf (d, "(%s + %d)",
1385                  aop->aopu.aop_dir, offset);
1386       else
1387         sprintf (d, "%s", aop->aopu.aop_dir);
1388
1389       if (strcmp (d, s) ||
1390           bvolatile)
1391           emitcode ("mov", "%s,%s", d, s);
1392       if (!strcmp (d, "acc"))
1393           accuse = TRUE;
1394
1395       break;
1396
1397     case AOP_REG:
1398       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1399           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1400         {
1401           if (*s == '@' ||
1402               strcmp (s, "r0") == 0 ||
1403               strcmp (s, "r1") == 0 ||
1404               strcmp (s, "r2") == 0 ||
1405               strcmp (s, "r3") == 0 ||
1406               strcmp (s, "r4") == 0 ||
1407               strcmp (s, "r5") == 0 ||
1408               strcmp (s, "r6") == 0 ||
1409               strcmp (s, "r7") == 0)
1410             emitcode ("mov", "%s,%s",
1411                       aop->aopu.aop_reg[offset]->dname, s);
1412           else
1413             emitcode ("mov", "%s,%s",
1414                       aop->aopu.aop_reg[offset]->name, s);
1415         }
1416       break;
1417
1418     case AOP_DPTR:
1419       if (aop->code)
1420         {
1421           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422                   "aopPut writing to code space");
1423           exit (1);
1424         }
1425
1426       while (offset > aop->coff)
1427         {
1428           aop->coff++;
1429           emitcode ("inc", "dptr");
1430         }
1431
1432       while (offset < aop->coff)
1433         {
1434           aop->coff--;
1435           emitcode ("lcall", "__decdptr");
1436         }
1437
1438       aop->coff = offset;
1439
1440       /* if not in accumulator */
1441       MOVA (s);
1442
1443       emitcode ("movx", "@dptr,a");
1444       break;
1445
1446     case AOP_R0:
1447     case AOP_R1:
1448       while (offset > aop->coff)
1449         {
1450           aop->coff++;
1451           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1452         }
1453       while (offset < aop->coff)
1454         {
1455           aop->coff--;
1456           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1457         }
1458       aop->coff = offset;
1459
1460       if (aop->paged)
1461         {
1462           MOVA (s);
1463           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1464
1465         }
1466       else if (*s == '@')
1467         {
1468           MOVA (s);
1469           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1470         }
1471       else if (strcmp (s, "r0") == 0 ||
1472                strcmp (s, "r1") == 0 ||
1473                strcmp (s, "r2") == 0 ||
1474                strcmp (s, "r3") == 0 ||
1475                strcmp (s, "r4") == 0 ||
1476                strcmp (s, "r5") == 0 ||
1477                strcmp (s, "r6") == 0 ||
1478                strcmp (s, "r7") == 0)
1479         {
1480           char buffer[10];
1481           sprintf (buffer, "a%s", s);
1482           emitcode ("mov", "@%s,%s",
1483                     aop->aopu.aop_ptr->name, buffer);
1484         }
1485       else
1486         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1487
1488       break;
1489
1490     case AOP_STK:
1491       if (strcmp (s, "a") == 0)
1492         emitcode ("push", "acc");
1493       else
1494         if (*s=='@') {
1495           MOVA(s);
1496           emitcode ("push", "acc");
1497         } else {
1498           emitcode ("push", s);
1499         }
1500
1501       break;
1502
1503     case AOP_CRY:
1504       /* if not bit variable */
1505       if (!aop->aopu.aop_dir)
1506         {
1507           /* inefficient: move carry into A and use jz/jnz */
1508           emitcode ("clr", "a");
1509           emitcode ("rlc", "a");
1510           accuse = TRUE;
1511         }
1512       else
1513         {
1514           if (s == zero)
1515             emitcode ("clr", "%s", aop->aopu.aop_dir);
1516           else if (s == one)
1517             emitcode ("setb", "%s", aop->aopu.aop_dir);
1518           else if (!strcmp (s, "c"))
1519             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1520           else if (strcmp (s, aop->aopu.aop_dir))
1521             {
1522               MOVA (s);
1523               /* set C, if a >= 1 */
1524               emitcode ("add", "a,#0xff");
1525               emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1526             }
1527         }
1528       break;
1529
1530     case AOP_STR:
1531       aop->coff = offset;
1532       if (strcmp (aop->aopu.aop_str[offset], s) ||
1533           bvolatile)
1534         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1535       break;
1536
1537     case AOP_ACC:
1538       accuse = TRUE;
1539       aop->coff = offset;
1540       if (!offset && (strcmp (s, "acc") == 0) &&
1541           !bvolatile)
1542         break;
1543
1544       if (strcmp (aop->aopu.aop_str[offset], s) &&
1545           !bvolatile)
1546         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1547       break;
1548
1549     default:
1550       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1551               "aopPut got unsupported aop->type");
1552       exit (1);
1553     }
1554
1555     return accuse;
1556 }
1557
1558
1559 #if 0
1560 /*-----------------------------------------------------------------*/
1561 /* pointToEnd :- points to the last byte of the operand            */
1562 /*-----------------------------------------------------------------*/
1563 static void
1564 pointToEnd (asmop * aop)
1565 {
1566   int count;
1567   if (!aop)
1568     return;
1569
1570   aop->coff = count = (aop->size - 1);
1571   switch (aop->type)
1572     {
1573     case AOP_R0:
1574     case AOP_R1:
1575       while (count--)
1576         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1577       break;
1578     case AOP_DPTR:
1579       while (count--)
1580         emitcode ("inc", "dptr");
1581       break;
1582     }
1583
1584 }
1585 #endif
1586
1587 /*-----------------------------------------------------------------*/
1588 /* reAdjustPreg - points a register back to where it should        */
1589 /*-----------------------------------------------------------------*/
1590 static void
1591 reAdjustPreg (asmop * aop)
1592 {
1593   if ((aop->coff==0) || aop->size <= 1)
1594     return;
1595
1596   switch (aop->type)
1597     {
1598     case AOP_R0:
1599     case AOP_R1:
1600       while (aop->coff--)
1601         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1602       break;
1603     case AOP_DPTR:
1604       while (aop->coff--)
1605         {
1606           emitcode ("lcall", "__decdptr");
1607         }
1608       break;
1609     }
1610   aop->coff = 0;
1611 }
1612
1613 /*-----------------------------------------------------------------*/
1614 /* opIsGptr: returns non-zero if the passed operand is       */
1615 /* a generic pointer type.             */
1616 /*-----------------------------------------------------------------*/
1617 static int
1618 opIsGptr (operand * op)
1619 {
1620   sym_link *type = operandType (op);
1621
1622   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1623     {
1624       return 1;
1625     }
1626   return 0;
1627 }
1628
1629 /*-----------------------------------------------------------------*/
1630 /* getDataSize - get the operand data size                         */
1631 /*-----------------------------------------------------------------*/
1632 static int
1633 getDataSize (operand * op)
1634 {
1635   int size;
1636   size = AOP_SIZE (op);
1637   if (size == GPTRSIZE)
1638     {
1639       sym_link *type = operandType (op);
1640       if (IS_GENPTR (type))
1641         {
1642           /* generic pointer; arithmetic operations
1643            * should ignore the high byte (pointer type).
1644            */
1645           size--;
1646         }
1647     }
1648   return size;
1649 }
1650
1651 /*-----------------------------------------------------------------*/
1652 /* outAcc - output Acc                                             */
1653 /*-----------------------------------------------------------------*/
1654 static void
1655 outAcc (operand * result)
1656 {
1657   int size, offset;
1658   size = getDataSize (result);
1659   if (size)
1660     {
1661       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1662       size--;
1663       offset = 1;
1664       /* unsigned or positive */
1665       while (size--)
1666         {
1667           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1668         }
1669     }
1670 }
1671
1672 /*-----------------------------------------------------------------*/
1673 /* outBitC - output a bit C                                        */
1674 /*-----------------------------------------------------------------*/
1675 static void
1676 outBitC (operand * result)
1677 {
1678   /* if the result is bit */
1679   if (AOP_TYPE (result) == AOP_CRY)
1680     aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1681   else
1682     {
1683       emitcode ("clr", "a");
1684       emitcode ("rlc", "a");
1685       outAcc (result);
1686     }
1687 }
1688
1689 /*-----------------------------------------------------------------*/
1690 /* toBoolean - emit code for orl a,operator(sizeop)                */
1691 /*-----------------------------------------------------------------*/
1692 static void
1693 toBoolean (operand * oper)
1694 {
1695   int size = AOP_SIZE (oper) - 1;
1696   int offset = 1;
1697   bool AccUsed = FALSE;
1698   bool pushedB;
1699
1700   while (!AccUsed && size--)
1701     {
1702       AccUsed |= aopGetUsesAcc(oper, offset++);
1703     }
1704
1705   size = AOP_SIZE (oper) - 1;
1706   offset = 1;
1707   MOVA (aopGet (oper, 0, FALSE, FALSE));
1708   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1709     {
1710       pushedB = pushB ();
1711       emitcode("mov", "b,a");
1712       while (--size)
1713         {
1714           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1715           emitcode ("orl", "b,a");
1716         }
1717       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1718       emitcode ("orl", "a,b");
1719       popB (pushedB);
1720     }
1721   else
1722     {
1723       while (size--)
1724         {
1725           emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1726         }
1727     }
1728 }
1729
1730
1731 /*-----------------------------------------------------------------*/
1732 /* genNot - generate code for ! operation                          */
1733 /*-----------------------------------------------------------------*/
1734 static void
1735 genNot (iCode * ic)
1736 {
1737   symbol *tlbl;
1738
1739   D(emitcode (";     genNot",""));
1740
1741   /* assign asmOps to operand & result */
1742   aopOp (IC_LEFT (ic), ic, FALSE);
1743   aopOp (IC_RESULT (ic), ic, TRUE);
1744
1745   /* if in bit space then a special case */
1746   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1747     {
1748       /* if left==result then cpl bit */
1749       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1750         {
1751           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1752         }
1753       else
1754         {
1755           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1756           emitcode ("cpl", "c");
1757           outBitC (IC_RESULT (ic));
1758         }
1759       goto release;
1760     }
1761
1762   toBoolean (IC_LEFT (ic));
1763
1764   /* set C, if a == 0 */
1765   tlbl = newiTempLabel (NULL);
1766   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1767   emitcode ("", "%05d$:", tlbl->key + 100);
1768   outBitC (IC_RESULT (ic));
1769
1770 release:
1771   /* release the aops */
1772   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1773   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1774 }
1775
1776
1777 /*-----------------------------------------------------------------*/
1778 /* genCpl - generate code for complement                           */
1779 /*-----------------------------------------------------------------*/
1780 static void
1781 genCpl (iCode * ic)
1782 {
1783   int offset = 0;
1784   int size;
1785   symbol *tlbl;
1786   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1787
1788   D(emitcode (";", "genCpl"));
1789
1790   /* assign asmOps to operand & result */
1791   aopOp (IC_LEFT (ic), ic, FALSE);
1792   aopOp (IC_RESULT (ic), ic, TRUE);
1793
1794   /* special case if in bit space */
1795   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1796     {
1797       char *l;
1798
1799       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1800           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1801         {
1802           /* promotion rules are responsible for this strange result:
1803              bit -> int -> ~int -> bit
1804              uchar -> int -> ~int -> bit
1805           */
1806           werror(W_COMPLEMENT);
1807           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1808           goto release;
1809         }
1810
1811       tlbl=newiTempLabel(NULL);
1812       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1813       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1814           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1815           IS_AOP_PREG (IC_LEFT (ic)))
1816         {
1817           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1818         }
1819       else
1820         {
1821           MOVA (l);
1822           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1823         }
1824       emitcode ("", "%05d$:", tlbl->key + 100);
1825       outBitC (IC_RESULT(ic));
1826       goto release;
1827     }
1828
1829   size = AOP_SIZE (IC_RESULT (ic));
1830   while (size--)
1831     {
1832       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1833       MOVA (l);
1834       emitcode ("cpl", "a");
1835       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1836     }
1837
1838
1839 release:
1840   /* release the aops */
1841   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* genUminusFloat - unary minus for floating points                */
1847 /*-----------------------------------------------------------------*/
1848 static void
1849 genUminusFloat (operand * op, operand * result)
1850 {
1851   int size, offset = 0;
1852   char *l;
1853
1854   D(emitcode (";     genUminusFloat",""));
1855
1856   /* for this we just copy and then flip the bit */
1857
1858   size = AOP_SIZE (op) - 1;
1859
1860   while (size--)
1861     {
1862       aopPut (result,
1863               aopGet (op, offset, FALSE, FALSE),
1864               offset,
1865               isOperandVolatile (result, FALSE));
1866       offset++;
1867     }
1868
1869   l = aopGet (op, offset, FALSE, FALSE);
1870
1871   MOVA (l);
1872
1873   emitcode ("cpl", "acc.7");
1874   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1875 }
1876
1877 /*-----------------------------------------------------------------*/
1878 /* genUminus - unary minus code generation                         */
1879 /*-----------------------------------------------------------------*/
1880 static void
1881 genUminus (iCode * ic)
1882 {
1883   int offset, size;
1884   sym_link *optype, *rtype;
1885
1886
1887   D(emitcode (";     genUminus",""));
1888
1889   /* assign asmops */
1890   aopOp (IC_LEFT (ic), ic, FALSE);
1891   aopOp (IC_RESULT (ic), ic, TRUE);
1892
1893   /* if both in bit space then special
1894      case */
1895   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1896       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1897     {
1898
1899       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1900       emitcode ("cpl", "c");
1901       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1902       goto release;
1903     }
1904
1905   optype = operandType (IC_LEFT (ic));
1906   rtype = operandType (IC_RESULT (ic));
1907
1908   /* if float then do float stuff */
1909   if (IS_FLOAT (optype))
1910     {
1911       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1912       goto release;
1913     }
1914
1915   /* otherwise subtract from zero */
1916   size = AOP_SIZE (IC_LEFT (ic));
1917   offset = 0;
1918   //CLRC ;
1919   while (size--)
1920     {
1921       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1922       if (!strcmp (l, "a"))
1923         {
1924           if (offset == 0)
1925             SETC;
1926           emitcode ("cpl", "a");
1927           emitcode ("addc", "a,#0");
1928         }
1929       else
1930         {
1931           if (offset == 0)
1932             CLRC;
1933           emitcode ("clr", "a");
1934           emitcode ("subb", "a,%s", l);
1935         }
1936       aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1937     }
1938
1939   /* if any remaining bytes in the result */
1940   /* we just need to propagate the sign   */
1941   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1942     {
1943       emitcode ("rlc", "a");
1944       emitcode ("subb", "a,acc");
1945       while (size--)
1946         aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1947     }
1948
1949 release:
1950   /* release the aops */
1951   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1952   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1953 }
1954
1955 /*-----------------------------------------------------------------*/
1956 /* saveRegisters - will look for a call and save the registers     */
1957 /*-----------------------------------------------------------------*/
1958 static void
1959 saveRegisters (iCode * lic)
1960 {
1961   int i;
1962   iCode *ic;
1963   bitVect *rsave;
1964
1965   /* look for call */
1966   for (ic = lic; ic; ic = ic->next)
1967     if (ic->op == CALL || ic->op == PCALL)
1968       break;
1969
1970   if (!ic)
1971     {
1972       fprintf (stderr, "found parameter push with no function call\n");
1973       return;
1974     }
1975
1976   /* if the registers have been saved already or don't need to be then
1977      do nothing */
1978   if (ic->regsSaved)
1979     return;
1980   if (IS_SYMOP(IC_LEFT(ic)) &&
1981       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1982        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1983     return;
1984
1985   /* save the registers in use at this time but skip the
1986      ones for the result */
1987   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1988                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1989
1990   ic->regsSaved = 1;
1991   if (options.useXstack)
1992     {
1993       int count = bitVectnBitsOn (rsave);
1994
1995       if (count == 1)
1996         {
1997           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1998           if (reg->type == REG_BIT)
1999             {
2000               emitcode ("mov", "a,%s", reg->base);
2001             }
2002           else
2003             {
2004               emitcode ("mov", "a,%s", reg->name);
2005             }
2006           emitcode ("mov", "r0,%s", spname);
2007           emitcode ("inc", "%s", spname);// allocate before use
2008           emitcode ("movx", "@r0,a");
2009           if (bitVectBitValue (rsave, R0_IDX))
2010             emitcode ("mov", "r0,a");
2011         }
2012       else if (count != 0)
2013         {
2014           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2015           int nBits = bitVectnBitsOn (rsavebits);
2016
2017           if (nBits != 0)
2018             {
2019               count = count - nBits + 1;
2020               /* remove all but the first bits as they are pushed all at once */
2021               rsave = bitVectCplAnd (rsave, rsavebits);
2022               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2023             }
2024
2025           if (bitVectBitValue (rsave, R0_IDX))
2026             {
2027               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2028             }
2029           emitcode ("mov", "r0,%s", spname);
2030           MOVA ("r0");
2031           emitcode ("add", "a,#%d", count);
2032           emitcode ("mov", "%s,a", spname);
2033           for (i = 0; i < mcs51_nRegs; i++)
2034             {
2035               if (bitVectBitValue (rsave, i))
2036                 {
2037                   regs * reg = mcs51_regWithIdx (i);
2038                   if (i == R0_IDX)
2039                     {
2040                       emitcode ("pop", "acc");
2041                       emitcode ("push", "acc");
2042                     }
2043                   else if (reg->type == REG_BIT)
2044                     {
2045                       emitcode ("mov", "a,%s", reg->base);
2046                     }
2047                   else
2048                     {
2049                       emitcode ("mov", "a,%s", reg->name);
2050                     }
2051                   emitcode ("movx", "@r0,a");
2052                   if (--count)
2053                     {
2054                       emitcode ("inc", "r0");
2055                     }
2056                 }
2057             }
2058           if (bitVectBitValue (rsave, R0_IDX))
2059             {
2060               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2061             }
2062         }
2063     }
2064   else
2065     {
2066       bool bits_pushed = FALSE;
2067       for (i = 0; i < mcs51_nRegs; i++)
2068         {
2069           if (bitVectBitValue (rsave, i))
2070             {
2071               bits_pushed = pushReg (i, bits_pushed);
2072             }
2073         }
2074     }
2075 }
2076
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRegisters - pop the pushed registers                      */
2079 /*-----------------------------------------------------------------*/
2080 static void
2081 unsaveRegisters (iCode * ic)
2082 {
2083   int i;
2084   bitVect *rsave;
2085
2086   /* restore the registers in use at this time but skip the
2087      ones for the result */
2088   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2089                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2090
2091   if (options.useXstack)
2092     {
2093       int count = bitVectnBitsOn (rsave);
2094
2095       if (count == 1)
2096         {
2097           regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2098           emitcode ("mov", "r0,%s", spname);
2099           emitcode ("dec", "r0");
2100           emitcode ("movx", "a,@r0");
2101           if (reg->type == REG_BIT)
2102             {
2103               emitcode ("mov", "%s,a", reg->base);
2104             }
2105           else
2106             {
2107               emitcode ("mov", "%s,a", reg->name);
2108             }
2109           emitcode ("dec", "%s", spname);
2110         }
2111       else if (count != 0)
2112         {
2113           bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2114           int nBits = bitVectnBitsOn (rsavebits);
2115
2116           if (nBits != 0)
2117             {
2118               count = count - nBits + 1;
2119               /* remove all but the first bits as they are popped all at once */
2120               rsave = bitVectCplAnd (rsave, rsavebits);
2121               rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2122             }
2123
2124           emitcode ("mov", "r0,%s", spname);
2125           for (i = mcs51_nRegs; i >= 0; i--)
2126             {
2127               if (bitVectBitValue (rsave, i))
2128                 {
2129                   regs * reg = mcs51_regWithIdx (i);
2130                   emitcode ("dec", "r0");
2131                   emitcode ("movx", "a,@r0");
2132                   if (i == R0_IDX)
2133                     {
2134                       emitcode ("push", "acc");
2135                     }
2136                   else if (reg->type == REG_BIT)
2137                     {
2138                       emitcode ("mov", "%s,a", reg->base);
2139                     }
2140                   else
2141                     {
2142                       emitcode ("mov", "%s,a", reg->name);
2143                     }
2144                 }
2145             }
2146           emitcode ("mov", "%s,r0", spname);
2147           if (bitVectBitValue (rsave, R0_IDX))
2148             {
2149               emitcode ("pop", "ar0");
2150             }
2151         }
2152     }
2153   else
2154     {
2155       bool bits_popped = FALSE;
2156       for (i = mcs51_nRegs; i >= 0; i--)
2157         {
2158           if (bitVectBitValue (rsave, i))
2159             {
2160               bits_popped = popReg (i, bits_popped);
2161             }
2162         }
2163     }
2164 }
2165
2166
2167 /*-----------------------------------------------------------------*/
2168 /* pushSide -                                                      */
2169 /*-----------------------------------------------------------------*/
2170 static void
2171 pushSide (operand * oper, int size)
2172 {
2173   int offset = 0;
2174   while (size--)
2175     {
2176       char *l = aopGet (oper, offset++, FALSE, TRUE);
2177       if (AOP_TYPE (oper) != AOP_REG &&
2178           AOP_TYPE (oper) != AOP_DIR &&
2179           strcmp (l, "a"))
2180         {
2181           MOVA (l);
2182           emitcode ("push", "acc");
2183         }
2184       else
2185         {
2186           emitcode ("push", "%s", l);
2187         }
2188     }
2189 }
2190
2191 /*-----------------------------------------------------------------*/
2192 /* assignResultValue - also indicates if acc is in use afterwards  */
2193 /*-----------------------------------------------------------------*/
2194 static bool
2195 assignResultValue (operand * oper, operand * func)
2196 {
2197   int offset = 0;
2198   int size = AOP_SIZE (oper);
2199   bool accuse = FALSE;
2200
2201   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2202     {
2203       outBitC (oper);
2204       return FALSE;
2205     }
2206
2207   while (size--)
2208     {
2209       accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2210       offset++;
2211     }
2212   return accuse;
2213 }
2214
2215
2216 /*-----------------------------------------------------------------*/
2217 /* genXpush - pushes onto the external stack                       */
2218 /*-----------------------------------------------------------------*/
2219 static void
2220 genXpush (iCode * ic)
2221 {
2222   asmop *aop = newAsmop (0);
2223   regs *r;
2224   int size, offset = 0;
2225
2226   D(emitcode (";     genXpush",""));
2227
2228   aopOp (IC_LEFT (ic), ic, FALSE);
2229   r = getFreePtr (ic, &aop, FALSE);
2230
2231   size = AOP_SIZE (IC_LEFT (ic));
2232
2233   if (size == 1)
2234     {
2235       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2236       emitcode ("mov", "%s,%s", r->name, spname);
2237       emitcode ("inc", "%s", spname); // allocate space first
2238       emitcode ("movx", "@%s,a", r->name);
2239     }
2240   else
2241     {
2242       // allocate space first
2243       emitcode ("mov", "%s,%s", r->name, spname);
2244       MOVA (r->name);
2245       emitcode ("add", "a,#%d", size);
2246       emitcode ("mov", "%s,a", spname);
2247
2248       while (size--)
2249         {
2250           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2251           emitcode ("movx", "@%s,a", r->name);
2252           emitcode ("inc", "%s", r->name);
2253         }
2254     }
2255
2256   freeAsmop (NULL, aop, ic, TRUE);
2257   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2258 }
2259
2260 /*-----------------------------------------------------------------*/
2261 /* genIpush - generate code for pushing this gets a little complex */
2262 /*-----------------------------------------------------------------*/
2263 static void
2264 genIpush (iCode * ic)
2265 {
2266   int size, offset = 0;
2267   char *l;
2268   char *prev = "";
2269
2270   D(emitcode (";     genIpush",""));
2271
2272   /* if this is not a parm push : ie. it is spill push
2273      and spill push is always done on the local stack */
2274   if (!ic->parmPush)
2275     {
2276
2277       /* and the item is spilt then do nothing */
2278       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2279         return;
2280
2281       aopOp (IC_LEFT (ic), ic, FALSE);
2282       size = AOP_SIZE (IC_LEFT (ic));
2283       /* push it on the stack */
2284       while (size--)
2285         {
2286           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2287           if (*l == '#')
2288             {
2289               MOVA (l);
2290               l = "acc";
2291             }
2292           emitcode ("push", "%s", l);
2293         }
2294       return;
2295     }
2296
2297   /* this is a parameter push: in this case we call
2298      the routine to find the call and save those
2299      registers that need to be saved */
2300   saveRegisters (ic);
2301
2302   /* if use external stack then call the external
2303      stack pushing routine */
2304   if (options.useXstack)
2305     {
2306       genXpush (ic);
2307       return;
2308     }
2309
2310   /* then do the push */
2311   aopOp (IC_LEFT (ic), ic, FALSE);
2312
2313   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2314   size = AOP_SIZE (IC_LEFT (ic));
2315
2316   while (size--)
2317     {
2318       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2319       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2320           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2321           strcmp (l, "a"))
2322         {
2323           if (strcmp (l, prev) || *l == '@')
2324             MOVA (l);
2325           emitcode ("push", "acc");
2326         }
2327       else
2328         {
2329           emitcode ("push", "%s", l);
2330         }
2331       prev = l;
2332     }
2333
2334   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2335 }
2336
2337 /*-----------------------------------------------------------------*/
2338 /* genIpop - recover the registers: can happen only for spilling   */
2339 /*-----------------------------------------------------------------*/
2340 static void
2341 genIpop (iCode * ic)
2342 {
2343   int size, offset;
2344
2345   D(emitcode (";     genIpop",""));
2346
2347   /* if the temp was not pushed then */
2348   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2349     return;
2350
2351   aopOp (IC_LEFT (ic), ic, FALSE);
2352   size = AOP_SIZE (IC_LEFT (ic));
2353   offset = (size - 1);
2354   while (size--)
2355     emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2356                                    FALSE, TRUE));
2357
2358   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2359 }
2360
2361 /*-----------------------------------------------------------------*/
2362 /* saveRBank - saves an entire register bank on the stack          */
2363 /*-----------------------------------------------------------------*/
2364 static void
2365 saveRBank (int bank, iCode * ic, bool pushPsw)
2366 {
2367   int i;
2368   int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2369   asmop *aop = NULL;
2370   regs *r = NULL;
2371
2372   if (options.useXstack)
2373     {
2374       if (!ic)
2375       {
2376           /* Assume r0 is available for use. */
2377           r = mcs51_regWithIdx (R0_IDX);;
2378       }
2379       else
2380       {
2381           aop = newAsmop (0);
2382           r = getFreePtr (ic, &aop, FALSE);
2383       }
2384       // allocate space first
2385       emitcode ("mov", "%s,%s", r->name, spname);
2386       MOVA (r->name);
2387       emitcode ("add", "a,#%d", count);
2388       emitcode ("mov", "%s,a", spname);
2389     }
2390
2391   for (i = 0; i < mcs51_nRegs; i++)
2392     {
2393       if (options.useXstack)
2394         {
2395           emitcode ("mov", "a,(%s+%d)",
2396                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2397           emitcode ("movx", "@%s,a", r->name);
2398           if (--count)
2399             emitcode ("inc", "%s", r->name);
2400         }
2401       else
2402         emitcode ("push", "(%s+%d)",
2403                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2404     }
2405
2406   if (pushPsw)
2407     {
2408       if (options.useXstack)
2409         {
2410           emitcode ("mov", "a,psw");
2411           emitcode ("movx", "@%s,a", r->name);
2412
2413         }
2414       else
2415         {
2416           emitcode ("push", "psw");
2417         }
2418
2419       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2420     }
2421
2422   if (aop)
2423     {
2424       freeAsmop (NULL, aop, ic, TRUE);
2425     }
2426
2427   if (ic)
2428   {
2429     ic->bankSaved = 1;
2430   }
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* unsaveRBank - restores the register bank from stack             */
2435 /*-----------------------------------------------------------------*/
2436 static void
2437 unsaveRBank (int bank, iCode * ic, bool popPsw)
2438 {
2439   int i;
2440   asmop *aop = NULL;
2441   regs *r = NULL;
2442
2443   if (options.useXstack)
2444     {
2445       if (!ic)
2446         {
2447           /* Assume r0 is available for use. */
2448           r = mcs51_regWithIdx (R0_IDX);;
2449         }
2450       else
2451         {
2452           aop = newAsmop (0);
2453           r = getFreePtr (ic, &aop, FALSE);
2454         }
2455       emitcode ("mov", "%s,%s", r->name, spname);
2456     }
2457
2458   if (popPsw)
2459     {
2460       if (options.useXstack)
2461         {
2462           emitcode ("dec", "%s", r->name);
2463           emitcode ("movx", "a,@%s", r->name);
2464           emitcode ("mov", "psw,a");
2465         }
2466       else
2467         {
2468           emitcode ("pop", "psw");
2469         }
2470     }
2471
2472   for (i = (mcs51_nRegs - 1); i >= 0; i--)
2473     {
2474       if (options.useXstack)
2475         {
2476           emitcode ("dec", "%s", r->name);
2477           emitcode ("movx", "a,@%s", r->name);
2478           emitcode ("mov", "(%s+%d),a",
2479                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2480         }
2481       else
2482         {
2483           emitcode ("pop", "(%s+%d)",
2484                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2485         }
2486     }
2487
2488   if (options.useXstack)
2489     {
2490       emitcode ("mov", "%s,%s", spname, r->name);
2491     }
2492
2493   if (aop)
2494     {
2495       freeAsmop (NULL, aop, ic, TRUE);
2496     }
2497 }
2498
2499 /*-----------------------------------------------------------------*/
2500 /* genSend - gen code for SEND                                     */
2501 /*-----------------------------------------------------------------*/
2502 static void genSend(set *sendSet)
2503 {
2504   iCode *sic;
2505   int bit_count = 0;
2506
2507   /* first we do all bit parameters */
2508   for (sic = setFirstItem (sendSet); sic;
2509        sic = setNextItem (sendSet))
2510     {
2511       aopOp (IC_LEFT (sic), sic, FALSE);
2512
2513       if (sic->argreg > 12)
2514         {
2515           int bit = sic->argreg-13;
2516
2517           /* if left is a literal then
2518              we know what the value is */
2519           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2520             {
2521               if (((int) operandLitValue (IC_LEFT (sic))))
2522                   emitcode ("setb", "b[%d]", bit);
2523               else
2524                   emitcode ("clr", "b[%d]", bit);
2525             }
2526           else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2527             {
2528               char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2529                 if (strcmp (l, "c"))
2530                     emitcode ("mov", "c,%s", l);
2531                 emitcode ("mov", "b[%d],c", bit);
2532             }
2533           else
2534             {
2535               /* we need to or */
2536               toBoolean (IC_LEFT (sic));
2537               /* set C, if a >= 1 */
2538               emitcode ("add", "a,#0xff");
2539               emitcode ("mov", "b[%d],c", bit);
2540             }
2541           bit_count++;
2542           BitBankUsed = 1;
2543         }
2544       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2545     }
2546
2547   if (bit_count)
2548     {
2549       saveRegisters (setFirstItem (sendSet));
2550       emitcode ("mov", "bits,b");
2551     }
2552
2553   /* then we do all other parameters */
2554   for (sic = setFirstItem (sendSet); sic;
2555        sic = setNextItem (sendSet))
2556     {
2557       int size, offset = 0;
2558       aopOp (IC_LEFT (sic), sic, FALSE);
2559       size = AOP_SIZE (IC_LEFT (sic));
2560
2561       if (sic->argreg == 1)
2562         {
2563           while (size--)
2564             {
2565               char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2566               if (strcmp (l, fReturn[offset]))
2567                   emitcode ("mov", "%s,%s", fReturn[offset], l);
2568               offset++;
2569             }
2570         }
2571       else if (sic->argreg <= 12)
2572         {
2573           while (size--)
2574             {
2575               emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2576                         aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2577               offset++;
2578             }
2579         }
2580       freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2581     }
2582 }
2583
2584 /*-----------------------------------------------------------------*/
2585 /* selectRegBank - emit code to select the register bank           */
2586 /*-----------------------------------------------------------------*/
2587 static void
2588 selectRegBank (short bank, bool keepFlags)
2589 {
2590   /* if f.e. result is in carry */
2591   if (keepFlags)
2592     {
2593       emitcode ("anl", "psw,#0xE7");
2594       if (bank)
2595         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2596     }
2597   else
2598     {
2599       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2600     }
2601 }
2602
2603 /*-----------------------------------------------------------------*/
2604 /* genCall - generates a call statement                            */
2605 /*-----------------------------------------------------------------*/
2606 static void
2607 genCall (iCode * ic)
2608 {
2609   sym_link *dtype;
2610   sym_link *etype;
2611 //  bool restoreBank = FALSE;
2612   bool swapBanks = FALSE;
2613   bool accuse = FALSE;
2614   bool accPushed = FALSE;
2615   bool resultInF0 = FALSE;
2616
2617   D(emitcode(";     genCall",""));
2618
2619   dtype = operandType (IC_LEFT (ic));
2620   etype = getSpec(dtype);
2621   /* if send set is not empty then assign */
2622   if (_G.sendSet)
2623     {
2624         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2625             genSend(reverseSet(_G.sendSet));
2626         } else {
2627             genSend(_G.sendSet);
2628         }
2629
2630       _G.sendSet = NULL;
2631     }
2632
2633   /* if we are calling a not _naked function that is not using
2634      the same register bank then we need to save the
2635      destination registers on the stack */
2636   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2637       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2638        !IFFUNC_ISISR (dtype))
2639     {
2640       swapBanks = TRUE;
2641     }
2642
2643   /* if caller saves & we have not saved then */
2644   if (!ic->regsSaved)
2645       saveRegisters (ic);
2646
2647   if (swapBanks)
2648     {
2649         emitcode ("mov", "psw,#0x%02x",
2650            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2651     }
2652
2653   /* make the call */
2654   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2655     {
2656       if (IFFUNC_CALLEESAVES(dtype))
2657         {
2658           werror (E_BANKED_WITH_CALLEESAVES);
2659         }
2660       else
2661         {
2662           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2663                      OP_SYMBOL (IC_LEFT (ic))->rname :
2664                      OP_SYMBOL (IC_LEFT (ic))->name);
2665
2666           emitcode ("mov", "r0,#%s", l);
2667           emitcode ("mov", "r1,#(%s >> 8)", l);
2668           emitcode ("mov", "r2,#(%s >> 16)", l);
2669           emitcode ("lcall", "__sdcc_banked_call");
2670         }
2671     }
2672   else
2673     {
2674       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2675                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2676                                 OP_SYMBOL (IC_LEFT (ic))->name));
2677     }
2678
2679   if (swapBanks)
2680     {
2681       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2682     }
2683
2684   /* if we need assign a result value */
2685   if ((IS_ITEMP (IC_RESULT (ic)) &&
2686        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2687        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2688         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2689         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2690       IS_TRUE_SYMOP (IC_RESULT (ic)))
2691     {
2692
2693       _G.accInUse++;
2694       aopOp (IC_RESULT (ic), ic, FALSE);
2695       _G.accInUse--;
2696
2697       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2698
2699       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2700     }
2701
2702   /* adjust the stack for parameters if required */
2703   if (ic->parmBytes)
2704     {
2705       int i;
2706       if (ic->parmBytes > 3)
2707         {
2708           if (accuse)
2709             {
2710               emitcode ("push", "acc");
2711               accPushed = TRUE;
2712             }
2713           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2714               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2715             {
2716               emitcode ("mov", "F0,c");
2717               resultInF0 = TRUE;
2718             }
2719
2720           emitcode ("mov", "a,%s", spname);
2721           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2722           emitcode ("mov", "%s,a", spname);
2723
2724           /* unsaveRegisters from xstack needs acc, but */
2725           /* unsaveRegisters from stack needs this popped */
2726           if (accPushed && !options.useXstack)
2727             {
2728               emitcode ("pop", "acc");
2729               accPushed = FALSE;
2730             }
2731         }
2732       else
2733         for (i = 0; i < ic->parmBytes; i++)
2734           emitcode ("dec", "%s", spname);
2735     }
2736
2737   /* if we had saved some registers then unsave them */
2738   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739     {
2740       if (accuse && !accPushed && options.useXstack)
2741         {
2742           /* xstack needs acc, but doesn't touch normal stack */
2743           emitcode ("push", "acc");
2744           accPushed = TRUE;
2745         }
2746       unsaveRegisters (ic);
2747     }
2748
2749 //  /* if register bank was saved then pop them */
2750 //  if (restoreBank)
2751 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2752
2753   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2754     {
2755       if (resultInF0)
2756           emitcode ("mov", "c,F0");
2757
2758       aopOp (IC_RESULT (ic), ic, FALSE);
2759       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2760       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2761     }
2762
2763   if (accPushed)
2764     emitcode ("pop", "acc");
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* -10l - generates a call by pointer statement                */
2769 /*-----------------------------------------------------------------*/
2770 static void
2771 genPcall (iCode * ic)
2772 {
2773   sym_link *dtype;
2774   sym_link *etype;
2775   symbol *rlbl = newiTempLabel (NULL);
2776 //  bool restoreBank=FALSE;
2777   bool swapBanks = FALSE;
2778   bool resultInF0 = FALSE;
2779
2780   D(emitcode(";     genPCall",""));
2781
2782   dtype = operandType (IC_LEFT (ic))->next;
2783   etype = getSpec(dtype);
2784   /* if caller saves & we have not saved then */
2785   if (!ic->regsSaved)
2786     saveRegisters (ic);
2787
2788   /* if we are calling a not _naked function that is not using
2789      the same register bank then we need to save the
2790      destination registers on the stack */
2791   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2792       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2793       !IFFUNC_ISISR (dtype))
2794     {
2795 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2796 //    restoreBank=TRUE;
2797       swapBanks = TRUE;
2798       // need caution message to user here
2799     }
2800
2801   if (IS_LITERAL(etype))
2802     {
2803       /* if send set is not empty then assign */
2804       if (_G.sendSet)
2805         {
2806           genSend(reverseSet(_G.sendSet));
2807           _G.sendSet = NULL;
2808         }
2809
2810       if (swapBanks)
2811         {
2812           emitcode ("mov", "psw,#0x%02x",
2813            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2814         }
2815
2816       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2817         {
2818           if (IFFUNC_CALLEESAVES(dtype))
2819             {
2820               werror (E_BANKED_WITH_CALLEESAVES);
2821             }
2822           else
2823             {
2824               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2825
2826               emitcode ("mov", "r0,#%s", l);
2827               emitcode ("mov", "r1,#(%s >> 8)", l);
2828               emitcode ("mov", "r2,#(%s >> 16)", l);
2829               emitcode ("lcall", "__sdcc_banked_call");
2830             }
2831         }
2832       else
2833         {
2834           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2835         }
2836     }
2837   else
2838     {
2839       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2840         {
2841           if (IFFUNC_CALLEESAVES(dtype))
2842             {
2843               werror (E_BANKED_WITH_CALLEESAVES);
2844             }
2845           else
2846             {
2847               aopOp (IC_LEFT (ic), ic, FALSE);
2848
2849               if (!swapBanks)
2850                 {
2851                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2852                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2853                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2854                 }
2855               else
2856                 {
2857                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2858                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2859                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2860                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2861                 }
2862
2863               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2864
2865               /* if send set is not empty then assign */
2866               if (_G.sendSet)
2867                 {
2868                   genSend(reverseSet(_G.sendSet));
2869                   _G.sendSet = NULL;
2870                 }
2871
2872               if (swapBanks)
2873                 {
2874                   emitcode ("mov", "psw,#0x%02x",
2875                    ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2876                 }
2877
2878               /* make the call */
2879               emitcode ("lcall", "__sdcc_banked_call");
2880             }
2881         }
2882       else
2883         {
2884           /* push the return address on to the stack */
2885           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2886           emitcode ("push", "acc");
2887           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2888           emitcode ("push", "acc");
2889
2890           /* now push the calling address */
2891           aopOp (IC_LEFT (ic), ic, FALSE);
2892
2893           pushSide (IC_LEFT (ic), FPTRSIZE);
2894
2895           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2896
2897           /* if send set is not empty the assign */
2898           if (_G.sendSet)
2899             {
2900               genSend(reverseSet(_G.sendSet));
2901               _G.sendSet = NULL;
2902             }
2903
2904           if (swapBanks)
2905             {
2906               emitcode ("mov", "psw,#0x%02x",
2907                ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2908             }
2909
2910           /* make the call */
2911           emitcode ("ret", "");
2912           emitcode ("", "%05d$:", (rlbl->key + 100));
2913         }
2914     }
2915   if (swapBanks)
2916     {
2917       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2918     }
2919
2920   /* if we need assign a result value */
2921   if ((IS_ITEMP (IC_RESULT (ic)) &&
2922        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2923        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2924         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2925       IS_TRUE_SYMOP (IC_RESULT (ic)))
2926     {
2927
2928       _G.accInUse++;
2929       aopOp (IC_RESULT (ic), ic, FALSE);
2930       _G.accInUse--;
2931
2932       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2933
2934       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2935     }
2936
2937   /* adjust the stack for parameters if required */
2938   if (ic->parmBytes)
2939     {
2940       int i;
2941       if (ic->parmBytes > 3)
2942         {
2943           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2944               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2945             {
2946               emitcode ("mov", "F0,c");
2947               resultInF0 = TRUE;
2948             }
2949
2950           emitcode ("mov", "a,%s", spname);
2951           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2952           emitcode ("mov", "%s,a", spname);
2953         }
2954       else
2955         for (i = 0; i < ic->parmBytes; i++)
2956           emitcode ("dec", "%s", spname);
2957
2958     }
2959
2960 //  /* if register bank was saved then unsave them */
2961 //  if (restoreBank)
2962 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2963
2964   /* if we had saved some registers then unsave them */
2965   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2966     unsaveRegisters (ic);
2967
2968   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2969     {
2970       if (resultInF0)
2971           emitcode ("mov", "c,F0");
2972
2973       aopOp (IC_RESULT (ic), ic, FALSE);
2974       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2975       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2976     }
2977 }
2978
2979 /*-----------------------------------------------------------------*/
2980 /* resultRemat - result  is rematerializable                       */
2981 /*-----------------------------------------------------------------*/
2982 static int
2983 resultRemat (iCode * ic)
2984 {
2985   if (SKIP_IC (ic) || ic->op == IFX)
2986     return 0;
2987
2988   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2989     {
2990       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2991       if (sym->remat && !POINTER_SET (ic))
2992         return 1;
2993     }
2994
2995   return 0;
2996 }
2997
2998 #if defined(__BORLANDC__) || defined(_MSC_VER)
2999 #define STRCASECMP stricmp
3000 #else
3001 #define STRCASECMP strcasecmp
3002 #endif
3003
3004 /*-----------------------------------------------------------------*/
3005 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3006 /*-----------------------------------------------------------------*/
3007 static int
3008 regsCmp(void *p1, void *p2)
3009 {
3010   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3011 }
3012
3013 static bool
3014 inExcludeList (char *s)
3015 {
3016   const char *p = setFirstItem(options.excludeRegsSet);
3017
3018   if (p == NULL || STRCASECMP(p, "none") == 0)
3019     return FALSE;
3020
3021
3022   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3023 }
3024
3025 /*-----------------------------------------------------------------*/
3026 /* genFunction - generated code for function entry                 */
3027 /*-----------------------------------------------------------------*/
3028 static void
3029 genFunction (iCode * ic)
3030 {
3031   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3032   sym_link *ftype;
3033   bool     switchedPSW = FALSE;
3034   int      calleesaves_saved_register = -1;
3035   int      stackAdjust = sym->stack;
3036   int      accIsFree = sym->recvSize < 4;
3037   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3038   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3039
3040   _G.nRegsSaved = 0;
3041   /* create the function header */
3042   emitcode (";", "-----------------------------------------");
3043   emitcode (";", " function %s", sym->name);
3044   emitcode (";", "-----------------------------------------");
3045
3046   emitcode ("", "%s:", sym->rname);
3047   ftype = operandType (IC_LEFT (ic));
3048   _G.currentFunc = sym;
3049
3050   if (IFFUNC_ISNAKED(ftype))
3051   {
3052       emitcode(";", "naked function: no prologue.");
3053       return;
3054   }
3055
3056   /* here we need to generate the equates for the
3057      register bank if required */
3058   if (FUNC_REGBANK (ftype) != rbank)
3059     {
3060       int i;
3061
3062       rbank = FUNC_REGBANK (ftype);
3063       for (i = 0; i < mcs51_nRegs; i++)
3064         {
3065           if (regs8051[i].type != REG_BIT)
3066             {
3067               if (strcmp (regs8051[i].base, "0") == 0)
3068                 emitcode ("", "%s = 0x%02x",
3069                           regs8051[i].dname,
3070                           8 * rbank + regs8051[i].offset);
3071               else
3072                 emitcode ("", "%s = %s + 0x%02x",
3073                           regs8051[i].dname,
3074                           regs8051[i].base,
3075                           8 * rbank + regs8051[i].offset);
3076             }
3077         }
3078     }
3079
3080   /* if this is an interrupt service routine then
3081      save acc, b, dpl, dph  */
3082   if (IFFUNC_ISISR (sym->type))
3083     {
3084
3085       if (!inExcludeList ("acc"))
3086         emitcode ("push", "acc");
3087       if (!inExcludeList ("b"))
3088         emitcode ("push", "b");
3089       if (!inExcludeList ("dpl"))
3090         emitcode ("push", "dpl");
3091       if (!inExcludeList ("dph"))
3092         emitcode ("push", "dph");
3093       /* if this isr has no bank i.e. is going to
3094          run with bank 0 , then we need to save more
3095          registers :-) */
3096       if (!FUNC_REGBANK (sym->type))
3097         {
3098
3099           /* if this function does not call any other
3100              function then we can be economical and
3101              save only those registers that are used */
3102           if (!IFFUNC_HASFCALL(sym->type))
3103             {
3104               int i;
3105
3106               /* if any registers used */
3107               if (sym->regsUsed)
3108                 {
3109                   bool bits_pushed = FALSE;
3110                   /* save the registers used */
3111                   for (i = 0; i < sym->regsUsed->size; i++)
3112                     {
3113                       if (bitVectBitValue (sym->regsUsed, i))
3114                         bits_pushed = pushReg (i, bits_pushed);
3115                     }
3116                 }
3117             }
3118           else
3119             {
3120
3121               /* this function has a function call. We cannot
3122                  determines register usage so we will have to push the
3123                  entire bank */
3124                 saveRBank (0, ic, FALSE);
3125                 if (options.parms_in_bank1) {
3126                     int i;
3127                     for (i=0; i < 8 ; i++ ) {
3128                         emitcode ("push","%s",rb1regs[i]);
3129                     }
3130                 }
3131             }
3132         }
3133         else
3134         {
3135             /* This ISR uses a non-zero bank.
3136              *
3137              * We assume that the bank is available for our
3138              * exclusive use.
3139              *
3140              * However, if this ISR calls a function which uses some
3141              * other bank, we must save that bank entirely.
3142              */
3143             unsigned long banksToSave = 0;
3144
3145             if (IFFUNC_HASFCALL(sym->type))
3146             {
3147
3148 #define MAX_REGISTER_BANKS 4
3149
3150                 iCode *i;
3151                 int ix;
3152
3153                 for (i = ic; i; i = i->next)
3154                 {
3155                     if (i->op == ENDFUNCTION)
3156                     {
3157                         /* we got to the end OK. */
3158                         break;
3159                     }
3160
3161                     if (i->op == CALL)
3162                     {
3163                         sym_link *dtype;
3164
3165                         dtype = operandType (IC_LEFT(i));
3166                         if (dtype
3167                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3168                         {
3169                              /* Mark this bank for saving. */
3170                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3171                              {
3172                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3173                              }
3174                              else
3175                              {
3176                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3177                              }
3178
3179                              /* And note that we don't need to do it in
3180                               * genCall.
3181                               */
3182                              i->bankSaved = 1;
3183                         }
3184                     }
3185                     if (i->op == PCALL)
3186                     {
3187                         /* This is a mess; we have no idea what
3188                          * register bank the called function might
3189                          * use.
3190                          *
3191                          * The only thing I can think of to do is
3192                          * throw a warning and hope.
3193                          */
3194                         werror(W_FUNCPTR_IN_USING_ISR);
3195                     }
3196                 }
3197
3198                 if (banksToSave && options.useXstack)
3199                 {
3200                     /* Since we aren't passing it an ic,
3201                      * saveRBank will assume r0 is available to abuse.
3202                      *
3203                      * So switch to our (trashable) bank now, so
3204                      * the caller's R0 isn't trashed.
3205                      */
3206                     emitcode ("push", "psw");
3207                     emitcode ("mov", "psw,#0x%02x",
3208                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3209                     switchedPSW = TRUE;
3210                 }
3211
3212                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3213                 {
3214                      if (banksToSave & (1 << ix))
3215                      {
3216                          saveRBank(ix, NULL, FALSE);
3217                      }
3218                 }
3219             }
3220             // TODO: this needs a closer look
3221             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3222         }
3223
3224       /* Set the register bank to the desired value if nothing else */
3225       /* has done so yet. */
3226       if (!switchedPSW)
3227         {
3228           emitcode ("push", "psw");
3229           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3230         }
3231     }
3232   else
3233     {
3234       /* This is a non-ISR function. The caller has already switched register */
3235       /* banks, if necessary, so just handle the callee-saves option. */
3236
3237       /* if callee-save to be used for this function
3238          then save the registers being used in this function */
3239       if (IFFUNC_CALLEESAVES(sym->type))
3240         {
3241           int i;
3242
3243           /* if any registers used */
3244           if (sym->regsUsed)
3245             {
3246               bool bits_pushed = FALSE;
3247               /* save the registers used */
3248               for (i = 0; i < sym->regsUsed->size; i++)
3249                 {
3250                   if (bitVectBitValue (sym->regsUsed, i))
3251                     {
3252                       /* remember one saved register for later usage */
3253                       if (calleesaves_saved_register < 0)
3254                         calleesaves_saved_register = i;
3255                       bits_pushed = pushReg (i, bits_pushed);
3256                       _G.nRegsSaved++;
3257                     }
3258                 }
3259             }
3260         }
3261     }
3262
3263
3264   if (fReentrant)
3265     {
3266       if (options.useXstack)
3267         {
3268           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3269             {
3270               emitcode ("mov", "r0,%s", spname);
3271               emitcode ("inc", "%s", spname);
3272               emitcode ("xch", "a,_bpx");
3273               emitcode ("movx", "@r0,a");
3274               emitcode ("inc", "r0");
3275               emitcode ("mov", "a,r0");
3276               emitcode ("xch", "a,_bpx");
3277             }
3278           if (sym->stack)
3279             {
3280               emitcode ("push", "_bp");     /* save the callers stack  */
3281               emitcode ("mov", "_bp,sp");
3282             }
3283         }
3284       else
3285         {
3286           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3287             {
3288               /* set up the stack */
3289               emitcode ("push", "_bp");     /* save the callers stack  */
3290               emitcode ("mov", "_bp,sp");
3291             }
3292         }
3293     }
3294
3295   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3296   /* before setting up the stack frame completely. */
3297   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3298     {
3299       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3300
3301       if (rsym->isitmp)
3302         {
3303           if (rsym && rsym->regType == REG_CND)
3304             rsym = NULL;
3305           if (rsym && (rsym->accuse || rsym->ruonly))
3306             rsym = NULL;
3307           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3308             rsym = rsym->usl.spillLoc;
3309         }
3310
3311       /* If the RECEIVE operand immediately spills to the first entry on the */
3312       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3313       /* rather than the usual @r0/r1 machinations. */
3314       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3315         {
3316           int ofs;
3317
3318           _G.current_iCode = ric;
3319           D(emitcode (";     genReceive",""));
3320           for (ofs=0; ofs < sym->recvSize; ofs++)
3321             {
3322               if (!strcmp (fReturn[ofs], "a"))
3323                 emitcode ("push", "acc");
3324               else
3325                 emitcode ("push", fReturn[ofs]);
3326             }
3327           stackAdjust -= sym->recvSize;
3328           if (stackAdjust<0)
3329             {
3330               assert (stackAdjust>=0);
3331               stackAdjust = 0;
3332             }
3333           _G.current_iCode = ic;
3334           ric->generated = 1;
3335           accIsFree = 1;
3336         }
3337       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3338       /* to free up the accumulator. */
3339       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3340         {
3341           int ofs;
3342
3343           _G.current_iCode = ric;
3344           D(emitcode (";     genReceive",""));
3345           for (ofs=0; ofs < sym->recvSize; ofs++)
3346             {
3347               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3348             }
3349           _G.current_iCode = ic;
3350           ric->generated = 1;
3351           accIsFree = 1;
3352         }
3353     }
3354
3355   /* adjust the stack for the function */
3356   if (stackAdjust)
3357     {
3358       int i = stackAdjust;
3359       if (i > 256)
3360         werror (W_STACK_OVERFLOW, sym->name);
3361
3362       if (i > 3 && accIsFree)
3363         {
3364           emitcode ("mov", "a,sp");
3365           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3366           emitcode ("mov", "sp,a");
3367         }
3368       else if (i > 5)
3369         {
3370           /* The accumulator is not free, so we will need another register */
3371           /* to clobber. No need to worry about a possible conflict with */
3372           /* the above early RECEIVE optimizations since they would have */
3373           /* freed the accumulator if they were generated. */
3374
3375           if (IFFUNC_CALLEESAVES(sym->type))
3376             {
3377               /* if it's a callee-saves function we need a saved register */
3378               if (calleesaves_saved_register >= 0)
3379                 {
3380                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3381                   emitcode ("mov", "a,sp");
3382                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3383                   emitcode ("mov", "sp,a");
3384                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3385                 }
3386               else
3387                 /* do it the hard way */
3388                 while (i--)
3389                   emitcode ("inc", "sp");
3390             }
3391           else
3392             {
3393               /* not callee-saves, we can clobber r0 */
3394               emitcode ("mov", "r0,a");
3395               emitcode ("mov", "a,sp");
3396               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3397               emitcode ("mov", "sp,a");
3398               emitcode ("mov", "a,r0");
3399             }
3400         }
3401       else
3402         while (i--)
3403           emitcode ("inc", "sp");
3404     }
3405
3406   if (sym->xstack)
3407     {
3408       char i = ((char) sym->xstack & 0xff);
3409
3410       if (i > 3 && accIsFree)
3411         {
3412           emitcode ("mov", "a,_spx");
3413           emitcode ("add", "a,#0x%02x", i);
3414           emitcode ("mov", "_spx,a");
3415         }
3416       else if (i > 5)
3417         {
3418           emitcode ("push", "acc");
3419           emitcode ("mov", "a,_spx");
3420           emitcode ("add", "a,#0x%02x", i);
3421           emitcode ("mov", "_spx,a");
3422           emitcode ("pop", "acc");
3423         }
3424       else
3425         {
3426           while (i--)
3427             emitcode ("inc", "_spx");
3428         }
3429     }
3430
3431   /* if critical function then turn interrupts off */
3432   if (IFFUNC_ISCRITICAL (ftype))
3433     {
3434       symbol *tlbl = newiTempLabel (NULL);
3435       emitcode ("setb", "c");
3436       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3437       emitcode ("clr", "c");
3438       emitcode ("", "%05d$:", (tlbl->key + 100));
3439       emitcode ("push", "psw"); /* save old ea via c in psw */
3440     }
3441 }
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genEndFunction - generates epilogue for functions               */
3445 /*-----------------------------------------------------------------*/
3446 static void
3447 genEndFunction (iCode * ic)
3448 {
3449   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3450   lineNode *lnp = lineCurr;
3451   bitVect  *regsUsed;
3452   bitVect  *regsUsedPrologue;
3453   bitVect  *regsUnneeded;
3454   int      idx;
3455
3456   _G.currentFunc = NULL;
3457   if (IFFUNC_ISNAKED(sym->type))
3458   {
3459       emitcode(";", "naked function: no epilogue.");
3460       if (options.debug && currFunc)
3461         debugFile->writeEndFunction (currFunc, ic, 0);
3462       return;
3463   }
3464
3465   if (IFFUNC_ISCRITICAL (sym->type))
3466     {
3467       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3468         {
3469           emitcode ("rlc", "a");   /* save c in a */
3470           emitcode ("pop", "psw"); /* restore ea via c in psw */
3471           emitcode ("mov", "ea,c");
3472           emitcode ("rrc", "a");   /* restore c from a */
3473         }
3474       else
3475         {
3476           emitcode ("pop", "psw"); /* restore ea via c in psw */
3477           emitcode ("mov", "ea,c");
3478         }
3479     }
3480
3481   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3482     {
3483       if (options.useXstack)
3484         {
3485           if (sym->stack)
3486             {
3487               emitcode ("mov", "sp,_bp");
3488               emitcode ("pop", "_bp");
3489             }
3490           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3491             {
3492               emitcode ("xch", "a,_bpx");
3493               emitcode ("mov", "r0,a");
3494               emitcode ("dec", "r0");
3495               emitcode ("movx", "a,@r0");
3496               emitcode ("xch", "a,_bpx");
3497               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3498             }
3499         }
3500       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3501         {
3502           emitcode ("mov", "sp,_bp");
3503           emitcode ("pop", "_bp");
3504         }
3505     }
3506
3507   /* restore the register bank  */
3508   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3509   {
3510     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3511      || !options.useXstack)
3512     {
3513         /* Special case of ISR using non-zero bank with useXstack
3514          * is handled below.
3515          */
3516         emitcode ("pop", "psw");
3517     }
3518   }
3519
3520   if (IFFUNC_ISISR (sym->type))
3521     {
3522
3523       /* now we need to restore the registers */
3524       /* if this isr has no bank i.e. is going to
3525          run with bank 0 , then we need to save more
3526          registers :-) */
3527       if (!FUNC_REGBANK (sym->type))
3528         {
3529           /* if this function does not call any other
3530              function then we can be economical and
3531              save only those registers that are used */
3532           if (!IFFUNC_HASFCALL(sym->type))
3533             {
3534               int i;
3535
3536               /* if any registers used */
3537               if (sym->regsUsed)
3538                 {
3539                   bool bits_popped = FALSE;
3540                   /* save the registers used */
3541                   for (i = sym->regsUsed->size; i >= 0; i--)
3542                     {
3543                       if (bitVectBitValue (sym->regsUsed, i))
3544                         bits_popped = popReg (i, bits_popped);
3545                     }
3546                 }
3547             }
3548           else
3549             {
3550               if (options.parms_in_bank1) {
3551                   int i;
3552                   for (i = 7 ; i >= 0 ; i-- ) {
3553                       emitcode ("pop","%s",rb1regs[i]);
3554                   }
3555               }
3556               /* this function has  a function call cannot
3557                  determines register usage so we will have to pop the
3558                  entire bank */
3559               unsaveRBank (0, ic, FALSE);
3560             }
3561         }
3562         else
3563         {
3564             /* This ISR uses a non-zero bank.
3565              *
3566              * Restore any register banks saved by genFunction
3567              * in reverse order.
3568              */
3569             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3570             int ix;
3571
3572             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3573             {
3574                 if (savedBanks & (1 << ix))
3575                 {
3576                     unsaveRBank(ix, NULL, FALSE);
3577                 }
3578             }
3579
3580             if (options.useXstack)
3581             {
3582                 /* Restore bank AFTER calling unsaveRBank,
3583                  * since it can trash r0.
3584                  */
3585                 emitcode ("pop", "psw");
3586             }
3587         }
3588
3589       if (!inExcludeList ("dph"))
3590         emitcode ("pop", "dph");
3591       if (!inExcludeList ("dpl"))
3592         emitcode ("pop", "dpl");
3593       if (!inExcludeList ("b"))
3594         emitcode ("pop", "b");
3595       if (!inExcludeList ("acc"))
3596         emitcode ("pop", "acc");
3597
3598       /* if debug then send end of function */
3599       if (options.debug && currFunc)
3600         {
3601           debugFile->writeEndFunction (currFunc, ic, 1);
3602         }
3603
3604       emitcode ("reti", "");
3605     }
3606   else
3607     {
3608       if (IFFUNC_CALLEESAVES(sym->type))
3609         {
3610           int i;
3611
3612           /* if any registers used */
3613           if (sym->regsUsed)
3614             {
3615               /* save the registers used */
3616               for (i = sym->regsUsed->size; i >= 0; i--)
3617                 {
3618                   if (bitVectBitValue (sym->regsUsed, i) ||
3619                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3620                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3621                 }
3622             }
3623           else if (mcs51_ptrRegReq)
3624             {
3625               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3626               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3627             }
3628
3629         }
3630
3631       /* if debug then send end of function */
3632       if (options.debug && currFunc)
3633         {
3634           debugFile->writeEndFunction (currFunc, ic, 1);
3635         }
3636
3637       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3638         {
3639           emitcode ("ljmp", "__sdcc_banked_ret");
3640         }
3641       else
3642         {
3643           emitcode ("ret", "");
3644         }
3645     }
3646
3647   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3648     return;
3649
3650   /* If this was an interrupt handler using bank 0 that called another */
3651   /* function, then all registers must be saved; nothing to optimized. */
3652   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3653       && !FUNC_REGBANK(sym->type))
3654     return;
3655
3656   /* There are no push/pops to optimize if not callee-saves or ISR */
3657   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3658     return;
3659
3660   /* If there were stack parameters, we cannot optimize without also    */
3661   /* fixing all of the stack offsets; this is too dificult to consider. */
3662   if (FUNC_HASSTACKPARM(sym->type))
3663     return;
3664
3665   /* Compute the registers actually used */
3666   regsUsed = newBitVect (mcs51_nRegs);
3667   regsUsedPrologue = newBitVect (mcs51_nRegs);
3668   while (lnp)
3669     {
3670       if (lnp->ic && lnp->ic->op == FUNCTION)
3671         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3672       else
3673         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3674
3675       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3676           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3677         break;
3678       if (!lnp->prev)
3679         break;
3680       lnp = lnp->prev;
3681     }
3682
3683   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3684       && !bitVectBitValue (regsUsed, CND_IDX))
3685     {
3686       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3687       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3688           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3689         bitVectUnSetBit (regsUsed, CND_IDX);
3690     }
3691   else
3692     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3693
3694   /* If this was an interrupt handler that called another function */
3695   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3696   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3697     {
3698       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3699       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3700       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3701       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3702       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3703     }
3704
3705   /* Remove the unneeded push/pops */
3706   regsUnneeded = newBitVect (mcs51_nRegs);
3707   while (lnp)
3708     {
3709       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3710         {
3711           if (!strncmp(lnp->line, "push", 4))
3712             {
3713               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3714               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3715                 {
3716                   connectLine (lnp->prev, lnp->next);
3717                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3718                 }
3719             }
3720           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3721             {
3722               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3723               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3724                 {
3725                   connectLine (lnp->prev, lnp->next);
3726                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3727                 }
3728             }
3729         }
3730       lnp = lnp->next;
3731     }
3732
3733   for (idx = 0; idx < regsUnneeded->size; idx++)
3734     if (bitVectBitValue (regsUnneeded, idx))
3735       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3736
3737   freeBitVect (regsUnneeded);
3738   freeBitVect (regsUsed);
3739   freeBitVect (regsUsedPrologue);
3740 }
3741
3742 /*-----------------------------------------------------------------*/
3743 /* genRet - generate code for return statement                     */
3744 /*-----------------------------------------------------------------*/
3745 static void
3746 genRet (iCode * ic)
3747 {
3748   int size, offset = 0, pushed = 0;
3749
3750   D(emitcode (";     genRet",""));
3751
3752   /* if we have no return value then
3753      just generate the "ret" */
3754   if (!IC_LEFT (ic))
3755     goto jumpret;
3756
3757   /* we have something to return then
3758      move the return value into place */
3759   aopOp (IC_LEFT (ic), ic, FALSE);
3760   size = AOP_SIZE (IC_LEFT (ic));
3761
3762
3763   if (IS_BIT(_G.currentFunc->etype))
3764     {
3765       movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3766       size = 0;
3767     }
3768
3769   while (size--)
3770     {
3771       char *l;
3772       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3773         {
3774           /* #NOCHANGE */
3775           l = aopGet (IC_LEFT (ic), offset++,
3776                       FALSE, TRUE);
3777           emitcode ("push", "%s", l);
3778           pushed++;
3779         }
3780       else
3781         {
3782           l = aopGet (IC_LEFT (ic), offset,
3783                       FALSE, FALSE);
3784           if (strcmp (fReturn[offset], l))
3785             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3786         }
3787     }
3788
3789   while (pushed)
3790     {
3791       pushed--;
3792       if (strcmp (fReturn[pushed], "a"))
3793         emitcode ("pop", fReturn[pushed]);
3794       else
3795         emitcode ("pop", "acc");
3796     }
3797   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3798
3799 jumpret:
3800   /* generate a jump to the return label
3801      if the next is not the return statement */
3802   if (!(ic->next && ic->next->op == LABEL &&
3803         IC_LABEL (ic->next) == returnLabel))
3804
3805     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3806
3807 }
3808
3809 /*-----------------------------------------------------------------*/
3810 /* genLabel - generates a label                                    */
3811 /*-----------------------------------------------------------------*/
3812 static void
3813 genLabel (iCode * ic)
3814 {
3815   /* special case never generate */
3816   if (IC_LABEL (ic) == entryLabel)
3817     return;
3818
3819   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3820 }
3821
3822 /*-----------------------------------------------------------------*/
3823 /* genGoto - generates a ljmp                                      */
3824 /*-----------------------------------------------------------------*/
3825 static void
3826 genGoto (iCode * ic)
3827 {
3828   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3829 }
3830
3831 /*-----------------------------------------------------------------*/
3832 /* findLabelBackwards: walks back through the iCode chain looking  */
3833 /* for the given label. Returns number of iCode instructions     */
3834 /* between that label and given ic.          */
3835 /* Returns zero if label not found.          */
3836 /*-----------------------------------------------------------------*/
3837 static int
3838 findLabelBackwards (iCode * ic, int key)
3839 {
3840   int count = 0;
3841
3842   while (ic->prev)
3843     {
3844       ic = ic->prev;
3845       count++;
3846
3847       /* If we have any pushes or pops, we cannot predict the distance.
3848          I don't like this at all, this should be dealt with in the
3849          back-end */
3850       if (ic->op == IPUSH || ic->op == IPOP) {
3851         return 0;
3852       }
3853
3854       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3855         {
3856           return count;
3857         }
3858     }
3859
3860   return 0;
3861 }
3862
3863 /*-----------------------------------------------------------------*/
3864 /* genPlusIncr :- does addition with increment if possible         */
3865 /*-----------------------------------------------------------------*/
3866 static bool
3867 genPlusIncr (iCode * ic)
3868 {
3869   unsigned int icount;
3870   unsigned int size = getDataSize (IC_RESULT (ic));
3871
3872   /* will try to generate an increment */
3873   /* if the right side is not a literal
3874      we cannot */
3875   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3876     return FALSE;
3877
3878   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3879
3880   D(emitcode (";     genPlusIncr",""));
3881
3882   /* if increment >=16 bits in register or direct space */
3883   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3884       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3885       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3886       (size > 1) &&
3887       (icount == 1))
3888     {
3889       symbol *tlbl;
3890       int emitTlbl;
3891       int labelRange;
3892
3893       /* If the next instruction is a goto and the goto target
3894        * is < 10 instructions previous to this, we can generate
3895        * jumps straight to that target.
3896        */
3897       if (ic->next && ic->next->op == GOTO
3898           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3899           && labelRange <= 10)
3900         {
3901           emitcode (";", "tail increment optimized");
3902           tlbl = IC_LABEL (ic->next);
3903           emitTlbl = 0;
3904         }
3905       else
3906         {
3907           tlbl = newiTempLabel (NULL);
3908           emitTlbl = 1;
3909         }
3910       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3911       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3912           IS_AOP_PREG (IC_RESULT (ic)))
3913         emitcode ("cjne", "%s,#0x00,%05d$",
3914                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3915                   tlbl->key + 100);
3916       else
3917         {
3918           emitcode ("clr", "a");
3919           emitcode ("cjne", "a,%s,%05d$",
3920                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3921                     tlbl->key + 100);
3922         }
3923
3924       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3925       if (size > 2)
3926         {
3927           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3928               IS_AOP_PREG (IC_RESULT (ic)))
3929             emitcode ("cjne", "%s,#0x00,%05d$",
3930                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3931                       tlbl->key + 100);
3932           else
3933             emitcode ("cjne", "a,%s,%05d$",
3934                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3935                       tlbl->key + 100);
3936
3937           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3938         }
3939       if (size > 3)
3940         {
3941           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3942               IS_AOP_PREG (IC_RESULT (ic)))
3943             emitcode ("cjne", "%s,#0x00,%05d$",
3944                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3945                       tlbl->key + 100);
3946           else
3947             {
3948               emitcode ("cjne", "a,%s,%05d$",
3949                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3950                         tlbl->key + 100);
3951             }
3952           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3953         }
3954
3955       if (emitTlbl)
3956         {
3957           emitcode ("", "%05d$:", tlbl->key + 100);
3958         }
3959       return TRUE;
3960     }
3961
3962   /* if result is dptr */
3963   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3964       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3965       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3966       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3967     {
3968       if (aopGetUsesAcc (IC_LEFT (ic), 0))
3969         return FALSE;
3970
3971       if (icount > 9)
3972         return FALSE;
3973
3974       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3975         return FALSE;
3976
3977       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3978       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3979       while (icount--)
3980         emitcode ("inc", "dptr");
3981
3982       return TRUE;
3983     }
3984
3985   /* if the literal value of the right hand side
3986      is greater than 4 then it is not worth it */
3987   if (icount > 4)
3988     return FALSE;
3989
3990   /* if the sizes are greater than 1 then we cannot */
3991   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3992       AOP_SIZE (IC_LEFT (ic)) > 1)
3993     return FALSE;
3994
3995   /* we can if the aops of the left & result match or
3996      if they are in registers and the registers are the
3997      same */
3998   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3999     {
4000
4001       if (icount > 3)
4002         {
4003           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4004           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4005           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4006         }
4007       else
4008         {
4009
4010           while (icount--)
4011             emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4012         }
4013
4014       return TRUE;
4015     }
4016
4017   return FALSE;
4018 }
4019
4020 /*-----------------------------------------------------------------*/
4021 /* outBitAcc - output a bit in acc                                 */
4022 /*-----------------------------------------------------------------*/
4023 static void
4024 outBitAcc (operand * result)
4025 {
4026   symbol *tlbl = newiTempLabel (NULL);
4027   /* if the result is a bit */
4028   if (AOP_TYPE (result) == AOP_CRY)
4029     {
4030       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4031     }
4032   else
4033     {
4034       emitcode ("jz", "%05d$", tlbl->key + 100);
4035       emitcode ("mov", "a,%s", one);
4036       emitcode ("", "%05d$:", tlbl->key + 100);
4037       outAcc (result);
4038     }
4039 }
4040
4041 /*-----------------------------------------------------------------*/
4042 /* genPlusBits - generates code for addition of two bits           */
4043 /*-----------------------------------------------------------------*/
4044 static void
4045 genPlusBits (iCode * ic)
4046 {
4047   D(emitcode (";     genPlusBits",""));
4048
4049   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4050     {
4051       symbol *lbl = newiTempLabel (NULL);
4052       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4053       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4054       emitcode ("cpl", "c");
4055       emitcode ("", "%05d$:", (lbl->key + 100));
4056       outBitC (IC_RESULT (ic));
4057     }
4058   else
4059     {
4060       emitcode ("clr", "a");
4061       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4062       emitcode ("rlc", "a");
4063       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4064       emitcode ("addc", "a,#0x00");
4065       outAcc (IC_RESULT (ic));
4066     }
4067 }
4068
4069 #if 0
4070 /* This is the original version of this code.
4071
4072  * This is being kept around for reference,
4073  * because I am not entirely sure I got it right...
4074  */
4075 static void
4076 adjustArithmeticResult (iCode * ic)
4077 {
4078   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4079       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4080       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4081     aopPut (IC_RESULT (ic),
4082             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4083             2,
4084             isOperandVolatile (IC_RESULT (ic), FALSE));
4085
4086   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4087       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4088       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4089     aopPut (IC_RESULT (ic),
4090             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4091             2,
4092             isOperandVolatile (IC_RESULT (ic), FALSE));
4093
4094   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4095       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4096       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4097       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4098       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4099     {
4100       char buffer[5];
4101       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4102       aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4103     }
4104 }
4105 #else
4106 /* This is the pure and virtuous version of this code.
4107  * I'm pretty certain it's right, but not enough to toss the old
4108  * code just yet...
4109  */
4110 static void
4111 adjustArithmeticResult (iCode * ic)
4112 {
4113   if (opIsGptr (IC_RESULT (ic)) &&
4114       opIsGptr (IC_LEFT (ic)) &&
4115       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4116     {
4117       aopPut (IC_RESULT (ic),
4118               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4119               GPTRSIZE - 1,
4120               isOperandVolatile (IC_RESULT (ic), FALSE));
4121     }
4122
4123   if (opIsGptr (IC_RESULT (ic)) &&
4124       opIsGptr (IC_RIGHT (ic)) &&
4125       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4126     {
4127       aopPut (IC_RESULT (ic),
4128               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4129               GPTRSIZE - 1,
4130               isOperandVolatile (IC_RESULT (ic), FALSE));
4131     }
4132
4133   if (opIsGptr (IC_RESULT (ic)) &&
4134       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4135       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4136       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4137       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4138     {
4139       char buffer[5];
4140       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4141       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4142     }
4143 }
4144 #endif
4145
4146 /*-----------------------------------------------------------------*/
4147 /* genPlus - generates code for addition                           */
4148 /*-----------------------------------------------------------------*/
4149 static void
4150 genPlus (iCode * ic)
4151 {
4152   int size, offset = 0;
4153   int skip_bytes = 0;
4154   char *add = "add";
4155   operand *leftOp, *rightOp;
4156   operand * op;
4157
4158   /* special cases :- */
4159
4160   D(emitcode (";     genPlus",""));
4161
4162   aopOp (IC_LEFT (ic), ic, FALSE);
4163   aopOp (IC_RIGHT (ic), ic, FALSE);
4164   aopOp (IC_RESULT (ic), ic, TRUE);
4165
4166   /* if literal, literal on the right or
4167      if left requires ACC or right is already
4168      in ACC */
4169   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4170       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4171       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4172     {
4173       operand *t = IC_RIGHT (ic);
4174       IC_RIGHT (ic) = IC_LEFT (ic);
4175       IC_LEFT (ic) = t;
4176     }
4177
4178   /* if both left & right are in bit
4179      space */
4180   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4181       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4182     {
4183       genPlusBits (ic);
4184       goto release;
4185     }
4186
4187   /* if left in bit space & right literal */
4188   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4189       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4190     {
4191       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4192       /* if result in bit space */
4193       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4194         {
4195           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4196             emitcode ("cpl", "c");
4197           outBitC (IC_RESULT (ic));
4198         }
4199       else
4200         {
4201           size = getDataSize (IC_RESULT (ic));
4202           while (size--)
4203             {
4204               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4205               emitcode ("addc", "a,#00");
4206               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4207             }
4208         }
4209       goto release;
4210     }
4211
4212   /* if I can do an increment instead
4213      of add then GOOD for ME */
4214   if (genPlusIncr (ic) == TRUE)
4215     goto release;
4216
4217   size = getDataSize (IC_RESULT (ic));
4218   leftOp = IC_LEFT(ic);
4219   rightOp = IC_RIGHT(ic);
4220   op=IC_LEFT(ic);
4221
4222   /* if this is an add for an array access
4223      at a 256 byte boundary */
4224   if ( 2 == size
4225        && AOP_TYPE (op) == AOP_IMMD
4226        && IS_SYMOP (op)
4227        && IS_SPEC (OP_SYM_ETYPE (op))
4228        && SPEC_ABSA (OP_SYM_ETYPE (op))
4229        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4230      )
4231     {
4232       D(emitcode (";     genPlus aligned array",""));
4233       aopPut (IC_RESULT (ic),
4234               aopGet (rightOp, 0, FALSE, FALSE),
4235               0,
4236               isOperandVolatile (IC_RESULT (ic), FALSE));
4237
4238       if( 1 == getDataSize (IC_RIGHT (ic)) )
4239         {
4240           aopPut (IC_RESULT (ic),
4241                   aopGet (leftOp, 1, FALSE, FALSE),
4242                   1,
4243                   isOperandVolatile (IC_RESULT (ic), FALSE));
4244         }
4245       else
4246         {
4247           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4248           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4249           aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4250         }
4251       goto release;
4252     }
4253
4254   /* if the lower bytes of a literal are zero skip the addition */
4255   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4256     {
4257        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4258               (skip_bytes+1 < size))
4259          {
4260            skip_bytes++;
4261          }
4262        if (skip_bytes)
4263          D(emitcode (";     genPlus shortcut",""));
4264     }
4265
4266   while (size--)
4267     {
4268       if( offset >= skip_bytes )
4269         {
4270           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4271             {
4272               bool pushedB;
4273               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4274               pushedB = pushB ();
4275               emitcode("xch", "a,b");
4276               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4277               emitcode (add, "a,b");
4278               popB (pushedB);
4279             }
4280           else if (aopGetUsesAcc (leftOp, offset))
4281             {
4282               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4283               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4284             }
4285           else
4286             {
4287               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4288               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4289             }
4290           aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4291           add = "addc";  /* further adds must propagate carry */
4292         }
4293       else
4294         {
4295           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4296               isOperandVolatile (IC_RESULT (ic), FALSE))
4297             {
4298               /* just move */
4299               aopPut (IC_RESULT (ic),
4300                       aopGet (leftOp, offset, FALSE, FALSE),
4301                       offset,
4302                       isOperandVolatile (IC_RESULT (ic), FALSE));
4303             }
4304         }
4305       offset++;
4306     }
4307
4308   adjustArithmeticResult (ic);
4309
4310 release:
4311   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4312   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4313   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4314 }
4315
4316 /*-----------------------------------------------------------------*/
4317 /* genMinusDec :- does subtraction with decrement if possible      */
4318 /*-----------------------------------------------------------------*/
4319 static bool
4320 genMinusDec (iCode * ic)
4321 {
4322   unsigned int icount;
4323   unsigned int size = getDataSize (IC_RESULT (ic));
4324
4325   /* will try to generate an increment */
4326   /* if the right side is not a literal
4327      we cannot */
4328   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4329     return FALSE;
4330
4331   /* if the literal value of the right hand side
4332      is greater than 4 then it is not worth it */
4333   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4334     return FALSE;
4335
4336   D(emitcode (";     genMinusDec",""));
4337
4338   /* if decrement >=16 bits in register or direct space */
4339   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4340       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4341       (size > 1) &&
4342       (icount == 1))
4343     {
4344       symbol *tlbl;
4345       int emitTlbl;
4346       int labelRange;
4347
4348       /* If the next instruction is a goto and the goto target
4349        * is <= 10 instructions previous to this, we can generate
4350        * jumps straight to that target.
4351        */
4352       if (ic->next && ic->next->op == GOTO
4353           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4354           && labelRange <= 10)
4355         {
4356           emitcode (";", "tail decrement optimized");
4357           tlbl = IC_LABEL (ic->next);
4358           emitTlbl = 0;
4359         }
4360       else
4361         {
4362           tlbl = newiTempLabel (NULL);
4363           emitTlbl = 1;
4364         }
4365
4366       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4367       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4368           IS_AOP_PREG (IC_RESULT (ic)))
4369         emitcode ("cjne", "%s,#0xff,%05d$"
4370                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4371                   ,tlbl->key + 100);
4372       else
4373         {
4374           emitcode ("mov", "a,#0xff");
4375           emitcode ("cjne", "a,%s,%05d$"
4376                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4377                     ,tlbl->key + 100);
4378         }
4379       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4380       if (size > 2)
4381         {
4382           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4383               IS_AOP_PREG (IC_RESULT (ic)))
4384             emitcode ("cjne", "%s,#0xff,%05d$"
4385                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4386                       ,tlbl->key + 100);
4387           else
4388             {
4389               emitcode ("cjne", "a,%s,%05d$"
4390                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4391                         ,tlbl->key + 100);
4392             }
4393           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4394         }
4395       if (size > 3)
4396         {
4397           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4398               IS_AOP_PREG (IC_RESULT (ic)))
4399             emitcode ("cjne", "%s,#0xff,%05d$"
4400                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4401                       ,tlbl->key + 100);
4402           else
4403             {
4404               emitcode ("cjne", "a,%s,%05d$"
4405                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4406                         ,tlbl->key + 100);
4407             }
4408           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4409         }
4410       if (emitTlbl)
4411         {
4412           emitcode ("", "%05d$:", tlbl->key + 100);
4413         }
4414       return TRUE;
4415     }
4416
4417   /* if the sizes are greater than 1 then we cannot */
4418   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4419       AOP_SIZE (IC_LEFT (ic)) > 1)
4420     return FALSE;
4421
4422   /* we can if the aops of the left & result match or
4423      if they are in registers and the registers are the
4424      same */
4425   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4426     {
4427
4428       while (icount--)
4429         emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4430
4431       return TRUE;
4432     }
4433
4434   return FALSE;
4435 }
4436
4437 /*-----------------------------------------------------------------*/
4438 /* addSign - complete with sign                                    */
4439 /*-----------------------------------------------------------------*/
4440 static void
4441 addSign (operand * result, int offset, int sign)
4442 {
4443   int size = (getDataSize (result) - offset);
4444   if (size > 0)
4445     {
4446       if (sign)
4447         {
4448           emitcode ("rlc", "a");
4449           emitcode ("subb", "a,acc");
4450           while (size--)
4451             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4452         }
4453       else
4454         while (size--)
4455           aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4456     }
4457 }
4458
4459 /*-----------------------------------------------------------------*/
4460 /* genMinusBits - generates code for subtraction  of two bits      */
4461 /*-----------------------------------------------------------------*/
4462 static void
4463 genMinusBits (iCode * ic)
4464 {
4465   symbol *lbl = newiTempLabel (NULL);
4466
4467   D(emitcode (";     genMinusBits",""));
4468
4469   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4470     {
4471       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4472       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4473       emitcode ("cpl", "c");
4474       emitcode ("", "%05d$:", (lbl->key + 100));
4475       outBitC (IC_RESULT (ic));
4476     }
4477   else
4478     {
4479       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4480       emitcode ("subb", "a,acc");
4481       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4482       emitcode ("inc", "a");
4483       emitcode ("", "%05d$:", (lbl->key + 100));
4484       aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4485       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4486     }
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* genMinus - generates code for subtraction                       */
4491 /*-----------------------------------------------------------------*/
4492 static void
4493 genMinus (iCode * ic)
4494 {
4495   int size, offset = 0;
4496
4497   D(emitcode (";     genMinus",""));
4498
4499   aopOp (IC_LEFT (ic), ic, FALSE);
4500   aopOp (IC_RIGHT (ic), ic, FALSE);
4501   aopOp (IC_RESULT (ic), ic, TRUE);
4502
4503   /* special cases :- */
4504   /* if both left & right are in bit space */
4505   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4506       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4507     {
4508       genMinusBits (ic);
4509       goto release;
4510     }
4511
4512   /* if I can do an decrement instead
4513      of subtract then GOOD for ME */
4514   if (genMinusDec (ic) == TRUE)
4515     goto release;
4516
4517   size = getDataSize (IC_RESULT (ic));
4518
4519   /* if literal, add a,#-lit, else normal subb */
4520   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4521     {
4522       unsigned long lit = 0L;
4523       bool useCarry = FALSE;
4524
4525       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4526       lit = -(long) lit;
4527
4528       while (size--)
4529         {
4530           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4531             {
4532             MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4533               if (!offset && !size && lit== (unsigned long) -1)
4534                 {
4535                   emitcode ("dec", "a");
4536                 }
4537               else if (!useCarry)
4538                 {
4539                   /* first add without previous c */
4540                   emitcode ("add", "a,#0x%02x",
4541                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4542                   useCarry = TRUE;
4543                 }
4544               else
4545                 {
4546                   emitcode ("addc", "a,#0x%02x",
4547                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4548                 }
4549               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4550             }
4551           else
4552             {
4553               /* no need to add zeroes */
4554               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4555                 {
4556                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4557                           offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4558                 }
4559               offset++;
4560             }
4561         }
4562     }
4563   else
4564     {
4565       operand *leftOp, *rightOp;
4566
4567       leftOp = IC_LEFT(ic);
4568       rightOp = IC_RIGHT(ic);
4569
4570       while (size--)
4571         {
4572           if (aopGetUsesAcc(rightOp, offset)) {
4573             if (aopGetUsesAcc(leftOp, offset)) {
4574               bool pushedB;
4575
4576               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4577               pushedB = pushB ();
4578               emitcode ("mov", "b,a");
4579               if (offset == 0)
4580                 CLRC;
4581               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4582               emitcode ("subb", "a,b");
4583               popB (pushedB);
4584             } else {
4585               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4586               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4587               if (offset == 0) {
4588                 emitcode( "setb", "c");
4589               }
4590               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4591               emitcode("cpl", "a");
4592             }
4593           } else {
4594             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4595             if (offset == 0)
4596               CLRC;
4597             emitcode ("subb", "a,%s",
4598                       aopGet(rightOp, offset, FALSE, TRUE));
4599           }
4600
4601           aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4602         }
4603     }
4604
4605
4606   adjustArithmeticResult (ic);
4607
4608 release:
4609   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4612 }
4613
4614
4615 /*-----------------------------------------------------------------*/
4616 /* genMultbits :- multiplication of bits                           */
4617 /*-----------------------------------------------------------------*/
4618 static void
4619 genMultbits (operand * left,
4620              operand * right,
4621              operand * result)
4622 {
4623   D(emitcode (";     genMultbits",""));
4624
4625   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4626   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4627   outBitC (result);
4628 }
4629
4630 /*-----------------------------------------------------------------*/
4631 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4632 /*-----------------------------------------------------------------*/
4633 static void
4634 genMultOneByte (operand * left,
4635                 operand * right,
4636                 operand * result)
4637 {
4638   symbol *lbl;
4639   int size = AOP_SIZE (result);
4640   bool runtimeSign, compiletimeSign;
4641   bool lUnsigned, rUnsigned, pushedB;
4642
4643   D(emitcode (";     genMultOneByte",""));
4644
4645   if (size < 1 || size > 2)
4646     {
4647       /* this should never happen */
4648       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4649                AOP_SIZE(result), __FILE__, lineno);
4650       exit (1);
4651     }
4652
4653   /* (if two literals: the value is computed before) */
4654   /* if one literal, literal on the right */
4655   if (AOP_TYPE (left) == AOP_LIT)
4656     {
4657       operand *t = right;
4658       right = left;
4659       left = t;
4660       /* emitcode (";", "swapped left and right"); */
4661     }
4662   /* if no literal, unsigned on the right: shorter code */
4663   if (   AOP_TYPE (right) != AOP_LIT
4664       && SPEC_USIGN (getSpec (operandType (left))))
4665     {
4666       operand *t = right;
4667       right = left;
4668       left = t;
4669     }
4670
4671   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4672   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4673
4674   pushedB = pushB ();
4675
4676   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4677                    no need to take care about the signedness! */
4678       || (lUnsigned && rUnsigned))
4679     {
4680       /* just an unsigned 8 * 8 = 8 multiply
4681          or 8u * 8u = 16u */
4682       /* emitcode (";","unsigned"); */
4683       /* TODO: check for accumulator clash between left & right aops? */
4684
4685       if (AOP_TYPE (right) == AOP_LIT)
4686         {
4687           /* moving to accumulator first helps peepholes */
4688           MOVA (aopGet (left, 0, FALSE, FALSE));
4689           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4690         }
4691       else
4692         {
4693           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4694           MOVA (aopGet (left, 0, FALSE, FALSE));
4695         }
4696
4697       emitcode ("mul", "ab");
4698       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4699       if (size == 2)
4700         aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4701
4702       popB (pushedB);
4703       return;
4704     }
4705
4706   /* we have to do a signed multiply */
4707   /* emitcode (";", "signed"); */
4708
4709   /* now sign adjust for both left & right */
4710
4711   /* let's see what's needed: */
4712   /* apply negative sign during runtime */
4713   runtimeSign = FALSE;
4714   /* negative sign from literals */
4715   compiletimeSign = FALSE;
4716
4717   if (!lUnsigned)
4718     {
4719       if (AOP_TYPE(left) == AOP_LIT)
4720         {
4721           /* signed literal */
4722           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4723           if (val < 0)
4724             compiletimeSign = TRUE;
4725         }
4726       else
4727         /* signed but not literal */
4728         runtimeSign = TRUE;
4729     }
4730
4731   if (!rUnsigned)
4732     {
4733       if (AOP_TYPE(right) == AOP_LIT)
4734         {
4735           /* signed literal */
4736           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4737           if (val < 0)
4738             compiletimeSign ^= TRUE;
4739         }
4740       else
4741         /* signed but not literal */
4742         runtimeSign = TRUE;
4743     }
4744
4745   /* initialize F0, which stores the runtime sign */
4746   if (runtimeSign)
4747     {
4748       if (compiletimeSign)
4749         emitcode ("setb", "F0"); /* set sign flag */
4750       else
4751         emitcode ("clr", "F0"); /* reset sign flag */
4752     }
4753
4754   /* save the signs of the operands */
4755   if (AOP_TYPE(right) == AOP_LIT)
4756     {
4757       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4758
4759       if (!rUnsigned && val < 0)
4760         emitcode ("mov", "b,#0x%02x", -val);
4761       else
4762         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4763     }
4764   else /* ! literal */
4765     {
4766       if (rUnsigned)  /* emitcode (";", "signed"); */
4767
4768         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4769       else
4770         {
4771           MOVA (aopGet (right, 0, FALSE, FALSE));
4772           lbl = newiTempLabel (NULL);
4773           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4774           emitcode ("cpl", "F0"); /* complement sign flag */
4775           emitcode ("cpl", "a");  /* 2's complement */
4776           emitcode ("inc", "a");
4777           emitcode ("", "%05d$:", (lbl->key + 100));
4778           emitcode ("mov", "b,a");
4779         }
4780     }
4781
4782   if (AOP_TYPE(left) == AOP_LIT)
4783     {
4784       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4785
4786       if (!lUnsigned && val < 0)
4787         emitcode ("mov", "a,#0x%02x", -val);
4788       else
4789         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4790     }
4791   else /* ! literal */
4792     {
4793       MOVA (aopGet (left, 0, FALSE, FALSE));
4794
4795       if (!lUnsigned)
4796         {
4797           lbl = newiTempLabel (NULL);
4798           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4799           emitcode ("cpl", "F0"); /* complement sign flag */
4800           emitcode ("cpl", "a"); /* 2's complement */
4801           emitcode ("inc", "a");
4802           emitcode ("", "%05d$:", (lbl->key + 100));
4803         }
4804     }
4805
4806   /* now the multiplication */
4807   emitcode ("mul", "ab");
4808   if (runtimeSign || compiletimeSign)
4809     {
4810       lbl = newiTempLabel (NULL);
4811       if (runtimeSign)
4812         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4813       emitcode ("cpl", "a"); /* lsb 2's complement */
4814       if (size != 2)
4815         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4816       else
4817         {
4818           emitcode ("add", "a,#1"); /* this sets carry flag */
4819           emitcode ("xch", "a,b");
4820           emitcode ("cpl", "a"); /* msb 2's complement */
4821           emitcode ("addc", "a,#0");
4822           emitcode ("xch", "a,b");
4823         }
4824       emitcode ("", "%05d$:", (lbl->key + 100));
4825     }
4826   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4827   if (size == 2)
4828     aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4829
4830   popB (pushedB);
4831 }
4832
4833 /*-----------------------------------------------------------------*/
4834 /* genMult - generates code for multiplication                     */
4835 /*-----------------------------------------------------------------*/
4836 static void
4837 genMult (iCode * ic)
4838 {
4839   operand *left = IC_LEFT (ic);
4840   operand *right = IC_RIGHT (ic);
4841   operand *result = IC_RESULT (ic);
4842
4843   D(emitcode (";     genMult",""));
4844
4845   /* assign the amsops */
4846   aopOp (left, ic, FALSE);
4847   aopOp (right, ic, FALSE);
4848   aopOp (result, ic, TRUE);
4849
4850   /* special cases first */
4851   /* both are bits */
4852   if (AOP_TYPE (left) == AOP_CRY &&
4853       AOP_TYPE (right) == AOP_CRY)
4854     {
4855       genMultbits (left, right, result);
4856       goto release;
4857     }
4858
4859   /* if both are of size == 1 */
4860 #if 0 // one of them can be a sloc shared with the result
4861     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4862 #else
4863   if (getSize(operandType(left)) == 1 &&
4864       getSize(operandType(right)) == 1)
4865 #endif
4866     {
4867       genMultOneByte (left, right, result);
4868       goto release;
4869     }
4870
4871   /* should have been converted to function call */
4872     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4873              getSize(OP_SYMBOL(right)->type));
4874   assert (0);
4875
4876 release:
4877   freeAsmop (result, NULL, ic, TRUE);
4878   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4879   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4880 }
4881
4882 /*-----------------------------------------------------------------*/
4883 /* genDivbits :- division of bits                                  */
4884 /*-----------------------------------------------------------------*/
4885 static void
4886 genDivbits (operand * left,
4887             operand * right,
4888             operand * result)
4889 {
4890   char *l;
4891   bool pushedB;
4892
4893   D(emitcode (";     genDivbits",""));
4894
4895   pushedB = pushB ();
4896
4897   /* the result must be bit */
4898   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4899   l = aopGet (left, 0, FALSE, FALSE);
4900
4901   MOVA (l);
4902
4903   emitcode ("div", "ab");
4904   emitcode ("rrc", "a");
4905
4906   popB (pushedB);
4907
4908   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4909 }
4910
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division                                  */
4913 /*-----------------------------------------------------------------*/
4914 static void
4915 genDivOneByte (operand * left,
4916                operand * right,
4917                operand * result)
4918 {
4919   bool lUnsigned, rUnsigned, pushedB;
4920   bool runtimeSign, compiletimeSign;
4921   symbol *lbl;
4922   int size, offset;
4923
4924   D(emitcode (";     genDivOneByte",""));
4925
4926   /* Why is it necessary that genDivOneByte() can return an int result?
4927      Have a look at:
4928
4929         volatile unsigned char uc;
4930         volatile signed char sc1, sc2;
4931         volatile int i;
4932
4933         uc  = 255;
4934         sc1 = -1;
4935         i = uc / sc1;
4936
4937      Or:
4938
4939         sc1 = -128;
4940         sc2 = -1;
4941         i = sc1 / sc2;
4942
4943      In all cases a one byte result would overflow, the following cast to int
4944      would return the wrong result.
4945
4946      Two possible solution:
4947         a) cast operands to int, if ((unsigned) / (signed)) or
4948            ((signed) / (signed))
4949         b) return an 16 bit signed int; this is what we're doing here!
4950   */
4951
4952   size = AOP_SIZE (result) - 1;
4953   offset = 1;
4954   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4955   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4956
4957   pushedB = pushB ();
4958
4959   /* signed or unsigned */
4960   if (lUnsigned && rUnsigned)
4961     {
4962       /* unsigned is easy */
4963       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4964       MOVA (aopGet (left, 0, FALSE, FALSE));
4965       emitcode ("div", "ab");
4966       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4967       while (size--)
4968         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4969
4970       popB (pushedB);
4971       return;
4972     }
4973
4974   /* signed is a little bit more difficult */
4975
4976   /* now sign adjust for both left & right */
4977
4978   /* let's see what's needed: */
4979   /* apply negative sign during runtime */
4980   runtimeSign = FALSE;
4981   /* negative sign from literals */
4982   compiletimeSign = FALSE;
4983
4984   if (!lUnsigned)
4985     {
4986       if (AOP_TYPE(left) == AOP_LIT)
4987         {
4988           /* signed literal */
4989           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4990           if (val < 0)
4991             compiletimeSign = TRUE;
4992         }
4993       else
4994         /* signed but not literal */
4995         runtimeSign = TRUE;
4996     }
4997
4998   if (!rUnsigned)
4999     {
5000       if (AOP_TYPE(right) == AOP_LIT)
5001         {
5002           /* signed literal */
5003           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5004           if (val < 0)
5005             compiletimeSign ^= TRUE;
5006         }
5007       else
5008         /* signed but not literal */
5009         runtimeSign = TRUE;
5010     }
5011
5012   /* initialize F0, which stores the runtime sign */
5013   if (runtimeSign)
5014     {
5015       if (compiletimeSign)
5016         emitcode ("setb", "F0"); /* set sign flag */
5017       else
5018         emitcode ("clr", "F0"); /* reset sign flag */
5019     }
5020
5021   /* save the signs of the operands */
5022   if (AOP_TYPE(right) == AOP_LIT)
5023     {
5024       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5025
5026       if (!rUnsigned && val < 0)
5027         emitcode ("mov", "b,#0x%02x", -val);
5028       else
5029         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5030     }
5031   else /* ! literal */
5032     {
5033       if (rUnsigned)
5034         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5035       else
5036         {
5037           MOVA (aopGet (right, 0, FALSE, FALSE));
5038           lbl = newiTempLabel (NULL);
5039           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5040           emitcode ("cpl", "F0"); /* complement sign flag */
5041           emitcode ("cpl", "a");  /* 2's complement */
5042           emitcode ("inc", "a");
5043           emitcode ("", "%05d$:", (lbl->key + 100));
5044           emitcode ("mov", "b,a");
5045         }
5046     }
5047
5048   if (AOP_TYPE(left) == AOP_LIT)
5049     {
5050       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5051
5052       if (!lUnsigned && val < 0)
5053         emitcode ("mov", "a,#0x%02x", -val);
5054       else
5055         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5056     }
5057   else /* ! literal */
5058     {
5059       MOVA (aopGet (left, 0, FALSE, FALSE));
5060
5061       if (!lUnsigned)
5062         {
5063           lbl = newiTempLabel (NULL);
5064           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5065           emitcode ("cpl", "F0"); /* complement sign flag */
5066           emitcode ("cpl", "a");  /* 2's complement */
5067           emitcode ("inc", "a");
5068           emitcode ("", "%05d$:", (lbl->key + 100));
5069         }
5070     }
5071
5072   /* now the division */
5073   emitcode ("div", "ab");
5074
5075   if (runtimeSign || compiletimeSign)
5076     {
5077       lbl = newiTempLabel (NULL);
5078       if (runtimeSign)
5079         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5080       emitcode ("cpl", "a"); /* lsb 2's complement */
5081       emitcode ("inc", "a");
5082       emitcode ("", "%05d$:", (lbl->key + 100));
5083
5084       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5085       if (size > 0)
5086         {
5087           /* msb is 0x00 or 0xff depending on the sign */
5088           if (runtimeSign)
5089             {
5090               emitcode ("mov", "c,F0");
5091               emitcode ("subb", "a,acc");
5092               while (size--)
5093                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5094             }
5095           else /* compiletimeSign */
5096             while (size--)
5097               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5098         }
5099     }
5100   else
5101     {
5102       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5103       while (size--)
5104         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5105     }
5106
5107   popB (pushedB);
5108 }
5109
5110 /*-----------------------------------------------------------------*/
5111 /* genDiv - generates code for division                            */
5112 /*-----------------------------------------------------------------*/
5113 static void
5114 genDiv (iCode * ic)
5115 {
5116   operand *left = IC_LEFT (ic);
5117   operand *right = IC_RIGHT (ic);
5118   operand *result = IC_RESULT (ic);
5119
5120   D(emitcode (";     genDiv",""));
5121
5122   /* assign the amsops */
5123   aopOp (left, ic, FALSE);
5124   aopOp (right, ic, FALSE);
5125   aopOp (result, ic, TRUE);
5126
5127   /* special cases first */
5128   /* both are bits */
5129   if (AOP_TYPE (left) == AOP_CRY &&
5130       AOP_TYPE (right) == AOP_CRY)
5131     {
5132       genDivbits (left, right, result);
5133       goto release;
5134     }
5135
5136   /* if both are of size == 1 */
5137   if (AOP_SIZE (left) == 1 &&
5138       AOP_SIZE (right) == 1)
5139     {
5140       genDivOneByte (left, right, result);
5141       goto release;
5142     }
5143
5144   /* should have been converted to function call */
5145   assert (0);
5146 release:
5147   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5148   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5149   freeAsmop (result, NULL, ic, TRUE);
5150 }
5151
5152 /*-----------------------------------------------------------------*/
5153 /* genModbits :- modulus of bits                                   */
5154 /*-----------------------------------------------------------------*/
5155 static void
5156 genModbits (operand * left,
5157             operand * right,
5158             operand * result)
5159 {
5160   char *l;
5161   bool pushedB;
5162
5163   D(emitcode (";     genModbits",""));
5164
5165   pushedB = pushB ();
5166
5167   /* the result must be bit */
5168   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5169   l = aopGet (left, 0, FALSE, FALSE);
5170
5171   MOVA (l);
5172
5173   emitcode ("div", "ab");
5174   emitcode ("mov", "a,b");
5175   emitcode ("rrc", "a");
5176
5177   popB (pushedB);
5178
5179   aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5180 }
5181
5182 /*-----------------------------------------------------------------*/
5183 /* genModOneByte : 8 bit modulus                                   */
5184 /*-----------------------------------------------------------------*/
5185 static void
5186 genModOneByte (operand * left,
5187                operand * right,
5188                operand * result)
5189 {
5190   bool lUnsigned, rUnsigned, pushedB;
5191   bool runtimeSign, compiletimeSign;
5192   symbol *lbl;
5193   int size, offset;
5194
5195   D(emitcode (";     genModOneByte",""));
5196
5197   size = AOP_SIZE (result) - 1;
5198   offset = 1;
5199   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5200   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5201
5202   /* if right is a literal, check it for 2^n */
5203   if (AOP_TYPE(right) == AOP_LIT)
5204     {
5205       unsigned char val = abs((int) operandLitValue(right));
5206       symbol *lbl2 = NULL;
5207
5208       switch (val)
5209         {
5210           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5211           case 2:
5212           case 4:
5213           case 8:
5214           case 16:
5215           case 32:
5216           case 64:
5217           case 128:
5218             if (lUnsigned)
5219               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5220                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5221               /* because iCode should have been changed to genAnd  */
5222               /* see file "SDCCopt.c", function "convertToFcall()" */
5223
5224             MOVA (aopGet (left, 0, FALSE, FALSE));
5225             emitcode ("mov", "c,acc.7");
5226             emitcode ("anl", "a,#0x%02x", val - 1);
5227             lbl = newiTempLabel (NULL);
5228             emitcode ("jz", "%05d$", (lbl->key + 100));
5229             emitcode ("jnc", "%05d$", (lbl->key + 100));
5230             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5231             if (size)
5232               {
5233                 int size2 = size;
5234                 int offs2 = offset;
5235
5236                 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5237                 while (size2--)
5238                   aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5239                 lbl2 = newiTempLabel (NULL);
5240                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5241               }
5242             emitcode ("", "%05d$:", (lbl->key + 100));
5243             aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5244             while (size--)
5245               aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5246             if (lbl2)
5247               {
5248                 emitcode ("", "%05d$:", (lbl2->key + 100));
5249               }
5250             return;
5251
5252           default:
5253             break;
5254         }
5255     }
5256
5257   pushedB = pushB ();
5258
5259   /* signed or unsigned */
5260   if (lUnsigned && rUnsigned)
5261     {
5262       /* unsigned is easy */
5263       emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5264       MOVA (aopGet (left, 0, FALSE, FALSE));
5265       emitcode ("div", "ab");
5266       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5267       while (size--)
5268         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5269
5270       popB (pushedB);
5271       return;
5272     }
5273
5274   /* signed is a little bit more difficult */
5275
5276   /* now sign adjust for both left & right */
5277
5278   /* modulus: sign of the right operand has no influence on the result! */
5279   if (AOP_TYPE(right) == AOP_LIT)
5280     {
5281       signed char val = (char) operandLitValue(right);
5282
5283       if (!rUnsigned && val < 0)
5284         emitcode ("mov", "b,#0x%02x", -val);
5285       else
5286         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5287     }
5288   else /* not literal */
5289     {
5290       if (rUnsigned)
5291         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5292       else
5293         {
5294           MOVA (aopGet (right, 0, FALSE, FALSE));
5295           lbl = newiTempLabel (NULL);
5296           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5297           emitcode ("cpl", "a"); /* 2's complement */
5298           emitcode ("inc", "a");
5299           emitcode ("", "%05d$:", (lbl->key + 100));
5300           emitcode ("mov", "b,a");
5301         }
5302     }
5303
5304   /* let's see what's needed: */
5305   /* apply negative sign during runtime */
5306   runtimeSign = FALSE;
5307   /* negative sign from literals */
5308   compiletimeSign = FALSE;
5309
5310   /* sign adjust left side */
5311   if (AOP_TYPE(left) == AOP_LIT)
5312     {
5313       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5314
5315       if (!lUnsigned && val < 0)
5316         {
5317           compiletimeSign = TRUE; /* set sign flag */
5318           emitcode ("mov", "a,#0x%02x", -val);
5319         }
5320       else
5321         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5322     }
5323   else /* ! literal */
5324     {
5325       MOVA (aopGet (left, 0, FALSE, FALSE));
5326
5327       if (!lUnsigned)
5328         {
5329           runtimeSign = TRUE;
5330           emitcode ("clr", "F0"); /* clear sign flag */
5331
5332           lbl = newiTempLabel (NULL);
5333           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5334           emitcode ("setb", "F0"); /* set sign flag */
5335           emitcode ("cpl", "a");   /* 2's complement */
5336           emitcode ("inc", "a");
5337           emitcode ("", "%05d$:", (lbl->key + 100));
5338         }
5339     }
5340
5341   /* now the modulus */
5342   emitcode ("div", "ab");
5343
5344   if (runtimeSign || compiletimeSign)
5345     {
5346       emitcode ("mov", "a,b");
5347       lbl = newiTempLabel (NULL);
5348       if (runtimeSign)
5349         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5350       emitcode ("cpl", "a"); /* 2's complement */
5351       emitcode ("inc", "a");
5352       emitcode ("", "%05d$:", (lbl->key + 100));
5353
5354       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5355       if (size > 0)
5356         {
5357           /* msb is 0x00 or 0xff depending on the sign */
5358           if (runtimeSign)
5359             {
5360               emitcode ("mov", "c,F0");
5361               emitcode ("subb", "a,acc");
5362               while (size--)
5363                 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5364             }
5365           else /* compiletimeSign */
5366             while (size--)
5367               aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5368         }
5369     }
5370   else
5371     {
5372       aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5373       while (size--)
5374         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5375     }
5376
5377   popB (pushedB);
5378 }
5379
5380 /*-----------------------------------------------------------------*/
5381 /* genMod - generates code for division                            */
5382 /*-----------------------------------------------------------------*/
5383 static void
5384 genMod (iCode * ic)
5385 {
5386   operand *left = IC_LEFT (ic);
5387   operand *right = IC_RIGHT (ic);
5388   operand *result = IC_RESULT (ic);
5389
5390   D(emitcode (";     genMod",""));
5391
5392   /* assign the asmops */
5393   aopOp (left, ic, FALSE);
5394   aopOp (right, ic, FALSE);
5395   aopOp (result, ic, TRUE);
5396
5397   /* special cases first */
5398   /* both are bits */
5399   if (AOP_TYPE (left) == AOP_CRY &&
5400       AOP_TYPE (right) == AOP_CRY)
5401     {
5402       genModbits (left, right, result);
5403       goto release;
5404     }
5405
5406   /* if both are of size == 1 */
5407   if (AOP_SIZE (left) == 1 &&
5408       AOP_SIZE (right) == 1)
5409     {
5410       genModOneByte (left, right, result);
5411       goto release;
5412     }
5413
5414   /* should have been converted to function call */
5415   assert (0);
5416
5417 release:
5418   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5420   freeAsmop (result, NULL, ic, TRUE);
5421 }
5422
5423 /*-----------------------------------------------------------------*/
5424 /* genIfxJump :- will create a jump depending on the ifx           */
5425 /*-----------------------------------------------------------------*/
5426 static void
5427 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5428 {
5429   symbol *jlbl;
5430   symbol *tlbl = newiTempLabel (NULL);
5431   char *inst;
5432
5433   D(emitcode (";     genIfxJump",""));
5434
5435   /* if true label then we jump if condition
5436      supplied is true */
5437   if (IC_TRUE (ic))
5438     {
5439       jlbl = IC_TRUE (ic);
5440       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5441                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5442     }
5443   else
5444     {
5445       /* false label is present */
5446       jlbl = IC_FALSE (ic);
5447       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5448                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5449     }
5450   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5451     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5452   else
5453     emitcode (inst, "%05d$", tlbl->key + 100);
5454   freeForBranchAsmop (result);
5455   freeForBranchAsmop (right);
5456   freeForBranchAsmop (left);
5457   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5458   emitcode ("", "%05d$:", tlbl->key + 100);
5459
5460   /* mark the icode as generated */
5461   ic->generated = 1;
5462 }
5463
5464 /*-----------------------------------------------------------------*/
5465 /* genCmp :- greater or less than comparison                       */
5466 /*-----------------------------------------------------------------*/
5467 static void
5468 genCmp (operand * left, operand * right,
5469         operand * result, iCode * ifx, int sign, iCode *ic)
5470 {
5471   int size, offset = 0;
5472   unsigned long lit = 0L;
5473   bool rightInB;
5474
5475   D(emitcode (";     genCmp",""));
5476
5477   /* if left & right are bit variables */
5478   if (AOP_TYPE (left) == AOP_CRY &&
5479       AOP_TYPE (right) == AOP_CRY)
5480     {
5481       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5482       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5483     }
5484   else
5485     {
5486       /* subtract right from left if at the
5487          end the carry flag is set then we know that
5488          left is greater than right */
5489       size = max (AOP_SIZE (left), AOP_SIZE (right));
5490
5491       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5492       if ((size == 1) && !sign &&
5493           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5494         {
5495           symbol *lbl = newiTempLabel (NULL);
5496           emitcode ("cjne", "%s,%s,%05d$",
5497                     aopGet (left, offset, FALSE, FALSE),
5498                     aopGet (right, offset, FALSE, FALSE),
5499                     lbl->key + 100);
5500           emitcode ("", "%05d$:", lbl->key + 100);
5501         }
5502       else
5503         {
5504           if (AOP_TYPE (right) == AOP_LIT)
5505             {
5506               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5507               /* optimize if(x < 0) or if(x >= 0) */
5508               if (lit == 0L)
5509                 {
5510                   if (!sign)
5511                     {
5512                       CLRC;
5513                     }
5514                   else
5515                     {
5516                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5517                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5518                         {
5519                           genIfxJump (ifx, "acc.7", left, right, result);
5520                           freeAsmop (right, NULL, ic, TRUE);
5521                           freeAsmop (left, NULL, ic, TRUE);
5522
5523                           return;
5524                         }
5525                       else
5526                         emitcode ("rlc", "a");
5527                     }
5528                   goto release;
5529                 }
5530             }
5531           CLRC;
5532           while (size--)
5533             {
5534               bool pushedB = FALSE;
5535               rightInB = aopGetUsesAcc(right, offset);
5536               if (rightInB)
5537                 {
5538                   pushedB = pushB ();
5539                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5540                 }
5541               MOVA (aopGet (left, offset, FALSE, FALSE));
5542               if (sign && size == 0)
5543                 {
5544                   emitcode ("xrl", "a,#0x80");
5545                   if (AOP_TYPE (right) == AOP_LIT)
5546                     {
5547                       unsigned long lit = (unsigned long)
5548                       floatFromVal (AOP (right)->aopu.aop_lit);
5549                       emitcode ("subb", "a,#0x%02x",
5550                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5551                     }
5552                   else
5553                     {
5554                       if (!rightInB)
5555                         {
5556                           pushedB = pushB ();
5557                           rightInB++;
5558                           emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5559                         }
5560                       emitcode ("xrl", "b,#0x80");
5561                       emitcode ("subb", "a,b");
5562                     }
5563                 }
5564               else
5565                 {
5566                   if (rightInB)
5567                     emitcode ("subb", "a,b");
5568                   else
5569                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5570                 }
5571               if (rightInB)
5572                 popB (pushedB);
5573               offset++;
5574             }
5575         }
5576     }
5577
5578 release:
5579   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5580   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5581   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5582     {
5583       outBitC (result);
5584     }
5585   else
5586     {
5587       /* if the result is used in the next
5588          ifx conditional branch then generate
5589          code a little differently */
5590       if (ifx)
5591         genIfxJump (ifx, "c", NULL, NULL, result);
5592       else
5593         outBitC (result);
5594       /* leave the result in acc */
5595     }
5596 }
5597
5598 /*-----------------------------------------------------------------*/
5599 /* genCmpGt :- greater than comparison                             */
5600 /*-----------------------------------------------------------------*/
5601 static void
5602 genCmpGt (iCode * ic, iCode * ifx)
5603 {
5604   operand *left, *right, *result;
5605   sym_link *letype, *retype;
5606   int sign;
5607
5608   D(emitcode (";     genCmpGt",""));
5609
5610   left = IC_LEFT (ic);
5611   right = IC_RIGHT (ic);
5612   result = IC_RESULT (ic);
5613
5614   letype = getSpec (operandType (left));
5615   retype = getSpec (operandType (right));
5616   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5617            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5618   /* assign the amsops */
5619   aopOp (left, ic, FALSE);
5620   aopOp (right, ic, FALSE);
5621   aopOp (result, ic, TRUE);
5622
5623   genCmp (right, left, result, ifx, sign, ic);
5624
5625   freeAsmop (result, NULL, ic, TRUE);
5626 }
5627
5628 /*-----------------------------------------------------------------*/
5629 /* genCmpLt - less than comparisons                                */
5630 /*-----------------------------------------------------------------*/
5631 static void
5632 genCmpLt (iCode * ic, iCode * ifx)
5633 {
5634   operand *left, *right, *result;
5635   sym_link *letype, *retype;
5636   int sign;
5637
5638   D(emitcode (";     genCmpLt",""));
5639
5640   left = IC_LEFT (ic);
5641   right = IC_RIGHT (ic);
5642   result = IC_RESULT (ic);
5643
5644   letype = getSpec (operandType (left));
5645   retype = getSpec (operandType (right));
5646   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5647            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5648   /* assign the amsops */
5649   aopOp (left, ic, FALSE);
5650   aopOp (right, ic, FALSE);
5651   aopOp (result, ic, TRUE);
5652
5653   genCmp (left, right, result, ifx, sign, ic);
5654
5655   freeAsmop (result, NULL, ic, TRUE);
5656 }
5657
5658 /*-----------------------------------------------------------------*/
5659 /* gencjneshort - compare and jump if not equal                    */
5660 /*-----------------------------------------------------------------*/
5661 static void
5662 gencjneshort (operand * left, operand * right, symbol * lbl)
5663 {
5664   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5665   int offset = 0;
5666   unsigned long lit = 0L;
5667
5668   /* if the left side is a literal or
5669      if the right is in a pointer register and left
5670      is not */
5671   if ((AOP_TYPE (left) == AOP_LIT) ||
5672       (AOP_TYPE (left) == AOP_IMMD) ||
5673       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5674     {
5675       operand *t = right;
5676       right = left;
5677       left = t;
5678     }
5679
5680   if (AOP_TYPE (right) == AOP_LIT)
5681     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5682
5683   /* if the right side is a literal then anything goes */
5684   if (AOP_TYPE (right) == AOP_LIT &&
5685       AOP_TYPE (left) != AOP_DIR  &&
5686       AOP_TYPE (left) != AOP_IMMD)
5687     {
5688       while (size--)
5689         {
5690           emitcode ("cjne", "%s,%s,%05d$",
5691                     aopGet (left, offset, FALSE, FALSE),
5692                     aopGet (right, offset, FALSE, FALSE),
5693                     lbl->key + 100);
5694           offset++;
5695         }
5696     }
5697
5698   /* if the right side is in a register or in direct space or
5699      if the left is a pointer register & right is not */
5700   else if (AOP_TYPE (right) == AOP_REG ||
5701            AOP_TYPE (right) == AOP_DIR ||
5702            AOP_TYPE (right) == AOP_LIT ||
5703            AOP_TYPE (right) == AOP_IMMD ||
5704            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5705            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5706     {
5707       while (size--)
5708         {
5709           MOVA (aopGet (left, offset, FALSE, FALSE));
5710           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5711               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5712             emitcode ("jnz", "%05d$", lbl->key + 100);
5713           else
5714             emitcode ("cjne", "a,%s,%05d$",
5715                       aopGet (right, offset, FALSE, TRUE),
5716                       lbl->key + 100);
5717           offset++;
5718         }
5719     }
5720   else
5721     {
5722       /* right is a pointer reg need both a & b */
5723       while (size--)
5724         {
5725           char *l;
5726           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5727           wassertl(!BINUSE, "B was in use");
5728           l = aopGet (left, offset, FALSE, FALSE);
5729           if (strcmp (l, "b"))
5730             emitcode ("mov", "b,%s", l);
5731           MOVA (aopGet (right, offset, FALSE, FALSE));
5732           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5733           offset++;
5734         }
5735     }
5736 }
5737
5738 /*-----------------------------------------------------------------*/
5739 /* gencjne - compare and jump if not equal                         */
5740 /*-----------------------------------------------------------------*/
5741 static void
5742 gencjne (operand * left, operand * right, symbol * lbl)
5743 {
5744   symbol *tlbl = newiTempLabel (NULL);
5745
5746   gencjneshort (left, right, lbl);
5747
5748   emitcode ("mov", "a,%s", one);
5749   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5750   emitcode ("", "%05d$:", lbl->key + 100);
5751   emitcode ("clr", "a");
5752   emitcode ("", "%05d$:", tlbl->key + 100);
5753 }
5754
5755 /*-----------------------------------------------------------------*/
5756 /* genCmpEq - generates code for equal to                          */
5757 /*-----------------------------------------------------------------*/
5758 static void
5759 genCmpEq (iCode * ic, iCode * ifx)
5760 {
5761   operand *left, *right, *result;
5762
5763   D(emitcode (";     genCmpEq",""));
5764
5765   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5766   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5767   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5768
5769   /* if literal, literal on the right or
5770      if the right is in a pointer register and left
5771      is not */
5772   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5773       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5774     {
5775       operand *t = IC_RIGHT (ic);
5776       IC_RIGHT (ic) = IC_LEFT (ic);
5777       IC_LEFT (ic) = t;
5778     }
5779
5780   if (ifx && !AOP_SIZE (result))
5781     {
5782       symbol *tlbl;
5783       /* if they are both bit variables */
5784       if (AOP_TYPE (left) == AOP_CRY &&
5785           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5786         {
5787           if (AOP_TYPE (right) == AOP_LIT)
5788             {
5789               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5790               if (lit == 0L)
5791                 {
5792                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793                   emitcode ("cpl", "c");
5794                 }
5795               else if (lit == 1L)
5796                 {
5797                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5798                 }
5799               else
5800                 {
5801                   emitcode ("clr", "c");
5802                 }
5803               /* AOP_TYPE(right) == AOP_CRY */
5804             }
5805           else
5806             {
5807               symbol *lbl = newiTempLabel (NULL);
5808               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810               emitcode ("cpl", "c");
5811               emitcode ("", "%05d$:", (lbl->key + 100));
5812             }
5813           /* if true label then we jump if condition
5814              supplied is true */
5815           tlbl = newiTempLabel (NULL);
5816           if (IC_TRUE (ifx))
5817             {
5818               emitcode ("jnc", "%05d$", tlbl->key + 100);
5819               freeForBranchAsmop (result);
5820               freeForBranchAsmop (right);
5821               freeForBranchAsmop (left);
5822               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5823             }
5824           else
5825             {
5826               emitcode ("jc", "%05d$", tlbl->key + 100);
5827               freeForBranchAsmop (result);
5828               freeForBranchAsmop (right);
5829               freeForBranchAsmop (left);
5830               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5831             }
5832           emitcode ("", "%05d$:", tlbl->key + 100);
5833         }
5834       else
5835         {
5836           tlbl = newiTempLabel (NULL);
5837           gencjneshort (left, right, tlbl);
5838           if (IC_TRUE (ifx))
5839             {
5840               freeForBranchAsmop (result);
5841               freeForBranchAsmop (right);
5842               freeForBranchAsmop (left);
5843               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5844               emitcode ("", "%05d$:", tlbl->key + 100);
5845             }
5846           else
5847             {
5848               symbol *lbl = newiTempLabel (NULL);
5849               emitcode ("sjmp", "%05d$", lbl->key + 100);
5850               emitcode ("", "%05d$:", tlbl->key + 100);
5851               freeForBranchAsmop (result);
5852               freeForBranchAsmop (right);
5853               freeForBranchAsmop (left);
5854               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5855               emitcode ("", "%05d$:", lbl->key + 100);
5856             }
5857         }
5858       /* mark the icode as generated */
5859       ifx->generated = 1;
5860       goto release;
5861     }
5862
5863   /* if they are both bit variables */
5864   if (AOP_TYPE (left) == AOP_CRY &&
5865       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5866     {
5867       if (AOP_TYPE (right) == AOP_LIT)
5868         {
5869           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5870           if (lit == 0L)
5871             {
5872               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5873               emitcode ("cpl", "c");
5874             }
5875           else if (lit == 1L)
5876             {
5877               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5878             }
5879           else
5880             {
5881               emitcode ("clr", "c");
5882             }
5883           /* AOP_TYPE(right) == AOP_CRY */
5884         }
5885       else
5886         {
5887           symbol *lbl = newiTempLabel (NULL);
5888           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5889           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5890           emitcode ("cpl", "c");
5891           emitcode ("", "%05d$:", (lbl->key + 100));
5892         }
5893       /* c = 1 if egal */
5894       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5895         {
5896           outBitC (result);
5897           goto release;
5898         }
5899       if (ifx)
5900         {
5901           genIfxJump (ifx, "c", left, right, result);
5902           goto release;
5903         }
5904       /* if the result is used in an arithmetic operation
5905          then put the result in place */
5906       outBitC (result);
5907     }
5908   else
5909     {
5910       gencjne (left, right, newiTempLabel (NULL));
5911       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5912         {
5913           aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5914           goto release;
5915         }
5916       if (ifx)
5917         {
5918           genIfxJump (ifx, "a", left, right, result);
5919           goto release;
5920         }
5921       /* if the result is used in an arithmetic operation
5922          then put the result in place */
5923       if (AOP_TYPE (result) != AOP_CRY)
5924         outAcc (result);
5925       /* leave the result in acc */
5926     }
5927
5928 release:
5929   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5930   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931   freeAsmop (result, NULL, ic, TRUE);
5932 }
5933
5934 /*-----------------------------------------------------------------*/
5935 /* ifxForOp - returns the icode containing the ifx for operand     */
5936 /*-----------------------------------------------------------------*/
5937 static iCode *
5938 ifxForOp (operand * op, iCode * ic)
5939 {
5940   /* if true symbol then needs to be assigned */
5941   if (IS_TRUE_SYMOP (op))
5942     return NULL;
5943
5944   /* if this has register type condition and
5945      the next instruction is ifx with the same operand
5946      and live to of the operand is upto the ifx only then */
5947   if (ic->next &&
5948       ic->next->op == IFX &&
5949       IC_COND (ic->next)->key == op->key &&
5950       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5951     return ic->next;
5952
5953   return NULL;
5954 }
5955
5956 /*-----------------------------------------------------------------*/
5957 /* hasInc - operand is incremented before any other use            */
5958 /*-----------------------------------------------------------------*/
5959 static iCode *
5960 hasInc (operand *op, iCode *ic,int osize)
5961 {
5962   sym_link *type = operandType(op);
5963   sym_link *retype = getSpec (type);
5964   iCode *lic = ic->next;
5965   int isize ;
5966
5967   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5968   if (!IS_SYMOP(op)) return NULL;
5969
5970   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5971   if (IS_AGGREGATE(type->next)) return NULL;
5972   if (osize != (isize = getSize(type->next))) return NULL;
5973
5974   while (lic) {
5975     /* if operand of the form op = op + <sizeof *op> */
5976     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5977         isOperandEqual(IC_RESULT(lic),op) &&
5978         isOperandLiteral(IC_RIGHT(lic)) &&
5979         operandLitValue(IC_RIGHT(lic)) == isize) {
5980       return lic;
5981     }
5982     /* if the operand used or deffed */
5983     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5984       return NULL;
5985     }
5986     /* if GOTO or IFX */
5987     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5988     lic = lic->next;
5989   }
5990   return NULL;
5991 }
5992
5993 /*-----------------------------------------------------------------*/
5994 /* genAndOp - for && operation                                     */
5995 /*-----------------------------------------------------------------*/
5996 static void
5997 genAndOp (iCode * ic)
5998 {
5999   operand *left, *right, *result;
6000   symbol *tlbl;
6001
6002   D(emitcode (";     genAndOp",""));
6003
6004   /* note here that && operations that are in an
6005      if statement are taken away by backPatchLabels
6006      only those used in arthmetic operations remain */
6007   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6008   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6009   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6010
6011   /* if both are bit variables */
6012   if (AOP_TYPE (left) == AOP_CRY &&
6013       AOP_TYPE (right) == AOP_CRY)
6014     {
6015       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6016       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6017       outBitC (result);
6018     }
6019   else
6020     {
6021       tlbl = newiTempLabel (NULL);
6022       toBoolean (left);
6023       emitcode ("jz", "%05d$", tlbl->key + 100);
6024       toBoolean (right);
6025       emitcode ("", "%05d$:", tlbl->key + 100);
6026       outBitAcc (result);
6027     }
6028
6029   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6031   freeAsmop (result, NULL, ic, TRUE);
6032 }
6033
6034
6035 /*-----------------------------------------------------------------*/
6036 /* genOrOp - for || operation                                      */
6037 /*-----------------------------------------------------------------*/
6038 static void
6039 genOrOp (iCode * ic)
6040 {
6041   operand *left, *right, *result;
6042   symbol *tlbl;
6043
6044   D(emitcode (";     genOrOp",""));
6045
6046   /* note here that || operations that are in an
6047      if statement are taken away by backPatchLabels
6048      only those used in arthmetic operations remain */
6049   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6050   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6051   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6052
6053   /* if both are bit variables */
6054   if (AOP_TYPE (left) == AOP_CRY &&
6055       AOP_TYPE (right) == AOP_CRY)
6056     {
6057       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6058       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6059       outBitC (result);
6060     }
6061   else
6062     {
6063       tlbl = newiTempLabel (NULL);
6064       toBoolean (left);
6065       emitcode ("jnz", "%05d$", tlbl->key + 100);
6066       toBoolean (right);
6067       emitcode ("", "%05d$:", tlbl->key + 100);
6068       outBitAcc (result);
6069     }
6070
6071   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6072   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6073   freeAsmop (result, NULL, ic, TRUE);
6074 }
6075
6076 /*-----------------------------------------------------------------*/
6077 /* isLiteralBit - test if lit == 2^n                               */
6078 /*-----------------------------------------------------------------*/
6079 static int
6080 isLiteralBit (unsigned long lit)
6081 {
6082   unsigned long pw[32] =
6083   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6084    0x100L, 0x200L, 0x400L, 0x800L,
6085    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6086    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6087    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6088    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6089    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6090   int idx;
6091
6092   for (idx = 0; idx < 32; idx++)
6093     if (lit == pw[idx])
6094       return idx + 1;
6095   return 0;
6096 }
6097
6098 /*-----------------------------------------------------------------*/
6099 /* continueIfTrue -                                                */
6100 /*-----------------------------------------------------------------*/
6101 static void
6102 continueIfTrue (iCode * ic)
6103 {
6104   if (IC_TRUE (ic))
6105     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6106   ic->generated = 1;
6107 }
6108
6109 /*-----------------------------------------------------------------*/
6110 /* jmpIfTrue -                                                     */
6111 /*-----------------------------------------------------------------*/
6112 static void
6113 jumpIfTrue (iCode * ic)
6114 {
6115   if (!IC_TRUE (ic))
6116     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6117   ic->generated = 1;
6118 }
6119
6120 /*-----------------------------------------------------------------*/
6121 /* jmpTrueOrFalse -                                                */
6122 /*-----------------------------------------------------------------*/
6123 static void
6124 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6125 {
6126   // ugly but optimized by peephole
6127   if (IC_TRUE (ic))
6128     {
6129       symbol *nlbl = newiTempLabel (NULL);
6130       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6131       emitcode ("", "%05d$:", tlbl->key + 100);
6132       freeForBranchAsmop (result);
6133       freeForBranchAsmop (right);
6134       freeForBranchAsmop (left);
6135       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6136       emitcode ("", "%05d$:", nlbl->key + 100);
6137     }
6138   else
6139     {
6140       freeForBranchAsmop (result);
6141       freeForBranchAsmop (right);
6142       freeForBranchAsmop (left);
6143       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6144       emitcode ("", "%05d$:", tlbl->key + 100);
6145     }
6146   ic->generated = 1;
6147 }
6148
6149 /*-----------------------------------------------------------------*/
6150 /* genAnd  - code for and                                          */
6151 /*-----------------------------------------------------------------*/
6152 static void
6153 genAnd (iCode * ic, iCode * ifx)
6154 {
6155   operand *left, *right, *result;
6156   int size, offset = 0;
6157   unsigned long lit = 0L;
6158   int bytelit = 0;
6159   char buffer[10];
6160
6161   D(emitcode (";     genAnd",""));
6162
6163   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6164   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6165   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6166
6167 #ifdef DEBUG_TYPE
6168   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6169             AOP_TYPE (result),
6170             AOP_TYPE (left), AOP_TYPE (right));
6171   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6172             AOP_SIZE (result),
6173             AOP_SIZE (left), AOP_SIZE (right));
6174 #endif
6175
6176   /* if left is a literal & right is not then exchange them */
6177   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6178       AOP_NEEDSACC (left))
6179     {
6180       operand *tmp = right;
6181       right = left;
6182       left = tmp;
6183     }
6184
6185   /* if result = right then exchange left and right */
6186   if (sameRegs (AOP (result), AOP (right)))
6187     {
6188       operand *tmp = right;
6189       right = left;
6190       left = tmp;
6191     }
6192
6193   /* if right is bit then exchange them */
6194   if (AOP_TYPE (right) == AOP_CRY &&
6195       AOP_TYPE (left) != AOP_CRY)
6196     {
6197       operand *tmp = right;
6198       right = left;
6199       left = tmp;
6200     }
6201   if (AOP_TYPE (right) == AOP_LIT)
6202     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6203
6204   size = AOP_SIZE (result);
6205
6206   // if(bit & yy)
6207   // result = bit & yy;
6208   if (AOP_TYPE (left) == AOP_CRY)
6209     {
6210       // c = bit & literal;
6211       if (AOP_TYPE (right) == AOP_LIT)
6212         {
6213           if (lit & 1)
6214             {
6215               if (size && sameRegs (AOP (result), AOP (left)))
6216                 // no change
6217                 goto release;
6218               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6219             }
6220           else
6221             {
6222               // bit(result) = 0;
6223               if (size && (AOP_TYPE (result) == AOP_CRY))
6224                 {
6225                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6226                   goto release;
6227                 }
6228               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6229                 {
6230                   jumpIfTrue (ifx);
6231                   goto release;
6232                 }
6233               emitcode ("clr", "c");
6234             }
6235         }
6236       else
6237         {
6238           if (AOP_TYPE (right) == AOP_CRY)
6239             {
6240               // c = bit & bit;
6241               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6242               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6243             }
6244           else
6245             {
6246               // c = bit & val;
6247               MOVA (aopGet (right, 0, FALSE, FALSE));
6248               // c = lsb
6249               emitcode ("rrc", "a");
6250               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6251             }
6252         }
6253       // bit = c
6254       // val = c
6255       if (size)
6256         outBitC (result);
6257       // if(bit & ...)
6258       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6259         genIfxJump (ifx, "c", left, right, result);
6260       goto release;
6261     }
6262
6263   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6264   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6265   if ((AOP_TYPE (right) == AOP_LIT) &&
6266       (AOP_TYPE (result) == AOP_CRY) &&
6267       (AOP_TYPE (left) != AOP_CRY))
6268     {
6269       int posbit = isLiteralBit (lit);
6270       /* left &  2^n */
6271       if (posbit)
6272         {
6273           posbit--;
6274           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6275           // bit = left & 2^n
6276           if (size)
6277             {
6278               switch (posbit & 0x07)
6279                 {
6280                   case 0: emitcode ("rrc", "a");
6281                           break;
6282                   case 7: emitcode ("rlc", "a");
6283                           break;
6284                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6285                           break;
6286                 }
6287             }
6288           // if(left &  2^n)
6289           else
6290             {
6291               if (ifx)
6292                 {
6293                   SNPRINTF (buffer, sizeof(buffer),
6294                             "acc.%d", posbit & 0x07);
6295                   genIfxJump (ifx, buffer, left, right, result);
6296                 }
6297               else
6298                 {// what is this case? just found it in ds390/gen.c
6299                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6300                 }
6301               goto release;
6302             }
6303         }
6304       else
6305         {
6306           symbol *tlbl = newiTempLabel (NULL);
6307           int sizel = AOP_SIZE (left);
6308           if (size)
6309             emitcode ("setb", "c");
6310           while (sizel--)
6311             {
6312               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6313                 {
6314                   MOVA (aopGet (left, offset, FALSE, FALSE));
6315                   // byte ==  2^n ?
6316                   if ((posbit = isLiteralBit (bytelit)) != 0)
6317                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6318                   else
6319                     {
6320                       if (bytelit != 0x0FFL)
6321                         emitcode ("anl", "a,%s",
6322                                   aopGet (right, offset, FALSE, TRUE));
6323                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6324                     }
6325                 }
6326               offset++;
6327             }
6328           // bit = left & literal
6329           if (size)
6330             {
6331               emitcode ("clr", "c");
6332               emitcode ("", "%05d$:", tlbl->key + 100);
6333             }
6334           // if(left & literal)
6335           else
6336             {
6337               if (ifx)
6338                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6339               else
6340                 emitcode ("", "%05d$:", tlbl->key + 100);
6341               goto release;
6342             }
6343         }
6344       outBitC (result);
6345       goto release;
6346     }
6347
6348   /* if left is same as result */
6349   if (sameRegs (AOP (result), AOP (left)))
6350     {
6351       for (; size--; offset++)
6352         {
6353           if (AOP_TYPE (right) == AOP_LIT)
6354             {
6355               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6356               if (bytelit == 0x0FF)
6357                 {
6358                   /* dummy read of volatile operand */
6359                   if (isOperandVolatile (left, FALSE))
6360                     MOVA (aopGet (left, offset, FALSE, FALSE));
6361                   else
6362                     continue;
6363                 }
6364               else if (bytelit == 0)
6365                 {
6366                   aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6367                 }
6368               else if (IS_AOP_PREG (result))
6369                 {
6370                   MOVA (aopGet (left, offset, FALSE, TRUE));
6371                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6372                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6373                 }
6374               else
6375                 emitcode ("anl", "%s,%s",
6376                           aopGet (left, offset, FALSE, TRUE),
6377                           aopGet (right, offset, FALSE, FALSE));
6378             }
6379           else
6380             {
6381               if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6382                 {
6383                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6384                 }
6385               else
6386                 {
6387                   MOVA (aopGet (right, offset, FALSE, FALSE));
6388                   if (IS_AOP_PREG (result))
6389                     {
6390                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6391                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6392                     }
6393                   else
6394                     emitcode ("anl", "%s,a",
6395                               aopGet (left, offset, FALSE, TRUE));
6396                 }
6397             }
6398         }
6399     }
6400   else
6401     {
6402       // left & result in different registers
6403       if (AOP_TYPE (result) == AOP_CRY)
6404         {
6405           // result = bit
6406           // if(size), result in bit
6407           // if(!size && ifx), conditional oper: if(left & right)
6408           symbol *tlbl = newiTempLabel (NULL);
6409           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6410           if (size)
6411             emitcode ("setb", "c");
6412           while (sizer--)
6413             {
6414               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6415                   && AOP_TYPE(left)==AOP_ACC)
6416                 {
6417                   if (offset)
6418                     emitcode("mov", "a,b");
6419                   emitcode ("anl", "a,%s",
6420                             aopGet (right, offset, FALSE, FALSE));
6421                 } else {
6422                   if (AOP_TYPE(left)==AOP_ACC)
6423                     {
6424                       if (!offset)
6425                         {
6426                           bool pushedB = pushB ();
6427                           emitcode("mov", "b,a");
6428                           MOVA (aopGet (right, offset, FALSE, FALSE));
6429                           emitcode("anl", "a,b");
6430                           popB (pushedB);
6431                         }
6432                       else
6433                         {
6434                           MOVA (aopGet (right, offset, FALSE, FALSE));
6435                           emitcode("anl", "a,b");
6436                         }
6437                     } else {
6438                       MOVA (aopGet (right, offset, FALSE, FALSE));
6439                       emitcode ("anl", "a,%s",
6440                                 aopGet (left, offset, FALSE, FALSE));
6441                     }
6442                 }
6443               emitcode ("jnz", "%05d$", tlbl->key + 100);
6444               offset++;
6445             }
6446           if (size)
6447             {
6448               CLRC;
6449               emitcode ("", "%05d$:", tlbl->key + 100);
6450               outBitC (result);
6451             }
6452           else if (ifx)
6453             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6454           else
6455             emitcode ("", "%05d$:", tlbl->key + 100);
6456         }
6457       else
6458         {
6459           for (; (size--); offset++)
6460             {
6461               // normal case
6462               // result = left & right
6463               if (AOP_TYPE (right) == AOP_LIT)
6464                 {
6465                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6466                   if (bytelit == 0x0FF)
6467                     {
6468                       aopPut (result,
6469                               aopGet (left, offset, FALSE, FALSE),
6470                               offset,
6471                               isOperandVolatile (result, FALSE));
6472                       continue;
6473                     }
6474                   else if (bytelit == 0)
6475                     {
6476                       /* dummy read of volatile operand */
6477                       if (isOperandVolatile (left, FALSE))
6478                         MOVA (aopGet (left, offset, FALSE, FALSE));
6479                       aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6480                       continue;
6481                     }
6482                   else if (AOP_TYPE (left) == AOP_ACC)
6483                     {
6484                       if (!offset)
6485                         {
6486                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6487                           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6488                           continue;
6489                         }
6490                       else
6491                         {
6492                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6493                           aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6494                           continue;
6495                         }
6496                     }
6497                 }
6498               // faster than result <- left, anl result,right
6499               // and better if result is SFR
6500               if (AOP_TYPE (left) == AOP_ACC)
6501                 {
6502                   if (offset)
6503                     emitcode("mov", "a,b");
6504                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6505                 }
6506               else
6507                 {
6508                   MOVA (aopGet (right, offset, FALSE, FALSE));
6509                   emitcode ("anl", "a,%s",
6510                             aopGet (left, offset, FALSE, FALSE));
6511                 }
6512               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6513             }
6514         }
6515     }
6516
6517 release:
6518   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6519   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6520   freeAsmop (result, NULL, ic, TRUE);
6521 }
6522
6523 /*-----------------------------------------------------------------*/
6524 /* genOr  - code for or                                            */
6525 /*-----------------------------------------------------------------*/
6526 static void
6527 genOr (iCode * ic, iCode * ifx)
6528 {
6529   operand *left, *right, *result;
6530   int size, offset = 0;
6531   unsigned long lit = 0L;
6532   int bytelit = 0;
6533
6534   D(emitcode (";     genOr",""));
6535
6536   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6537   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6538   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6539
6540 #ifdef DEBUG_TYPE
6541   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6542             AOP_TYPE (result),
6543             AOP_TYPE (left), AOP_TYPE (right));
6544   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6545             AOP_SIZE (result),
6546             AOP_SIZE (left), AOP_SIZE (right));
6547 #endif
6548
6549   /* if left is a literal & right is not then exchange them */
6550   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6551       AOP_NEEDSACC (left))
6552     {
6553       operand *tmp = right;
6554       right = left;
6555       left = tmp;
6556     }
6557
6558   /* if result = right then exchange them */
6559   if (sameRegs (AOP (result), AOP (right)))
6560     {
6561       operand *tmp = right;
6562       right = left;
6563       left = tmp;
6564     }
6565
6566   /* if right is bit then exchange them */
6567   if (AOP_TYPE (right) == AOP_CRY &&
6568       AOP_TYPE (left) != AOP_CRY)
6569     {
6570       operand *tmp = right;
6571       right = left;
6572       left = tmp;
6573     }
6574   if (AOP_TYPE (right) == AOP_LIT)
6575     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6576
6577   size = AOP_SIZE (result);
6578
6579   // if(bit | yy)
6580   // xx = bit | yy;
6581   if (AOP_TYPE (left) == AOP_CRY)
6582     {
6583       if (AOP_TYPE (right) == AOP_LIT)
6584         {
6585           // c = bit | literal;
6586           if (lit)
6587             {
6588               // lit != 0 => result = 1
6589               if (AOP_TYPE (result) == AOP_CRY)
6590                 {
6591                   if (size)
6592                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6593                   else if (ifx)
6594                     continueIfTrue (ifx);
6595                   goto release;
6596                 }
6597               emitcode ("setb", "c");
6598             }
6599           else
6600             {
6601               // lit == 0 => result = left
6602               if (size && sameRegs (AOP (result), AOP (left)))
6603                 goto release;
6604               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6605             }
6606         }
6607       else
6608         {
6609           if (AOP_TYPE (right) == AOP_CRY)
6610             {
6611               // c = bit | bit;
6612               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6613               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6614             }
6615           else
6616             {
6617               // c = bit | val;
6618               symbol *tlbl = newiTempLabel (NULL);
6619               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6620                 emitcode ("setb", "c");
6621               emitcode ("jb", "%s,%05d$",
6622                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6623               toBoolean (right);
6624               emitcode ("jnz", "%05d$", tlbl->key + 100);
6625               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626                 {
6627                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6628                   goto release;
6629                 }
6630               else
6631                 {
6632                   CLRC;
6633                   emitcode ("", "%05d$:", tlbl->key + 100);
6634                 }
6635             }
6636         }
6637       // bit = c
6638       // val = c
6639       if (size)
6640         outBitC (result);
6641       // if(bit | ...)
6642       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6643         genIfxJump (ifx, "c", left, right, result);
6644       goto release;
6645     }
6646
6647   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6648   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6649   if ((AOP_TYPE (right) == AOP_LIT) &&
6650       (AOP_TYPE (result) == AOP_CRY) &&
6651       (AOP_TYPE (left) != AOP_CRY))
6652     {
6653       if (lit)
6654         {
6655           // result = 1
6656           if (size)
6657             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6658           else
6659             continueIfTrue (ifx);
6660           goto release;
6661         }
6662       else
6663         {
6664           // lit = 0, result = boolean(left)
6665           if (size)
6666             emitcode ("setb", "c");
6667           toBoolean (right);
6668           if (size)
6669             {
6670               symbol *tlbl = newiTempLabel (NULL);
6671               emitcode ("jnz", "%05d$", tlbl->key + 100);
6672               CLRC;
6673               emitcode ("", "%05d$:", tlbl->key + 100);
6674             }
6675           else
6676             {
6677               genIfxJump (ifx, "a", left, right, result);
6678               goto release;
6679             }
6680         }
6681       outBitC (result);
6682       goto release;
6683     }
6684
6685   /* if left is same as result */
6686   if (sameRegs (AOP (result), AOP (left)))
6687     {
6688       for (; size--; offset++)
6689         {
6690           if (AOP_TYPE (right) == AOP_LIT)
6691             {
6692               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6693               if (bytelit == 0)
6694                 {
6695                   /* dummy read of volatile operand */
6696                   if (isOperandVolatile (left, FALSE))
6697                     MOVA (aopGet (left, offset, FALSE, FALSE));
6698                   else
6699                     continue;
6700                 }
6701               else if (bytelit == 0x0FF)
6702                 {
6703                   aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6704                 }
6705               else if (IS_AOP_PREG (left))
6706                 {
6707                   MOVA (aopGet (left, offset, FALSE, TRUE));
6708                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6709                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6710                 }
6711               else
6712                 {
6713                   emitcode ("orl", "%s,%s",
6714                             aopGet (left, offset, FALSE, TRUE),
6715                             aopGet (right, offset, FALSE, FALSE));
6716                 }
6717             }
6718           else
6719             {
6720               if (AOP_TYPE (left) == AOP_ACC)
6721                 {
6722                   if (offset)
6723                     emitcode("mov", "a,b");
6724                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6725                 }
6726               else
6727                 {
6728                   MOVA (aopGet (right, offset, FALSE, FALSE));
6729                   if (IS_AOP_PREG (left))
6730                     {
6731                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6732                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6733                     }
6734                   else
6735                     {
6736                       emitcode ("orl", "%s,a",
6737                                 aopGet (left, offset, FALSE, TRUE));
6738                     }
6739                 }
6740             }
6741         }
6742     }
6743   else
6744     {
6745       // left & result in different registers
6746       if (AOP_TYPE (result) == AOP_CRY)
6747         {
6748           // result = bit
6749           // if(size), result in bit
6750           // if(!size && ifx), conditional oper: if(left | right)
6751           symbol *tlbl = newiTempLabel (NULL);
6752           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6753           if (size)
6754             emitcode ("setb", "c");
6755           while (sizer--)
6756             {
6757               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6758                 if (offset)
6759                   emitcode("mov", "a,b");
6760                 emitcode ("orl", "a,%s",
6761                           aopGet (right, offset, FALSE, FALSE));
6762               } else {
6763                 MOVA (aopGet (right, offset, FALSE, FALSE));
6764                 emitcode ("orl", "a,%s",
6765                           aopGet (left, offset, FALSE, FALSE));
6766               }
6767               emitcode ("jnz", "%05d$", tlbl->key + 100);
6768               offset++;
6769             }
6770           if (size)
6771             {
6772               CLRC;
6773               emitcode ("", "%05d$:", tlbl->key + 100);
6774               outBitC (result);
6775             }
6776           else if (ifx)
6777             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6778           else
6779             emitcode ("", "%05d$:", tlbl->key + 100);
6780         }
6781       else
6782         {
6783           for (; (size--); offset++)
6784             {
6785               // normal case
6786               // result = left | right
6787               if (AOP_TYPE (right) == AOP_LIT)
6788                 {
6789                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6790                   if (bytelit == 0)
6791                     {
6792                       aopPut (result,
6793                               aopGet (left, offset, FALSE, FALSE),
6794                               offset,
6795                               isOperandVolatile (result, FALSE));
6796                       continue;
6797                     }
6798                   else if (bytelit == 0x0FF)
6799                     {
6800                       /* dummy read of volatile operand */
6801                       if (isOperandVolatile (left, FALSE))
6802                         MOVA (aopGet (left, offset, FALSE, FALSE));
6803                       aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6804                       continue;
6805                     }
6806                 }
6807               // faster than result <- left, anl result,right
6808               // and better if result is SFR
6809               if (AOP_TYPE (left) == AOP_ACC)
6810                 {
6811                   if (offset)
6812                     emitcode("mov", "a,b");
6813                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6814                 }
6815               else
6816                 {
6817                   MOVA (aopGet (right, offset, FALSE, FALSE));
6818                   emitcode ("orl", "a,%s",
6819                             aopGet (left, offset, FALSE, FALSE));
6820                 }
6821               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6822             }
6823         }
6824     }
6825
6826 release:
6827   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829   freeAsmop (result, NULL, ic, TRUE);
6830 }
6831
6832 /*-----------------------------------------------------------------*/
6833 /* genXor - code for xclusive or                                   */
6834 /*-----------------------------------------------------------------*/
6835 static void
6836 genXor (iCode * ic, iCode * ifx)
6837 {
6838   operand *left, *right, *result;
6839   int size, offset = 0;
6840   unsigned long lit = 0L;
6841   int bytelit = 0;
6842
6843   D(emitcode (";     genXor",""));
6844
6845   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6846   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6847   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6848
6849 #ifdef DEBUG_TYPE
6850   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6851             AOP_TYPE (result),
6852             AOP_TYPE (left), AOP_TYPE (right));
6853   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6854             AOP_SIZE (result),
6855             AOP_SIZE (left), AOP_SIZE (right));
6856 #endif
6857
6858   /* if left is a literal & right is not ||
6859      if left needs acc & right does not */
6860   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6861       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6862     {
6863       operand *tmp = right;
6864       right = left;
6865       left = tmp;
6866     }
6867
6868   /* if result = right then exchange them */
6869   if (sameRegs (AOP (result), AOP (right)))
6870     {
6871       operand *tmp = right;
6872       right = left;
6873       left = tmp;
6874     }
6875
6876   /* if right is bit then exchange them */
6877   if (AOP_TYPE (right) == AOP_CRY &&
6878       AOP_TYPE (left) != AOP_CRY)
6879     {
6880       operand *tmp = right;
6881       right = left;
6882       left = tmp;
6883     }
6884   if (AOP_TYPE (right) == AOP_LIT)
6885     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6886
6887   size = AOP_SIZE (result);
6888
6889   // if(bit ^ yy)
6890   // xx = bit ^ yy;
6891   if (AOP_TYPE (left) == AOP_CRY)
6892     {
6893       if (AOP_TYPE (right) == AOP_LIT)
6894         {
6895           // c = bit & literal;
6896           if (lit >> 1)
6897             {
6898               // lit>>1  != 0 => result = 1
6899               if (AOP_TYPE (result) == AOP_CRY)
6900                 {
6901                   if (size)
6902                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6903                   else if (ifx)
6904                     continueIfTrue (ifx);
6905                   goto release;
6906                 }
6907               emitcode ("setb", "c");
6908             }
6909           else
6910             {
6911               // lit == (0 or 1)
6912               if (lit == 0)
6913                 {
6914                   // lit == 0, result = left
6915                   if (size && sameRegs (AOP (result), AOP (left)))
6916                     goto release;
6917                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6918                 }
6919               else
6920                 {
6921                   // lit == 1, result = not(left)
6922                   if (size && sameRegs (AOP (result), AOP (left)))
6923                     {
6924                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6925                       goto release;
6926                     }
6927                   else
6928                     {
6929                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6930                       emitcode ("cpl", "c");
6931                     }
6932                 }
6933             }
6934
6935         }
6936       else
6937         {
6938           // right != literal
6939           symbol *tlbl = newiTempLabel (NULL);
6940           if (AOP_TYPE (right) == AOP_CRY)
6941             {
6942               // c = bit ^ bit;
6943               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6944             }
6945           else
6946             {
6947               int sizer = AOP_SIZE (right);
6948               // c = bit ^ val
6949               // if val>>1 != 0, result = 1
6950               emitcode ("setb", "c");
6951               while (sizer)
6952                 {
6953                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6954                   if (sizer == 1)
6955                     // test the msb of the lsb
6956                     emitcode ("anl", "a,#0xfe");
6957                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6958                   sizer--;
6959                 }
6960               // val = (0,1)
6961               emitcode ("rrc", "a");
6962             }
6963           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6964           emitcode ("cpl", "c");
6965           emitcode ("", "%05d$:", (tlbl->key + 100));
6966         }
6967       // bit = c
6968       // val = c
6969       if (size)
6970         outBitC (result);
6971       // if(bit | ...)
6972       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6973         genIfxJump (ifx, "c", left, right, result);
6974       goto release;
6975     }
6976
6977   /* if left is same as result */
6978   if (sameRegs (AOP (result), AOP (left)))
6979     {
6980       for (; size--; offset++)
6981         {
6982           if (AOP_TYPE (right) == AOP_LIT)
6983             {
6984               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6985               if (bytelit == 0)
6986                 {
6987                   /* dummy read of volatile operand */
6988                   if (isOperandVolatile (left, FALSE))
6989                     MOVA (aopGet (left, offset, FALSE, FALSE));
6990                   else
6991                     continue;
6992                 }
6993               else if (IS_AOP_PREG (left))
6994                 {
6995                   MOVA (aopGet (left, offset, FALSE, TRUE));
6996                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6997                   aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6998                 }
6999               else
7000                 {
7001                   emitcode ("xrl", "%s,%s",
7002                             aopGet (left, offset, FALSE, TRUE),
7003                             aopGet (right, offset, FALSE, FALSE));
7004                 }
7005             }
7006           else
7007             {
7008               if (AOP_TYPE (left) == AOP_ACC)
7009                 {
7010                   if (offset)
7011                     emitcode("mov", "a,b");
7012                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7013                 }
7014               else
7015                 {
7016                   MOVA (aopGet (right, offset, FALSE, FALSE));
7017                   if (IS_AOP_PREG (left))
7018                     {
7019                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7020                       aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7021                     }
7022                   else
7023                     emitcode ("xrl", "%s,a",
7024                               aopGet (left, offset, FALSE, TRUE));
7025                 }
7026             }
7027         }
7028     }
7029   else
7030     {
7031       // left & result in different registers
7032       if (AOP_TYPE (result) == AOP_CRY)
7033         {
7034           // result = bit
7035           // if(size), result in bit
7036           // if(!size && ifx), conditional oper: if(left ^ right)
7037           symbol *tlbl = newiTempLabel (NULL);
7038           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7039           if (size)
7040             emitcode ("setb", "c");
7041           while (sizer--)
7042             {
7043               if ((AOP_TYPE (right) == AOP_LIT) &&
7044                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7045                 {
7046                   MOVA (aopGet (left, offset, FALSE, FALSE));
7047                 }
7048               else
7049                 {
7050                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7051                     if (offset)
7052                       emitcode("mov", "a,b");
7053                     emitcode ("xrl", "a,%s",
7054                               aopGet (right, offset, FALSE, FALSE));
7055                   } else {
7056                     MOVA (aopGet (right, offset, FALSE, FALSE));
7057                     emitcode ("xrl", "a,%s",
7058                               aopGet (left, offset, FALSE, FALSE));
7059                   }
7060                 }
7061               emitcode ("jnz", "%05d$", tlbl->key + 100);
7062               offset++;
7063             }
7064           if (size)
7065             {
7066               CLRC;
7067               emitcode ("", "%05d$:", tlbl->key + 100);
7068               outBitC (result);
7069             }
7070           else if (ifx)
7071             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7072         }
7073       else
7074         {
7075           for (; (size--); offset++)
7076             {
7077               // normal case
7078               // result = left & right
7079               if (AOP_TYPE (right) == AOP_LIT)
7080                 {
7081                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7082                   if (bytelit == 0)
7083                     {
7084                       aopPut (result,
7085                               aopGet (left, offset, FALSE, FALSE),
7086                               offset,
7087                               isOperandVolatile (result, FALSE));
7088                       continue;
7089                     }
7090                 }
7091               // faster than result <- left, anl result,right
7092               // and better if result is SFR
7093               if (AOP_TYPE (left) == AOP_ACC)
7094                 {
7095                   if (offset)
7096                     emitcode("mov", "a,b");
7097                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7098                 }
7099               else
7100                 {
7101                   MOVA (aopGet (right, offset, FALSE, FALSE));
7102                   emitcode ("xrl", "a,%s",
7103                             aopGet (left, offset, FALSE, TRUE));
7104                 }
7105               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7106             }
7107         }
7108     }
7109
7110 release:
7111   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7112   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7113   freeAsmop (result, NULL, ic, TRUE);
7114 }
7115
7116 /*-----------------------------------------------------------------*/
7117 /* genInline - write the inline code out                           */
7118 /*-----------------------------------------------------------------*/
7119 static void
7120 genInline (iCode * ic)
7121 {
7122   char *buffer, *bp, *bp1;
7123
7124   D(emitcode (";     genInline",""));
7125
7126   _G.inLine += (!options.asmpeep);
7127
7128   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7129   strcpy (buffer, IC_INLINE (ic));
7130
7131   /* emit each line as a code */
7132   while (*bp)
7133     {
7134       if (*bp == '\n')
7135         {
7136           *bp++ = '\0';
7137           emitcode (bp1, "");
7138           bp1 = bp;
7139         }
7140       else
7141         {
7142           /* Add \n for labels, not dirs such as c:\mydir */
7143           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7144             {
7145               bp++;
7146               *bp = '\0';
7147               bp++;
7148               emitcode (bp1, "");
7149               bp1 = bp;
7150             }
7151           else
7152             bp++;
7153         }
7154     }
7155   if (bp1 != bp)
7156     emitcode (bp1, "");
7157   /*     emitcode("",buffer); */
7158   _G.inLine -= (!options.asmpeep);
7159 }
7160
7161 /*-----------------------------------------------------------------*/
7162 /* genRRC - rotate right with carry                                */
7163 /*-----------------------------------------------------------------*/
7164 static void
7165 genRRC (iCode * ic)
7166 {
7167   operand *left, *result;
7168   int size, offset = 0;
7169   char *l;
7170
7171   D(emitcode (";     genRRC",""));
7172
7173   /* rotate right with carry */
7174   left = IC_LEFT (ic);
7175   result = IC_RESULT (ic);
7176   aopOp (left, ic, FALSE);
7177   aopOp (result, ic, FALSE);
7178
7179   /* move it to the result */
7180   size = AOP_SIZE (result);
7181   offset = size - 1;
7182   if (size == 1) { /* special case for 1 byte */
7183       l = aopGet (left, offset, FALSE, FALSE);
7184       MOVA (l);
7185       emitcode ("rr", "a");
7186       goto release;
7187   }
7188   /* no need to clear carry, bit7 will be written later */
7189   while (size--)
7190     {
7191       l = aopGet (left, offset, FALSE, FALSE);
7192       MOVA (l);
7193       emitcode ("rrc", "a");
7194       if (AOP_SIZE (result) > 1)
7195         aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7196     }
7197   /* now we need to put the carry into the
7198      highest order byte of the result */
7199   if (AOP_SIZE (result) > 1)
7200     {
7201       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7202       MOVA (l);
7203     }
7204   emitcode ("mov", "acc.7,c");
7205  release:
7206   aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7207   freeAsmop (left, NULL, ic, TRUE);
7208   freeAsmop (result, NULL, ic, TRUE);
7209 }
7210
7211 /*-----------------------------------------------------------------*/
7212 /* genRLC - generate code for rotate left with carry               */
7213 /*-----------------------------------------------------------------*/
7214 static void
7215 genRLC (iCode * ic)
7216 {
7217   operand *left, *result;
7218   int size, offset = 0;
7219   char *l;
7220
7221   D(emitcode (";     genRLC",""));
7222
7223   /* rotate right with carry */
7224   left = IC_LEFT (ic);
7225   result = IC_RESULT (ic);
7226   aopOp (left, ic, FALSE);
7227   aopOp (result, ic, FALSE);
7228
7229   /* move it to the result */
7230   size = AOP_SIZE (result);
7231   offset = 0;
7232   if (size--)
7233     {
7234       l = aopGet (left, offset, FALSE, FALSE);
7235       MOVA (l);
7236       if (size == 0) { /* special case for 1 byte */
7237               emitcode("rl","a");
7238               goto release;
7239       }
7240       emitcode("rlc","a"); /* bit0 will be written later */
7241       if (AOP_SIZE (result) > 1)
7242         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7243       while (size--)
7244         {
7245           l = aopGet (left, offset, FALSE, FALSE);
7246           MOVA (l);
7247           emitcode ("rlc", "a");
7248           if (AOP_SIZE (result) > 1)
7249             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7250         }
7251     }
7252   /* now we need to put the carry into the
7253      highest order byte of the result */
7254   if (AOP_SIZE (result) > 1)
7255     {
7256       l = aopGet (result, 0, FALSE, FALSE);
7257       MOVA (l);
7258     }
7259   emitcode ("mov", "acc.0,c");
7260  release:
7261   aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7262   freeAsmop (left, NULL, ic, TRUE);
7263   freeAsmop (result, NULL, ic, TRUE);
7264 }
7265
7266 /*-----------------------------------------------------------------*/
7267 /* genGetHbit - generates code get highest order bit               */
7268 /*-----------------------------------------------------------------*/
7269 static void
7270 genGetHbit (iCode * ic)
7271 {
7272   operand *left, *result;
7273
7274   D(emitcode (";     genGetHbit",""));
7275
7276   left = IC_LEFT (ic);
7277   result = IC_RESULT (ic);
7278   aopOp (left, ic, FALSE);
7279   aopOp (result, ic, FALSE);
7280
7281   /* get the highest order byte into a */
7282   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7283   if (AOP_TYPE (result) == AOP_CRY)
7284     {
7285       emitcode ("rlc", "a");
7286       outBitC (result);
7287     }
7288   else
7289     {
7290       emitcode ("rl", "a");
7291       emitcode ("anl", "a,#0x01");
7292       outAcc (result);
7293     }
7294
7295
7296   freeAsmop (left, NULL, ic, TRUE);
7297   freeAsmop (result, NULL, ic, TRUE);
7298 }
7299
7300 /*-----------------------------------------------------------------*/
7301 /* genGetAbit - generates code get a single bit                    */
7302 /*-----------------------------------------------------------------*/
7303 static void
7304 genGetAbit (iCode * ic)
7305 {
7306   operand *left, *right, *result;
7307   int shCount;
7308
7309   D(emitcode (";     genGetAbit",""));
7310
7311   left = IC_LEFT (ic);
7312   right = IC_RIGHT (ic);
7313   result = IC_RESULT (ic);
7314   aopOp (left, ic, FALSE);
7315   aopOp (right, ic, FALSE);
7316   aopOp (result, ic, FALSE);
7317
7318   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7319
7320   /* get the needed byte into a */
7321   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7322   shCount %= 8;
7323   if (AOP_TYPE (result) == AOP_CRY)
7324     {
7325       if ((shCount) == 7)
7326           emitcode ("rlc", "a");
7327       else if ((shCount) == 0)
7328           emitcode ("rrc", "a");
7329       else
7330           emitcode ("mov", "c,acc[%d]", shCount);
7331       outBitC (result);
7332     }
7333   else
7334     {
7335       switch (shCount)
7336         {
7337         case 2:
7338           emitcode ("rr", "a");
7339           //fallthrough
7340         case 1:
7341           emitcode ("rr", "a");
7342           //fallthrough
7343         case 0:
7344           emitcode ("anl", "a,#0x01");
7345           break;
7346         case 3:
7347         case 5:
7348           emitcode ("mov", "c,acc[%d]", shCount);
7349           emitcode ("clr", "a");
7350           emitcode ("rlc", "a");
7351           break;
7352         case 4:
7353           emitcode ("swap", "a");
7354           emitcode ("anl", "a,#0x01");
7355           break;
7356         case 6:
7357           emitcode ("rl", "a");
7358           //fallthrough
7359         case 7:
7360           emitcode ("rl", "a");
7361           emitcode ("anl", "a,#0x01");
7362           break;
7363         }
7364       outAcc (result);
7365     }
7366
7367   freeAsmop (left, NULL, ic, TRUE);
7368   freeAsmop (right, NULL, ic, TRUE);
7369   freeAsmop (result, NULL, ic, TRUE);
7370 }
7371
7372 /*-----------------------------------------------------------------*/
7373 /* genGetByte - generates code get a single byte                   */
7374 /*-----------------------------------------------------------------*/
7375 static void
7376 genGetByte (iCode * ic)
7377 {
7378   operand *left, *right, *result;
7379   int offset;
7380
7381   D(emitcode (";     genGetByte",""));
7382
7383   left = IC_LEFT (ic);
7384   right = IC_RIGHT (ic);
7385   result = IC_RESULT (ic);
7386   aopOp (left, ic, FALSE);
7387   aopOp (right, ic, FALSE);
7388   aopOp (result, ic, FALSE);
7389
7390   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7391   aopPut (result,
7392           aopGet (left, offset, FALSE, FALSE),
7393           0,
7394           isOperandVolatile (result, FALSE));
7395
7396   freeAsmop (left, NULL, ic, TRUE);
7397   freeAsmop (right, NULL, ic, TRUE);
7398   freeAsmop (result, NULL, ic, TRUE);
7399 }
7400
7401 /*-----------------------------------------------------------------*/
7402 /* genGetWord - generates code get two bytes                       */
7403 /*-----------------------------------------------------------------*/
7404 static void
7405 genGetWord (iCode * ic)
7406 {
7407   operand *left, *right, *result;
7408   int offset;
7409
7410   D(emitcode (";     genGetWord",""));
7411
7412   left = IC_LEFT (ic);
7413   right = IC_RIGHT (ic);
7414   result = IC_RESULT (ic);
7415   aopOp (left, ic, FALSE);
7416   aopOp (right, ic, FALSE);
7417   aopOp (result, ic, FALSE);
7418
7419   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7420   aopPut (result,
7421           aopGet (left, offset, FALSE, FALSE),
7422           0,
7423           isOperandVolatile (result, FALSE));
7424   aopPut (result,
7425           aopGet (left, offset+1, FALSE, FALSE),
7426           1,
7427           isOperandVolatile (result, FALSE));
7428
7429   freeAsmop (left, NULL, ic, TRUE);
7430   freeAsmop (right, NULL, ic, TRUE);
7431   freeAsmop (result, NULL, ic, TRUE);
7432 }
7433
7434 /*-----------------------------------------------------------------*/
7435 /* genSwap - generates code to swap nibbles or bytes               */
7436 /*-----------------------------------------------------------------*/
7437 static void
7438 genSwap (iCode * ic)
7439 {
7440   operand *left, *result;
7441
7442   D(emitcode (";     genSwap",""));
7443
7444   left = IC_LEFT (ic);
7445   result = IC_RESULT (ic);
7446   aopOp (left, ic, FALSE);
7447   aopOp (result, ic, FALSE);
7448
7449   switch (AOP_SIZE (left))
7450     {
7451     case 1: /* swap nibbles in byte */
7452       MOVA (aopGet (left, 0, FALSE, FALSE));
7453       emitcode ("swap", "a");
7454       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7455       break;
7456     case 2: /* swap bytes in word */
7457       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7458         {
7459           MOVA (aopGet (left, 0, FALSE, FALSE));
7460           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7461                   0, isOperandVolatile (result, FALSE));
7462           aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7463         }
7464       else if (operandsEqu (left, result))
7465         {
7466           char * reg = "a";
7467           bool pushedB = FALSE, leftInB = FALSE;
7468
7469           MOVA (aopGet (left, 0, FALSE, FALSE));
7470           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7471             {
7472               pushedB = pushB ();
7473               emitcode ("mov", "b,a");
7474               reg = "b";
7475               leftInB = TRUE;
7476             }
7477           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7478                   0, isOperandVolatile (result, FALSE));
7479           aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7480
7481           if (leftInB)
7482             popB (pushedB);
7483         }
7484       else
7485         {
7486           aopPut (result, aopGet (left, 1, FALSE, FALSE),
7487                   0, isOperandVolatile (result, FALSE));
7488           aopPut (result, aopGet (left, 0, FALSE, FALSE),
7489                   1, isOperandVolatile (result, FALSE));
7490         }
7491       break;
7492     default:
7493       wassertl(FALSE, "unsupported SWAP operand size");
7494     }
7495
7496   freeAsmop (left, NULL, ic, TRUE);
7497   freeAsmop (result, NULL, ic, TRUE);
7498 }
7499
7500
7501 /*-----------------------------------------------------------------*/
7502 /* AccRol - rotate left accumulator by known count                 */
7503 /*-----------------------------------------------------------------*/
7504 static void
7505 AccRol (int shCount)
7506 {
7507   shCount &= 0x0007;            // shCount : 0..7
7508
7509   switch (shCount)
7510     {
7511     case 0:
7512       break;
7513     case 1:
7514       emitcode ("rl", "a");
7515       break;
7516     case 2:
7517       emitcode ("rl", "a");
7518       emitcode ("rl", "a");
7519       break;
7520     case 3:
7521       emitcode ("swap", "a");
7522       emitcode ("rr", "a");
7523       break;
7524     case 4:
7525       emitcode ("swap", "a");
7526       break;
7527     case 5:
7528       emitcode ("swap", "a");
7529       emitcode ("rl", "a");
7530       break;
7531     case 6:
7532       emitcode ("rr", "a");
7533       emitcode ("rr", "a");
7534       break;
7535     case 7:
7536       emitcode ("rr", "a");
7537       break;
7538     }
7539 }
7540
7541 /*-----------------------------------------------------------------*/
7542 /* AccLsh - left shift accumulator by known count                  */
7543 /*-----------------------------------------------------------------*/
7544 static void
7545 AccLsh (int shCount)
7546 {
7547   if (shCount != 0)
7548     {
7549       if (shCount == 1)
7550         emitcode ("add", "a,acc");
7551       else if (shCount == 2)
7552         {
7553           emitcode ("add", "a,acc");
7554           emitcode ("add", "a,acc");
7555         }
7556       else
7557         {
7558           /* rotate left accumulator */
7559           AccRol (shCount);
7560           /* and kill the lower order bits */
7561           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7562         }
7563     }
7564 }
7565
7566 /*-----------------------------------------------------------------*/
7567 /* AccRsh - right shift accumulator by known count                 */
7568 /*-----------------------------------------------------------------*/
7569 static void
7570 AccRsh (int shCount)
7571 {
7572   if (shCount != 0)
7573     {
7574       if (shCount == 1)
7575         {
7576           CLRC;
7577           emitcode ("rrc", "a");
7578         }
7579       else
7580         {
7581           /* rotate right accumulator */
7582           AccRol (8 - shCount);
7583           /* and kill the higher order bits */
7584           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7585         }
7586     }
7587 }
7588
7589 /*-----------------------------------------------------------------*/
7590 /* AccSRsh - signed right shift accumulator by known count                 */
7591 /*-----------------------------------------------------------------*/
7592 static void
7593 AccSRsh (int shCount)
7594 {
7595   symbol *tlbl;
7596   if (shCount != 0)
7597     {
7598       if (shCount == 1)
7599         {
7600           emitcode ("mov", "c,acc.7");
7601           emitcode ("rrc", "a");
7602         }
7603       else if (shCount == 2)
7604         {
7605           emitcode ("mov", "c,acc.7");
7606           emitcode ("rrc", "a");
7607           emitcode ("mov", "c,acc.7");
7608           emitcode ("rrc", "a");
7609         }
7610       else
7611         {
7612           tlbl = newiTempLabel (NULL);
7613           /* rotate right accumulator */
7614           AccRol (8 - shCount);
7615           /* and kill the higher order bits */
7616           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7617           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7618           emitcode ("orl", "a,#0x%02x",
7619                     (unsigned char) ~SRMask[shCount]);
7620           emitcode ("", "%05d$:", tlbl->key + 100);
7621         }
7622     }
7623 }
7624
7625 /*-----------------------------------------------------------------*/
7626 /* shiftR1Left2Result - shift right one byte from left to result   */
7627 /*-----------------------------------------------------------------*/
7628 static void
7629 shiftR1Left2Result (operand * left, int offl,
7630                     operand * result, int offr,
7631                     int shCount, int sign)
7632 {
7633   MOVA (aopGet (left, offl, FALSE, FALSE));
7634   /* shift right accumulator */
7635   if (sign)
7636     AccSRsh (shCount);
7637   else
7638     AccRsh (shCount);
7639   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7640 }
7641
7642 /*-----------------------------------------------------------------*/
7643 /* shiftL1Left2Result - shift left one byte from left to result    */
7644 /*-----------------------------------------------------------------*/
7645 static void
7646 shiftL1Left2Result (operand * left, int offl,
7647                     operand * result, int offr, int shCount)
7648 {
7649   char *l;
7650   l = aopGet (left, offl, FALSE, FALSE);
7651   MOVA (l);
7652   /* shift left accumulator */
7653   AccLsh (shCount);
7654   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7655 }
7656
7657 /*-----------------------------------------------------------------*/
7658 /* movLeft2Result - move byte from left to result                  */
7659 /*-----------------------------------------------------------------*/
7660 static void
7661 movLeft2Result (operand * left, int offl,
7662                 operand * result, int offr, int sign)
7663 {
7664   char *l;
7665   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7666     {
7667       l = aopGet (left, offl, FALSE, FALSE);
7668
7669       if (*l == '@' && (IS_AOP_PREG (result)))
7670         {
7671           emitcode ("mov", "a,%s", l);
7672           aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7673         }
7674       else
7675         {
7676           if (!sign)
7677             aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7678           else
7679             {
7680               /* MSB sign in acc.7 ! */
7681               if (getDataSize (left) == offl + 1)
7682                 {
7683                   emitcode ("mov", "a,%s", l);
7684                   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7685                 }
7686             }
7687         }
7688     }
7689 }
7690
7691 /*-----------------------------------------------------------------*/
7692 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7693 /*-----------------------------------------------------------------*/
7694 static void
7695 AccAXRrl1 (char *x)
7696 {
7697   emitcode ("rrc", "a");
7698   emitcode ("xch", "a,%s", x);
7699   emitcode ("rrc", "a");
7700   emitcode ("xch", "a,%s", x);
7701 }
7702
7703 /*-----------------------------------------------------------------*/
7704 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7705 /*-----------------------------------------------------------------*/
7706 static void
7707 AccAXLrl1 (char *x)
7708 {
7709   emitcode ("xch", "a,%s", x);
7710   emitcode ("rlc", "a");
7711   emitcode ("xch", "a,%s", x);
7712   emitcode ("rlc", "a");
7713 }
7714
7715 /*-----------------------------------------------------------------*/
7716 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7717 /*-----------------------------------------------------------------*/
7718 static void
7719 AccAXLsh1 (char *x)
7720 {
7721   emitcode ("xch", "a,%s", x);
7722   emitcode ("add", "a,acc");
7723   emitcode ("xch", "a,%s", x);
7724   emitcode ("rlc", "a");
7725 }
7726
7727 /*-----------------------------------------------------------------*/
7728 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7729 /*-----------------------------------------------------------------*/
7730 static void
7731 AccAXLsh (char *x, int shCount)
7732 {
7733   switch (shCount)
7734     {
7735     case 0:
7736       break;
7737     case 1:
7738       AccAXLsh1 (x);
7739       break;
7740     case 2:
7741       AccAXLsh1 (x);
7742       AccAXLsh1 (x);
7743       break;
7744     case 3:
7745     case 4:
7746     case 5:                     // AAAAABBB:CCCCCDDD
7747
7748       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7749
7750       emitcode ("anl", "a,#0x%02x",
7751                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7752
7753       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7754
7755       AccRol (shCount);         // DDDCCCCC:BBB00000
7756
7757       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7758
7759       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7760
7761       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7762
7763       emitcode ("anl", "a,#0x%02x",
7764                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7765
7766       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7767
7768       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7769
7770       break;
7771     case 6:                     // AAAAAABB:CCCCCCDD
7772       emitcode ("anl", "a,#0x%02x",
7773                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7774       emitcode ("mov", "c,acc.0");      // c = B
7775       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7776 #if 0 // REMOVE ME
7777       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7778       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7779 #else
7780       emitcode("rrc","a");
7781       emitcode("xch","a,%s", x);
7782       emitcode("rrc","a");
7783       emitcode("mov","c,acc.0"); //<< get correct bit
7784       emitcode("xch","a,%s", x);
7785
7786       emitcode("rrc","a");
7787       emitcode("xch","a,%s", x);
7788       emitcode("rrc","a");
7789       emitcode("xch","a,%s", x);
7790 #endif
7791       break;
7792     case 7:                     // a:x <<= 7
7793
7794       emitcode ("anl", "a,#0x%02x",
7795                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7796
7797       emitcode ("mov", "c,acc.0");      // c = B
7798
7799       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7800
7801       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7802
7803       break;
7804     default:
7805       break;
7806     }
7807 }
7808
7809 /*-----------------------------------------------------------------*/
7810 /* AccAXRsh - right shift a:x known count (0..7)                   */
7811 /*-----------------------------------------------------------------*/
7812 static void
7813 AccAXRsh (char *x, int shCount)
7814 {
7815   switch (shCount)
7816     {
7817     case 0:
7818       break;
7819     case 1:
7820       CLRC;
7821       AccAXRrl1 (x);            // 0->a:x
7822
7823       break;
7824     case 2:
7825       CLRC;
7826       AccAXRrl1 (x);            // 0->a:x
7827
7828       CLRC;
7829       AccAXRrl1 (x);            // 0->a:x
7830
7831       break;
7832     case 3:
7833     case 4:
7834     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7835
7836       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7837
7838       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7839
7840       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7841
7842       emitcode ("anl", "a,#0x%02x",
7843                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7844
7845       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7846
7847       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7848
7849       emitcode ("anl", "a,#0x%02x",
7850                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7851
7852       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7853
7854       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7855
7856       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7857
7858       break;
7859     case 6:                     // AABBBBBB:CCDDDDDD
7860
7861       emitcode ("mov", "c,acc.7");
7862       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7863
7864       emitcode ("mov", "c,acc.7");
7865       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7866
7867       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7868
7869       emitcode ("anl", "a,#0x%02x",
7870                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7871
7872       break;
7873     case 7:                     // ABBBBBBB:CDDDDDDD
7874
7875       emitcode ("mov", "c,acc.7");      // c = A
7876
7877       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7878
7879       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7880
7881       emitcode ("anl", "a,#0x%02x",
7882                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7883
7884       break;
7885     default:
7886       break;
7887     }
7888 }
7889
7890 /*-----------------------------------------------------------------*/
7891 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7892 /*-----------------------------------------------------------------*/
7893 static void
7894 AccAXRshS (char *x, int shCount)
7895 {
7896   symbol *tlbl;
7897   switch (shCount)
7898     {
7899     case 0:
7900       break;
7901     case 1:
7902       emitcode ("mov", "c,acc.7");
7903       AccAXRrl1 (x);            // s->a:x
7904
7905       break;
7906     case 2:
7907       emitcode ("mov", "c,acc.7");
7908       AccAXRrl1 (x);            // s->a:x
7909
7910       emitcode ("mov", "c,acc.7");
7911       AccAXRrl1 (x);            // s->a:x
7912
7913       break;
7914     case 3:
7915     case 4:
7916     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7917
7918       tlbl = newiTempLabel (NULL);
7919       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7920
7921       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7922
7923       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7924
7925       emitcode ("anl", "a,#0x%02x",
7926                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7927
7928       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7929
7930       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7931
7932       emitcode ("anl", "a,#0x%02x",
7933                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7934
7935       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7936
7937       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7938
7939       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7940
7941       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7942       emitcode ("orl", "a,#0x%02x",
7943                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7944
7945       emitcode ("", "%05d$:", tlbl->key + 100);
7946       break;                    // SSSSAAAA:BBBCCCCC
7947
7948     case 6:                     // AABBBBBB:CCDDDDDD
7949
7950       tlbl = newiTempLabel (NULL);
7951       emitcode ("mov", "c,acc.7");
7952       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7953
7954       emitcode ("mov", "c,acc.7");
7955       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7956
7957       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7958
7959       emitcode ("anl", "a,#0x%02x",
7960                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7961
7962       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7963       emitcode ("orl", "a,#0x%02x",
7964                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7965
7966       emitcode ("", "%05d$:", tlbl->key + 100);
7967       break;
7968     case 7:                     // ABBBBBBB:CDDDDDDD
7969
7970       tlbl = newiTempLabel (NULL);
7971       emitcode ("mov", "c,acc.7");      // c = A
7972
7973       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7974
7975       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7976
7977       emitcode ("anl", "a,#0x%02x",
7978                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7979
7980       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7981       emitcode ("orl", "a,#0x%02x",
7982                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7983
7984       emitcode ("", "%05d$:", tlbl->key + 100);
7985       break;
7986     default:
7987       break;
7988     }
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* shiftL2Left2Result - shift left two bytes from left to result   */
7993 /*-----------------------------------------------------------------*/
7994 static void
7995 shiftL2Left2Result (operand * left, int offl,
7996                     operand * result, int offr, int shCount)
7997 {
7998   if (sameRegs (AOP (result), AOP (left)) &&
7999       ((offl + MSB16) == offr))
8000     {
8001       /* don't crash result[offr] */
8002       MOVA (aopGet (left, offl, FALSE, FALSE));
8003       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8004     }
8005   else
8006     {
8007       movLeft2Result (left, offl, result, offr, 0);
8008       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8009     }
8010   /* ax << shCount (x = lsb(result)) */
8011   AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
8012   aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8013 }
8014
8015
8016 /*-----------------------------------------------------------------*/
8017 /* shiftR2Left2Result - shift right two bytes from left to result  */
8018 /*-----------------------------------------------------------------*/
8019 static void
8020 shiftR2Left2Result (operand * left, int offl,
8021                     operand * result, int offr,
8022                     int shCount, int sign)
8023 {
8024   if (sameRegs (AOP (result), AOP (left)) &&
8025       ((offl + MSB16) == offr))
8026     {
8027       /* don't crash result[offr] */
8028       MOVA (aopGet (left, offl, FALSE, FALSE));
8029       emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8030     }
8031   else
8032     {
8033       movLeft2Result (left, offl, result, offr, 0);
8034       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8035     }
8036   /* a:x >> shCount (x = lsb(result)) */
8037   if (sign)
8038     AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
8039   else
8040     AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
8041   if (getDataSize (result) > 1)
8042     aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8043 }
8044
8045 /*-----------------------------------------------------------------*/
8046 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8047 /*-----------------------------------------------------------------*/
8048 static void
8049 shiftLLeftOrResult (operand * left, int offl,
8050                     operand * result, int offr, int shCount)
8051 {
8052   MOVA (aopGet (left, offl, FALSE, FALSE));
8053   /* shift left accumulator */
8054   AccLsh (shCount);
8055   /* or with result */
8056   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8057   /* back to result */
8058   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8059 }
8060
8061 /*-----------------------------------------------------------------*/
8062 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8063 /*-----------------------------------------------------------------*/
8064 static void
8065 shiftRLeftOrResult (operand * left, int offl,
8066                     operand * result, int offr, int shCount)
8067 {
8068   MOVA (aopGet (left, offl, FALSE, FALSE));
8069   /* shift right accumulator */
8070   AccRsh (shCount);
8071   /* or with result */
8072   emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8073   /* back to result */
8074   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8075 }
8076
8077 /*-----------------------------------------------------------------*/
8078 /* genlshOne - left shift a one byte quantity by known count       */
8079 /*-----------------------------------------------------------------*/
8080 static void
8081 genlshOne (operand * result, operand * left, int shCount)
8082 {
8083   D(emitcode (";     genlshOne",""));
8084
8085   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8086 }
8087
8088 /*-----------------------------------------------------------------*/
8089 /* genlshTwo - left shift two bytes by known amount != 0           */
8090 /*-----------------------------------------------------------------*/
8091 static void
8092 genlshTwo (operand * result, operand * left, int shCount)
8093 {
8094   int size;
8095
8096   D(emitcode (";     genlshTwo",""));
8097
8098   size = getDataSize (result);
8099
8100   /* if shCount >= 8 */
8101   if (shCount >= 8)
8102     {
8103       shCount -= 8;
8104
8105       if (size > 1)
8106         {
8107           if (shCount)
8108             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8109           else
8110             movLeft2Result (left, LSB, result, MSB16, 0);
8111         }
8112       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8113     }
8114
8115   /*  1 <= shCount <= 7 */
8116   else
8117     {
8118       if (size == 1)
8119         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8120       else
8121         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8122     }
8123 }
8124
8125 /*-----------------------------------------------------------------*/
8126 /* shiftLLong - shift left one long from left to result            */
8127 /* offl = LSB or MSB16                                             */
8128 /*-----------------------------------------------------------------*/
8129 static void
8130 shiftLLong (operand * left, operand * result, int offr)
8131 {
8132   char *l;
8133   int size = AOP_SIZE (result);
8134
8135   if (size >= LSB + offr)
8136     {
8137       l = aopGet (left, LSB, FALSE, FALSE);
8138       MOVA (l);
8139       emitcode ("add", "a,acc");
8140       if (sameRegs (AOP (left), AOP (result)) &&
8141           size >= MSB16 + offr && offr != LSB)
8142         emitcode ("xch", "a,%s",
8143                   aopGet (left, LSB + offr, FALSE, FALSE));
8144       else
8145         aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8146     }
8147
8148   if (size >= MSB16 + offr)
8149     {
8150       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8151         {
8152           l = aopGet (left, MSB16, FALSE, FALSE);
8153           MOVA (l);
8154         }
8155       emitcode ("rlc", "a");
8156       if (sameRegs (AOP (left), AOP (result)) &&
8157           size >= MSB24 + offr && offr != LSB)
8158         emitcode ("xch", "a,%s",
8159                   aopGet (left, MSB16 + offr, FALSE, FALSE));
8160       else
8161         aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8162     }
8163
8164   if (size >= MSB24 + offr)
8165     {
8166       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8167         {
8168           l = aopGet (left, MSB24, FALSE, FALSE);
8169           MOVA (l);
8170         }
8171       emitcode ("rlc", "a");
8172       if (sameRegs (AOP (left), AOP (result)) &&
8173           size >= MSB32 + offr && offr != LSB)
8174         emitcode ("xch", "a,%s",
8175                   aopGet (left, MSB24 + offr, FALSE, FALSE));
8176       else
8177         aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8178     }
8179
8180   if (size > MSB32 + offr)
8181     {
8182       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8183         {
8184           l = aopGet (left, MSB32, FALSE, FALSE);
8185           MOVA (l);
8186         }
8187       emitcode ("rlc", "a");
8188       aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8189     }
8190   if (offr != LSB)
8191     aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8192 }
8193
8194 /*-----------------------------------------------------------------*/
8195 /* genlshFour - shift four byte by a known amount != 0             */
8196 /*-----------------------------------------------------------------*/
8197 static void
8198 genlshFour (operand * result, operand * left, int shCount)
8199 {
8200   int size;
8201
8202   D(emitcode (";     genlshFour",""));
8203
8204   size = AOP_SIZE (result);
8205
8206   /* if shifting more that 3 bytes */
8207   if (shCount >= 24)
8208     {
8209       shCount -= 24;
8210       if (shCount)
8211         /* lowest order of left goes to the highest
8212            order of the destination */
8213         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8214       else
8215         movLeft2Result (left, LSB, result, MSB32, 0);
8216       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8217       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8218       aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8219       return;
8220     }
8221
8222   /* more than two bytes */
8223   else if (shCount >= 16)
8224     {
8225       /* lower order two bytes goes to higher order two bytes */
8226       shCount -= 16;
8227       /* if some more remaining */
8228       if (shCount)
8229         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8230       else
8231         {
8232           movLeft2Result (left, MSB16, result, MSB32, 0);
8233           movLeft2Result (left, LSB, result, MSB24, 0);
8234         }
8235       aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8236       aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8237       return;
8238     }
8239
8240   /* if more than 1 byte */
8241   else if (shCount >= 8)
8242     {
8243       /* lower order three bytes goes to higher order  three bytes */
8244       shCount -= 8;
8245       if (size == 2)
8246         {
8247           if (shCount)
8248             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8249           else
8250             movLeft2Result (left, LSB, result, MSB16, 0);
8251         }
8252       else
8253         {                       /* size = 4 */
8254           if (shCount == 0)
8255             {
8256               movLeft2Result (left, MSB24, result, MSB32, 0);
8257               movLeft2Result (left, MSB16, result, MSB24, 0);
8258               movLeft2Result (left, LSB, result, MSB16, 0);
8259               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8260             }
8261           else if (shCount == 1)
8262             shiftLLong (left, result, MSB16);
8263           else
8264             {
8265               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8266               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8267               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8268               aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8269             }
8270         }
8271     }
8272
8273   /* 1 <= shCount <= 7 */
8274   else if (shCount <= 2)
8275     {
8276       shiftLLong (left, result, LSB);
8277       if (shCount == 2)
8278         shiftLLong (result, result, LSB);
8279     }
8280   /* 3 <= shCount <= 7, optimize */
8281   else
8282     {
8283       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8284       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8285       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8286     }
8287 }
8288
8289 /*-----------------------------------------------------------------*/
8290 /* genLeftShiftLiteral - left shifting by known count              */
8291 /*-----------------------------------------------------------------*/
8292 static void
8293 genLeftShiftLiteral (operand * left,
8294                      operand * right,
8295                      operand * result,
8296                      iCode * ic)
8297 {
8298   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8299   int size;
8300
8301   D(emitcode (";     genLeftShiftLiteral",""));
8302
8303   freeAsmop (right, NULL, ic, TRUE);
8304
8305   aopOp (left, ic, FALSE);
8306   aopOp (result, ic, FALSE);
8307
8308   size = getSize (operandType (result));
8309
8310 #if VIEW_SIZE
8311   emitcode ("; shift left ", "result %d, left %d", size,
8312             AOP_SIZE (left));
8313 #endif
8314
8315   /* I suppose that the left size >= result size */
8316   if (shCount == 0)
8317     {
8318       while (size--)
8319         {
8320           movLeft2Result (left, size, result, size, 0);
8321         }
8322     }
8323
8324   else if (shCount >= (size * 8))
8325     while (size--)
8326       aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8327   else
8328     {
8329       switch (size)
8330         {
8331         case 1:
8332           genlshOne (result, left, shCount);
8333           break;
8334
8335         case 2:
8336           genlshTwo (result, left, shCount);
8337           break;
8338
8339         case 4:
8340           genlshFour (result, left, shCount);
8341           break;
8342         default:
8343           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8344                   "*** ack! mystery literal shift!\n");
8345           break;
8346         }
8347     }
8348   freeAsmop (left, NULL, ic, TRUE);
8349   freeAsmop (result, NULL, ic, TRUE);
8350 }
8351
8352 /*-----------------------------------------------------------------*/
8353 /* genLeftShift - generates code for left shifting                 */
8354 /*-----------------------------------------------------------------*/
8355 static void
8356 genLeftShift (iCode * ic)
8357 {
8358   operand *left, *right, *result;
8359   int size, offset;
8360   char *l;
8361   symbol *tlbl, *tlbl1;
8362   bool pushedB;
8363
8364   D(emitcode (";     genLeftShift",""));
8365
8366   right = IC_RIGHT (ic);
8367   left = IC_LEFT (ic);
8368   result = IC_RESULT (ic);
8369
8370   aopOp (right, ic, FALSE);
8371
8372   /* if the shift count is known then do it
8373      as efficiently as possible */
8374   if (AOP_TYPE (right) == AOP_LIT)
8375     {
8376       genLeftShiftLiteral (left, right, result, ic);
8377       return;
8378     }
8379
8380   /* shift count is unknown then we have to form
8381      a loop get the loop count in B : Note: we take
8382      only the lower order byte since shifting
8383      more that 32 bits make no sense anyway, ( the
8384      largest size of an object can be only 32 bits ) */
8385
8386   pushedB = pushB ();
8387   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8388   emitcode ("inc", "b");
8389   freeAsmop (right, NULL, ic, TRUE);
8390   aopOp (left, ic, FALSE);
8391   aopOp (result, ic, FALSE);
8392
8393   /* now move the left to the result if they are not the same */
8394   if (!sameRegs (AOP (left), AOP (result)) &&
8395       AOP_SIZE (result) > 1)
8396     {
8397
8398       size = AOP_SIZE (result);
8399       offset = 0;
8400       while (size--)
8401         {
8402           l = aopGet (left, offset, FALSE, TRUE);
8403           if (*l == '@' && (IS_AOP_PREG (result)))
8404             {
8405
8406               emitcode ("mov", "a,%s", l);
8407               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8408             }
8409           else
8410             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8411           offset++;
8412         }
8413     }
8414
8415   tlbl = newiTempLabel (NULL);
8416   size = AOP_SIZE (result);
8417   offset = 0;
8418   tlbl1 = newiTempLabel (NULL);
8419
8420   /* if it is only one byte then */
8421   if (size == 1)
8422     {
8423       symbol *tlbl1 = newiTempLabel (NULL);
8424
8425       l = aopGet (left, 0, FALSE, FALSE);
8426       MOVA (l);
8427       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8428       emitcode ("", "%05d$:", tlbl->key + 100);
8429       emitcode ("add", "a,acc");
8430       emitcode ("", "%05d$:", tlbl1->key + 100);
8431       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8432       popB (pushedB);
8433       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8434       goto release;
8435     }
8436
8437   reAdjustPreg (AOP (result));
8438
8439   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8440   emitcode ("", "%05d$:", tlbl->key + 100);
8441   l = aopGet (result, offset, FALSE, FALSE);
8442   MOVA (l);
8443   emitcode ("add", "a,acc");
8444   aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8445   while (--size)
8446     {
8447       l = aopGet (result, offset, FALSE, FALSE);
8448       MOVA (l);
8449       emitcode ("rlc", "a");
8450       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8451     }
8452   reAdjustPreg (AOP (result));
8453
8454   emitcode ("", "%05d$:", tlbl1->key + 100);
8455   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8456   popB (pushedB);
8457 release:
8458   freeAsmop (left, NULL, ic, TRUE);
8459   freeAsmop (result, NULL, ic, TRUE);
8460 }
8461
8462 /*-----------------------------------------------------------------*/
8463 /* genrshOne - right shift a one byte quantity by known count      */
8464 /*-----------------------------------------------------------------*/
8465 static void
8466 genrshOne (operand * result, operand * left,
8467            int shCount, int sign)
8468 {
8469   D(emitcode (";     genrshOne",""));
8470
8471   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8472 }
8473
8474 /*-----------------------------------------------------------------*/
8475 /* genrshTwo - right shift two bytes by known amount != 0          */
8476 /*-----------------------------------------------------------------*/
8477 static void
8478 genrshTwo (operand * result, operand * left,
8479            int shCount, int sign)
8480 {
8481   D(emitcode (";     genrshTwo",""));
8482
8483   /* if shCount >= 8 */
8484   if (shCount >= 8)
8485     {
8486       shCount -= 8;
8487       if (shCount)
8488         shiftR1Left2Result (left, MSB16, result, LSB,
8489                             shCount, sign);
8490       else
8491         movLeft2Result (left, MSB16, result, LSB, sign);
8492       addSign (result, MSB16, sign);
8493     }
8494
8495   /*  1 <= shCount <= 7 */
8496   else
8497     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8498 }
8499
8500 /*-----------------------------------------------------------------*/
8501 /* shiftRLong - shift right one long from left to result           */
8502 /* offl = LSB or MSB16                                             */
8503 /*-----------------------------------------------------------------*/
8504 static void
8505 shiftRLong (operand * left, int offl,
8506             operand * result, int sign)
8507 {
8508   int isSameRegs=sameRegs(AOP(left),AOP(result));
8509
8510   if (isSameRegs && offl>1) {
8511     // we are in big trouble, but this shouldn't happen
8512     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8513   }
8514
8515   MOVA (aopGet (left, MSB32, FALSE, FALSE));
8516
8517   if (offl==MSB16) {
8518     // shift is > 8
8519     if (sign) {
8520       emitcode ("rlc", "a");
8521       emitcode ("subb", "a,acc");
8522       if (isSameRegs)
8523         emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8524       else {
8525         aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8526         MOVA (aopGet (left, MSB32, FALSE, FALSE));
8527       }
8528     } else {
8529       aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8530     }
8531   }
8532
8533   if (!sign) {
8534     emitcode ("clr", "c");
8535   } else {
8536     emitcode ("mov", "c,acc.7");
8537   }
8538
8539   emitcode ("rrc", "a");
8540
8541   if (isSameRegs && offl==MSB16) {
8542     emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8543   } else {
8544     aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8545     MOVA (aopGet (left, MSB24, FALSE, FALSE));
8546   }
8547
8548   emitcode ("rrc", "a");
8549   if (isSameRegs && offl==1) {
8550     emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8551   } else {
8552     aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8553     MOVA (aopGet (left, MSB16, FALSE, FALSE));
8554   }
8555   emitcode ("rrc", "a");
8556   aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8557
8558   if (offl == LSB)
8559     {
8560       MOVA (aopGet (left, LSB, FALSE, FALSE));
8561       emitcode ("rrc", "a");
8562       aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8563     }
8564 }
8565
8566 /*-----------------------------------------------------------------*/
8567 /* genrshFour - shift four byte by a known amount != 0             */
8568 /*-----------------------------------------------------------------*/
8569 static void
8570 genrshFour (operand * result, operand * left,
8571             int shCount, int sign)
8572 {
8573   D(emitcode (";     genrshFour",""));
8574
8575   /* if shifting more that 3 bytes */
8576   if (shCount >= 24)
8577     {
8578       shCount -= 24;
8579       if (shCount)
8580         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8581       else
8582         movLeft2Result (left, MSB32, result, LSB, sign);
8583       addSign (result, MSB16, sign);
8584     }
8585   else if (shCount >= 16)
8586     {
8587       shCount -= 16;
8588       if (shCount)
8589         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8590       else
8591         {
8592           movLeft2Result (left, MSB24, result, LSB, 0);
8593           movLeft2Result (left, MSB32, result, MSB16, sign);
8594         }
8595       addSign (result, MSB24, sign);
8596     }
8597   else if (shCount >= 8)
8598     {
8599       shCount -= 8;
8600       if (shCount == 1)
8601         shiftRLong (left, MSB16, result, sign);
8602       else if (shCount == 0)
8603         {
8604           movLeft2Result (left, MSB16, result, LSB, 0);
8605           movLeft2Result (left, MSB24, result, MSB16, 0);
8606           movLeft2Result (left, MSB32, result, MSB24, sign);
8607           addSign (result, MSB32, sign);
8608         }
8609       else
8610         {
8611           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8612           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8613           /* the last shift is signed */
8614           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8615           addSign (result, MSB32, sign);
8616         }
8617     }
8618   else
8619     {                           /* 1 <= shCount <= 7 */
8620       if (shCount <= 2)
8621         {
8622           shiftRLong (left, LSB, result, sign);
8623           if (shCount == 2)
8624             shiftRLong (result, LSB, result, sign);
8625         }
8626       else
8627         {
8628           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8629           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8630           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8631         }
8632     }
8633 }
8634
8635 /*-----------------------------------------------------------------*/
8636 /* genRightShiftLiteral - right shifting by known count            */
8637 /*-----------------------------------------------------------------*/
8638 static void
8639 genRightShiftLiteral (operand * left,
8640                       operand * right,
8641                       operand * result,
8642                       iCode * ic,
8643                       int sign)
8644 {
8645   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8646   int size;
8647
8648   D(emitcode (";     genRightShiftLiteral",""));
8649
8650   freeAsmop (right, NULL, ic, TRUE);
8651
8652   aopOp (left, ic, FALSE);
8653   aopOp (result, ic, FALSE);
8654
8655 #if VIEW_SIZE
8656   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8657             AOP_SIZE (left));
8658 #endif
8659
8660   size = getDataSize (left);
8661   /* test the LEFT size !!! */
8662
8663   /* I suppose that the left size >= result size */
8664   if (shCount == 0)
8665     {
8666       size = getDataSize (result);
8667       while (size--)
8668         movLeft2Result (left, size, result, size, 0);
8669     }
8670
8671   else if (shCount >= (size * 8))
8672     {
8673       if (sign) {
8674         /* get sign in acc.7 */
8675         MOVA (aopGet (left, size - 1, FALSE, FALSE));
8676       }
8677       addSign (result, LSB, sign);
8678     }
8679   else
8680     {
8681       switch (size)
8682         {
8683         case 1:
8684           genrshOne (result, left, shCount, sign);
8685           break;
8686
8687         case 2:
8688           genrshTwo (result, left, shCount, sign);
8689           break;
8690
8691         case 4:
8692           genrshFour (result, left, shCount, sign);
8693           break;
8694         default:
8695           break;
8696         }
8697     }
8698   freeAsmop (left, NULL, ic, TRUE);
8699   freeAsmop (result, NULL, ic, TRUE);
8700 }
8701
8702 /*-----------------------------------------------------------------*/
8703 /* genSignedRightShift - right shift of signed number              */
8704 /*-----------------------------------------------------------------*/
8705 static void
8706 genSignedRightShift (iCode * ic)
8707 {
8708   operand *right, *left, *result;
8709   int size, offset;
8710   char *l;
8711   symbol *tlbl, *tlbl1;
8712   bool pushedB;
8713
8714   D(emitcode (";     genSignedRightShift",""));
8715
8716   /* we do it the hard way put the shift count in b
8717      and loop thru preserving the sign */
8718
8719   right = IC_RIGHT (ic);
8720   left = IC_LEFT (ic);
8721   result = IC_RESULT (ic);
8722
8723   aopOp (right, ic, FALSE);
8724
8725
8726   if (AOP_TYPE (right) == AOP_LIT)
8727     {
8728       genRightShiftLiteral (left, right, result, ic, 1);
8729       return;
8730     }
8731   /* shift count is unknown then we have to form
8732      a loop get the loop count in B : Note: we take
8733      only the lower order byte since shifting
8734      more that 32 bits make no sense anyway, ( the
8735      largest size of an object can be only 32 bits ) */
8736
8737   pushedB = pushB ();
8738   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8739   emitcode ("inc", "b");
8740   freeAsmop (right, NULL, ic, TRUE);
8741   aopOp (left, ic, FALSE);
8742   aopOp (result, ic, FALSE);
8743
8744   /* now move the left to the result if they are not the
8745      same */
8746   if (!sameRegs (AOP (left), AOP (result)) &&
8747       AOP_SIZE (result) > 1)
8748     {
8749
8750       size = AOP_SIZE (result);
8751       offset = 0;
8752       while (size--)
8753         {
8754           l = aopGet (left, offset, FALSE, TRUE);
8755           if (*l == '@' && IS_AOP_PREG (result))
8756             {
8757
8758               emitcode ("mov", "a,%s", l);
8759               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8760             }
8761           else
8762             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8763           offset++;
8764         }
8765     }
8766
8767   /* mov the highest order bit to OVR */
8768   tlbl = newiTempLabel (NULL);
8769   tlbl1 = newiTempLabel (NULL);
8770
8771   size = AOP_SIZE (result);
8772   offset = size - 1;
8773   MOVA (aopGet (left, offset, FALSE, FALSE));
8774   emitcode ("rlc", "a");
8775   emitcode ("mov", "ov,c");
8776   /* if it is only one byte then */
8777   if (size == 1)
8778     {
8779       l = aopGet (left, 0, FALSE, FALSE);
8780       MOVA (l);
8781       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8782       emitcode ("", "%05d$:", tlbl->key + 100);
8783       emitcode ("mov", "c,ov");
8784       emitcode ("rrc", "a");
8785       emitcode ("", "%05d$:", tlbl1->key + 100);
8786       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8787       popB (pushedB);
8788       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8789       goto release;
8790     }
8791
8792   reAdjustPreg (AOP (result));
8793   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8794   emitcode ("", "%05d$:", tlbl->key + 100);
8795   emitcode ("mov", "c,ov");
8796   while (size--)
8797     {
8798       l = aopGet (result, offset, FALSE, FALSE);
8799       MOVA (l);
8800       emitcode ("rrc", "a");
8801       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8802     }
8803   reAdjustPreg (AOP (result));
8804   emitcode ("", "%05d$:", tlbl1->key + 100);
8805   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8806   popB (pushedB);
8807
8808 release:
8809   freeAsmop (left, NULL, ic, TRUE);
8810   freeAsmop (result, NULL, ic, TRUE);
8811 }
8812
8813 /*-----------------------------------------------------------------*/
8814 /* genRightShift - generate code for right shifting                */
8815 /*-----------------------------------------------------------------*/
8816 static void
8817 genRightShift (iCode * ic)
8818 {
8819   operand *right, *left, *result;
8820   sym_link *letype;
8821   int size, offset;
8822   char *l;
8823   symbol *tlbl, *tlbl1;
8824   bool pushedB;
8825
8826   D(emitcode (";     genRightShift",""));
8827
8828   /* if signed then we do it the hard way preserve the
8829      sign bit moving it inwards */
8830   letype = getSpec (operandType (IC_LEFT (ic)));
8831
8832   if (!SPEC_USIGN (letype))
8833     {
8834       genSignedRightShift (ic);
8835       return;
8836     }
8837
8838   /* signed & unsigned types are treated the same : i.e. the
8839      signed is NOT propagated inwards : quoting from the
8840      ANSI - standard : "for E1 >> E2, is equivalent to division
8841      by 2**E2 if unsigned or if it has a non-negative value,
8842      otherwise the result is implementation defined ", MY definition
8843      is that the sign does not get propagated */
8844
8845   right = IC_RIGHT (ic);
8846   left = IC_LEFT (ic);
8847   result = IC_RESULT (ic);
8848
8849   aopOp (right, ic, FALSE);
8850
8851   /* if the shift count is known then do it
8852      as efficiently as possible */
8853   if (AOP_TYPE (right) == AOP_LIT)
8854     {
8855       genRightShiftLiteral (left, right, result, ic, 0);
8856       return;
8857     }
8858
8859   /* shift count is unknown then we have to form
8860      a loop get the loop count in B : Note: we take
8861      only the lower order byte since shifting
8862      more that 32 bits make no sense anyway, ( the
8863      largest size of an object can be only 32 bits ) */
8864
8865   pushedB = pushB ();
8866   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8867   emitcode ("inc", "b");
8868   freeAsmop (right, NULL, ic, TRUE);
8869   aopOp (left, ic, FALSE);
8870   aopOp (result, ic, FALSE);
8871
8872   /* now move the left to the result if they are not the
8873      same */
8874   if (!sameRegs (AOP (left), AOP (result)) &&
8875       AOP_SIZE (result) > 1)
8876     {
8877
8878       size = AOP_SIZE (result);
8879       offset = 0;
8880       while (size--)
8881         {
8882           l = aopGet (left, offset, FALSE, TRUE);
8883           if (*l == '@' && IS_AOP_PREG (result))
8884             {
8885
8886               emitcode ("mov", "a,%s", l);
8887               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8888             }
8889           else
8890             aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8891           offset++;
8892         }
8893     }
8894
8895   tlbl = newiTempLabel (NULL);
8896   tlbl1 = newiTempLabel (NULL);
8897   size = AOP_SIZE (result);
8898   offset = size - 1;
8899
8900   /* if it is only one byte then */
8901   if (size == 1)
8902     {
8903       l = aopGet (left, 0, FALSE, FALSE);
8904       MOVA (l);
8905       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8906       emitcode ("", "%05d$:", tlbl->key + 100);
8907       CLRC;
8908       emitcode ("rrc", "a");
8909       emitcode ("", "%05d$:", tlbl1->key + 100);
8910       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8911       popB (pushedB);
8912       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8913       goto release;
8914     }
8915
8916   reAdjustPreg (AOP (result));
8917   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8918   emitcode ("", "%05d$:", tlbl->key + 100);
8919   CLRC;
8920   while (size--)
8921     {
8922       l = aopGet (result, offset, FALSE, FALSE);
8923       MOVA (l);
8924       emitcode ("rrc", "a");
8925       aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8926     }
8927   reAdjustPreg (AOP (result));
8928
8929   emitcode ("", "%05d$:", tlbl1->key + 100);
8930   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8931   popB (pushedB);
8932
8933 release:
8934   freeAsmop (left, NULL, ic, TRUE);
8935   freeAsmop (result, NULL, ic, TRUE);
8936 }
8937
8938 /*-----------------------------------------------------------------*/
8939 /* emitPtrByteGet - emits code to get a byte into A through a      */
8940 /*                  pointer register (R0, R1, or DPTR). The        */
8941 /*                  original value of A can be preserved in B.     */
8942 /*-----------------------------------------------------------------*/
8943 static void
8944 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8945 {
8946   switch (p_type)
8947     {
8948     case IPOINTER:
8949     case POINTER:
8950       if (preserveAinB)
8951         emitcode ("mov", "b,a");
8952       emitcode ("mov", "a,@%s", rname);
8953       break;
8954
8955     case PPOINTER:
8956       if (preserveAinB)
8957         emitcode ("mov", "b,a");
8958       emitcode ("movx", "a,@%s", rname);
8959       break;
8960
8961     case FPOINTER:
8962       if (preserveAinB)
8963         emitcode ("mov", "b,a");
8964       emitcode ("movx", "a,@dptr");
8965       break;
8966
8967     case CPOINTER:
8968       if (preserveAinB)
8969         emitcode ("mov", "b,a");
8970       emitcode ("clr", "a");
8971       emitcode ("movc", "a,@a+dptr");
8972       break;
8973
8974     case GPOINTER:
8975       if (preserveAinB)
8976         {
8977           emitcode ("push", "b");
8978           emitcode ("push", "acc");
8979         }
8980       emitcode ("lcall", "__gptrget");
8981       if (preserveAinB)
8982         emitcode ("pop", "b");
8983       break;
8984     }
8985 }
8986
8987 /*-----------------------------------------------------------------*/
8988 /* emitPtrByteSet - emits code to set a byte from src through a    */
8989 /*                  pointer register (R0, R1, or DPTR).            */
8990 /*-----------------------------------------------------------------*/
8991 static void
8992 emitPtrByteSet (char *rname, int p_type, char *src)
8993 {
8994   switch (p_type)
8995     {
8996     case IPOINTER:
8997     case POINTER:
8998       if (*src=='@')
8999         {
9000           MOVA (src);
9001           emitcode ("mov", "@%s,a", rname);
9002         }
9003       else
9004         emitcode ("mov", "@%s,%s", rname, src);
9005       break;
9006
9007     case PPOINTER:
9008       MOVA (src);
9009       emitcode ("movx", "@%s,a", rname);
9010       break;
9011
9012     case FPOINTER:
9013       MOVA (src);
9014       emitcode ("movx", "@dptr,a");
9015       break;
9016
9017     case GPOINTER:
9018       MOVA (src);
9019       emitcode ("lcall", "__gptrput");
9020       break;
9021     }
9022 }
9023
9024 /*-----------------------------------------------------------------*/
9025 /* genUnpackBits - generates code for unpacking bits               */
9026 /*-----------------------------------------------------------------*/
9027 static void
9028 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9029 {
9030   int offset = 0;       /* result byte offset */
9031   int rsize;            /* result size */
9032   int rlen = 0;         /* remaining bitfield length */
9033   sym_link *etype;      /* bitfield type information */
9034   int blen;             /* bitfield length */
9035   int bstr;             /* bitfield starting bit within byte */
9036   char buffer[10];
9037
9038   D(emitcode (";     genUnpackBits",""));
9039
9040   etype = getSpec (operandType (result));
9041   rsize = getSize (operandType (result));
9042   blen = SPEC_BLEN (etype);
9043   bstr = SPEC_BSTR (etype);
9044
9045   if (ifx && blen <= 8)
9046     {
9047       emitPtrByteGet (rname, ptype, FALSE);
9048       if (blen == 1)
9049         {
9050           SNPRINTF (buffer, sizeof(buffer),
9051                     "acc.%d", bstr);
9052           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9053         }
9054       else
9055         {
9056           if (blen < 8)
9057             emitcode ("anl", "a,#0x%02x",
9058                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9059           genIfxJump (ifx, "a", NULL, NULL, NULL);
9060         }
9061       return;
9062     }
9063   wassert (!ifx);
9064
9065   /* If the bitfield length is less than a byte */
9066   if (blen < 8)
9067     {
9068       emitPtrByteGet (rname, ptype, FALSE);
9069       AccRsh (bstr);
9070       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9071       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9072       goto finish;
9073     }
9074
9075   /* Bit field did not fit in a byte. Copy all
9076      but the partial byte at the end.  */
9077   for (rlen=blen;rlen>=8;rlen-=8)
9078     {
9079       emitPtrByteGet (rname, ptype, FALSE);
9080       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9081       if (rlen>8)
9082         emitcode ("inc", "%s", rname);
9083     }
9084
9085   /* Handle the partial byte at the end */
9086   if (rlen)
9087     {
9088       emitPtrByteGet (rname, ptype, FALSE);
9089       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9090       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9091     }
9092
9093 finish:
9094   if (offset < rsize)
9095     {
9096       rsize -= offset;
9097       while (rsize--)
9098         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
9099     }
9100 }
9101
9102
9103 /*-----------------------------------------------------------------*/
9104 /* genDataPointerGet - generates code when ptr offset is known     */
9105 /*-----------------------------------------------------------------*/
9106 static void
9107 genDataPointerGet (operand * left,
9108                    operand * result,
9109                    iCode * ic)
9110 {
9111   char *l;
9112   char buffer[256];
9113   int size, offset = 0;
9114
9115   D(emitcode (";     genDataPointerGet",""));
9116
9117   aopOp (result, ic, TRUE);
9118
9119   /* get the string representation of the name */
9120   l = aopGet (left, 0, FALSE, TRUE);
9121   size = AOP_SIZE (result);
9122   while (size--)
9123     {
9124       if (offset)
9125         sprintf (buffer, "(%s + %d)", l + 1, offset);
9126       else
9127         sprintf (buffer, "%s", l + 1);
9128       aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9129     }
9130
9131   freeAsmop (left, NULL, ic, TRUE);
9132   freeAsmop (result, NULL, ic, TRUE);
9133 }
9134
9135 /*-----------------------------------------------------------------*/
9136 /* genNearPointerGet - emitcode for near pointer fetch             */
9137 /*-----------------------------------------------------------------*/
9138 static void
9139 genNearPointerGet (operand * left,
9140                    operand * result,
9141                    iCode * ic,
9142                    iCode * pi,
9143                    iCode * ifx)
9144 {
9145   asmop *aop = NULL;
9146   regs *preg = NULL;
9147   char *rname;
9148   sym_link *rtype, *retype;
9149   sym_link *ltype = operandType (left);
9150   char buffer[80];
9151
9152   D(emitcode (";     genNearPointerGet",""));
9153
9154   rtype = operandType (result);
9155   retype = getSpec (rtype);
9156
9157   aopOp (left, ic, FALSE);
9158
9159   /* if left is rematerialisable and
9160      result is not bitfield variable type and
9161      the left is pointer to data space i.e
9162      lower 128 bytes of space */
9163   if (AOP_TYPE (left) == AOP_IMMD &&
9164       !IS_BITFIELD (retype) &&
9165       DCL_TYPE (ltype) == POINTER)
9166     {
9167       genDataPointerGet (left, result, ic);
9168       return;
9169     }
9170
9171  /* if the value is already in a pointer register
9172      then don't need anything more */
9173   if (!AOP_INPREG (AOP (left)))
9174     {
9175       if (IS_AOP_PREG (left))
9176         {
9177           // Aha, it is a pointer, just in disguise.
9178           rname = aopGet (left, 0, FALSE, FALSE);
9179           if (*rname != '@')
9180             {
9181               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9182                       __FILE__, __LINE__);
9183             }
9184           else
9185             {
9186               // Expected case.
9187               emitcode ("mov", "a%s,%s", rname + 1, rname);
9188               rname++;  // skip the '@'.
9189             }
9190         }
9191       else
9192         {
9193           /* otherwise get a free pointer register */
9194           aop = newAsmop (0);
9195           preg = getFreePtr (ic, &aop, FALSE);
9196           emitcode ("mov", "%s,%s",
9197                     preg->name,
9198                     aopGet (left, 0, FALSE, TRUE));
9199           rname = preg->name;
9200         }
9201     }
9202   else
9203     rname = aopGet (left, 0, FALSE, FALSE);
9204
9205   //aopOp (result, ic, FALSE);
9206   aopOp (result, ic, result?TRUE:FALSE);
9207
9208   /* if bitfield then unpack the bits */
9209   if (IS_BITFIELD (retype))
9210     genUnpackBits (result, rname, POINTER, ifx);
9211   else
9212     {
9213       /* we have can just get the values */
9214       int size = AOP_SIZE (result);
9215       int offset = 0;
9216
9217       while (size--)
9218         {
9219           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9220             {
9221
9222               emitcode ("mov", "a,@%s", rname);
9223               if (!ifx)
9224               aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9225             }
9226           else
9227             {
9228               sprintf (buffer, "@%s", rname);
9229               aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9230             }
9231           offset++;
9232           if (size || pi)
9233             emitcode ("inc", "%s", rname);
9234         }
9235     }
9236
9237   /* now some housekeeping stuff */
9238   if (aop)       /* we had to allocate for this iCode */
9239     {
9240       if (pi) { /* post increment present */
9241         aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9242       }
9243       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9244     }
9245   else
9246     {
9247       /* we did not allocate which means left
9248          already in a pointer register, then
9249          if size > 0 && this could be used again
9250          we have to point it back to where it
9251          belongs */
9252       if ((AOP_SIZE (result) > 1 &&
9253            !OP_SYMBOL (left)->remat &&
9254            (OP_SYMBOL (left)->liveTo > ic->seq ||
9255             ic->depth)) &&
9256           !pi)
9257         {
9258           int size = AOP_SIZE (result) - 1;
9259           while (size--)
9260             emitcode ("dec", "%s", rname);
9261         }
9262     }
9263
9264   if (ifx && !ifx->generated)
9265     {
9266       genIfxJump (ifx, "a", left, NULL, result);
9267     }
9268
9269   /* done */
9270   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9271   freeAsmop (left, NULL, ic, TRUE);
9272   if (pi) pi->generated = 1;
9273 }
9274
9275 /*-----------------------------------------------------------------*/
9276 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9277 /*-----------------------------------------------------------------*/
9278 static void
9279 genPagedPointerGet (operand * left,
9280                     operand * result,
9281                     iCode * ic,
9282                     iCode *pi,
9283                     iCode *ifx)
9284 {
9285   asmop *aop = NULL;
9286   regs *preg = NULL;
9287   char *rname;
9288   sym_link *rtype, *retype;
9289
9290   D(emitcode (";     genPagedPointerGet",""));
9291
9292   rtype = operandType (result);
9293   retype = getSpec (rtype);
9294
9295   aopOp (left, ic, FALSE);
9296
9297   /* if the value is already in a pointer register
9298      then don't need anything more */
9299   if (!AOP_INPREG (AOP (left)))
9300     {
9301       /* otherwise get a free pointer register */
9302       aop = newAsmop (0);
9303       preg = getFreePtr (ic, &aop, FALSE);
9304       emitcode ("mov", "%s,%s",
9305                 preg->name,
9306                 aopGet (left, 0, FALSE, TRUE));
9307       rname = preg->name;
9308     }
9309   else
9310     rname = aopGet (left, 0, FALSE, FALSE);
9311
9312   aopOp (result, ic, FALSE);
9313
9314   /* if bitfield then unpack the bits */
9315   if (IS_BITFIELD (retype))
9316     genUnpackBits (result, rname, PPOINTER, ifx);
9317   else
9318     {
9319       /* we have can just get the values */
9320       int size = AOP_SIZE (result);
9321       int offset = 0;
9322
9323       while (size--)
9324         {
9325
9326           emitcode ("movx", "a,@%s", rname);
9327           if (!ifx)
9328           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9329
9330           offset++;
9331
9332           if (size || pi)
9333             emitcode ("inc", "%s", rname);
9334         }
9335     }
9336
9337   /* now some housekeeping stuff */
9338   if (aop) /* we had to allocate for this iCode */
9339     {
9340       if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9341       freeAsmop (NULL, aop, ic, TRUE);
9342     }
9343   else
9344     {
9345       /* we did not allocate which means left
9346          already in a pointer register, then
9347          if size > 0 && this could be used again
9348          we have to point it back to where it
9349          belongs */
9350       if ((AOP_SIZE (result) > 1 &&
9351            !OP_SYMBOL (left)->remat &&
9352            (OP_SYMBOL (left)->liveTo > ic->seq ||
9353             ic->depth)) &&
9354           !pi)
9355         {
9356           int size = AOP_SIZE (result) - 1;
9357           while (size--)
9358             emitcode ("dec", "%s", rname);
9359         }
9360     }
9361
9362   if (ifx && !ifx->generated)
9363     {
9364       genIfxJump (ifx, "a", left, NULL, result);
9365     }
9366
9367   /* done */
9368   freeAsmop (left, NULL, ic, TRUE);
9369   freeAsmop (result, NULL, ic, TRUE);
9370   if (pi) pi->generated = 1;
9371
9372 }
9373
9374 /*--------------------------------------------------------------------*/
9375 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9376 /*--------------------------------------------------------------------*/
9377 static void
9378 loadDptrFromOperand (operand *op, bool loadBToo)
9379 {
9380   if (AOP_TYPE (op) != AOP_STR)
9381     {
9382       /* if this is rematerializable */
9383       if (AOP_TYPE (op) == AOP_IMMD)
9384         {
9385           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9386           if (loadBToo)
9387             {
9388               if (AOP(op)->aopu.aop_immd.from_cast_remat)
9389                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9390               else
9391                 {
9392                   wassertl(FALSE, "need pointerCode");
9393                   emitcode ("", "; mov b,???");
9394                   /* genPointerGet and genPointerSet originally did different
9395                   ** things for this case. Both seem wrong.
9396                   ** from genPointerGet:
9397                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
9398                   ** from genPointerSet:
9399                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9400                   */
9401                 }
9402             }
9403         }
9404       else if (AOP_TYPE (op) == AOP_DPTR)
9405         {
9406           if (loadBToo)
9407             {
9408               MOVA (aopGet (op, 0, FALSE, FALSE));
9409               emitcode ("push", "acc");
9410               MOVA (aopGet (op, 1, FALSE, FALSE));
9411               emitcode ("push", "acc");
9412               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9413               emitcode ("pop", "dph");
9414               emitcode ("pop", "dpl");
9415             }
9416           else
9417             {
9418               MOVA (aopGet (op, 0, FALSE, FALSE));
9419               emitcode ("push", "acc");
9420               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9421               emitcode ("pop", "dpl");
9422             }
9423         }
9424       else
9425         {                       /* we need to get it byte by byte */
9426           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9427           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9428           if (loadBToo)
9429             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9430         }
9431     }
9432 }
9433
9434 /*-----------------------------------------------------------------*/
9435 /* genFarPointerGet - gget value from far space                    */
9436 /*-----------------------------------------------------------------*/
9437 static void
9438 genFarPointerGet (operand * left,
9439                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
9440 {
9441   int size, offset;
9442   sym_link *retype = getSpec (operandType (result));
9443
9444   D(emitcode (";     genFarPointerGet",""));
9445
9446   aopOp (left, ic, FALSE);
9447   loadDptrFromOperand (left, FALSE);
9448
9449   /* so dptr now contains the address */
9450   aopOp (result, ic, FALSE);
9451
9452   /* if bit then unpack */
9453   if (IS_BITFIELD (retype))
9454     genUnpackBits (result, "dptr", FPOINTER, ifx);
9455   else
9456     {
9457       size = AOP_SIZE (result);
9458       offset = 0;
9459
9460       while (size--)
9461         {
9462           emitcode ("movx", "a,@dptr");
9463           if (!ifx)
9464             aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9465           if (size || pi)
9466             emitcode ("inc", "dptr");
9467         }
9468     }
9469
9470   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9471     {
9472     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9473     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9474     pi->generated = 1;
9475   }
9476
9477   if (ifx && !ifx->generated)
9478     {
9479       genIfxJump (ifx, "a", left, NULL, result);
9480     }
9481
9482   freeAsmop (left, NULL, ic, TRUE);
9483   freeAsmop (result, NULL, ic, TRUE);
9484 }
9485
9486 /*-----------------------------------------------------------------*/
9487 /* genCodePointerGet - gget value from code space                  */
9488 /*-----------------------------------------------------------------*/
9489 static void
9490 genCodePointerGet (operand * left,
9491                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
9492 {
9493   int size, offset;
9494   sym_link *retype = getSpec (operandType (result));
9495
9496   D(emitcode (";     genCodePointerGet",""));
9497
9498   aopOp (left, ic, FALSE);
9499   loadDptrFromOperand (left, FALSE);
9500
9501   /* so dptr now contains the address */
9502   aopOp (result, ic, FALSE);
9503
9504   /* if bit then unpack */
9505   if (IS_BITFIELD (retype))
9506     genUnpackBits (result, "dptr", CPOINTER, ifx);
9507   else
9508     {
9509       size = AOP_SIZE (result);
9510       offset = 0;
9511
9512       while (size--)
9513         {
9514           if (pi)
9515             {
9516               emitcode ("clr", "a");
9517               emitcode ("movc", "a,@a+dptr");
9518               if (!ifx)
9519               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9520               emitcode ("inc", "dptr");
9521             }
9522           else
9523             {
9524               emitcode ("mov", "a,#0x%02x", offset);
9525               emitcode ("movc", "a,@a+dptr");
9526               if (!ifx)
9527               aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9528             }
9529         }
9530     }
9531
9532   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9533     {
9534     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9535     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9536     pi->generated = 1;
9537   }
9538
9539   if (ifx && !ifx->generated)
9540     {
9541       genIfxJump (ifx, "a", left, NULL, result);
9542     }
9543
9544   freeAsmop (left, NULL, ic, TRUE);
9545   freeAsmop (result, NULL, ic, TRUE);
9546 }
9547
9548 /*-----------------------------------------------------------------*/
9549 /* genGenPointerGet - gget value from generic pointer space        */
9550 /*-----------------------------------------------------------------*/
9551 static void
9552 genGenPointerGet (operand * left,
9553                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
9554 {
9555   int size, offset;
9556   sym_link *retype = getSpec (operandType (result));
9557
9558   D(emitcode (";     genGenPointerGet",""));
9559
9560   aopOp (left, ic, FALSE);
9561   loadDptrFromOperand (left, TRUE);
9562
9563   /* so dptr know contains the address */
9564   aopOp (result, ic, FALSE);
9565
9566   /* if bit then unpack */
9567   if (IS_BITFIELD (retype))
9568     genUnpackBits (result, "dptr", GPOINTER, ifx);
9569   else
9570     {
9571       size = AOP_SIZE (result);
9572       offset = 0;
9573
9574       while (size--)
9575         {
9576           emitcode ("lcall", "__gptrget");
9577           if (!ifx)
9578           aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9579           if (size || pi)
9580             emitcode ("inc", "dptr");
9581         }
9582     }
9583
9584   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9585     {
9586     aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9587     aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9588     pi->generated = 1;
9589   }
9590
9591   if (ifx && !ifx->generated)
9592     {
9593       genIfxJump (ifx, "a", left, NULL, result);
9594     }
9595
9596
9597   freeAsmop (left, NULL, ic, TRUE);
9598   freeAsmop (result, NULL, ic, TRUE);
9599 }
9600
9601 /*-----------------------------------------------------------------*/
9602 /* genPointerGet - generate code for pointer get                   */
9603 /*-----------------------------------------------------------------*/
9604 static void
9605 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9606 {
9607   operand *left, *result;
9608   sym_link *type, *etype;
9609   int p_type;
9610
9611   D(emitcode (";     genPointerGet",""));
9612
9613   left = IC_LEFT (ic);
9614   result = IC_RESULT (ic);
9615
9616   if (getSize (operandType (result))>1)
9617     ifx = NULL;
9618
9619   /* depending on the type of pointer we need to
9620      move it to the correct pointer register */
9621   type = operandType (left);
9622   etype = getSpec (type);
9623   /* if left is of type of pointer then it is simple */
9624   if (IS_PTR (type) && !IS_FUNC (type->next))
9625     p_type = DCL_TYPE (type);
9626   else
9627     {
9628       /* we have to go by the storage class */
9629       p_type = PTR_TYPE (SPEC_OCLS (etype));
9630     }
9631
9632   /* special case when cast remat */
9633   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9634       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9635           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9636           type = operandType (left);
9637           p_type = DCL_TYPE (type);
9638   }
9639   /* now that we have the pointer type we assign
9640      the pointer values */
9641   switch (p_type)
9642     {
9643
9644     case POINTER:
9645     case IPOINTER:
9646       genNearPointerGet (left, result, ic, pi, ifx);
9647       break;
9648
9649     case PPOINTER:
9650       genPagedPointerGet (left, result, ic, pi, ifx);
9651       break;
9652
9653     case FPOINTER:
9654       genFarPointerGet (left, result, ic, pi, ifx);
9655       break;
9656
9657     case CPOINTER:
9658       genCodePointerGet (left, result, ic, pi, ifx);
9659       break;
9660
9661     case GPOINTER:
9662       genGenPointerGet (left, result, ic, pi, ifx);
9663       break;
9664     }
9665
9666 }
9667
9668
9669
9670 /*-----------------------------------------------------------------*/
9671 /* genPackBits - generates code for packed bit storage             */
9672 /*-----------------------------------------------------------------*/
9673 static void
9674 genPackBits (sym_link * etype,
9675              operand * right,
9676              char *rname, int p_type)
9677 {
9678   int offset = 0;       /* source byte offset */
9679   int rlen = 0;         /* remaining bitfield length */
9680   int blen;             /* bitfield length */
9681   int bstr;             /* bitfield starting bit within byte */
9682   int litval;           /* source literal value (if AOP_LIT) */
9683   unsigned char mask;   /* bitmask within current byte */
9684
9685   D(emitcode (";     genPackBits",""));
9686
9687   blen = SPEC_BLEN (etype);
9688   bstr = SPEC_BSTR (etype);
9689
9690   /* If the bitfield length is less than a byte */
9691   if (blen < 8)
9692     {
9693       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9694               (unsigned char) (0xFF >> (8 - bstr)));
9695
9696       if (AOP_TYPE (right) == AOP_LIT)
9697         {
9698           /* Case with a bitfield length <8 and literal source
9699           */
9700           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9701           litval <<= bstr;
9702           litval &= (~mask) & 0xff;
9703           emitPtrByteGet (rname, p_type, FALSE);
9704           if ((mask|litval)!=0xff)
9705             emitcode ("anl","a,#0x%02x", mask);
9706           if (litval)
9707             emitcode ("orl","a,#0x%02x", litval);
9708         }
9709       else
9710         {
9711           if ((blen==1) && (p_type!=GPOINTER))
9712             {
9713               /* Case with a bitfield length == 1 and no generic pointer
9714               */
9715               if (AOP_TYPE (right) == AOP_CRY)
9716                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9717               else
9718                 {
9719                   MOVA (aopGet (right, 0, FALSE, FALSE));
9720                   emitcode ("rrc","a");
9721                 }
9722               emitPtrByteGet (rname, p_type, FALSE);
9723               emitcode ("mov","acc.%d,c",bstr);
9724             }
9725           else
9726             {
9727               bool pushedB;
9728               /* Case with a bitfield length < 8 and arbitrary source
9729               */
9730               MOVA (aopGet (right, 0, FALSE, FALSE));
9731               /* shift and mask source value */
9732               AccLsh (bstr);
9733               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9734
9735               pushedB = pushB ();
9736               /* transfer A to B and get next byte */
9737               emitPtrByteGet (rname, p_type, TRUE);
9738
9739               emitcode ("anl", "a,#0x%02x", mask);
9740               emitcode ("orl", "a,b");
9741               if (p_type == GPOINTER)
9742                 emitcode ("pop", "b");
9743
9744               popB (pushedB);
9745            }
9746         }
9747
9748       emitPtrByteSet (rname, p_type, "a");
9749       return;
9750     }
9751
9752   /* Bit length is greater than 7 bits. In this case, copy  */
9753   /* all except the partial byte at the end                 */
9754   for (rlen=blen;rlen>=8;rlen-=8)
9755     {
9756       emitPtrByteSet (rname, p_type,
9757                       aopGet (right, offset++, FALSE, TRUE) );
9758       if (rlen>8)
9759         emitcode ("inc", "%s", rname);
9760     }
9761
9762   /* If there was a partial byte at the end */
9763   if (rlen)
9764     {
9765       mask = (((unsigned char) -1 << rlen) & 0xff);
9766
9767       if (AOP_TYPE (right) == AOP_LIT)
9768         {
9769           /* Case with partial byte and literal source
9770           */
9771           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9772           litval >>= (blen-rlen);
9773           litval &= (~mask) & 0xff;
9774           emitPtrByteGet (rname, p_type, FALSE);
9775           if ((mask|litval)!=0xff)
9776             emitcode ("anl","a,#0x%02x", mask);
9777           if (litval)
9778             emitcode ("orl","a,#0x%02x", litval);
9779         }
9780       else
9781         {
9782           bool pushedB;
9783           /* Case with partial byte and arbitrary source
9784           */
9785           MOVA (aopGet (right, offset++, FALSE, FALSE));
9786           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9787
9788           pushedB = pushB ();
9789           /* transfer A to B and get next byte */
9790           emitPtrByteGet (rname, p_type, TRUE);
9791
9792           emitcode ("anl", "a,#0x%02x", mask);
9793           emitcode ("orl", "a,b");
9794           if (p_type == GPOINTER)
9795             emitcode ("pop", "b");
9796
9797           popB (pushedB);
9798         }
9799       emitPtrByteSet (rname, p_type, "a");
9800     }
9801
9802 }
9803
9804
9805 /*-----------------------------------------------------------------*/
9806 /* genDataPointerSet - remat pointer to data space                 */
9807 /*-----------------------------------------------------------------*/
9808 static void
9809 genDataPointerSet (operand * right,
9810                    operand * result,
9811                    iCode * ic)
9812 {
9813   int size, offset = 0;
9814   char *l, buffer[256];
9815
9816   D(emitcode (";     genDataPointerSet",""));
9817
9818   aopOp (right, ic, FALSE);
9819
9820   l = aopGet (result, 0, FALSE, TRUE);
9821   size = AOP_SIZE (right);
9822   while (size--)
9823     {
9824       if (offset)
9825         sprintf (buffer, "(%s + %d)", l + 1, offset);
9826       else
9827         sprintf (buffer, "%s", l + 1);
9828       emitcode ("mov", "%s,%s", buffer,
9829                 aopGet (right, offset++, FALSE, FALSE));
9830     }
9831
9832   freeAsmop (right, NULL, ic, TRUE);
9833   freeAsmop (result, NULL, ic, TRUE);
9834 }
9835
9836 /*-----------------------------------------------------------------*/
9837 /* genNearPointerSet - emitcode for near pointer put                */
9838 /*-----------------------------------------------------------------*/
9839 static void
9840 genNearPointerSet (operand * right,
9841                    operand * result,
9842                    iCode * ic,
9843                    iCode * pi)
9844 {
9845   asmop *aop = NULL;
9846   regs *preg = NULL;
9847   char *rname, *l;
9848   sym_link *retype, *letype;
9849   sym_link *ptype = operandType (result);
9850
9851   D(emitcode (";     genNearPointerSet",""));
9852
9853   retype = getSpec (operandType (right));
9854   letype = getSpec (ptype);
9855   aopOp (result, ic, FALSE);
9856
9857   /* if the result is rematerializable &
9858      in data space & not a bit variable */
9859   if (AOP_TYPE (result) == AOP_IMMD &&
9860       DCL_TYPE (ptype) == POINTER &&
9861       !IS_BITVAR (retype) &&
9862       !IS_BITVAR (letype))
9863     {
9864       genDataPointerSet (right, result, ic);
9865       return;
9866     }
9867
9868   /* if the value is already in a pointer register
9869      then don't need anything more */
9870   if (!AOP_INPREG (AOP (result)))
9871     {
9872         if (
9873             //AOP_TYPE (result) == AOP_STK
9874             IS_AOP_PREG(result)
9875             )
9876         {
9877             // Aha, it is a pointer, just in disguise.
9878             rname = aopGet (result, 0, FALSE, FALSE);
9879             if (*rname != '@')
9880             {
9881                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9882                         __FILE__, __LINE__);
9883             }
9884             else
9885             {
9886                 // Expected case.
9887                 emitcode ("mov", "a%s,%s", rname + 1, rname);
9888                 rname++;  // skip the '@'.
9889             }
9890         }
9891         else
9892         {
9893             /* otherwise get a free pointer register */
9894             aop = newAsmop (0);
9895             preg = getFreePtr (ic, &aop, FALSE);
9896             emitcode ("mov", "%s,%s",
9897                       preg->name,
9898                       aopGet (result, 0, FALSE, TRUE));
9899             rname = preg->name;
9900         }
9901     }
9902     else
9903     {
9904         rname = aopGet (result, 0, FALSE, FALSE);
9905     }
9906
9907   aopOp (right, ic, FALSE);
9908
9909   /* if bitfield then unpack the bits */
9910   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9911     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9912   else
9913     {
9914       /* we have can just get the values */
9915       int size = AOP_SIZE (right);
9916       int offset = 0;
9917
9918       while (size--)
9919         {
9920           l = aopGet (right, offset, FALSE, TRUE);
9921           if (*l == '@')
9922             {
9923               MOVA (l);
9924               emitcode ("mov", "@%s,a", rname);
9925             }
9926           else
9927             emitcode ("mov", "@%s,%s", rname, l);
9928           if (size || pi)
9929             emitcode ("inc", "%s", rname);
9930           offset++;
9931         }
9932     }
9933
9934   /* now some housekeeping stuff */
9935   if (aop) /* we had to allocate for this iCode */
9936     {
9937       if (pi)
9938         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9939       freeAsmop (NULL, aop, ic, TRUE);
9940     }
9941   else
9942     {
9943       /* we did not allocate which means left
9944          already in a pointer register, then
9945          if size > 0 && this could be used again
9946          we have to point it back to where it
9947          belongs */
9948       if ((AOP_SIZE (right) > 1 &&
9949            !OP_SYMBOL (result)->remat &&
9950            (OP_SYMBOL (result)->liveTo > ic->seq ||
9951             ic->depth)) &&
9952           !pi)
9953         {
9954           int size = AOP_SIZE (right) - 1;
9955           while (size--)
9956             emitcode ("dec", "%s", rname);
9957         }
9958     }
9959
9960   /* done */
9961   if (pi) pi->generated = 1;
9962   freeAsmop (result, NULL, ic, TRUE);
9963   freeAsmop (right, NULL, ic, TRUE);
9964 }
9965
9966 /*-----------------------------------------------------------------*/
9967 /* genPagedPointerSet - emitcode for Paged pointer put             */
9968 /*-----------------------------------------------------------------*/
9969 static void
9970 genPagedPointerSet (operand * right,
9971                     operand * result,
9972                     iCode * ic,
9973                     iCode * pi)
9974 {
9975   asmop *aop = NULL;
9976   regs *preg = NULL;
9977   char *rname, *l;
9978   sym_link *retype, *letype;
9979
9980   D(emitcode (";     genPagedPointerSet",""));
9981
9982   retype = getSpec (operandType (right));
9983   letype = getSpec (operandType (result));
9984
9985   aopOp (result, ic, FALSE);
9986
9987   /* if the value is already in a pointer register
9988      then don't need anything more */
9989   if (!AOP_INPREG (AOP (result)))
9990     {
9991       /* otherwise get a free pointer register */
9992       aop = newAsmop (0);
9993       preg = getFreePtr (ic, &aop, FALSE);
9994       emitcode ("mov", "%s,%s",
9995                 preg->name,
9996                 aopGet (result, 0, FALSE, TRUE));
9997       rname = preg->name;
9998     }
9999   else
10000     rname = aopGet (result, 0, FALSE, FALSE);
10001
10002   aopOp (right, ic, FALSE);
10003
10004   /* if bitfield then unpack the bits */
10005   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10006     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10007   else
10008     {
10009       /* we have can just get the values */
10010       int size = AOP_SIZE (right);
10011       int offset = 0;
10012
10013       while (size--)
10014         {
10015           l = aopGet (right, offset, FALSE, TRUE);
10016
10017           MOVA (l);
10018           emitcode ("movx", "@%s,a", rname);
10019
10020           if (size || pi)
10021             emitcode ("inc", "%s", rname);
10022
10023           offset++;
10024         }
10025     }
10026
10027   /* now some housekeeping stuff */
10028   if (aop) /* we had to allocate for this iCode */
10029     {
10030       if (pi)
10031         aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10032       freeAsmop (NULL, aop, ic, TRUE);
10033     }
10034   else
10035     {
10036       /* we did not allocate which means left
10037          already in a pointer register, then
10038          if size > 0 && this could be used again
10039          we have to point it back to where it
10040          belongs */
10041       if (AOP_SIZE (right) > 1 &&
10042           !OP_SYMBOL (result)->remat &&
10043           (OP_SYMBOL (result)->liveTo > ic->seq ||
10044            ic->depth))
10045         {
10046           int size = AOP_SIZE (right) - 1;
10047           while (size--)
10048             emitcode ("dec", "%s", rname);
10049         }
10050     }
10051
10052   /* done */
10053   if (pi) pi->generated = 1;
10054   freeAsmop (result, NULL, ic, TRUE);
10055   freeAsmop (right, NULL, ic, TRUE);
10056
10057
10058 }
10059
10060 /*-----------------------------------------------------------------*/
10061 /* genFarPointerSet - set value from far space                     */
10062 /*-----------------------------------------------------------------*/
10063 static void
10064 genFarPointerSet (operand * right,
10065                   operand * result, iCode * ic, iCode * pi)
10066 {
10067   int size, offset;
10068   sym_link *retype = getSpec (operandType (right));
10069   sym_link *letype = getSpec (operandType (result));
10070
10071   D(emitcode (";     genFarPointerSet",""));
10072
10073   aopOp (result, ic, FALSE);
10074   loadDptrFromOperand (result, FALSE);
10075
10076   /* so dptr know contains the address */
10077   aopOp (right, ic, FALSE);
10078
10079   /* if bit then unpack */
10080   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10081     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10082   else
10083     {
10084       size = AOP_SIZE (right);
10085       offset = 0;
10086
10087       while (size--)
10088         {
10089           char *l = aopGet (right, offset++, FALSE, FALSE);
10090           MOVA (l);
10091           emitcode ("movx", "@dptr,a");
10092           if (size || pi)
10093             emitcode ("inc", "dptr");
10094         }
10095     }
10096   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10097     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10098     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10099     pi->generated=1;
10100   }
10101   freeAsmop (result, NULL, ic, TRUE);
10102   freeAsmop (right, NULL, ic, TRUE);
10103 }
10104
10105 /*-----------------------------------------------------------------*/
10106 /* genGenPointerSet - set value from generic pointer space         */
10107 /*-----------------------------------------------------------------*/
10108 static void
10109 genGenPointerSet (operand * right,
10110                   operand * result, iCode * ic, iCode * pi)
10111 {
10112   int size, offset;
10113   sym_link *retype = getSpec (operandType (right));
10114   sym_link *letype = getSpec (operandType (result));
10115
10116   D(emitcode (";     genGenPointerSet",""));
10117
10118   aopOp (result, ic, FALSE);
10119   loadDptrFromOperand (result, TRUE);
10120
10121   /* so dptr know contains the address */
10122   aopOp (right, ic, FALSE);
10123
10124   /* if bit then unpack */
10125   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10126     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10127   else
10128     {
10129       size = AOP_SIZE (right);
10130       offset = 0;
10131
10132       while (size--)
10133         {
10134           char *l = aopGet (right, offset++, FALSE, FALSE);
10135           MOVA (l);
10136           emitcode ("lcall", "__gptrput");
10137           if (size || pi)
10138             emitcode ("inc", "dptr");
10139         }
10140     }
10141
10142   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10143     aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10144     aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10145     pi->generated=1;
10146   }
10147   freeAsmop (result, NULL, ic, TRUE);
10148   freeAsmop (right, NULL, ic, TRUE);
10149 }
10150
10151 /*-----------------------------------------------------------------*/
10152 /* genPointerSet - stores the value into a pointer location        */
10153 /*-----------------------------------------------------------------*/
10154 static void
10155 genPointerSet (iCode * ic, iCode *pi)
10156 {
10157   operand *right, *result;
10158   sym_link *type, *etype;
10159   int p_type;
10160
10161   D(emitcode (";     genPointerSet",""));
10162
10163   right = IC_RIGHT (ic);
10164   result = IC_RESULT (ic);
10165
10166   /* depending on the type of pointer we need to
10167      move it to the correct pointer register */
10168   type = operandType (result);
10169   etype = getSpec (type);
10170   /* if left is of type of pointer then it is simple */
10171   if (IS_PTR (type) && !IS_FUNC (type->next))
10172     {
10173       p_type = DCL_TYPE (type);
10174     }
10175   else
10176     {
10177       /* we have to go by the storage class */
10178       p_type = PTR_TYPE (SPEC_OCLS (etype));
10179     }
10180
10181   /* special case when cast remat */
10182   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10183       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10184           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10185           type = operandType (result);
10186           p_type = DCL_TYPE (type);
10187   }
10188   /* now that we have the pointer type we assign
10189      the pointer values */
10190   switch (p_type)
10191     {
10192
10193     case POINTER:
10194     case IPOINTER:
10195       genNearPointerSet (right, result, ic, pi);
10196       break;
10197
10198     case PPOINTER:
10199       genPagedPointerSet (right, result, ic, pi);
10200       break;
10201
10202     case FPOINTER:
10203       genFarPointerSet (right, result, ic, pi);
10204       break;
10205
10206     case GPOINTER:
10207       genGenPointerSet (right, result, ic, pi);
10208       break;
10209
10210     default:
10211       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10212               "genPointerSet: illegal pointer type");
10213     }
10214
10215 }
10216
10217 /*-----------------------------------------------------------------*/
10218 /* genIfx - generate code for Ifx statement                        */
10219 /*-----------------------------------------------------------------*/
10220 static void
10221 genIfx (iCode * ic, iCode * popIc)
10222 {
10223   operand *cond = IC_COND (ic);
10224   int isbit = 0;
10225   char *dup = NULL;
10226
10227   D(emitcode (";     genIfx",""));
10228
10229   aopOp (cond, ic, FALSE);
10230
10231   /* get the value into acc */
10232   if (AOP_TYPE (cond) != AOP_CRY)
10233     toBoolean (cond);
10234   else
10235     {
10236       isbit = 1;
10237       if (AOP(cond)->aopu.aop_dir)
10238         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10239     }
10240   /* the result is now in the accumulator or a directly addressable bit */
10241   freeAsmop (cond, NULL, ic, TRUE);
10242
10243   /* if there was something to be popped then do it */
10244   if (popIc)
10245     genIpop (popIc);
10246
10247   /* if the condition is a bit variable */
10248   if (isbit && dup)
10249     genIfxJump(ic, dup, NULL, NULL, NULL);
10250   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10251     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10252   else if (isbit && !IS_ITEMP (cond))
10253     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10254   else
10255     genIfxJump (ic, "a", NULL, NULL, NULL);
10256
10257   ic->generated = 1;
10258 }
10259
10260 /*-----------------------------------------------------------------*/
10261 /* genAddrOf - generates code for address of                       */
10262 /*-----------------------------------------------------------------*/
10263 static void
10264 genAddrOf (iCode * ic)
10265 {
10266   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10267   int size, offset;
10268
10269   D(emitcode (";     genAddrOf",""));
10270
10271   aopOp (IC_RESULT (ic), ic, FALSE);
10272
10273   /* if the operand is on the stack then we
10274      need to get the stack offset of this
10275      variable */
10276   if (sym->onStack)
10277     {
10278       /* if it has an offset then we need to compute
10279          it */
10280       if (sym->stack)
10281         {
10282           emitcode ("mov", "a,%s", SYM_BP (sym));
10283           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10284                                          ((char) (sym->stack - _G.nRegsSaved)) :
10285                                          ((char) sym->stack)) & 0xff);
10286           aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10287         }
10288       else
10289         {
10290           /* we can just move _bp */
10291           aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10292         }
10293       /* fill the result with zero */
10294       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10295
10296       offset = 1;
10297       while (size--)
10298         {
10299           aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10300         }
10301
10302       goto release;
10303     }
10304
10305   /* object not on stack then we need the name */
10306   size = AOP_SIZE (IC_RESULT (ic));
10307   offset = 0;
10308
10309   while (size--)
10310     {
10311       char s[SDCC_NAME_MAX];
10312       if (offset)
10313         sprintf (s, "#(%s >> %d)",
10314                  sym->rname,
10315                  offset * 8);
10316       else
10317         sprintf (s, "#%s", sym->rname);
10318       aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10319     }
10320
10321 release:
10322   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10323
10324 }
10325
10326 /*-----------------------------------------------------------------*/
10327 /* genFarFarAssign - assignment when both are in far space         */
10328 /*-----------------------------------------------------------------*/
10329 static void
10330 genFarFarAssign (operand * result, operand * right, iCode * ic)
10331 {
10332   int size = AOP_SIZE (right);
10333   int offset = 0;
10334   char *l;
10335
10336   D(emitcode (";     genFarFarAssign",""));
10337
10338   /* first push the right side on to the stack */
10339   while (size--)
10340     {
10341       l = aopGet (right, offset++, FALSE, FALSE);
10342       MOVA (l);
10343       emitcode ("push", "acc");
10344     }
10345
10346   freeAsmop (right, NULL, ic, FALSE);
10347   /* now assign DPTR to result */
10348   aopOp (result, ic, FALSE);
10349   size = AOP_SIZE (result);
10350   while (size--)
10351     {
10352       emitcode ("pop", "acc");
10353       aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10354     }
10355   freeAsmop (result, NULL, ic, FALSE);
10356
10357 }
10358
10359 /*-----------------------------------------------------------------*/
10360 /* genAssign - generate code for assignment                        */
10361 /*-----------------------------------------------------------------*/
10362 static void
10363 genAssign (iCode * ic)
10364 {
10365   operand *result, *right;
10366   int size, offset;
10367   unsigned long lit = 0L;
10368
10369   D(emitcode(";     genAssign",""));
10370
10371   result = IC_RESULT (ic);
10372   right = IC_RIGHT (ic);
10373
10374   /* if they are the same */
10375   if (operandsEqu (result, right) &&
10376       !isOperandVolatile (result, FALSE) &&
10377       !isOperandVolatile (right, FALSE))
10378     return;
10379
10380   aopOp (right, ic, FALSE);
10381
10382   /* special case both in far space */
10383   if (AOP_TYPE (right) == AOP_DPTR &&
10384       IS_TRUE_SYMOP (result) &&
10385       isOperandInFarSpace (result))
10386     {
10387
10388       genFarFarAssign (result, right, ic);
10389       return;
10390     }
10391
10392   aopOp (result, ic, TRUE);
10393
10394   /* if they are the same registers */
10395   if (sameRegs (AOP (right), AOP (result)) &&
10396       !isOperandVolatile (result, FALSE) &&
10397       !isOperandVolatile (right, FALSE))
10398     goto release;
10399
10400   /* if the result is a bit */
10401   if (AOP_TYPE (result) == AOP_CRY)
10402     {
10403
10404       /* if the right size is a literal then
10405          we know what the value is */
10406       if (AOP_TYPE (right) == AOP_LIT)
10407         {
10408           if (((int) operandLitValue (right)))
10409             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10410           else
10411             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10412           goto release;
10413         }
10414
10415       /* the right is also a bit variable */
10416       if (AOP_TYPE (right) == AOP_CRY)
10417         {
10418           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10419           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10420           goto release;
10421         }
10422
10423       /* we need to or */
10424       toBoolean (right);
10425       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10426       goto release;
10427     }
10428
10429   /* bit variables done */
10430   /* general case */
10431   size = AOP_SIZE (result);
10432   offset = 0;
10433   if (AOP_TYPE (right) == AOP_LIT)
10434     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10435   if ((size > 1) &&
10436       (AOP_TYPE (result) != AOP_REG) &&
10437       (AOP_TYPE (right) == AOP_LIT) &&
10438       !IS_FLOAT (operandType (right)) &&
10439       (lit < 256L))
10440     {
10441       while ((size) && (lit))
10442         {
10443           aopPut (result,
10444                   aopGet (right, offset, FALSE, FALSE),
10445                   offset,
10446                   isOperandVolatile (result, FALSE));
10447           lit >>= 8;
10448           offset++;
10449           size--;
10450         }
10451       emitcode ("clr", "a");
10452       while (size--)
10453         {
10454           aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10455           offset++;
10456         }
10457     }
10458   else
10459     {
10460       while (size--)
10461         {
10462           aopPut (result,
10463                   aopGet (right, offset, FALSE, FALSE),
10464                   offset,
10465                   isOperandVolatile (result, FALSE));
10466           offset++;
10467         }
10468     }
10469
10470 release:
10471   freeAsmop (right, NULL, ic, TRUE);
10472   freeAsmop (result, NULL, ic, TRUE);
10473 }
10474
10475 /*-----------------------------------------------------------------*/
10476 /* genJumpTab - generates code for jump table                      */
10477 /*-----------------------------------------------------------------*/
10478 static void
10479 genJumpTab (iCode * ic)
10480 {
10481   symbol *jtab,*jtablo,*jtabhi;
10482   char *l;
10483   unsigned int count;
10484
10485   D(emitcode (";     genJumpTab",""));
10486
10487   count = elementsInSet( IC_JTLABELS (ic) );
10488
10489   if( count <= 16 )
10490     {
10491       /* this algorithm needs 9 cycles and 7 + 3*n bytes
10492          if the switch argument is in a register.
10493          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10494       /* (MB) What if peephole converts ljmp to sjmp or ret ???
10495          How will multiply by three be updated ???*/
10496       aopOp (IC_JTCOND (ic), ic, FALSE);
10497       /* get the condition into accumulator */
10498       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10499       MOVA (l);
10500       /* multiply by three */
10501       emitcode ("add", "a,acc");
10502       emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10503       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10504
10505       jtab = newiTempLabel (NULL);
10506       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10507       emitcode ("jmp", "@a+dptr");
10508       emitcode ("", "%05d$:", jtab->key + 100);
10509       /* now generate the jump labels */
10510       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10511            jtab = setNextItem (IC_JTLABELS (ic)))
10512         emitcode ("ljmp", "%05d$", jtab->key + 100);
10513     }
10514   else
10515     {
10516       /* this algorithm needs 14 cycles and 13 + 2*n bytes
10517          if the switch argument is in a register.
10518          For n>6 this algorithm may be more compact */
10519       jtablo = newiTempLabel (NULL);
10520       jtabhi = newiTempLabel (NULL);
10521
10522       /* get the condition into accumulator.
10523          Using b as temporary storage, if register push/pop is needed */
10524       aopOp (IC_JTCOND (ic), ic, FALSE);
10525       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10526       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10527           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10528         {
10529           // (MB) what if B is in use???
10530           wassertl(!BINUSE, "B was in use");
10531           emitcode ("mov", "b,%s", l);
10532           l = "b";
10533         }
10534       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10535       MOVA (l);
10536       if( count <= 112 )
10537         {
10538           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10539           emitcode ("movc", "a,@a+pc");
10540           emitcode ("push", "acc");
10541
10542           MOVA (l);
10543           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10544           emitcode ("movc", "a,@a+pc");
10545           emitcode ("push", "acc");
10546         }
10547       else
10548         {
10549           /* this scales up to n<=255, but needs two more bytes
10550              and changes dptr */
10551           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10552           emitcode ("movc", "a,@a+dptr");
10553           emitcode ("push", "acc");
10554
10555           MOVA (l);
10556           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10557           emitcode ("movc", "a,@a+dptr");
10558           emitcode ("push", "acc");
10559         }
10560
10561       emitcode ("ret", "");
10562
10563       /* now generate jump table, LSB */
10564       emitcode ("", "%05d$:", jtablo->key + 100);
10565       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10566            jtab = setNextItem (IC_JTLABELS (ic)))
10567         emitcode (".db", "%05d$", jtab->key + 100);
10568
10569       /* now generate jump table, MSB */
10570       emitcode ("", "%05d$:", jtabhi->key + 100);
10571       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10572            jtab = setNextItem (IC_JTLABELS (ic)))
10573          emitcode (".db", "%05d$>>8", jtab->key + 100);
10574     }
10575 }
10576
10577 /*-----------------------------------------------------------------*/
10578 /* genCast - gen code for casting                                  */
10579 /*-----------------------------------------------------------------*/
10580 static void
10581 genCast (iCode * ic)
10582 {
10583   operand *result = IC_RESULT (ic);
10584   sym_link *ctype = operandType (IC_LEFT (ic));
10585   sym_link *rtype = operandType (IC_RIGHT (ic));
10586   operand *right = IC_RIGHT (ic);
10587   int size, offset;
10588
10589   D(emitcode(";     genCast",""));
10590
10591   /* if they are equivalent then do nothing */
10592   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10593     return;
10594
10595   aopOp (right, ic, FALSE);
10596   aopOp (result, ic, FALSE);
10597
10598   /* if the result is a bit (and not a bitfield) */
10599   // if (AOP_TYPE (result) == AOP_CRY)
10600   if (IS_BITVAR (OP_SYMBOL (result)->type)
10601       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10602     {
10603       /* if the right size is a literal then
10604          we know what the value is */
10605       if (AOP_TYPE (right) == AOP_LIT)
10606         {
10607           if (((int) operandLitValue (right)))
10608             aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10609           else
10610             aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10611
10612           goto release;
10613         }
10614
10615       /* the right is also a bit variable */
10616       if (AOP_TYPE (right) == AOP_CRY)
10617         {
10618           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10619           aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10620           goto release;
10621         }
10622
10623       /* we need to or */
10624       toBoolean (right);
10625       aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10626       goto release;
10627     }
10628
10629
10630   /* if they are the same size : or less */
10631   if (AOP_SIZE (result) <= AOP_SIZE (right))
10632     {
10633
10634       /* if they are in the same place */
10635       if (sameRegs (AOP (right), AOP (result)))
10636         goto release;
10637
10638       /* if they in different places then copy */
10639       size = AOP_SIZE (result);
10640       offset = 0;
10641       while (size--)
10642         {
10643           aopPut (result,
10644                   aopGet (right, offset, FALSE, FALSE),
10645                   offset,
10646                   isOperandVolatile (result, FALSE));
10647           offset++;
10648         }
10649       goto release;
10650     }
10651
10652
10653   /* if the result is of type pointer */
10654   if (IS_PTR (ctype))
10655     {
10656
10657       int p_type;
10658       sym_link *type = operandType (right);
10659       sym_link *etype = getSpec (type);
10660
10661       /* pointer to generic pointer */
10662       if (IS_GENPTR (ctype))
10663         {
10664           if (IS_PTR (type))
10665             p_type = DCL_TYPE (type);
10666           else
10667             {
10668               if (SPEC_SCLS(etype)==S_REGISTER) {
10669                 // let's assume it is a generic pointer
10670                 p_type=GPOINTER;
10671               } else {
10672                 /* we have to go by the storage class */
10673                 p_type = PTR_TYPE (SPEC_OCLS (etype));
10674               }
10675             }
10676
10677           /* the first two bytes are known */
10678           size = GPTRSIZE - 1;
10679           offset = 0;
10680           while (size--)
10681             {
10682               aopPut (result,
10683                       aopGet (right, offset, FALSE, FALSE),
10684                       offset,
10685                       isOperandVolatile (result, FALSE));
10686               offset++;
10687             }
10688           /* the last byte depending on type */
10689             {
10690                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10691                 char gpValStr[10];
10692
10693                 if (gpVal == -1)
10694                 {
10695                     // pointerTypeToGPByte will have bitched.
10696                     exit(1);
10697                 }
10698
10699                 sprintf(gpValStr, "#0x%x", gpVal);
10700                 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10701             }
10702           goto release;
10703         }
10704
10705       /* just copy the pointers */
10706       size = AOP_SIZE (result);
10707       offset = 0;
10708       while (size--)
10709         {
10710           aopPut (result,
10711                   aopGet (right, offset, FALSE, FALSE),
10712                   offset,
10713                   isOperandVolatile (result, FALSE));
10714           offset++;
10715         }
10716       goto release;
10717     }
10718
10719   /* so we now know that the size of destination is greater
10720      than the size of the source */
10721   /* we move to result for the size of source */
10722   size = AOP_SIZE (right);
10723   offset = 0;
10724   while (size--)
10725     {
10726       aopPut (result,
10727               aopGet (right, offset, FALSE, FALSE),
10728               offset,
10729               isOperandVolatile (result, FALSE));
10730       offset++;
10731     }
10732
10733   /* now depending on the sign of the source && destination */
10734   size = AOP_SIZE (result) - AOP_SIZE (right);
10735   /* if unsigned or not an integral type */
10736   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10737     {
10738       while (size--)
10739         aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10740     }
10741   else
10742     {
10743       /* we need to extend the sign :{ */
10744       char *l = aopGet (right, AOP_SIZE (right) - 1,
10745                         FALSE, FALSE);
10746       MOVA (l);
10747       emitcode ("rlc", "a");
10748       emitcode ("subb", "a,acc");
10749       while (size--)
10750         aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10751     }
10752
10753   /* we are done hurray !!!! */
10754
10755 release:
10756   freeAsmop (right, NULL, ic, TRUE);
10757   freeAsmop (result, NULL, ic, TRUE);
10758
10759 }
10760
10761 /*-----------------------------------------------------------------*/
10762 /* genDjnz - generate decrement & jump if not zero instrucion      */
10763 /*-----------------------------------------------------------------*/
10764 static int
10765 genDjnz (iCode * ic, iCode * ifx)
10766 {
10767   symbol *lbl, *lbl1;
10768   if (!ifx)
10769     return 0;
10770
10771   D(emitcode (";     genDjnz",""));
10772
10773   /* if the if condition has a false label
10774      then we cannot save */
10775   if (IC_FALSE (ifx))
10776     return 0;
10777
10778   /* if the minus is not of the form
10779      a = a - 1 */
10780   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10781       !IS_OP_LITERAL (IC_RIGHT (ic)))
10782     return 0;
10783
10784   if (operandLitValue (IC_RIGHT (ic)) != 1)
10785     return 0;
10786
10787   /* if the size of this greater than one then no
10788      saving */
10789   if (getSize (operandType (IC_RESULT (ic))) > 1)
10790     return 0;
10791
10792   /* otherwise we can save BIG */
10793   lbl = newiTempLabel (NULL);
10794   lbl1 = newiTempLabel (NULL);
10795
10796   aopOp (IC_RESULT (ic), ic, FALSE);
10797
10798   if (AOP_NEEDSACC(IC_RESULT(ic)))
10799   {
10800       /* If the result is accessed indirectly via
10801        * the accumulator, we must explicitly write
10802        * it back after the decrement.
10803        */
10804       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10805
10806       if (strcmp(rByte, "a"))
10807       {
10808            /* Something is hopelessly wrong */
10809            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10810                    __FILE__, __LINE__);
10811            /* We can just give up; the generated code will be inefficient,
10812             * but what the hey.
10813             */
10814            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10815            return 0;
10816       }
10817       emitcode ("dec", "%s", rByte);
10818       aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10819       emitcode ("jnz", "%05d$", lbl->key + 100);
10820   }
10821   else if (IS_AOP_PREG (IC_RESULT (ic)))
10822     {
10823       emitcode ("dec", "%s",
10824                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10825       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10826       emitcode ("jnz", "%05d$", lbl->key + 100);
10827     }
10828   else
10829     {
10830       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10831                 lbl->key + 100);
10832     }
10833   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10834   emitcode ("", "%05d$:", lbl->key + 100);
10835   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10836   emitcode ("", "%05d$:", lbl1->key + 100);
10837
10838   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10839   ifx->generated = 1;
10840   return 1;
10841 }
10842
10843 /*-----------------------------------------------------------------*/
10844 /* genReceive - generate code for a receive iCode                  */
10845 /*-----------------------------------------------------------------*/
10846 static void
10847 genReceive (iCode * ic)
10848 {
10849   int size = getSize (operandType (IC_RESULT (ic)));
10850   int offset = 0;
10851
10852   D(emitcode (";     genReceive",""));
10853
10854   if (ic->argreg == 1)
10855     { /* first parameter */
10856       if (isOperandInFarSpace (IC_RESULT (ic)) &&
10857           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10858            IS_TRUE_SYMOP (IC_RESULT (ic))))
10859         {
10860           regs *tempRegs[4];
10861           int receivingA = 0;
10862           int roffset = 0;
10863
10864           for (offset = 0; offset<size; offset++)
10865             if (!strcmp (fReturn[offset], "a"))
10866               receivingA = 1;
10867
10868           if (!receivingA)
10869             {
10870               if (size==1 || getTempRegs(tempRegs, size-1, ic))
10871                 {
10872                   for (offset = size-1; offset>0; offset--)
10873                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10874                   emitcode("mov","a,%s", fReturn[0]);
10875                   _G.accInUse++;
10876                   aopOp (IC_RESULT (ic), ic, FALSE);
10877                   _G.accInUse--;
10878                   aopPut (IC_RESULT (ic), "a", offset,
10879                           isOperandVolatile (IC_RESULT (ic), FALSE));
10880                   for (offset = 1; offset<size; offset++)
10881                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10882                             isOperandVolatile (IC_RESULT (ic), FALSE));
10883                   goto release;
10884                 }
10885             }
10886           else
10887             {
10888               if (getTempRegs(tempRegs, size, ic))
10889                 {
10890                   for (offset = 0; offset<size; offset++)
10891                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10892                   aopOp (IC_RESULT (ic), ic, FALSE);
10893                   for (offset = 0; offset<size; offset++)
10894                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10895                             isOperandVolatile (IC_RESULT (ic), FALSE));
10896                   goto release;
10897                 }
10898             }
10899
10900           offset = fReturnSizeMCS51 - size;
10901           while (size--)
10902             {
10903               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10904                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10905               offset++;
10906             }
10907           aopOp (IC_RESULT (ic), ic, FALSE);
10908           size = AOP_SIZE (IC_RESULT (ic));
10909           offset = 0;
10910           while (size--)
10911             {
10912               emitcode ("pop", "acc");
10913               aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10914             }
10915         }
10916       else
10917         {
10918           _G.accInUse++;
10919           aopOp (IC_RESULT (ic), ic, FALSE);
10920           _G.accInUse--;
10921           assignResultValue (IC_RESULT (ic), NULL);
10922         }
10923     }
10924   else if (ic->argreg > 12)
10925     { /* bit parameters */
10926       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
10927         {
10928           aopOp (IC_RESULT (ic), ic, FALSE);
10929           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
10930           outBitC(IC_RESULT (ic));
10931         }
10932     }
10933   else
10934     { /* other parameters */
10935       int rb1off ;
10936       aopOp (IC_RESULT (ic), ic, FALSE);
10937       rb1off = ic->argreg;
10938       while (size--)
10939         {
10940           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10941         }
10942     }
10943
10944 release:
10945   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10946 }
10947
10948 /*-----------------------------------------------------------------*/
10949 /* genDummyRead - generate code for dummy read of volatiles        */
10950 /*-----------------------------------------------------------------*/
10951 static void
10952 genDummyRead (iCode * ic)
10953 {
10954   operand *op;
10955   int size, offset;
10956
10957   D(emitcode(";     genDummyRead",""));
10958
10959   op = IC_RIGHT (ic);
10960   if (op && IS_SYMOP (op))
10961     {
10962       aopOp (op, ic, FALSE);
10963
10964       /* if the result is a bit */
10965       if (AOP_TYPE (op) == AOP_CRY)
10966         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10967       else
10968         {
10969           /* bit variables done */
10970           /* general case */
10971           size = AOP_SIZE (op);
10972           offset = 0;
10973           while (size--)
10974           {
10975             MOVA (aopGet (op, offset, FALSE, FALSE));
10976             offset++;
10977           }
10978         }
10979
10980       freeAsmop (op, NULL, ic, TRUE);
10981     }
10982
10983   op = IC_LEFT (ic);
10984   if (op && IS_SYMOP (op))
10985     {
10986       aopOp (op, ic, FALSE);
10987
10988       /* if the result is a bit */
10989       if (AOP_TYPE (op) == AOP_CRY)
10990         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10991       else
10992         {
10993           /* bit variables done */
10994           /* general case */
10995           size = AOP_SIZE (op);
10996           offset = 0;
10997           while (size--)
10998           {
10999             MOVA (aopGet (op, offset, FALSE, FALSE));
11000             offset++;
11001           }
11002         }
11003
11004       freeAsmop (op, NULL, ic, TRUE);
11005     }
11006 }
11007
11008 /*-----------------------------------------------------------------*/
11009 /* genCritical - generate code for start of a critical sequence    */
11010 /*-----------------------------------------------------------------*/
11011 static void
11012 genCritical (iCode *ic)
11013 {
11014   symbol *tlbl = newiTempLabel (NULL);
11015
11016   D(emitcode(";     genCritical",""));
11017
11018   if (IC_RESULT (ic))
11019     {
11020       aopOp (IC_RESULT (ic), ic, TRUE);
11021       aopPut (IC_RESULT (ic), one, 0, 0);
11022       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11023       aopPut (IC_RESULT (ic), zero, 0, 0);
11024       emitcode ("", "%05d$:", (tlbl->key + 100));
11025       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11026     }
11027   else
11028     {
11029       emitcode ("setb", "c");
11030       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11031       emitcode ("clr", "c");
11032       emitcode ("", "%05d$:", (tlbl->key + 100));
11033       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11034     }
11035 }
11036
11037 /*-----------------------------------------------------------------*/
11038 /* genEndCritical - generate code for end of a critical sequence   */
11039 /*-----------------------------------------------------------------*/
11040 static void
11041 genEndCritical (iCode *ic)
11042 {
11043   D(emitcode(";     genEndCritical",""));
11044
11045   if (IC_RIGHT (ic))
11046     {
11047       aopOp (IC_RIGHT (ic), ic, FALSE);
11048       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11049         {
11050           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11051           emitcode ("mov", "ea,c");
11052         }
11053       else
11054         {
11055           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11056             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11057           emitcode ("rrc", "a");
11058           emitcode ("mov", "ea,c");
11059         }
11060       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11061     }
11062   else
11063     {
11064       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11065       emitcode ("mov", "ea,c");
11066     }
11067 }
11068
11069 /*-----------------------------------------------------------------*/
11070 /* gen51Code - generate code for 8051 based controllers            */
11071 /*-----------------------------------------------------------------*/
11072 void
11073 gen51Code (iCode * lic)
11074 {
11075   iCode *ic;
11076   int cln = 0;
11077   /* int cseq = 0; */
11078
11079   _G.currentFunc = NULL;
11080   lineHead = lineCurr = NULL;
11081
11082   /* print the allocation information */
11083   if (allocInfo && currFunc)
11084     printAllocInfo (currFunc, codeOutFile);
11085   /* if debug information required */
11086   if (options.debug && currFunc)
11087     {
11088       debugFile->writeFunction (currFunc, lic);
11089     }
11090   /* stack pointer name */
11091   if (options.useXstack)
11092     spname = "_spx";
11093   else
11094     spname = "sp";
11095
11096
11097   for (ic = lic; ic; ic = ic->next)
11098     {
11099       _G.current_iCode = ic;
11100
11101       if (ic->lineno && cln != ic->lineno)
11102         {
11103           if (options.debug)
11104             {
11105               debugFile->writeCLine (ic);
11106             }
11107           if (!options.noCcodeInAsm) {
11108             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11109                       printCLine(ic->filename, ic->lineno));
11110           }
11111           cln = ic->lineno;
11112         }
11113       #if 0
11114       if (ic->seqPoint && ic->seqPoint != cseq)
11115         {
11116           emitcode ("", "; sequence point %d", ic->seqPoint);
11117           cseq = ic->seqPoint;
11118         }
11119       #endif
11120       if (options.iCodeInAsm) {
11121         char regsInUse[80];
11122         int i;
11123
11124         for (i=0; i<8; i++) {
11125           sprintf (&regsInUse[i],
11126                    "%c", ic->riu & (1<<i) ? i+'0' : '-');
11127         }
11128         regsInUse[i]=0;
11129         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11130       }
11131       /* if the result is marked as
11132          spilt and rematerializable or code for
11133          this has already been generated then
11134          do nothing */
11135       if (resultRemat (ic) || ic->generated)
11136         continue;
11137
11138       /* depending on the operation */
11139       switch (ic->op)
11140         {
11141         case '!':
11142           genNot (ic);
11143           break;
11144
11145         case '~':
11146           genCpl (ic);
11147           break;
11148
11149         case UNARYMINUS:
11150           genUminus (ic);
11151           break;
11152
11153         case IPUSH:
11154           genIpush (ic);
11155           break;
11156
11157         case IPOP:
11158           /* IPOP happens only when trying to restore a
11159              spilt live range, if there is an ifx statement
11160              following this pop then the if statement might
11161              be using some of the registers being popped which
11162              would destory the contents of the register so
11163              we need to check for this condition and handle it */
11164           if (ic->next &&
11165               ic->next->op == IFX &&
11166               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11167             genIfx (ic->next, ic);
11168           else
11169             genIpop (ic);
11170           break;
11171
11172         case CALL:
11173           genCall (ic);
11174           break;
11175
11176         case PCALL:
11177           genPcall (ic);
11178           break;
11179
11180         case FUNCTION:
11181           genFunction (ic);
11182           break;
11183
11184         case ENDFUNCTION:
11185           genEndFunction (ic);
11186           break;
11187
11188         case RETURN:
11189           genRet (ic);
11190           break;
11191
11192         case LABEL:
11193           genLabel (ic);
11194           break;
11195
11196         case GOTO:
11197           genGoto (ic);
11198           break;
11199
11200         case '+':
11201           genPlus (ic);
11202           break;
11203
11204         case '-':
11205           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11206             genMinus (ic);
11207           break;
11208
11209         case '*':
11210           genMult (ic);
11211           break;
11212
11213         case '/':
11214           genDiv (ic);
11215           break;
11216
11217         case '%':
11218           genMod (ic);
11219           break;
11220
11221         case '>':
11222           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11223           break;
11224
11225         case '<':
11226           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11227           break;
11228
11229         case LE_OP:
11230         case GE_OP:
11231         case NE_OP:
11232
11233           /* note these two are xlated by algebraic equivalence
11234              during parsing SDCC.y */
11235           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11236                   "got '>=' or '<=' shouldn't have come here");
11237           break;
11238
11239         case EQ_OP:
11240           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11241           break;
11242
11243         case AND_OP:
11244           genAndOp (ic);
11245           break;
11246
11247         case OR_OP:
11248           genOrOp (ic);
11249           break;
11250
11251         case '^':
11252           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11253           break;
11254
11255         case '|':
11256           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11257           break;
11258
11259         case BITWISEAND:
11260           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11261           break;
11262
11263         case INLINEASM:
11264           genInline (ic);
11265           break;
11266
11267         case RRC:
11268           genRRC (ic);
11269           break;
11270
11271         case RLC:
11272           genRLC (ic);
11273           break;
11274
11275         case GETHBIT:
11276           genGetHbit (ic);
11277           break;
11278
11279         case GETABIT:
11280           genGetAbit (ic);
11281           break;
11282
11283         case GETBYTE:
11284           genGetByte (ic);
11285           break;
11286
11287         case GETWORD:
11288           genGetWord (ic);
11289           break;
11290
11291         case LEFT_OP:
11292           genLeftShift (ic);
11293           break;
11294
11295         case RIGHT_OP:
11296           genRightShift (ic);
11297           break;
11298
11299         case GET_VALUE_AT_ADDRESS:
11300           genPointerGet (ic,
11301                          hasInc (IC_LEFT (ic), ic,
11302                                  getSize (operandType (IC_RESULT (ic)))),
11303                          ifxForOp (IC_RESULT (ic), ic) );
11304           break;
11305
11306         case '=':
11307           if (POINTER_SET (ic))
11308             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11309           else
11310             genAssign (ic);
11311           break;
11312
11313         case IFX:
11314           genIfx (ic, NULL);
11315           break;
11316
11317         case ADDRESS_OF:
11318           genAddrOf (ic);
11319           break;
11320
11321         case JUMPTABLE:
11322           genJumpTab (ic);
11323           break;
11324
11325         case CAST:
11326           genCast (ic);
11327           break;
11328
11329         case RECEIVE:
11330           genReceive (ic);
11331           break;
11332
11333         case SEND:
11334           addSet (&_G.sendSet, ic);
11335           break;
11336
11337         case DUMMY_READ_VOLATILE:
11338           genDummyRead (ic);
11339           break;
11340
11341         case CRITICAL:
11342           genCritical (ic);
11343           break;
11344
11345         case ENDCRITICAL:
11346           genEndCritical (ic);
11347           break;
11348
11349         case SWAP:
11350           genSwap (ic);
11351           break;
11352
11353         default:
11354           ic = ic;
11355         }
11356     }
11357
11358   _G.current_iCode = NULL;
11359
11360   /* now we are ready to call the
11361      peep hole optimizer */
11362   if (!options.nopeep)
11363     peepHole (&lineHead);
11364
11365   /* now do the actual printing */
11366   printLine (lineHead, codeOutFile);
11367   return;
11368 }