* src/SDCCast.c: added an additional type flow in decorateType() of opposite directio...
[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 extern int allocInfo;
48
49 /* this is the down and dirty file with all kinds of
50    kludgy & hacky stuff. This is what it is all about
51    CODE GENERATION for a specific MCU . some of the
52    routines may be reusable, will have to see */
53
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
56 static char *spname;
57
58 char *fReturn8051[] =
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
63 {"a", "b"};
64
65 static unsigned short rbank = -1;
66
67 static struct
68   {
69     short r0Pushed;
70     short r1Pushed;
71     short accInUse;
72     short inLine;
73     short debugLine;
74     short nRegsSaved;
75     set *sendSet;
76     iCode *current_iCode;
77     symbol *currentFunc;
78   }
79 _G;
80
81 static char *rb1regs[] = {
82     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
83 };
84
85 extern int mcs51_ptrRegReq;
86 extern int mcs51_nRegs;
87 extern FILE *codeOutFile;
88 static void saveRBank (int, iCode *, bool);
89 #define RESULTONSTACK(x) \
90                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
91                          IC_RESULT(x)->aop->type == AOP_STK )
92
93 #define MOVA(x) mova(x)  /* use function to avoid multiple eval */
94 #define CLRC    emitcode("clr","c")
95 #define SETC    emitcode("setb","c")
96
97 static lineNode *lineHead = NULL;
98 static lineNode *lineCurr = NULL;
99
100 static unsigned char SLMask[] =
101 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
102  0xE0, 0xC0, 0x80, 0x00};
103 static unsigned char SRMask[] =
104 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
105  0x07, 0x03, 0x01, 0x00};
106
107 #define LSB     0
108 #define MSB16   1
109 #define MSB24   2
110 #define MSB32   3
111
112 /*-----------------------------------------------------------------*/
113 /* emitcode - writes the code into a file : for now it is simple    */
114 /*-----------------------------------------------------------------*/
115 static void
116 emitcode (char *inst, const char *fmt,...)
117 {
118   va_list ap;
119   char lb[INITIAL_INLINEASM];
120   char *lbp = lb;
121
122   va_start (ap, fmt);
123
124   if (inst && *inst)
125     {
126       if (fmt && *fmt)
127         sprintf (lb, "%s\t", inst);
128       else
129         sprintf (lb, "%s", inst);
130       vsprintf (lb + (strlen (lb)), fmt, ap);
131     }
132   else
133     vsprintf (lb, fmt, ap);
134
135   while (isspace (*lbp))
136     lbp++;
137
138   if (lbp && *lbp)
139     lineCurr = (lineCurr ?
140                 connectLine (lineCurr, newLineNode (lb)) :
141                 (lineHead = newLineNode (lb)));
142   lineCurr->isInline = _G.inLine;
143   lineCurr->isDebug = _G.debugLine;
144   lineCurr->ic = _G.current_iCode;
145   lineCurr->isComment = (*lbp==';');
146   va_end (ap);
147 }
148
149 /*-----------------------------------------------------------------*/
150 /* mova - moves specified value into accumulator                   */
151 /*-----------------------------------------------------------------*/
152 static void
153 mova (const char *x)
154 {
155   /* do some early peephole optimization */
156   if (!strcmp(x, "a") || !strcmp(x, "acc"))
157     return;
158
159   emitcode("mov","a,%s", x);
160 }
161
162 /*-----------------------------------------------------------------*/
163 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
164 /*-----------------------------------------------------------------*/
165 static regs *
166 getFreePtr (iCode * ic, asmop ** aopp, bool result)
167 {
168   bool r0iu = FALSE, r1iu = FALSE;
169   bool r0ou = FALSE, r1ou = FALSE;
170
171   /* the logic: if r0 & r1 used in the instruction
172      then we are in trouble otherwise */
173
174   /* first check if r0 & r1 are used by this
175      instruction, in which case we are in trouble */
176   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
177   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178   if (r0iu && r1iu) {
179       goto endOfWorld;
180     }
181
182   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
183   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
184
185   /* if no usage of r0 then return it */
186   if (!r0iu && !r0ou)
187     {
188       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
189       (*aopp)->type = AOP_R0;
190
191       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
192     }
193
194   /* if no usage of r1 then return it */
195   if (!r1iu && !r1ou)
196     {
197       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
198       (*aopp)->type = AOP_R1;
199
200       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
201     }
202
203   /* now we know they both have usage */
204   /* if r0 not used in this instruction */
205   if (!r0iu)
206     {
207       /* push it if not already pushed */
208       if (!_G.r0Pushed)
209         {
210           emitcode ("push", "%s",
211                     mcs51_regWithIdx (R0_IDX)->dname);
212           _G.r0Pushed++;
213         }
214
215       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
216       (*aopp)->type = AOP_R0;
217
218       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
219     }
220
221   /* if r1 not used then */
222
223   if (!r1iu)
224     {
225       /* push it if not already pushed */
226       if (!_G.r1Pushed)
227         {
228           emitcode ("push", "%s",
229                     mcs51_regWithIdx (R1_IDX)->dname);
230           _G.r1Pushed++;
231         }
232
233       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
234       (*aopp)->type = AOP_R1;
235       return mcs51_regWithIdx (R1_IDX);
236     }
237 endOfWorld:
238   /* I said end of world, but not quite end of world yet */
239   if (result) {
240     /* we can push it on the stack */
241     (*aopp)->type = AOP_STK;
242     return NULL;
243   } else {
244     /* in the case that result AND left AND right needs a pointer reg
245        we can safely use the result's */
246     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
247       (*aopp)->type = AOP_R0;
248       return mcs51_regWithIdx (R0_IDX);
249     }
250     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
251       (*aopp)->type = AOP_R1;
252       return mcs51_regWithIdx (R1_IDX);
253     }
254   }
255
256   /* now this is REALLY the end of the world */
257   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
258           "getFreePtr should never reach here");
259   exit (1);
260 }
261
262
263 /*-----------------------------------------------------------------*/
264 /* getTempRegs - initialize an array of pointers to GPR registers */
265 /*               that are not in use. Returns 1 if the requested   */
266 /*               number of registers were available, 0 otherwise.  */
267 /*-----------------------------------------------------------------*/
268 int
269 getTempRegs(regs **tempRegs, int size, iCode *ic)
270 {
271   bitVect * freeRegs;
272   int i;
273   int offset;
274   
275   if (!ic)
276     ic = _G.current_iCode;
277   if (!ic)
278     return 0;
279   if (!_G.currentFunc)
280     return 0;
281  
282   freeRegs = newBitVect(8);
283   bitVectSetBit (freeRegs, R2_IDX);
284   bitVectSetBit (freeRegs, R3_IDX);
285   bitVectSetBit (freeRegs, R4_IDX);
286   bitVectSetBit (freeRegs, R5_IDX);
287   bitVectSetBit (freeRegs, R6_IDX);
288   bitVectSetBit (freeRegs, R7_IDX);
289   
290   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
291     {
292       bitVect * newfreeRegs;
293       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
294       freeBitVect(freeRegs);
295       freeRegs = newfreeRegs;
296     }
297   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
298   
299   offset = 0;     
300   for (i=0; i<freeRegs->size; i++)
301     {
302       if (bitVectBitValue(freeRegs,i))
303         tempRegs[offset++] = mcs51_regWithIdx(i);
304       if (offset>=size)
305         {
306           freeBitVect(freeRegs);
307           return 1;
308         }
309     }
310
311   freeBitVect(freeRegs);
312   return 1;
313 }
314
315
316 /*-----------------------------------------------------------------*/
317 /* newAsmop - creates a new asmOp                                  */
318 /*-----------------------------------------------------------------*/
319 static asmop *
320 newAsmop (short type)
321 {
322   asmop *aop;
323
324   aop = Safe_calloc (1, sizeof (asmop));
325   aop->type = type;
326   return aop;
327 }
328
329 /*-----------------------------------------------------------------*/
330 /* pointerCode - returns the code for a pointer type               */
331 /*-----------------------------------------------------------------*/
332 static int
333 pointerCode (sym_link * etype)
334 {
335
336   return PTR_TYPE (SPEC_OCLS (etype));
337
338 }
339
340
341 /*-----------------------------------------------------------------*/
342 /* leftRightUseAcc - returns size of accumulator use by operands   */
343 /*-----------------------------------------------------------------*/
344 static int
345 leftRightUseAcc(iCode *ic)
346 {
347   operand *op;
348   int size;
349   int accuseSize = 0;
350   int accuse = 0;
351   
352   if (!ic)
353     {
354       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
355               "null iCode pointer");
356       return 0;
357     }
358
359   if (ic->op == IFX)
360     {
361       op = IC_COND (ic);
362       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
363         {
364           accuse = 1;
365           size = getSize (OP_SYMBOL (op)->type);
366           if (size>accuseSize)
367             accuseSize = size;
368         }
369     }
370   else if (ic->op == JUMPTABLE)
371     {
372       op = IC_JTCOND (ic);
373       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
374         {
375           accuse = 1;
376           size = getSize (OP_SYMBOL (op)->type);
377           if (size>accuseSize)
378             accuseSize = size;
379         }
380     }
381   else
382     {
383       op = IC_LEFT (ic);
384       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
385         {
386           accuse = 1;
387           size = getSize (OP_SYMBOL (op)->type);
388           if (size>accuseSize)
389             accuseSize = size;
390         }
391       op = IC_RIGHT (ic);
392       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
393         {
394           accuse = 1;
395           size = getSize (OP_SYMBOL (op)->type);
396           if (size>accuseSize)
397             accuseSize = size;
398         }
399     }
400   
401   if (accuseSize)
402     return accuseSize;
403   else
404     return accuse;
405 }
406
407
408 /*-----------------------------------------------------------------*/
409 /* aopForSym - for a true symbol                                   */
410 /*-----------------------------------------------------------------*/
411 static asmop *
412 aopForSym (iCode * ic, symbol * sym, bool result)
413 {
414   asmop *aop;
415   memmap *space;
416
417   wassertl (ic != NULL, "Got a null iCode");
418   wassertl (sym != NULL, "Got a null symbol");
419
420   space = SPEC_OCLS (sym->etype);
421
422   /* if already has one */
423   if (sym->aop)
424     return sym->aop;
425
426   /* assign depending on the storage class */
427   /* if it is on the stack or indirectly addressable */
428   /* space we need to assign either r0 or r1 to it   */
429   if (sym->onStack || sym->iaccess)
430     {
431       sym->aop = aop = newAsmop (0);
432       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
433       aop->size = getSize (sym->type);
434
435       /* now assign the address of the variable to
436          the pointer register */
437       if (aop->type != AOP_STK)
438         {
439
440           if (sym->onStack)
441             {
442               if (_G.accInUse || leftRightUseAcc (ic))
443                 emitcode ("push", "acc");
444
445               emitcode ("mov", "a,_bp");
446               emitcode ("add", "a,#0x%02x",
447                         ((sym->stack < 0) ?
448                          ((char) (sym->stack - _G.nRegsSaved)) :
449                          ((char) sym->stack)) & 0xff);
450               emitcode ("mov", "%s,a",
451                         aop->aopu.aop_ptr->name);
452
453               if (_G.accInUse || leftRightUseAcc (ic))
454                 emitcode ("pop", "acc");
455             }
456           else
457             emitcode ("mov", "%s,#%s",
458                       aop->aopu.aop_ptr->name,
459                       sym->rname);
460           aop->paged = space->paged;
461         }
462       else
463         aop->aopu.aop_stk = sym->stack;
464       return aop;
465     }
466
467   /* if in bit space */
468   if (IN_BITSPACE (space))
469     {
470       sym->aop = aop = newAsmop (AOP_CRY);
471       aop->aopu.aop_dir = sym->rname;
472       aop->size = getSize (sym->type);
473       return aop;
474     }
475   /* if it is in direct space */
476   if (IN_DIRSPACE (space))
477     {
478       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
479       //printTypeChainRaw(sym->type, NULL);
480       //printf("space = %s\n", space ? space->sname : "NULL");
481       sym->aop = aop = newAsmop (AOP_DIR);
482       aop->aopu.aop_dir = sym->rname;
483       aop->size = getSize (sym->type);
484       return aop;
485     }
486
487   /* special case for a function */
488   if (IS_FUNC (sym->type))
489     {
490       sym->aop = aop = newAsmop (AOP_IMMD);
491       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
492       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
493       aop->size = FPTRSIZE;
494       return aop;
495     }
496
497   /* only remaining is far space */
498   /* in which case DPTR gets the address */
499   sym->aop = aop = newAsmop (AOP_DPTR);
500   emitcode ("mov", "dptr,#%s", sym->rname);
501   aop->size = getSize (sym->type);
502
503   /* if it is in code space */
504   if (IN_CODESPACE (space))
505     aop->code = 1;
506
507   return aop;
508 }
509
510 /*-----------------------------------------------------------------*/
511 /* aopForRemat - rematerialzes an object                           */
512 /*-----------------------------------------------------------------*/
513 static asmop *
514 aopForRemat (symbol * sym)
515 {
516   iCode *ic = sym->rematiCode;
517   asmop *aop = newAsmop (AOP_IMMD);
518   int ptr_type=0;
519   int val = 0;
520
521   for (;;)
522     {
523       if (ic->op == '+')
524         val += (int) operandLitValue (IC_RIGHT (ic));
525       else if (ic->op == '-')
526         val -= (int) operandLitValue (IC_RIGHT (ic));
527       else if (IS_CAST_ICODE(ic)) {
528               sym_link *from_type = operandType(IC_RIGHT(ic));
529               aop->aopu.aop_immd.from_cast_remat = 1;
530               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
531               ptr_type = DCL_TYPE(from_type);
532               if (ptr_type == IPOINTER) {
533                 // bug #481053
534                 ptr_type = POINTER;
535               }
536               continue ;
537       } else break;
538
539       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
540     }
541
542   if (val)
543     sprintf (buffer, "(%s %c 0x%04x)",
544              OP_SYMBOL (IC_LEFT (ic))->rname,
545              val >= 0 ? '+' : '-',
546              abs (val) & 0xffff);
547   else
548     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
549
550   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
551   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
552   /* set immd2 field if required */
553   if (aop->aopu.aop_immd.from_cast_remat) {
554           sprintf(buffer,"#0x%02x",ptr_type);
555           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
556           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
557   }
558
559   return aop;
560 }
561
562 /*-----------------------------------------------------------------*/
563 /* regsInCommon - two operands have some registers in common       */
564 /*-----------------------------------------------------------------*/
565 static bool
566 regsInCommon (operand * op1, operand * op2)
567 {
568   symbol *sym1, *sym2;
569   int i;
570
571   /* if they have registers in common */
572   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
573     return FALSE;
574
575   sym1 = OP_SYMBOL (op1);
576   sym2 = OP_SYMBOL (op2);
577
578   if (sym1->nRegs == 0 || sym2->nRegs == 0)
579     return FALSE;
580
581   for (i = 0; i < sym1->nRegs; i++)
582     {
583       int j;
584       if (!sym1->regs[i])
585         continue;
586
587       for (j = 0; j < sym2->nRegs; j++)
588         {
589           if (!sym2->regs[j])
590             continue;
591
592           if (sym2->regs[j] == sym1->regs[i])
593             return TRUE;
594         }
595     }
596
597   return FALSE;
598 }
599
600 /*-----------------------------------------------------------------*/
601 /* operandsEqu - equivalent                                        */
602 /*-----------------------------------------------------------------*/
603 static bool
604 operandsEqu (operand * op1, operand * op2)
605 {
606   symbol *sym1, *sym2;
607
608   /* if they not symbols */
609   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
610     return FALSE;
611
612   sym1 = OP_SYMBOL (op1);
613   sym2 = OP_SYMBOL (op2);
614
615   /* if both are itemps & one is spilt
616      and the other is not then false */
617   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
618       sym1->isspilt != sym2->isspilt)
619     return FALSE;
620
621   /* if they are the same */
622   if (sym1 == sym2)
623     return TRUE;
624
625   if (strcmp (sym1->rname, sym2->rname) == 0)
626     return TRUE;
627
628
629   /* if left is a tmp & right is not */
630   if (IS_ITEMP (op1) &&
631       !IS_ITEMP (op2) &&
632       sym1->isspilt &&
633       (sym1->usl.spillLoc == sym2))
634     return TRUE;
635
636   if (IS_ITEMP (op2) &&
637       !IS_ITEMP (op1) &&
638       sym2->isspilt &&
639       sym1->level > 0 &&
640       (sym2->usl.spillLoc == sym1))
641     return TRUE;
642
643   return FALSE;
644 }
645
646 /*-----------------------------------------------------------------*/
647 /* sameRegs - two asmops have the same registers                   */
648 /*-----------------------------------------------------------------*/
649 static bool
650 sameRegs (asmop * aop1, asmop * aop2)
651 {
652   int i;
653
654   if (aop1 == aop2)
655     return TRUE;
656
657   if (aop1->type != AOP_REG ||
658       aop2->type != AOP_REG)
659     return FALSE;
660
661   if (aop1->size != aop2->size)
662     return FALSE;
663
664   for (i = 0; i < aop1->size; i++)
665     if (aop1->aopu.aop_reg[i] !=
666         aop2->aopu.aop_reg[i])
667       return FALSE;
668
669   return TRUE;
670 }
671
672 /*-----------------------------------------------------------------*/
673 /* aopOp - allocates an asmop for an operand  :                    */
674 /*-----------------------------------------------------------------*/
675 static void
676 aopOp (operand * op, iCode * ic, bool result)
677 {
678   asmop *aop;
679   symbol *sym;
680   int i;
681
682   if (!op)
683     return;
684
685   /* if this a literal */
686   if (IS_OP_LITERAL (op))
687     {
688       op->aop = aop = newAsmop (AOP_LIT);
689       aop->aopu.aop_lit = op->operand.valOperand;
690       aop->size = getSize (operandType (op));
691       return;
692     }
693
694   /* if already has a asmop then continue */
695   if (op->aop )
696     return;
697
698   /* if the underlying symbol has a aop */
699   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
700     {
701       op->aop = OP_SYMBOL (op)->aop;
702       return;
703     }
704
705   /* if this is a true symbol */
706   if (IS_TRUE_SYMOP (op))
707     {
708       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
709       return;
710     }
711
712   /* this is a temporary : this has
713      only four choices :
714      a) register
715      b) spillocation
716      c) rematerialize
717      d) conditional
718      e) can be a return use only */
719
720   sym = OP_SYMBOL (op);
721
722   /* if the type is a conditional */
723   if (sym->regType == REG_CND)
724     {
725       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
726       aop->size = 0;
727       return;
728     }
729
730   /* if it is spilt then two situations
731      a) is rematerialize
732      b) has a spill location */
733   if (sym->isspilt || sym->nRegs == 0)
734     {
735
736       /* rematerialize it NOW */
737       if (sym->remat)
738         {
739           sym->aop = op->aop = aop =
740             aopForRemat (sym);
741           aop->size = getSize (sym->type);
742           return;
743         }
744
745       if (sym->accuse)
746         {
747           int i;
748           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
749           aop->size = getSize (sym->type);
750           for (i = 0; i < 2; i++)
751             aop->aopu.aop_str[i] = accUse[i];
752           return;
753         }
754
755       if (sym->ruonly)
756         {
757           unsigned i;
758
759           aop = op->aop = sym->aop = newAsmop (AOP_STR);
760           aop->size = getSize (sym->type);
761           for (i = 0; i < fReturnSizeMCS51; i++)
762             aop->aopu.aop_str[i] = fReturn[i];
763           return;
764         }
765
766       if (sym->usl.spillLoc)
767         {
768           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
769             {
770               /* force a new aop if sizes differ */
771               sym->usl.spillLoc->aop = NULL;
772             }
773           sym->aop = op->aop = aop =
774                      aopForSym (ic, sym->usl.spillLoc, result);
775           aop->size = getSize (sym->type);
776           return;
777         }
778       
779       /* else must be a dummy iTemp */
780       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
781       aop->size = getSize (sym->type);
782       return;
783     }
784
785   /* must be in a register */
786   sym->aop = op->aop = aop = newAsmop (AOP_REG);
787   aop->size = sym->nRegs;
788   for (i = 0; i < sym->nRegs; i++)
789     aop->aopu.aop_reg[i] = sym->regs[i];
790 }
791
792 /*-----------------------------------------------------------------*/
793 /* freeAsmop - free up the asmop given to an operand               */
794 /*----------------------------------------------------------------*/
795 static void
796 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
797 {
798   asmop *aop;
799
800   if (!op)
801     aop = aaop;
802   else
803     aop = op->aop;
804
805   if (!aop)
806     return;
807
808   if (aop->freed)
809     goto dealloc;
810
811   aop->freed = 1;
812
813   /* depending on the asmop type only three cases need work AOP_RO
814      , AOP_R1 && AOP_STK */
815   switch (aop->type)
816     {
817     case AOP_R0:
818       if (_G.r0Pushed)
819         {
820           if (pop)
821             {
822               emitcode ("pop", "ar0");
823               _G.r0Pushed--;
824             }
825         }
826       bitVectUnSetBit (ic->rUsed, R0_IDX);
827       break;
828
829     case AOP_R1:
830       if (_G.r1Pushed)
831         {
832           if (pop)
833             {
834               emitcode ("pop", "ar1");
835               _G.r1Pushed--;
836             }
837         }
838       bitVectUnSetBit (ic->rUsed, R1_IDX);
839       break;
840
841     case AOP_STK:
842       {
843         int sz = aop->size;
844         int stk = aop->aopu.aop_stk + aop->size - 1;
845         bitVectUnSetBit (ic->rUsed, R0_IDX);
846         bitVectUnSetBit (ic->rUsed, R1_IDX);
847
848         getFreePtr (ic, &aop, FALSE);
849
850         if (stk)
851           {
852             emitcode ("mov", "a,_bp");
853             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
854             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
855           }
856         else
857           {
858             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
859           }
860
861         while (sz--)
862           {
863             emitcode ("pop", "acc");
864             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
865             if (!sz)
866               break;
867             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
868           }
869         op->aop = aop;
870         freeAsmop (op, NULL, ic, TRUE);
871         if (_G.r1Pushed)
872           {
873             emitcode ("pop", "ar1");
874             _G.r1Pushed--;
875           }
876
877         if (_G.r0Pushed)
878           {
879             emitcode ("pop", "ar0");
880             _G.r0Pushed--;
881           }
882       }
883     }
884
885 dealloc:
886   /* all other cases just dealloc */
887   if (op)
888     {
889       op->aop = NULL;
890       if (IS_SYMOP (op))
891         {
892           OP_SYMBOL (op)->aop = NULL;
893           /* if the symbol has a spill */
894           if (SPIL_LOC (op))
895             SPIL_LOC (op)->aop = NULL;
896         }
897     }
898 }
899
900 /*-----------------------------------------------------------------*/
901 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
902 /*                 clobber the accumulator                         */
903 /*-----------------------------------------------------------------*/
904 static bool
905 aopGetUsesAcc (asmop *aop, int offset)
906 {
907   if (offset > (aop->size - 1))
908     return FALSE;
909
910   switch (aop->type)
911     {
912
913     case AOP_R0:
914     case AOP_R1:
915       if (aop->paged)
916         return TRUE;
917       return FALSE;
918     case AOP_DPTR:
919       return TRUE;
920     case AOP_IMMD:
921       return FALSE;
922     case AOP_DIR:
923       return FALSE;
924     case AOP_REG:
925       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
926       return FALSE;
927     case AOP_CRY:
928       return TRUE;
929     case AOP_ACC:
930       return TRUE;
931     case AOP_LIT:
932       return FALSE;
933     case AOP_STR:
934       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
935         return TRUE;
936       return FALSE;
937     case AOP_DUMMY:
938       return FALSE;
939     default:
940       /* Error case --- will have been caught already */
941       wassert(0);
942       return FALSE;
943     }
944 }
945
946 /*-----------------------------------------------------------------*/
947 /* aopGet - for fetching value of the aop                          */
948 /*-----------------------------------------------------------------*/
949 static char *
950 aopGet (asmop * aop, int offset, bool bit16, bool dname)
951 {
952   char *s = buffer;
953   char *rs;
954
955   /* offset is greater than
956      size then zero */
957   if (offset > (aop->size - 1) &&
958       aop->type != AOP_LIT)
959     return zero;
960
961   /* depending on type */
962   switch (aop->type)
963     {
964     case AOP_DUMMY:
965       return zero;
966       
967     case AOP_R0:
968     case AOP_R1:
969       /* if we need to increment it */
970       while (offset > aop->coff)
971         {
972           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
973           aop->coff++;
974         }
975
976       while (offset < aop->coff)
977         {
978           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
979           aop->coff--;
980         }
981
982       aop->coff = offset;
983       if (aop->paged)
984         {
985           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
986           return (dname ? "acc" : "a");
987         }
988       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
989       rs = Safe_calloc (1, strlen (s) + 1);
990       strcpy (rs, s);
991       return rs;
992
993     case AOP_DPTR:
994       if (aop->code && aop->coff==0 && offset>=1) {
995         emitcode ("mov", "a,#0x%02x", offset);
996         emitcode ("movc", "a,@a+dptr");
997         return (dname ? "acc" : "a");
998       }
999
1000       while (offset > aop->coff)
1001         {
1002           emitcode ("inc", "dptr");
1003           aop->coff++;
1004         }
1005
1006       while (offset < aop->coff)
1007         {
1008           emitcode ("lcall", "__decdptr");
1009           aop->coff--;
1010         }
1011
1012       aop->coff = offset;
1013       if (aop->code)
1014         {
1015           emitcode ("clr", "a");
1016           emitcode ("movc", "a,@a+dptr");
1017         }
1018       else
1019         {
1020           emitcode ("movx", "a,@dptr");
1021         }
1022       return (dname ? "acc" : "a");
1023
1024
1025     case AOP_IMMD:
1026       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1027               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1028       } else if (bit16)
1029         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1030       else if (offset)
1031         sprintf (s, "#(%s >> %d)",
1032                  aop->aopu.aop_immd.aop_immd1,
1033                  offset * 8);
1034       else
1035         sprintf (s, "#%s",
1036                  aop->aopu.aop_immd.aop_immd1);
1037       rs = Safe_calloc (1, strlen (s) + 1);
1038       strcpy (rs, s);
1039       return rs;
1040
1041     case AOP_DIR:
1042       if (offset)
1043         sprintf (s, "(%s + %d)",
1044                  aop->aopu.aop_dir,
1045                  offset);
1046       else
1047         sprintf (s, "%s", aop->aopu.aop_dir);
1048       rs = Safe_calloc (1, strlen (s) + 1);
1049       strcpy (rs, s);
1050       return rs;
1051
1052     case AOP_REG:
1053       if (dname)
1054         return aop->aopu.aop_reg[offset]->dname;
1055       else
1056         return aop->aopu.aop_reg[offset]->name;
1057
1058     case AOP_CRY:
1059       emitcode ("clr", "a");
1060       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1061       emitcode ("rlc", "a");
1062       return (dname ? "acc" : "a");
1063
1064     case AOP_ACC:
1065       if (!offset && dname)
1066         return "acc";
1067       return aop->aopu.aop_str[offset];
1068
1069     case AOP_LIT:
1070       return aopLiteral (aop->aopu.aop_lit, offset);
1071
1072     case AOP_STR:
1073       aop->coff = offset;
1074       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1075           dname)
1076         return "acc";
1077
1078       return aop->aopu.aop_str[offset];
1079
1080     }
1081
1082   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1083           "aopget got unsupported aop->type");
1084   exit (1);
1085 }
1086 /*-----------------------------------------------------------------*/
1087 /* aopPut - puts a string for a aop                                */
1088 /*-----------------------------------------------------------------*/
1089 static void
1090 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1091 {
1092   char *d = buffer;
1093
1094   if (aop->size && offset > (aop->size - 1))
1095     {
1096       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1097               "aopPut got offset > aop->size");
1098       exit (1);
1099     }
1100
1101   /* will assign value to value */
1102   /* depending on where it is ofcourse */
1103   switch (aop->type)
1104     {
1105     case AOP_DUMMY:
1106       MOVA (s);         /* read s in case it was volatile */
1107       break;
1108       
1109     case AOP_DIR:
1110       if (offset)
1111         sprintf (d, "(%s + %d)",
1112                  aop->aopu.aop_dir, offset);
1113       else
1114         sprintf (d, "%s", aop->aopu.aop_dir);
1115
1116       if (strcmp (d, s) ||
1117           bvolatile)
1118         emitcode ("mov", "%s,%s", d, s);
1119
1120       break;
1121
1122     case AOP_REG:
1123       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1124           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1125         {
1126           if (*s == '@' ||
1127               strcmp (s, "r0") == 0 ||
1128               strcmp (s, "r1") == 0 ||
1129               strcmp (s, "r2") == 0 ||
1130               strcmp (s, "r3") == 0 ||
1131               strcmp (s, "r4") == 0 ||
1132               strcmp (s, "r5") == 0 ||
1133               strcmp (s, "r6") == 0 ||
1134               strcmp (s, "r7") == 0)
1135             emitcode ("mov", "%s,%s",
1136                       aop->aopu.aop_reg[offset]->dname, s);
1137           else
1138             emitcode ("mov", "%s,%s",
1139                       aop->aopu.aop_reg[offset]->name, s);
1140         }
1141       break;
1142
1143     case AOP_DPTR:
1144       if (aop->code)
1145         {
1146           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1147                   "aopPut writing to code space");
1148           exit (1);
1149         }
1150
1151       while (offset > aop->coff)
1152         {
1153           aop->coff++;
1154           emitcode ("inc", "dptr");
1155         }
1156
1157       while (offset < aop->coff)
1158         {
1159           aop->coff--;
1160           emitcode ("lcall", "__decdptr");
1161         }
1162
1163       aop->coff = offset;
1164
1165       /* if not in accumulater */
1166       MOVA (s);
1167
1168       emitcode ("movx", "@dptr,a");
1169       break;
1170
1171     case AOP_R0:
1172     case AOP_R1:
1173       while (offset > aop->coff)
1174         {
1175           aop->coff++;
1176           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1177         }
1178       while (offset < aop->coff)
1179         {
1180           aop->coff--;
1181           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1182         }
1183       aop->coff = offset;
1184
1185       if (aop->paged)
1186         {
1187           MOVA (s);
1188           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1189
1190         }
1191       else if (*s == '@')
1192         {
1193           MOVA (s);
1194           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1195         }
1196       else if (strcmp (s, "r0") == 0 ||
1197                strcmp (s, "r1") == 0 ||
1198                strcmp (s, "r2") == 0 ||
1199                strcmp (s, "r3") == 0 ||
1200                strcmp (s, "r4") == 0 ||
1201                strcmp (s, "r5") == 0 ||
1202                strcmp (s, "r6") == 0 ||
1203                strcmp (s, "r7") == 0)
1204         {
1205           char buffer[10];
1206           sprintf (buffer, "a%s", s);
1207           emitcode ("mov", "@%s,%s",
1208                     aop->aopu.aop_ptr->name, buffer);
1209         }
1210       else
1211         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1212
1213       break;
1214
1215     case AOP_STK:
1216       if (strcmp (s, "a") == 0)
1217         emitcode ("push", "acc");
1218       else
1219         if (*s=='@') {
1220           MOVA(s);
1221           emitcode ("push", "acc");
1222         } else {
1223           emitcode ("push", s);
1224         }
1225
1226       break;
1227
1228     case AOP_CRY:
1229       /* if bit variable */
1230       if (!aop->aopu.aop_dir)
1231         {
1232           emitcode ("clr", "a");
1233           emitcode ("rlc", "a");
1234         }
1235       else
1236         {
1237           if (s == zero)
1238             emitcode ("clr", "%s", aop->aopu.aop_dir);
1239           else if (s == one)
1240             emitcode ("setb", "%s", aop->aopu.aop_dir);
1241           else if (!strcmp (s, "c"))
1242             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1243           else
1244             {
1245               if (strcmp (s, "a"))
1246                 {
1247                   MOVA (s);
1248                 }
1249               {
1250                 /* set C, if a >= 1 */
1251                 emitcode ("add", "a,#0xff");
1252                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1253               }
1254             }
1255         }
1256       break;
1257
1258     case AOP_STR:
1259       aop->coff = offset;
1260       if (strcmp (aop->aopu.aop_str[offset], s) ||
1261           bvolatile)
1262         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1263       break;
1264
1265     case AOP_ACC:
1266       aop->coff = offset;
1267       if (!offset && (strcmp (s, "acc") == 0) &&
1268           !bvolatile)
1269         break;
1270
1271       if (strcmp (aop->aopu.aop_str[offset], s) &&
1272           !bvolatile)
1273         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1274       break;
1275
1276     default:
1277       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1278               "aopPut got unsupported aop->type");
1279       exit (1);
1280     }
1281
1282 }
1283
1284
1285 #if 0
1286 /*-----------------------------------------------------------------*/
1287 /* pointToEnd :- points to the last byte of the operand            */
1288 /*-----------------------------------------------------------------*/
1289 static void
1290 pointToEnd (asmop * aop)
1291 {
1292   int count;
1293   if (!aop)
1294     return;
1295
1296   aop->coff = count = (aop->size - 1);
1297   switch (aop->type)
1298     {
1299     case AOP_R0:
1300     case AOP_R1:
1301       while (count--)
1302         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1303       break;
1304     case AOP_DPTR:
1305       while (count--)
1306         emitcode ("inc", "dptr");
1307       break;
1308     }
1309
1310 }
1311 #endif
1312
1313 /*-----------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should        */
1315 /*-----------------------------------------------------------------*/
1316 static void
1317 reAdjustPreg (asmop * aop)
1318 {
1319   if ((aop->coff==0) || aop->size <= 1)
1320     return;
1321
1322   switch (aop->type)
1323     {
1324     case AOP_R0:
1325     case AOP_R1:
1326       while (aop->coff--)
1327         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1328       break;
1329     case AOP_DPTR:
1330       while (aop->coff--)
1331         {
1332           emitcode ("lcall", "__decdptr");
1333         }
1334       break;
1335     }
1336   aop->coff = 0;
1337 }
1338
1339 #define AOP(op) op->aop
1340 #define AOP_TYPE(op) AOP(op)->type
1341 #define AOP_SIZE(op) AOP(op)->size
1342 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1343                        AOP_TYPE(x) == AOP_R0))
1344
1345 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1346                         AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1347
1348 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1349                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1350                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1351
1352
1353 /*-----------------------------------------------------------------*/
1354 /* opIsGptr: returns non-zero if the passed operand is       */
1355 /* a generic pointer type.             */
1356 /*-----------------------------------------------------------------*/
1357 static int
1358 opIsGptr (operand * op)
1359 {
1360   sym_link *type = operandType (op);
1361
1362   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1363     {
1364       return 1;
1365     }
1366   return 0;
1367 }
1368
1369 /*-----------------------------------------------------------------*/
1370 /* getDataSize - get the operand data size                         */
1371 /*-----------------------------------------------------------------*/
1372 static int
1373 getDataSize (operand * op)
1374 {
1375   int size;
1376   size = AOP_SIZE (op);
1377   if (size == GPTRSIZE)
1378     {
1379       sym_link *type = operandType (op);
1380       if (IS_GENPTR (type))
1381         {
1382           /* generic pointer; arithmetic operations
1383            * should ignore the high byte (pointer type).
1384            */
1385           size--;
1386         }
1387     }
1388   return size;
1389 }
1390
1391 /*-----------------------------------------------------------------*/
1392 /* outAcc - output Acc                                             */
1393 /*-----------------------------------------------------------------*/
1394 static void
1395 outAcc (operand * result)
1396 {
1397   int size, offset;
1398   size = getDataSize (result);
1399   if (size)
1400     {
1401       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1402       size--;
1403       offset = 1;
1404       /* unsigned or positive */
1405       while (size--)
1406         {
1407           aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1408         }
1409     }
1410 }
1411
1412 /*-----------------------------------------------------------------*/
1413 /* outBitC - output a bit C                                        */
1414 /*-----------------------------------------------------------------*/
1415 static void
1416 outBitC (operand * result)
1417 {
1418   /* if the result is bit */
1419   if (AOP_TYPE (result) == AOP_CRY)
1420     aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1421   else
1422     {
1423       emitcode ("clr", "a");
1424       emitcode ("rlc", "a");
1425       outAcc (result);
1426     }
1427 }
1428
1429 /*-----------------------------------------------------------------*/
1430 /* toBoolean - emit code for orl a,operator(sizeop)                */
1431 /*-----------------------------------------------------------------*/
1432 static void
1433 toBoolean (operand * oper)
1434 {
1435   int size = AOP_SIZE (oper) - 1;
1436   int offset = 1;
1437   MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1438   while (size--)
1439     emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1440 }
1441
1442
1443 /*-----------------------------------------------------------------*/
1444 /* genNot - generate code for ! operation                          */
1445 /*-----------------------------------------------------------------*/
1446 static void
1447 genNot (iCode * ic)
1448 {
1449   symbol *tlbl;
1450
1451   D(emitcode (";     genNot",""));
1452
1453   /* assign asmOps to operand & result */
1454   aopOp (IC_LEFT (ic), ic, FALSE);
1455   aopOp (IC_RESULT (ic), ic, TRUE);
1456
1457   /* if in bit space then a special case */
1458   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1459     {
1460       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1461       emitcode ("cpl", "c");
1462       outBitC (IC_RESULT (ic));
1463       goto release;
1464     }
1465
1466   toBoolean (IC_LEFT (ic));
1467
1468   tlbl = newiTempLabel (NULL);
1469   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1470   emitcode ("", "%05d$:", tlbl->key + 100);
1471   outBitC (IC_RESULT (ic));
1472
1473 release:
1474   /* release the aops */
1475   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1476   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1477 }
1478
1479
1480 /*-----------------------------------------------------------------*/
1481 /* genCpl - generate code for complement                           */
1482 /*-----------------------------------------------------------------*/
1483 static void
1484 genCpl (iCode * ic)
1485 {
1486   int offset = 0;
1487   int size;
1488   symbol *tlbl;
1489
1490   D(emitcode (";     genCpl",""));
1491
1492   /* assign asmOps to operand & result */
1493   aopOp (IC_LEFT (ic), ic, FALSE);
1494   aopOp (IC_RESULT (ic), ic, TRUE);
1495
1496   /* special case if in bit space */
1497   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1498     {
1499       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1500         {
1501           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1502           emitcode ("cpl", "c");
1503           emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1504           goto release;
1505         }
1506
1507       tlbl=newiTempLabel(NULL);
1508       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1509           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1510           IS_AOP_PREG (IC_LEFT (ic)))
1511         {
1512           emitcode ("cjne", "%s,#0x01,%05d$",
1513                     aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1514                     tlbl->key + 100);
1515         }
1516       else
1517         {
1518           char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1519           MOVA (l);
1520           emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1521         }
1522       emitcode ("", "%05d$:", tlbl->key + 100);
1523       outBitC (IC_RESULT(ic));
1524       goto release;
1525     }
1526
1527   size = AOP_SIZE (IC_RESULT (ic));
1528   while (size--)
1529     {
1530       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1531       MOVA (l);
1532       emitcode ("cpl", "a");
1533       aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1534     }
1535
1536
1537 release:
1538   /* release the aops */
1539   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1540   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1541 }
1542
1543 /*-----------------------------------------------------------------*/
1544 /* genUminusFloat - unary minus for floating points                */
1545 /*-----------------------------------------------------------------*/
1546 static void
1547 genUminusFloat (operand * op, operand * result)
1548 {
1549   int size, offset = 0;
1550   char *l;
1551
1552   D(emitcode (";     genUminusFloat",""));
1553
1554   /* for this we just copy and then flip the bit */
1555
1556   size = AOP_SIZE (op) - 1;
1557
1558   while (size--)
1559     {
1560       aopPut (AOP (result),
1561               aopGet (AOP (op), offset, FALSE, FALSE),
1562               offset,
1563               isOperandVolatile (result, FALSE));
1564       offset++;
1565     }
1566
1567   l = aopGet (AOP (op), offset, FALSE, FALSE);
1568
1569   MOVA (l);
1570
1571   emitcode ("cpl", "acc.7");
1572   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1573 }
1574
1575 /*-----------------------------------------------------------------*/
1576 /* genUminus - unary minus code generation                         */
1577 /*-----------------------------------------------------------------*/
1578 static void
1579 genUminus (iCode * ic)
1580 {
1581   int offset, size;
1582   sym_link *optype, *rtype;
1583
1584
1585   D(emitcode (";     genUminus",""));
1586
1587   /* assign asmops */
1588   aopOp (IC_LEFT (ic), ic, FALSE);
1589   aopOp (IC_RESULT (ic), ic, TRUE);
1590
1591   /* if both in bit space then special
1592      case */
1593   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1594       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1595     {
1596
1597       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1598       emitcode ("cpl", "c");
1599       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1600       goto release;
1601     }
1602
1603   optype = operandType (IC_LEFT (ic));
1604   rtype = operandType (IC_RESULT (ic));
1605
1606   /* if float then do float stuff */
1607   if (IS_FLOAT (optype))
1608     {
1609       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1610       goto release;
1611     }
1612
1613   /* otherwise subtract from zero */
1614   size = AOP_SIZE (IC_LEFT (ic));
1615   offset = 0;
1616   //CLRC ;
1617   while (size--)
1618     {
1619       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1620       if (!strcmp (l, "a"))
1621         {
1622           if (offset == 0)
1623             SETC;
1624           emitcode ("cpl", "a");
1625           emitcode ("addc", "a,#0");
1626         }
1627       else
1628         {
1629           if (offset == 0)
1630             CLRC;
1631           emitcode ("clr", "a");
1632           emitcode ("subb", "a,%s", l);
1633         }
1634       aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1635     }
1636
1637   /* if any remaining bytes in the result */
1638   /* we just need to propagate the sign   */
1639   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1640     {
1641       emitcode ("rlc", "a");
1642       emitcode ("subb", "a,acc");
1643       while (size--)
1644         aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1645     }
1646
1647 release:
1648   /* release the aops */
1649   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1650   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1651 }
1652
1653 /*-----------------------------------------------------------------*/
1654 /* saveRegisters - will look for a call and save the registers     */
1655 /*-----------------------------------------------------------------*/
1656 static void
1657 saveRegisters (iCode * lic)
1658 {
1659   int i;
1660   iCode *ic;
1661   bitVect *rsave;
1662
1663   /* look for call */
1664   for (ic = lic; ic; ic = ic->next)
1665     if (ic->op == CALL || ic->op == PCALL)
1666       break;
1667
1668   if (!ic)
1669     {
1670       fprintf (stderr, "found parameter push with no function call\n");
1671       return;
1672     }
1673
1674   /* if the registers have been saved already or don't need to be then
1675      do nothing */
1676   if (ic->regsSaved)
1677     return;
1678   if (IS_SYMOP(IC_LEFT(ic)) &&
1679       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1680        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1681     return;
1682   
1683   /* safe the registers in use at this time but skip the
1684      ones for the result */
1685   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1686                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1687
1688   ic->regsSaved = 1;
1689   if (options.useXstack)
1690     {
1691       if (bitVectBitValue (rsave, R0_IDX))
1692         emitcode ("mov", "b,r0");
1693       emitcode ("mov", "r0,%s", spname);
1694       for (i = 0; i < mcs51_nRegs; i++)
1695         {
1696           if (bitVectBitValue (rsave, i))
1697             {
1698               if (i == R0_IDX)
1699                 emitcode ("mov", "a,b");
1700               else
1701                 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1702               emitcode ("movx", "@r0,a");
1703               emitcode ("inc", "r0");
1704             }
1705         }
1706       emitcode ("mov", "%s,r0", spname);
1707       if (bitVectBitValue (rsave, R0_IDX))
1708         emitcode ("mov", "r0,b");
1709     }
1710   else
1711     for (i = 0; i < mcs51_nRegs; i++)
1712       {
1713         if (bitVectBitValue (rsave, i))
1714           emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1715       }
1716 }
1717
1718 /*-----------------------------------------------------------------*/
1719 /* unsaveRegisters - pop the pushed registers                      */
1720 /*-----------------------------------------------------------------*/
1721 static void
1722 unsaveRegisters (iCode * ic)
1723 {
1724   int i;
1725   bitVect *rsave;
1726
1727   /* restore the registers in use at this time but skip the
1728      ones for the result */
1729   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1730                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1731
1732   if (options.useXstack)
1733     {
1734       emitcode ("mov", "r0,%s", spname);
1735       for (i = mcs51_nRegs; i >= 0; i--)
1736         {
1737           if (bitVectBitValue (rsave, i))
1738             {
1739               emitcode ("dec", "r0");
1740               emitcode ("movx", "a,@r0");
1741               if (i == R0_IDX)
1742                 emitcode ("mov", "b,a");
1743               else
1744                 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1745             }
1746
1747         }
1748       emitcode ("mov", "%s,r0", spname);
1749       if (bitVectBitValue (rsave, R0_IDX))
1750         emitcode ("mov", "r0,b");
1751     }
1752   else
1753     for (i = mcs51_nRegs; i >= 0; i--)
1754       {
1755         if (bitVectBitValue (rsave, i))
1756           emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1757       }
1758
1759 }
1760
1761
1762 /*-----------------------------------------------------------------*/
1763 /* pushSide -                */
1764 /*-----------------------------------------------------------------*/
1765 static void
1766 pushSide (operand * oper, int size)
1767 {
1768   int offset = 0;
1769   while (size--)
1770     {
1771       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1772       if (AOP_TYPE (oper) != AOP_REG &&
1773           AOP_TYPE (oper) != AOP_DIR &&
1774           strcmp (l, "a"))
1775         {
1776           emitcode ("mov", "a,%s", l);
1777           emitcode ("push", "acc");
1778         }
1779       else
1780         emitcode ("push", "%s", l);
1781     }
1782 }
1783
1784 /*-----------------------------------------------------------------*/
1785 /* assignResultValue -               */
1786 /*-----------------------------------------------------------------*/
1787 static void
1788 assignResultValue (operand * oper)
1789 {
1790   int offset = 0;
1791   int size = AOP_SIZE (oper);
1792   while (size--)
1793     {
1794       aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1795       offset++;
1796     }
1797 }
1798
1799
1800 /*-----------------------------------------------------------------*/
1801 /* genXpush - pushes onto the external stack                       */
1802 /*-----------------------------------------------------------------*/
1803 static void
1804 genXpush (iCode * ic)
1805 {
1806   asmop *aop = newAsmop (0);
1807   regs *r;
1808   int size, offset = 0;
1809
1810   D(emitcode (";     genXpush",""));
1811
1812   aopOp (IC_LEFT (ic), ic, FALSE);
1813   r = getFreePtr (ic, &aop, FALSE);
1814
1815
1816   emitcode ("mov", "%s,_spx", r->name);
1817
1818   size = AOP_SIZE (IC_LEFT (ic));
1819   while (size--)
1820     {
1821
1822       char *l = aopGet (AOP (IC_LEFT (ic)),
1823                         offset++, FALSE, FALSE);
1824       MOVA (l);
1825       emitcode ("movx", "@%s,a", r->name);
1826       emitcode ("inc", "%s", r->name);
1827
1828     }
1829
1830
1831   emitcode ("mov", "_spx,%s", r->name);
1832
1833   freeAsmop (NULL, aop, ic, TRUE);
1834   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1835 }
1836
1837 /*-----------------------------------------------------------------*/
1838 /* genIpush - genrate code for pushing this gets a little complex  */
1839 /*-----------------------------------------------------------------*/
1840 static void
1841 genIpush (iCode * ic)
1842 {
1843   int size, offset = 0;
1844   char *l;
1845
1846   D(emitcode (";     genIpush",""));
1847
1848   /* if this is not a parm push : ie. it is spill push
1849      and spill push is always done on the local stack */
1850   if (!ic->parmPush)
1851     {
1852
1853       /* and the item is spilt then do nothing */
1854       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1855         return;
1856
1857       aopOp (IC_LEFT (ic), ic, FALSE);
1858       size = AOP_SIZE (IC_LEFT (ic));
1859       /* push it on the stack */
1860       while (size--)
1861         {
1862           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1863           if (*l == '#')
1864             {
1865               MOVA (l);
1866               l = "acc";
1867             }
1868           emitcode ("push", "%s", l);
1869         }
1870       return;
1871     }
1872
1873   /* this is a paramter push: in this case we call
1874      the routine to find the call and save those
1875      registers that need to be saved */
1876   saveRegisters (ic);
1877
1878   /* if use external stack then call the external
1879      stack pushing routine */
1880   if (options.useXstack)
1881     {
1882       genXpush (ic);
1883       return;
1884     }
1885
1886   /* then do the push */
1887   aopOp (IC_LEFT (ic), ic, FALSE);
1888
1889
1890   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1891   size = AOP_SIZE (IC_LEFT (ic));
1892
1893   while (size--)
1894     {
1895       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1896       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1897           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1898           strcmp (l, "a"))
1899         {
1900           emitcode ("mov", "a,%s", l);
1901           emitcode ("push", "acc");
1902         }
1903       else
1904         emitcode ("push", "%s", l);
1905     }
1906
1907   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1908 }
1909
1910 /*-----------------------------------------------------------------*/
1911 /* genIpop - recover the registers: can happen only for spilling   */
1912 /*-----------------------------------------------------------------*/
1913 static void
1914 genIpop (iCode * ic)
1915 {
1916   int size, offset;
1917
1918   D(emitcode (";     genIpop",""));
1919
1920   /* if the temp was not pushed then */
1921   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1922     return;
1923
1924   aopOp (IC_LEFT (ic), ic, FALSE);
1925   size = AOP_SIZE (IC_LEFT (ic));
1926   offset = (size - 1);
1927   while (size--)
1928     emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1929                                    FALSE, TRUE));
1930
1931   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1932 }
1933
1934 /*-----------------------------------------------------------------*/
1935 /* unsaveRBank - restores the resgister bank from stack            */
1936 /*-----------------------------------------------------------------*/
1937 static void
1938 unsaveRBank (int bank, iCode * ic, bool popPsw)
1939 {
1940   int i;
1941   asmop *aop = NULL;
1942   regs *r = NULL;
1943
1944   if (options.useXstack)
1945   {
1946       if (!ic)
1947       {
1948           /* Assume r0 is available for use. */
1949           r = mcs51_regWithIdx (R0_IDX);;          
1950       } 
1951       else
1952       {
1953           aop = newAsmop (0);
1954           r = getFreePtr (ic, &aop, FALSE);
1955       }
1956       emitcode ("mov", "%s,_spx", r->name);      
1957   }
1958   
1959   if (popPsw)
1960     {
1961       if (options.useXstack)
1962       {
1963           emitcode ("movx", "a,@%s", r->name);
1964           emitcode ("mov", "psw,a");
1965           emitcode ("dec", "%s", r->name);
1966         }
1967       else
1968       {
1969         emitcode ("pop", "psw");
1970       }
1971     }
1972
1973   for (i = (mcs51_nRegs - 1); i >= 0; i--)
1974     {
1975       if (options.useXstack)
1976         {
1977           emitcode ("movx", "a,@%s", r->name);
1978           emitcode ("mov", "(%s+%d),a",
1979                     regs8051[i].base, 8 * bank + regs8051[i].offset);
1980           emitcode ("dec", "%s", r->name);
1981
1982         }
1983       else
1984         emitcode ("pop", "(%s+%d)",
1985                   regs8051[i].base, 8 * bank + regs8051[i].offset);
1986     }
1987
1988   if (options.useXstack)
1989     {
1990       emitcode ("mov", "_spx,%s", r->name);
1991     }
1992     
1993   if (aop)
1994   {
1995       freeAsmop (NULL, aop, ic, TRUE);  
1996   }    
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* saveRBank - saves an entire register bank on the stack          */
2001 /*-----------------------------------------------------------------*/
2002 static void
2003 saveRBank (int bank, iCode * ic, bool pushPsw)
2004 {
2005   int i;
2006   asmop *aop = NULL;
2007   regs *r = NULL;
2008
2009   if (options.useXstack)
2010     {
2011       if (!ic)
2012       {
2013           /* Assume r0 is available for use. */
2014           r = mcs51_regWithIdx (R0_IDX);;
2015       }
2016       else
2017       {
2018           aop = newAsmop (0);
2019           r = getFreePtr (ic, &aop, FALSE);
2020       }
2021       emitcode ("mov", "%s,_spx", r->name);
2022     }
2023
2024   for (i = 0; i < mcs51_nRegs; i++)
2025     {
2026       if (options.useXstack)
2027         {
2028           emitcode ("inc", "%s", r->name);
2029           emitcode ("mov", "a,(%s+%d)",
2030                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2031           emitcode ("movx", "@%s,a", r->name);
2032         }
2033       else
2034         emitcode ("push", "(%s+%d)",
2035                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2036     }
2037
2038   if (pushPsw)
2039     {
2040       if (options.useXstack)
2041         {
2042           emitcode ("mov", "a,psw");
2043           emitcode ("movx", "@%s,a", r->name);
2044           emitcode ("inc", "%s", r->name);
2045           emitcode ("mov", "_spx,%s", r->name);
2046
2047         }
2048       else
2049       {
2050         emitcode ("push", "psw");
2051       }
2052
2053       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2054     }
2055
2056     if (aop)
2057     {
2058         freeAsmop (NULL, aop, ic, TRUE);
2059     }
2060
2061   if (ic)
2062   {  
2063       ic->bankSaved = 1;
2064   }
2065 }
2066
2067 /*-----------------------------------------------------------------*/
2068 /* genSend - gen code for SEND                                     */
2069 /*-----------------------------------------------------------------*/
2070 static void genSend(set *sendSet)
2071 {
2072     iCode *sic;
2073     int rb1_count = 0 ;
2074
2075     for (sic = setFirstItem (_G.sendSet); sic;
2076          sic = setNextItem (_G.sendSet)) {
2077           int size, offset = 0;
2078           aopOp (IC_LEFT (sic), sic, FALSE);
2079           size = AOP_SIZE (IC_LEFT (sic));
2080
2081           if (sic->argreg == 1) {
2082               while (size--) {
2083                   char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2084                                     FALSE, FALSE);
2085                   if (strcmp (l, fReturn[offset]))
2086                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2087                   offset++;
2088               }
2089               rb1_count = 0;
2090           } else {
2091               while (size--) {
2092                   emitcode ("mov","b1_%d,%s",rb1_count++,
2093                             aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2094               }
2095           }       
2096           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2097     }
2098 }
2099
2100 /*-----------------------------------------------------------------*/
2101 /* genCall - generates a call statement                            */
2102 /*-----------------------------------------------------------------*/
2103 static void
2104 genCall (iCode * ic)
2105 {
2106   sym_link *dtype;
2107 //  bool restoreBank = FALSE;
2108   bool swapBanks = FALSE;
2109
2110   D(emitcode(";     genCall",""));
2111
2112   dtype = operandType (IC_LEFT (ic));
2113   /* if send set is not empty the assign */
2114   if (_G.sendSet)
2115     {
2116         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2117             genSend(reverseSet(_G.sendSet));
2118         } else {
2119             genSend(_G.sendSet);
2120         }
2121
2122       _G.sendSet = NULL;
2123     }
2124
2125   /* if we are calling a not _naked function that is not using
2126      the same register bank then we need to save the
2127      destination registers on the stack */
2128   dtype = operandType (IC_LEFT (ic));
2129   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2130       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2131        !IFFUNC_ISISR (dtype))
2132   {
2133       swapBanks = TRUE;
2134   }
2135
2136   /* if caller saves & we have not saved then */
2137   if (!ic->regsSaved)
2138       saveRegisters (ic);
2139
2140   if (swapBanks)
2141   {
2142         emitcode ("mov", "psw,#0x%02x",
2143            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2144   }
2145
2146   /* make the call */
2147   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2148                             OP_SYMBOL (IC_LEFT (ic))->rname :
2149                             OP_SYMBOL (IC_LEFT (ic))->name));
2150
2151   if (swapBanks)
2152   {
2153        emitcode ("mov", "psw,#0x%02x",
2154           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2155   }
2156
2157   /* if we need assign a result value */
2158   if ((IS_ITEMP (IC_RESULT (ic)) &&
2159        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2160         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2161         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2162       IS_TRUE_SYMOP (IC_RESULT (ic)))
2163     {
2164
2165       _G.accInUse++;
2166       aopOp (IC_RESULT (ic), ic, FALSE);
2167       _G.accInUse--;
2168
2169       assignResultValue (IC_RESULT (ic));
2170
2171       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2172     }
2173
2174   /* adjust the stack for parameters if
2175      required */
2176   if (ic->parmBytes)
2177     {
2178       int i;
2179       if (ic->parmBytes > 3)
2180         {
2181           emitcode ("mov", "a,%s", spname);
2182           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2183           emitcode ("mov", "%s,a", spname);
2184         }
2185       else
2186         for (i = 0; i < ic->parmBytes; i++)
2187           emitcode ("dec", "%s", spname);
2188     }
2189
2190   /* if we hade saved some registers then unsave them */
2191   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2192     unsaveRegisters (ic);
2193
2194 //  /* if register bank was saved then pop them */
2195 //  if (restoreBank)
2196 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2197 }
2198
2199 /*-----------------------------------------------------------------*/
2200 /* -10l - generates a call by pointer statement                */
2201 /*-----------------------------------------------------------------*/
2202 static void
2203 genPcall (iCode * ic)
2204 {
2205   sym_link *dtype;
2206   symbol *rlbl = newiTempLabel (NULL);
2207 //  bool restoreBank=FALSE;
2208   bool swapBanks = FALSE;
2209
2210   D(emitcode(";     genPCall",""));
2211
2212   /* if caller saves & we have not saved then */
2213   if (!ic->regsSaved)
2214     saveRegisters (ic);
2215
2216   /* if we are calling a not _naked function that is not using
2217      the same register bank then we need to save the
2218      destination registers on the stack */
2219   dtype = operandType (IC_LEFT (ic))->next;
2220   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2221       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2222       !IFFUNC_ISISR (dtype))
2223   {
2224 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2225 //    restoreBank=TRUE;
2226       swapBanks = TRUE;
2227       // need caution message to user here
2228   }
2229
2230   /* push the return address on to the stack */
2231   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2232   emitcode ("push", "acc");
2233   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2234   emitcode ("push", "acc");
2235
2236   /* now push the calling address */
2237   aopOp (IC_LEFT (ic), ic, FALSE);
2238
2239   pushSide (IC_LEFT (ic), FPTRSIZE);
2240
2241   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2242
2243   /* if send set is not empty the assign */
2244   if (_G.sendSet)
2245     {
2246         genSend(reverseSet(_G.sendSet));
2247         _G.sendSet = NULL;
2248     }
2249
2250   if (swapBanks)
2251   {
2252         emitcode ("mov", "psw,#0x%02x", 
2253            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2254   }
2255
2256   /* make the call */
2257   emitcode ("ret", "");
2258   emitcode ("", "%05d$:", (rlbl->key + 100));
2259
2260
2261   if (swapBanks)
2262   {
2263        emitcode ("mov", "psw,#0x%02x", 
2264           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2265   }
2266
2267   /* if we need assign a result value */
2268   if ((IS_ITEMP (IC_RESULT (ic)) &&
2269        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2270         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2271       IS_TRUE_SYMOP (IC_RESULT (ic)))
2272     {
2273
2274       _G.accInUse++;
2275       aopOp (IC_RESULT (ic), ic, FALSE);
2276       _G.accInUse--;
2277
2278       assignResultValue (IC_RESULT (ic));
2279
2280       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2281     }
2282
2283   /* adjust the stack for parameters if
2284      required */
2285   if (ic->parmBytes)
2286     {
2287       int i;
2288       if (ic->parmBytes > 3)
2289         {
2290           emitcode ("mov", "a,%s", spname);
2291           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2292           emitcode ("mov", "%s,a", spname);
2293         }
2294       else
2295         for (i = 0; i < ic->parmBytes; i++)
2296           emitcode ("dec", "%s", spname);
2297
2298     }
2299
2300 //  /* if register bank was saved then unsave them */
2301 //  if (restoreBank)
2302 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2303
2304   /* if we hade saved some registers then
2305      unsave them */
2306   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2307     unsaveRegisters (ic);
2308 }
2309
2310 /*-----------------------------------------------------------------*/
2311 /* resultRemat - result  is rematerializable                       */
2312 /*-----------------------------------------------------------------*/
2313 static int
2314 resultRemat (iCode * ic)
2315 {
2316   if (SKIP_IC (ic) || ic->op == IFX)
2317     return 0;
2318
2319   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2320     {
2321       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2322       if (sym->remat && !POINTER_SET (ic))
2323         return 1;
2324     }
2325
2326   return 0;
2327 }
2328
2329 #if defined(__BORLANDC__) || defined(_MSC_VER)
2330 #define STRCASECMP stricmp
2331 #else
2332 #define STRCASECMP strcasecmp
2333 #endif
2334
2335 /*-----------------------------------------------------------------*/
2336 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2337 /*-----------------------------------------------------------------*/
2338 static int
2339 regsCmp(void *p1, void *p2)
2340 {
2341   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2342 }
2343
2344 static bool
2345 inExcludeList (char *s)
2346 {
2347   const char *p = setFirstItem(options.excludeRegsSet);
2348
2349   if (p == NULL || STRCASECMP(p, "none") == 0)
2350     return FALSE;
2351
2352
2353   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2354 }
2355
2356 /*-----------------------------------------------------------------*/
2357 /* genFunction - generated code for function entry                 */
2358 /*-----------------------------------------------------------------*/
2359 static void
2360 genFunction (iCode * ic)
2361 {
2362   symbol *sym;
2363   sym_link *ftype;
2364   bool   switchedPSW = FALSE;
2365   int calleesaves_saved_register = -1;
2366
2367   _G.nRegsSaved = 0;
2368   /* create the function header */
2369   emitcode (";", "-----------------------------------------");
2370   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2371   emitcode (";", "-----------------------------------------");
2372
2373   emitcode ("", "%s:", sym->rname);
2374   ftype = operandType (IC_LEFT (ic));
2375   _G.currentFunc = sym;
2376
2377   if (IFFUNC_ISNAKED(ftype))
2378   {
2379       emitcode(";", "naked function: no prologue.");
2380       return;
2381   }
2382
2383   /* here we need to generate the equates for the
2384      register bank if required */
2385   if (FUNC_REGBANK (ftype) != rbank)
2386     {
2387       int i;
2388
2389       rbank = FUNC_REGBANK (ftype);
2390       for (i = 0; i < mcs51_nRegs; i++)
2391         {
2392           if (strcmp (regs8051[i].base, "0") == 0)
2393             emitcode ("", "%s = 0x%02x",
2394                       regs8051[i].dname,
2395                       8 * rbank + regs8051[i].offset);
2396           else
2397             emitcode ("", "%s = %s + 0x%02x",
2398                       regs8051[i].dname,
2399                       regs8051[i].base,
2400                       8 * rbank + regs8051[i].offset);
2401         }
2402     }
2403
2404   /* if this is an interrupt service routine then
2405      save acc, b, dpl, dph  */
2406   if (IFFUNC_ISISR (sym->type))
2407     {
2408
2409       if (!inExcludeList ("acc"))
2410         emitcode ("push", "acc");
2411       if (!inExcludeList ("b"))
2412         emitcode ("push", "b");
2413       if (!inExcludeList ("dpl"))
2414         emitcode ("push", "dpl");
2415       if (!inExcludeList ("dph"))
2416         emitcode ("push", "dph");
2417       /* if this isr has no bank i.e. is going to
2418          run with bank 0 , then we need to save more
2419          registers :-) */
2420       if (!FUNC_REGBANK (sym->type))
2421         {
2422
2423           /* if this function does not call any other
2424              function then we can be economical and
2425              save only those registers that are used */
2426           if (!IFFUNC_HASFCALL(sym->type))
2427             {
2428               int i;
2429
2430               /* if any registers used */
2431               if (sym->regsUsed)
2432                 {
2433                   /* save the registers used */
2434                   for (i = 0; i < sym->regsUsed->size; i++)
2435                     {
2436                       if (bitVectBitValue (sym->regsUsed, i) ||
2437                           (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2438                         emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2439                     }
2440                 }
2441
2442             }
2443           else
2444             {
2445                 
2446               /* this function has  a function call cannot
2447                  determines register usage so we will have to push the
2448                  entire bank */
2449                 saveRBank (0, ic, FALSE);
2450                 if (options.parms_in_bank1) {
2451                     int i;
2452                     for (i=0; i < 8 ; i++ ) {
2453                         emitcode ("push","%s",rb1regs[i]);
2454                     }
2455                 }
2456             }
2457         }
2458         else
2459         {
2460             /* This ISR uses a non-zero bank.
2461              *
2462              * We assume that the bank is available for our
2463              * exclusive use.
2464              *
2465              * However, if this ISR calls a function which uses some
2466              * other bank, we must save that bank entirely.
2467              */
2468             unsigned long banksToSave = 0;
2469             
2470             if (IFFUNC_HASFCALL(sym->type))
2471             {
2472
2473 #define MAX_REGISTER_BANKS 4
2474
2475                 iCode *i;
2476                 int ix;
2477
2478                 for (i = ic; i; i = i->next)
2479                 {
2480                     if (i->op == ENDFUNCTION)
2481                     {
2482                         /* we got to the end OK. */
2483                         break;
2484                     }
2485                     
2486                     if (i->op == CALL)
2487                     {
2488                         sym_link *dtype;
2489                         
2490                         dtype = operandType (IC_LEFT(i));
2491                         if (dtype
2492                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2493                         {
2494                              /* Mark this bank for saving. */
2495                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2496                              {
2497                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2498                              }
2499                              else
2500                              {
2501                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2502                              }
2503                              
2504                              /* And note that we don't need to do it in 
2505                               * genCall.
2506                               */
2507                              i->bankSaved = 1;
2508                         }
2509                     }
2510                     if (i->op == PCALL)
2511                     {
2512                         /* This is a mess; we have no idea what
2513                          * register bank the called function might
2514                          * use.
2515                          *
2516                          * The only thing I can think of to do is
2517                          * throw a warning and hope.
2518                          */
2519                         werror(W_FUNCPTR_IN_USING_ISR);   
2520                     }
2521                 }
2522
2523                 if (banksToSave && options.useXstack)
2524                 {
2525                     /* Since we aren't passing it an ic, 
2526                      * saveRBank will assume r0 is available to abuse.
2527                      *
2528                      * So switch to our (trashable) bank now, so
2529                      * the caller's R0 isn't trashed.
2530                      */
2531                     emitcode ("push", "psw");
2532                     emitcode ("mov", "psw,#0x%02x", 
2533                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2534                     switchedPSW = TRUE;
2535                 }
2536                 
2537                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2538                 {
2539                      if (banksToSave & (1 << ix))
2540                      {
2541                          saveRBank(ix, NULL, FALSE);
2542                      }
2543                 }
2544             }
2545             // TODO: this needs a closer look
2546             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2547         }
2548     }
2549   else
2550     {
2551       /* if callee-save to be used for this function
2552          then save the registers being used in this function */
2553       if (IFFUNC_CALLEESAVES(sym->type))
2554         {
2555           int i;
2556
2557           /* if any registers used */
2558           if (sym->regsUsed)
2559             {
2560               /* save the registers used */
2561               for (i = 0; i < sym->regsUsed->size; i++)
2562                 {
2563                   if (bitVectBitValue (sym->regsUsed, i) ||
2564                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2565                     {
2566                       /* remember one saved register for later usage */
2567                       if (calleesaves_saved_register < 0)
2568                         calleesaves_saved_register = i;
2569                       emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2570                       _G.nRegsSaved++;
2571                     }
2572                 }
2573             }
2574         }
2575     }
2576
2577   /* set the register bank to the desired value */
2578   if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2579    && !switchedPSW)
2580     {
2581       emitcode ("push", "psw");
2582       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2583     }
2584
2585   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2586     {
2587
2588       if (options.useXstack)
2589         {
2590           emitcode ("mov", "r0,%s", spname);
2591           emitcode ("mov", "a,_bp");
2592           emitcode ("movx", "@r0,a");
2593           emitcode ("inc", "%s", spname);
2594         }
2595       else
2596         {
2597           /* set up the stack */
2598           emitcode ("push", "_bp");     /* save the callers stack  */
2599         }
2600       emitcode ("mov", "_bp,%s", spname);
2601     }
2602
2603   /* adjust the stack for the function */
2604   if (sym->stack)
2605     {
2606
2607       int i = sym->stack;
2608       if (i > 256)
2609         werror (W_STACK_OVERFLOW, sym->name);
2610
2611       if (i > 3 && sym->recvSize < 4)
2612         {
2613
2614           emitcode ("mov", "a,sp");
2615           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2616           emitcode ("mov", "sp,a");
2617
2618         }
2619       else if (i > 5)
2620         {
2621           if (IFFUNC_CALLEESAVES(sym->type))
2622             {
2623               /* if it's a callee-saves function we need a saved register */
2624               if (calleesaves_saved_register >= 0)
2625                 {
2626                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2627                   emitcode ("mov", "a,sp");
2628                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2629                   emitcode ("mov", "sp,a");
2630                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2631                 }
2632               else
2633                 /* do it the hard way */
2634                 while (i--)
2635                   emitcode ("inc", "sp");
2636             }
2637           else
2638             {
2639               /* not callee-saves, we can clobber r0 */
2640               emitcode ("mov", "r0,a");
2641               emitcode ("mov", "a,sp");
2642               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2643               emitcode ("mov", "sp,a");
2644               emitcode ("mov", "a,r0");
2645             }
2646         }
2647       else
2648         while (i--)
2649           emitcode ("inc", "sp");
2650     }
2651
2652   if (sym->xstack)
2653     {
2654
2655       emitcode ("mov", "a,_spx");
2656       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2657       emitcode ("mov", "_spx,a");
2658     }
2659   
2660   /* if critical function then turn interrupts off */
2661   if (IFFUNC_ISCRITICAL (ftype))
2662     {
2663       symbol *tlbl = newiTempLabel (NULL);
2664       emitcode ("setb", "c");
2665       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2666       emitcode ("clr", "c");
2667       emitcode ("", "%05d$:", (tlbl->key + 100));
2668       emitcode ("push", "psw"); /* save old ea via c in psw */
2669     }
2670 }
2671
2672 /*-----------------------------------------------------------------*/
2673 /* genEndFunction - generates epilogue for functions               */
2674 /*-----------------------------------------------------------------*/
2675 static void
2676 genEndFunction (iCode * ic)
2677 {
2678   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2679
2680   _G.currentFunc = NULL;
2681   if (IFFUNC_ISNAKED(sym->type))
2682   {
2683       emitcode(";", "naked function: no epilogue.");
2684       return;
2685   }
2686       
2687   if (IFFUNC_ISCRITICAL (sym->type))
2688     {
2689       emitcode ("pop", "psw"); /* restore ea via c in psw */
2690       emitcode ("mov", "ea,c");
2691     }
2692
2693   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2694     {
2695       emitcode ("mov", "%s,_bp", spname);
2696     }
2697
2698   /* if use external stack but some variables were
2699      added to the local stack then decrement the
2700      local stack */
2701   if (options.useXstack && sym->stack)
2702     {
2703       emitcode ("mov", "a,sp");
2704       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2705       emitcode ("mov", "sp,a");
2706     }
2707
2708
2709   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2710     {
2711       if (options.useXstack)
2712         {
2713           emitcode ("mov", "r0,%s", spname);
2714           emitcode ("movx", "a,@r0");
2715           emitcode ("mov", "_bp,a");
2716           emitcode ("dec", "%s", spname);
2717         }
2718       else
2719         {
2720           emitcode ("pop", "_bp");
2721         }
2722     }
2723
2724   /* restore the register bank  */
2725   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2726   {
2727     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2728      || !options.useXstack)
2729     {
2730         /* Special case of ISR using non-zero bank with useXstack
2731          * is handled below.
2732          */
2733         emitcode ("pop", "psw");
2734     }
2735   }
2736
2737   if (IFFUNC_ISISR (sym->type))
2738     {
2739
2740       /* now we need to restore the registers */
2741       /* if this isr has no bank i.e. is going to
2742          run with bank 0 , then we need to save more
2743          registers :-) */
2744       if (!FUNC_REGBANK (sym->type))
2745         {
2746           /* if this function does not call any other
2747              function then we can be economical and
2748              save only those registers that are used */
2749           if (!IFFUNC_HASFCALL(sym->type))
2750             {
2751               int i;
2752
2753               /* if any registers used */
2754               if (sym->regsUsed)
2755                 {
2756                   /* save the registers used */
2757                   for (i = sym->regsUsed->size; i >= 0; i--)
2758                     {
2759                       if (bitVectBitValue (sym->regsUsed, i) ||
2760                           (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2761                         emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2762                     }
2763                 }
2764
2765             }
2766           else
2767             {
2768               if (options.parms_in_bank1) {
2769                   int i;
2770                   for (i = 7 ; i >= 0 ; i-- ) {               
2771                       emitcode ("pop","%s",rb1regs[i]);
2772                   }
2773               }
2774               /* this function has  a function call cannot
2775                  determines register usage so we will have to pop the
2776                  entire bank */
2777               unsaveRBank (0, ic, FALSE);
2778             }
2779         }
2780         else
2781         {
2782             /* This ISR uses a non-zero bank.
2783              *
2784              * Restore any register banks saved by genFunction
2785              * in reverse order.
2786              */
2787             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2788             int ix;
2789           
2790             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2791             {
2792                 if (savedBanks & (1 << ix))
2793                 {
2794                     unsaveRBank(ix, NULL, FALSE);
2795                 }
2796             }
2797             
2798             if (options.useXstack)
2799             {
2800                 /* Restore bank AFTER calling unsaveRBank,
2801                  * since it can trash r0.
2802                  */
2803                 emitcode ("pop", "psw");
2804             }
2805         }
2806
2807       if (!inExcludeList ("dph"))
2808         emitcode ("pop", "dph");
2809       if (!inExcludeList ("dpl"))
2810         emitcode ("pop", "dpl");
2811       if (!inExcludeList ("b"))
2812         emitcode ("pop", "b");
2813       if (!inExcludeList ("acc"))
2814         emitcode ("pop", "acc");
2815
2816       /* if debug then send end of function */
2817       if (options.debug && currFunc)
2818         {
2819           _G.debugLine = 1;
2820           emitcode ("", "C$%s$%d$%d$%d ==.",
2821                     FileBaseName (ic->filename), currFunc->lastLine,
2822                     ic->level, ic->block);
2823           if (IS_STATIC (currFunc->etype))
2824             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2825           else
2826             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2827           _G.debugLine = 0;
2828         }
2829
2830       emitcode ("reti", "");
2831     }
2832   else
2833     {
2834       if (IFFUNC_CALLEESAVES(sym->type))
2835         {
2836           int i;
2837
2838           /* if any registers used */
2839           if (sym->regsUsed)
2840             {
2841               /* save the registers used */
2842               for (i = sym->regsUsed->size; i >= 0; i--)
2843                 {
2844                   if (bitVectBitValue (sym->regsUsed, i) ||
2845                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2846                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2847                 }
2848             }
2849
2850         }
2851
2852       /* if debug then send end of function */
2853       if (options.debug && currFunc)
2854         {
2855           _G.debugLine = 1;
2856           emitcode ("", "C$%s$%d$%d$%d ==.",
2857                     FileBaseName (ic->filename), currFunc->lastLine,
2858                     ic->level, ic->block);
2859           if (IS_STATIC (currFunc->etype))
2860             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2861           else
2862             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2863           _G.debugLine = 0;
2864         }
2865
2866       emitcode ("ret", "");
2867     }
2868
2869 }
2870
2871 /*-----------------------------------------------------------------*/
2872 /* genRet - generate code for return statement                     */
2873 /*-----------------------------------------------------------------*/
2874 static void
2875 genRet (iCode * ic)
2876 {
2877   int size, offset = 0, pushed = 0;
2878
2879   D(emitcode (";     genRet",""));
2880
2881   /* if we have no return value then
2882      just generate the "ret" */
2883   if (!IC_LEFT (ic))
2884     goto jumpret;
2885
2886   /* we have something to return then
2887      move the return value into place */
2888   aopOp (IC_LEFT (ic), ic, FALSE);
2889   size = AOP_SIZE (IC_LEFT (ic));
2890
2891   while (size--)
2892     {
2893       char *l;
2894       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2895         {
2896           /* #NOCHANGE */
2897           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2898                       FALSE, TRUE);
2899           emitcode ("push", "%s", l);
2900           pushed++;
2901         }
2902       else
2903         {
2904           l = aopGet (AOP (IC_LEFT (ic)), offset,
2905                       FALSE, FALSE);
2906           if (strcmp (fReturn[offset], l))
2907             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2908         }
2909     }
2910
2911   if (pushed)
2912     {
2913       while (pushed)
2914         {
2915           pushed--;
2916           if (strcmp (fReturn[pushed], "a"))
2917             emitcode ("pop", fReturn[pushed]);
2918           else
2919             emitcode ("pop", "acc");
2920         }
2921     }
2922   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2923
2924 jumpret:
2925   /* generate a jump to the return label
2926      if the next is not the return statement */
2927   if (!(ic->next && ic->next->op == LABEL &&
2928         IC_LABEL (ic->next) == returnLabel))
2929
2930     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2931
2932 }
2933
2934 /*-----------------------------------------------------------------*/
2935 /* genLabel - generates a label                                    */
2936 /*-----------------------------------------------------------------*/
2937 static void
2938 genLabel (iCode * ic)
2939 {
2940   /* special case never generate */
2941   if (IC_LABEL (ic) == entryLabel)
2942     return;
2943
2944   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2945 }
2946
2947 /*-----------------------------------------------------------------*/
2948 /* genGoto - generates a ljmp                                      */
2949 /*-----------------------------------------------------------------*/
2950 static void
2951 genGoto (iCode * ic)
2952 {
2953   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2954 }
2955
2956 /*-----------------------------------------------------------------*/
2957 /* findLabelBackwards: walks back through the iCode chain looking  */
2958 /* for the given label. Returns number of iCode instructions     */
2959 /* between that label and given ic.          */
2960 /* Returns zero if label not found.          */
2961 /*-----------------------------------------------------------------*/
2962 static int
2963 findLabelBackwards (iCode * ic, int key)
2964 {
2965   int count = 0;
2966
2967   while (ic->prev)
2968     {
2969       ic = ic->prev;
2970       count++;
2971
2972       /* If we have any pushes or pops, we cannot predict the distance.
2973          I don't like this at all, this should be dealt with in the 
2974          back-end */
2975       if (ic->op == IPUSH || ic->op == IPOP) {
2976         return 0;
2977       }
2978
2979       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2980         {
2981           return count;
2982         }
2983     }
2984
2985   return 0;
2986 }
2987
2988 /*-----------------------------------------------------------------*/
2989 /* genPlusIncr :- does addition with increment if possible         */
2990 /*-----------------------------------------------------------------*/
2991 static bool
2992 genPlusIncr (iCode * ic)
2993 {
2994   unsigned int icount;
2995   unsigned int size = getDataSize (IC_RESULT (ic));
2996
2997   /* will try to generate an increment */
2998   /* if the right side is not a literal
2999      we cannot */
3000   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3001     return FALSE;
3002
3003   /* if the literal value of the right hand side
3004      is greater than 4 then it is not worth it */
3005   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3006     return FALSE;
3007
3008   D(emitcode (";     genPlusIncr",""));
3009
3010   /* if increment >=16 bits in register or direct space */
3011   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3012       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && 
3013       (size > 1) &&
3014       (icount == 1))
3015     {
3016       symbol *tlbl;
3017       int emitTlbl;
3018       int labelRange;
3019
3020       /* If the next instruction is a goto and the goto target
3021        * is < 10 instructions previous to this, we can generate
3022        * jumps straight to that target.
3023        */
3024       if (ic->next && ic->next->op == GOTO
3025           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3026           && labelRange <= 10)
3027         {
3028           emitcode (";", "tail increment optimized");
3029           tlbl = IC_LABEL (ic->next);
3030           emitTlbl = 0;
3031         }
3032       else
3033         {
3034           tlbl = newiTempLabel (NULL);
3035           emitTlbl = 1;
3036         }
3037       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3038       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3039           IS_AOP_PREG (IC_RESULT (ic)))
3040         emitcode ("cjne", "%s,#0x00,%05d$",
3041                   aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3042                   tlbl->key + 100);
3043       else
3044         {
3045           emitcode ("clr", "a");
3046           emitcode ("cjne", "a,%s,%05d$",
3047                     aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3048                     tlbl->key + 100);
3049         }
3050
3051       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3052       if (size > 2)
3053         {
3054           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3055               IS_AOP_PREG (IC_RESULT (ic)))
3056             emitcode ("cjne", "%s,#0x00,%05d$",
3057                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3058                       tlbl->key + 100);
3059           else
3060             emitcode ("cjne", "a,%s,%05d$",
3061                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3062                       tlbl->key + 100);
3063
3064           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3065         }
3066       if (size > 3)
3067         {
3068           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3069               IS_AOP_PREG (IC_RESULT (ic)))
3070             emitcode ("cjne", "%s,#0x00,%05d$",
3071                       aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3072                       tlbl->key + 100);
3073           else
3074             {
3075               emitcode ("cjne", "a,%s,%05d$",
3076                         aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3077                         tlbl->key + 100);
3078             }
3079           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3080         }
3081
3082       if (emitTlbl)
3083         {
3084           emitcode ("", "%05d$:", tlbl->key + 100);
3085         }
3086       return TRUE;
3087     }
3088
3089   /* if the sizes are greater than 1 then we cannot */
3090   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3091       AOP_SIZE (IC_LEFT (ic)) > 1)
3092     return FALSE;
3093
3094   /* we can if the aops of the left & result match or
3095      if they are in registers and the registers are the
3096      same */
3097   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3098     {
3099
3100       if (icount > 3)
3101         {
3102           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3103           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3104           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3105         }
3106       else
3107         {
3108
3109           while (icount--)
3110             emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3111         }
3112
3113       return TRUE;
3114     }
3115
3116   return FALSE;
3117 }
3118
3119 /*-----------------------------------------------------------------*/
3120 /* outBitAcc - output a bit in acc                                 */
3121 /*-----------------------------------------------------------------*/
3122 static void
3123 outBitAcc (operand * result)
3124 {
3125   symbol *tlbl = newiTempLabel (NULL);
3126   /* if the result is a bit */
3127   if (AOP_TYPE (result) == AOP_CRY)
3128     {
3129       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3130     }
3131   else
3132     {
3133       emitcode ("jz", "%05d$", tlbl->key + 100);
3134       emitcode ("mov", "a,%s", one);
3135       emitcode ("", "%05d$:", tlbl->key + 100);
3136       outAcc (result);
3137     }
3138 }
3139
3140 /*-----------------------------------------------------------------*/
3141 /* genPlusBits - generates code for addition of two bits           */
3142 /*-----------------------------------------------------------------*/
3143 static void
3144 genPlusBits (iCode * ic)
3145 {
3146   D(emitcode (";     genPlusBits",""));
3147
3148   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3149     {
3150       symbol *lbl = newiTempLabel (NULL);
3151       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3152       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3153       emitcode ("cpl", "c");
3154       emitcode ("", "%05d$:", (lbl->key + 100));
3155       outBitC (IC_RESULT (ic));
3156     }
3157   else
3158     {
3159       emitcode ("clr", "a");
3160       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3161       emitcode ("rlc", "a");
3162       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3163       emitcode ("addc", "a,#0x00");
3164       outAcc (IC_RESULT (ic));
3165     }
3166 }
3167
3168 #if 0
3169 /* This is the original version of this code.
3170
3171  * This is being kept around for reference,
3172  * because I am not entirely sure I got it right...
3173  */
3174 static void
3175 adjustArithmeticResult (iCode * ic)
3176 {
3177   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3178       AOP_SIZE (IC_LEFT (ic)) == 3 &&
3179       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3180     aopPut (AOP (IC_RESULT (ic)),
3181             aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3182             2,
3183             isOperandVolatile (IC_RESULT (ic), FALSE));
3184
3185   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3186       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3187       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3188     aopPut (AOP (IC_RESULT (ic)),
3189             aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3190             2,
3191             isOperandVolatile (IC_RESULT (ic), FALSE));
3192
3193   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3194       AOP_SIZE (IC_LEFT (ic)) < 3 &&
3195       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3196       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3197       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3198     {
3199       char buffer[5];
3200       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3201       aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3202     }
3203 }
3204 #else
3205 /* This is the pure and virtuous version of this code.
3206  * I'm pretty certain it's right, but not enough to toss the old
3207  * code just yet...
3208  */
3209 static void
3210 adjustArithmeticResult (iCode * ic)
3211 {
3212   if (opIsGptr (IC_RESULT (ic)) &&
3213       opIsGptr (IC_LEFT (ic)) &&
3214       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3215     {
3216       aopPut (AOP (IC_RESULT (ic)),
3217               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3218               GPTRSIZE - 1,
3219               isOperandVolatile (IC_RESULT (ic), FALSE));
3220     }
3221
3222   if (opIsGptr (IC_RESULT (ic)) &&
3223       opIsGptr (IC_RIGHT (ic)) &&
3224       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3225     {
3226       aopPut (AOP (IC_RESULT (ic)),
3227               aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3228               GPTRSIZE - 1,
3229               isOperandVolatile (IC_RESULT (ic), FALSE));
3230     }
3231
3232   if (opIsGptr (IC_RESULT (ic)) &&
3233       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3234       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3235       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3236       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3237     {
3238       char buffer[5];
3239       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3240       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3241     }
3242 }
3243 #endif
3244
3245 /*-----------------------------------------------------------------*/
3246 /* genPlus - generates code for addition                           */
3247 /*-----------------------------------------------------------------*/
3248 static void
3249 genPlus (iCode * ic)
3250 {
3251   int size, offset = 0;
3252   int skip_bytes = 0;
3253   char *add = "add";
3254   asmop *leftOp, *rightOp;
3255   operand * op;
3256
3257   /* special cases :- */
3258
3259   D(emitcode (";     genPlus",""));
3260
3261   aopOp (IC_LEFT (ic), ic, FALSE);
3262   aopOp (IC_RIGHT (ic), ic, FALSE);
3263   aopOp (IC_RESULT (ic), ic, TRUE);
3264
3265   /* if literal, literal on the right or
3266      if left requires ACC or right is already
3267      in ACC */
3268   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3269       (AOP_NEEDSACC (IC_LEFT (ic))) ||
3270       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3271     {
3272       operand *t = IC_RIGHT (ic);
3273       IC_RIGHT (ic) = IC_LEFT (ic);
3274       IC_LEFT (ic) = t;
3275     }
3276
3277   /* if both left & right are in bit
3278      space */
3279   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3280       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3281     {
3282       genPlusBits (ic);
3283       goto release;
3284     }
3285
3286   /* if left in bit space & right literal */
3287   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3288       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3289     {
3290       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3291       /* if result in bit space */
3292       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3293         {
3294           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3295             emitcode ("cpl", "c");
3296           outBitC (IC_RESULT (ic));
3297         }
3298       else
3299         {
3300           size = getDataSize (IC_RESULT (ic));
3301           while (size--)
3302             {
3303               MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3304               emitcode ("addc", "a,#00");
3305               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3306             }
3307         }
3308       goto release;
3309     }
3310
3311   /* if I can do an increment instead
3312      of add then GOOD for ME */
3313   if (genPlusIncr (ic) == TRUE)
3314     goto release;
3315
3316   size = getDataSize (IC_RESULT (ic));
3317   leftOp = AOP(IC_LEFT(ic));
3318   rightOp = AOP(IC_RIGHT(ic));
3319   op=IC_LEFT(ic);
3320
3321   /* if this is an add for an array access
3322      at a 256 byte boundary */
3323   if ( 2 == size
3324        && AOP_TYPE (op) == AOP_IMMD
3325        && IS_SYMOP (op)
3326        && IS_SPEC (OP_SYM_ETYPE (op))
3327        && SPEC_ABSA (OP_SYM_ETYPE (op))
3328        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3329      )
3330     {
3331       D(emitcode (";     genPlus aligned array",""));
3332       aopPut (AOP (IC_RESULT (ic)),
3333               aopGet (rightOp, 0, FALSE, FALSE),
3334               0,
3335               isOperandVolatile (IC_RESULT (ic), FALSE));
3336
3337       if( 1 == getDataSize (IC_RIGHT (ic)) )
3338         {
3339           aopPut (AOP (IC_RESULT (ic)),
3340                   aopGet (leftOp, 1, FALSE, FALSE),
3341                   1,
3342                   isOperandVolatile (IC_RESULT (ic), FALSE));
3343         }
3344       else
3345         {
3346           MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3347           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3348           aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3349         }
3350       goto release;
3351     }
3352
3353   /* if the lower bytes of a literal are zero skip the addition */
3354   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3355     {
3356        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3357               (skip_bytes+1 < size))
3358          {
3359            skip_bytes++;
3360          }
3361        if (skip_bytes)
3362          D(emitcode (";     genPlus shortcut",""));
3363     }
3364
3365   while (size--)
3366     {
3367       if( offset >= skip_bytes )
3368         {
3369           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3370             {
3371               emitcode("mov", "b,a");
3372               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
3373               emitcode("xch", "a,b");
3374               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3375               emitcode (add, "a,b");
3376             }
3377           else if (aopGetUsesAcc (leftOp, offset))
3378             {
3379               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3380               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3381             }
3382           else
3383             {
3384               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3385               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3386             }
3387           aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3388           add = "addc";  /* further adds must propagate carry */
3389         }
3390       else
3391         {
3392           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) || 
3393               isOperandVolatile (IC_RESULT (ic), FALSE))
3394             {
3395               /* just move */
3396               aopPut (AOP (IC_RESULT (ic)),
3397                       aopGet (leftOp, offset, FALSE, FALSE),
3398                       offset,
3399                       isOperandVolatile (IC_RESULT (ic), FALSE));
3400             }
3401         }
3402       offset++;
3403     }
3404
3405   adjustArithmeticResult (ic);
3406
3407 release:
3408   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3409   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3410   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3411 }
3412
3413 /*-----------------------------------------------------------------*/
3414 /* genMinusDec :- does subtraction with deccrement if possible     */
3415 /*-----------------------------------------------------------------*/
3416 static bool
3417 genMinusDec (iCode * ic)
3418 {
3419   unsigned int icount;
3420   unsigned int size = getDataSize (IC_RESULT (ic));
3421
3422   /* will try to generate an increment */
3423   /* if the right side is not a literal
3424      we cannot */
3425   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3426     return FALSE;
3427
3428   /* if the literal value of the right hand side
3429      is greater than 4 then it is not worth it */
3430   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3431     return FALSE;
3432
3433   D(emitcode (";     genMinusDec",""));
3434
3435   /* if decrement >=16 bits in register or direct space */
3436   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3437       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3438       (size > 1) &&
3439       (icount == 1))
3440     {
3441       symbol *tlbl;
3442       int emitTlbl;
3443       int labelRange;
3444
3445       /* If the next instruction is a goto and the goto target
3446        * is <= 10 instructions previous to this, we can generate
3447        * jumps straight to that target.
3448        */
3449       if (ic->next && ic->next->op == GOTO
3450           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3451           && labelRange <= 10)
3452         {
3453           emitcode (";", "tail decrement optimized");
3454           tlbl = IC_LABEL (ic->next);
3455           emitTlbl = 0;
3456         }
3457       else
3458         {
3459           tlbl = newiTempLabel (NULL);
3460           emitTlbl = 1;
3461         }
3462
3463       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3464       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3465           IS_AOP_PREG (IC_RESULT (ic)))
3466         emitcode ("cjne", "%s,#0xff,%05d$"
3467                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3468                   ,tlbl->key + 100);
3469       else
3470         {
3471           emitcode ("mov", "a,#0xff");
3472           emitcode ("cjne", "a,%s,%05d$"
3473                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3474                     ,tlbl->key + 100);
3475         }
3476       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3477       if (size > 2)
3478         {
3479           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3480               IS_AOP_PREG (IC_RESULT (ic)))
3481             emitcode ("cjne", "%s,#0xff,%05d$"
3482                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3483                       ,tlbl->key + 100);
3484           else
3485             {
3486               emitcode ("cjne", "a,%s,%05d$"
3487                         ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3488                         ,tlbl->key + 100);
3489             }
3490           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3491         }
3492       if (size > 3)
3493         {
3494           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3495               IS_AOP_PREG (IC_RESULT (ic)))
3496             emitcode ("cjne", "%s,#0xff,%05d$"
3497                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3498                       ,tlbl->key + 100);
3499           else
3500             {
3501               emitcode ("cjne", "a,%s,%05d$"
3502                         ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3503                         ,tlbl->key + 100);
3504             }
3505           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3506         }
3507       if (emitTlbl)
3508         {
3509           emitcode ("", "%05d$:", tlbl->key + 100);
3510         }
3511       return TRUE;
3512     }
3513
3514   /* if the sizes are greater than 1 then we cannot */
3515   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3516       AOP_SIZE (IC_LEFT (ic)) > 1)
3517     return FALSE;
3518
3519   /* we can if the aops of the left & result match or
3520      if they are in registers and the registers are the
3521      same */
3522   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3523     {
3524
3525       while (icount--)
3526         emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3527
3528       return TRUE;
3529     }
3530
3531   return FALSE;
3532 }
3533
3534 /*-----------------------------------------------------------------*/
3535 /* addSign - complete with sign                                    */
3536 /*-----------------------------------------------------------------*/
3537 static void
3538 addSign (operand * result, int offset, int sign)
3539 {
3540   int size = (getDataSize (result) - offset);
3541   if (size > 0)
3542     {
3543       if (sign)
3544         {
3545           emitcode ("rlc", "a");
3546           emitcode ("subb", "a,acc");
3547           while (size--)
3548             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3549         }
3550       else
3551         while (size--)
3552           aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3553     }
3554 }
3555
3556 /*-----------------------------------------------------------------*/
3557 /* genMinusBits - generates code for subtraction  of two bits      */
3558 /*-----------------------------------------------------------------*/
3559 static void
3560 genMinusBits (iCode * ic)
3561 {
3562   symbol *lbl = newiTempLabel (NULL);
3563
3564   D(emitcode (";     genMinusBits",""));
3565
3566   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3567     {
3568       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3569       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3570       emitcode ("cpl", "c");
3571       emitcode ("", "%05d$:", (lbl->key + 100));
3572       outBitC (IC_RESULT (ic));
3573     }
3574   else
3575     {
3576       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3577       emitcode ("subb", "a,acc");
3578       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3579       emitcode ("inc", "a");
3580       emitcode ("", "%05d$:", (lbl->key + 100));
3581       aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3582       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3583     }
3584 }
3585
3586 /*-----------------------------------------------------------------*/
3587 /* genMinus - generates code for subtraction                       */
3588 /*-----------------------------------------------------------------*/
3589 static void
3590 genMinus (iCode * ic)
3591 {
3592   int size, offset = 0;
3593
3594   D(emitcode (";     genMinus",""));
3595
3596   aopOp (IC_LEFT (ic), ic, FALSE);
3597   aopOp (IC_RIGHT (ic), ic, FALSE);
3598   aopOp (IC_RESULT (ic), ic, TRUE);
3599
3600   /* special cases :- */
3601   /* if both left & right are in bit space */
3602   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3603       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3604     {
3605       genMinusBits (ic);
3606       goto release;
3607     }
3608
3609   /* if I can do an decrement instead
3610      of subtract then GOOD for ME */
3611   if (genMinusDec (ic) == TRUE)
3612     goto release;
3613
3614   size = getDataSize (IC_RESULT (ic));
3615
3616   /* if literal, add a,#-lit, else normal subb */
3617   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3618     {
3619       unsigned long lit = 0L;
3620
3621       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3622       lit = -(long) lit;
3623
3624       while (size--)
3625         {
3626           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3627           /* first add without previous c */
3628           if (!offset) {
3629             if (!size && lit== (unsigned long) -1) {
3630               emitcode ("dec", "a");
3631             } else {
3632               emitcode ("add", "a,#0x%02x",
3633                         (unsigned int) (lit & 0x0FFL));
3634             }
3635           } else {
3636             emitcode ("addc", "a,#0x%02x",
3637                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3638           }
3639           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3640         }
3641     }
3642   else
3643     {
3644       asmop *leftOp, *rightOp;
3645
3646       leftOp = AOP(IC_LEFT(ic));
3647       rightOp = AOP(IC_RIGHT(ic));
3648
3649       while (size--)
3650         {
3651           if (aopGetUsesAcc(rightOp, offset)) {
3652             wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3653             MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3654             if (offset == 0) {
3655               emitcode( "setb", "c");
3656             }
3657             emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3658             emitcode("cpl", "a");
3659           } else {
3660             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3661             if (offset == 0)
3662               CLRC;
3663             emitcode ("subb", "a,%s",
3664                       aopGet(rightOp, offset, FALSE, TRUE));
3665           }
3666
3667           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3668         }
3669     }
3670   
3671   
3672   adjustArithmeticResult (ic);
3673
3674 release:
3675   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3676   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3677   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3678 }
3679
3680
3681 /*-----------------------------------------------------------------*/
3682 /* genMultbits :- multiplication of bits                           */
3683 /*-----------------------------------------------------------------*/
3684 static void
3685 genMultbits (operand * left,
3686              operand * right,
3687              operand * result)
3688 {
3689   D(emitcode (";     genMultbits",""));
3690
3691   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3692   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3693   outBitC (result);
3694 }
3695
3696
3697 /*-----------------------------------------------------------------*/
3698 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3699 /*-----------------------------------------------------------------*/
3700 static void
3701 genMultOneByte (operand * left,
3702                 operand * right,
3703                 operand * result)
3704 {
3705   sym_link *opetype = operandType (result);
3706   symbol *lbl;
3707   int size=AOP_SIZE(result);
3708
3709   D(emitcode (";     genMultOneByte",""));
3710
3711   if (size<1 || size>2) {
3712     // this should never happen
3713       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3714                AOP_SIZE(result), __FILE__, lineno);
3715       exit (1);
3716   }
3717
3718   /* (if two literals: the value is computed before) */
3719   /* if one literal, literal on the right */
3720   if (AOP_TYPE (left) == AOP_LIT)
3721     {
3722       operand *t = right;
3723       right = left;
3724       left = t;
3725       //emitcode (";", "swapped left and right");
3726     }
3727
3728   if (SPEC_USIGN(opetype)
3729       // ignore the sign of left and right, what else can we do?
3730       || (SPEC_USIGN(operandType(left)) &&
3731           SPEC_USIGN(operandType(right)))) {
3732     // just an unsigned 8*8=8/16 multiply
3733     //emitcode (";","unsigned");
3734     // TODO: check for accumulator clash between left & right aops?
3735   
3736     if( AOP_TYPE(right)==AOP_LIT ){
3737       // moving to accumulator first helps peepholes 
3738       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3739       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3740     } else {
3741       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3742       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3743     }
3744     
3745     emitcode ("mul", "ab");
3746     aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3747     if (size==2) {
3748       aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3749     }
3750     return;
3751   }
3752
3753   // we have to do a signed multiply
3754
3755   //emitcode (";", "signed");
3756   emitcode ("clr", "F0"); // reset sign flag
3757   MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3758
3759   lbl=newiTempLabel(NULL);
3760   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3761   // left side is negative, 8-bit two's complement, this fails for -128
3762   emitcode ("setb", "F0"); // set sign flag
3763   emitcode ("cpl", "a");
3764   emitcode ("inc", "a");
3765
3766   emitcode ("", "%05d$:", lbl->key+100);
3767
3768   /* if literal */
3769   if (AOP_TYPE(right)==AOP_LIT) {
3770     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3771     /* AND literal negative */
3772     if (val < 0) {
3773       emitcode ("cpl", "F0"); // complement sign flag
3774       emitcode ("mov", "b,#0x%02x", -val);
3775     } else {
3776       emitcode ("mov", "b,#0x%02x", val);
3777     }
3778   } else {
3779     lbl=newiTempLabel(NULL);
3780     emitcode ("mov", "b,a");
3781     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3782     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3783     // right side is negative, 8-bit two's complement
3784     emitcode ("cpl", "F0"); // complement sign flag
3785     emitcode ("cpl", "a");
3786     emitcode ("inc", "a");
3787     emitcode ("", "%05d$:", lbl->key+100);
3788   }
3789   emitcode ("mul", "ab");
3790
3791   lbl=newiTempLabel(NULL);
3792   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3793   // only ONE op was negative, we have to do a 8/16-bit two's complement
3794   emitcode ("cpl", "a"); // lsb
3795   if (size==1) {
3796     emitcode ("inc", "a");
3797   } else {
3798     emitcode ("add", "a,#1");
3799     emitcode ("xch", "a,b");
3800     emitcode ("cpl", "a"); // msb
3801     emitcode ("addc", "a,#0");
3802     emitcode ("xch", "a,b");
3803   }
3804
3805   emitcode ("", "%05d$:", lbl->key+100);
3806   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3807   if (size==2) {
3808     aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3809   }
3810 }
3811
3812 /*-----------------------------------------------------------------*/
3813 /* genMult - generates code for multiplication                     */
3814 /*-----------------------------------------------------------------*/
3815 static void
3816 genMult (iCode * ic)
3817 {
3818   operand *left = IC_LEFT (ic);
3819   operand *right = IC_RIGHT (ic);
3820   operand *result = IC_RESULT (ic);
3821
3822   D(emitcode (";     genMult",""));
3823
3824   /* assign the amsops */
3825   aopOp (left, ic, FALSE);
3826   aopOp (right, ic, FALSE);
3827   aopOp (result, ic, TRUE);
3828
3829   /* special cases first */
3830   /* both are bits */
3831   if (AOP_TYPE (left) == AOP_CRY &&
3832       AOP_TYPE (right) == AOP_CRY)
3833     {
3834       genMultbits (left, right, result);
3835       goto release;
3836     }
3837
3838   /* if both are of size == 1 */
3839 #if 0 // one of them can be a sloc shared with the result
3840     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3841 #else
3842   if (getSize(operandType(left)) == 1 &&
3843       getSize(operandType(right)) == 1)
3844 #endif
3845     {
3846       genMultOneByte (left, right, result);
3847       goto release;
3848     }
3849
3850   /* should have been converted to function call */
3851     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3852              getSize(OP_SYMBOL(right)->type));
3853   assert (0);
3854
3855 release:
3856   freeAsmop (result, NULL, ic, TRUE);
3857   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3858   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3859 }
3860
3861 /*-----------------------------------------------------------------*/
3862 /* genDivbits :- division of bits                                  */
3863 /*-----------------------------------------------------------------*/
3864 static void
3865 genDivbits (operand * left,
3866             operand * right,
3867             operand * result)
3868 {
3869
3870   char *l;
3871
3872   D(emitcode (";     genDivbits",""));
3873
3874   /* the result must be bit */
3875   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3876   l = aopGet (AOP (left), 0, FALSE, FALSE);
3877
3878   MOVA (l);
3879
3880   emitcode ("div", "ab");
3881   emitcode ("rrc", "a");
3882   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3883 }
3884
3885 /*-----------------------------------------------------------------*/
3886 /* genDivOneByte : 8 bit division                                  */
3887 /*-----------------------------------------------------------------*/
3888 static void
3889 genDivOneByte (operand * left,
3890                operand * right,
3891                operand * result)
3892 {
3893   sym_link *opetype = operandType (result);
3894   char *l;
3895   symbol *lbl;
3896   int size, offset;
3897
3898   D(emitcode (";     genDivOneByte",""));
3899
3900   size = AOP_SIZE (result) - 1;
3901   offset = 1;
3902   /* signed or unsigned */
3903   if (SPEC_USIGN (opetype))
3904     {
3905       /* unsigned is easy */
3906       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3907       l = aopGet (AOP (left), 0, FALSE, FALSE);
3908       MOVA (l);
3909       emitcode ("div", "ab");
3910       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3911       while (size--)
3912         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3913       return;
3914     }
3915
3916   /* signed is a little bit more difficult */
3917
3918   /* save the signs of the operands */
3919   l = aopGet (AOP (left), 0, FALSE, FALSE);
3920   MOVA (l);
3921   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3922   emitcode ("push", "acc");     /* save it on the stack */
3923
3924   /* now sign adjust for both left & right */
3925   l = aopGet (AOP (right), 0, FALSE, FALSE);
3926   MOVA (l);
3927   lbl = newiTempLabel (NULL);
3928   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3929   emitcode ("cpl", "a");
3930   emitcode ("inc", "a");
3931   emitcode ("", "%05d$:", (lbl->key + 100));
3932   emitcode ("mov", "b,a");
3933
3934   /* sign adjust left side */
3935   l = aopGet (AOP (left), 0, FALSE, FALSE);
3936   MOVA (l);
3937
3938   lbl = newiTempLabel (NULL);
3939   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3940   emitcode ("cpl", "a");
3941   emitcode ("inc", "a");
3942   emitcode ("", "%05d$:", (lbl->key + 100));
3943
3944   /* now the division */
3945   emitcode ("div", "ab");
3946   /* we are interested in the lower order
3947      only */
3948   emitcode ("mov", "b,a");
3949   lbl = newiTempLabel (NULL);
3950   emitcode ("pop", "acc");
3951   /* if there was an over flow we don't
3952      adjust the sign of the result */
3953   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3954   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3955   CLRC;
3956   emitcode ("clr", "a");
3957   emitcode ("subb", "a,b");
3958   emitcode ("mov", "b,a");
3959   emitcode ("", "%05d$:", (lbl->key + 100));
3960
3961   /* now we are done */
3962   aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3963   if (size > 0)
3964     {
3965       emitcode ("mov", "c,b.7");
3966       emitcode ("subb", "a,acc");
3967     }
3968   while (size--)
3969     aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3970
3971 }
3972
3973 /*-----------------------------------------------------------------*/
3974 /* genDiv - generates code for division                            */
3975 /*-----------------------------------------------------------------*/
3976 static void
3977 genDiv (iCode * ic)
3978 {
3979   operand *left = IC_LEFT (ic);
3980   operand *right = IC_RIGHT (ic);
3981   operand *result = IC_RESULT (ic);
3982
3983   D(emitcode (";     genDiv",""));
3984
3985   /* assign the amsops */
3986   aopOp (left, ic, FALSE);
3987   aopOp (right, ic, FALSE);
3988   aopOp (result, ic, TRUE);
3989
3990   /* special cases first */
3991   /* both are bits */
3992   if (AOP_TYPE (left) == AOP_CRY &&
3993       AOP_TYPE (right) == AOP_CRY)
3994     {
3995       genDivbits (left, right, result);
3996       goto release;
3997     }
3998
3999   /* if both are of size == 1 */
4000   if (AOP_SIZE (left) == 1 &&
4001       AOP_SIZE (right) == 1)
4002     {
4003       genDivOneByte (left, right, result);
4004       goto release;
4005     }
4006
4007   /* should have been converted to function call */
4008   assert (0);
4009 release:
4010   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4011   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4012   freeAsmop (result, NULL, ic, TRUE);
4013 }
4014
4015 /*-----------------------------------------------------------------*/
4016 /* genModbits :- modulus of bits                                   */
4017 /*-----------------------------------------------------------------*/
4018 static void
4019 genModbits (operand * left,
4020             operand * right,
4021             operand * result)
4022 {
4023
4024   char *l;
4025
4026   D(emitcode (";     genModbits",""));
4027
4028   /* the result must be bit */
4029   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4030   l = aopGet (AOP (left), 0, FALSE, FALSE);
4031
4032   MOVA (l);
4033
4034   emitcode ("div", "ab");
4035   emitcode ("mov", "a,b");
4036   emitcode ("rrc", "a");
4037   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4038 }
4039
4040 /*-----------------------------------------------------------------*/
4041 /* genModOneByte : 8 bit modulus                                   */
4042 /*-----------------------------------------------------------------*/
4043 static void
4044 genModOneByte (operand * left,
4045                operand * right,
4046                operand * result)
4047 {
4048   sym_link *opetype = operandType (result);
4049   char *l;
4050   symbol *lbl;
4051
4052   D(emitcode (";     genModOneByte",""));
4053
4054   /* signed or unsigned */
4055   if (SPEC_USIGN (opetype))
4056     {
4057       /* unsigned is easy */
4058       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4059       l = aopGet (AOP (left), 0, FALSE, FALSE);
4060       MOVA (l);
4061       emitcode ("div", "ab");
4062       aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4063       return;
4064     }
4065
4066   /* signed is a little bit more difficult */
4067
4068   /* save the signs of the operands */
4069   l = aopGet (AOP (left), 0, FALSE, FALSE);
4070   MOVA (l);
4071
4072   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4073   emitcode ("push", "acc");     /* save it on the stack */
4074
4075   /* now sign adjust for both left & right */
4076   l = aopGet (AOP (right), 0, FALSE, FALSE);
4077   MOVA (l);
4078
4079   lbl = newiTempLabel (NULL);
4080   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4081   emitcode ("cpl", "a");
4082   emitcode ("inc", "a");
4083   emitcode ("", "%05d$:", (lbl->key + 100));
4084   emitcode ("mov", "b,a");
4085
4086   /* sign adjust left side */
4087   l = aopGet (AOP (left), 0, FALSE, FALSE);
4088   MOVA (l);
4089
4090   lbl = newiTempLabel (NULL);
4091   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4092   emitcode ("cpl", "a");
4093   emitcode ("inc", "a");
4094   emitcode ("", "%05d$:", (lbl->key + 100));
4095
4096   /* now the multiplication */
4097   emitcode ("div", "ab");
4098   /* we are interested in the lower order
4099      only */
4100   lbl = newiTempLabel (NULL);
4101   emitcode ("pop", "acc");
4102   /* if there was an over flow we don't
4103      adjust the sign of the result */
4104   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4105   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4106   CLRC;
4107   emitcode ("clr", "a");
4108   emitcode ("subb", "a,b");
4109   emitcode ("mov", "b,a");
4110   emitcode ("", "%05d$:", (lbl->key + 100));
4111
4112   /* now we are done */
4113   aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4114
4115 }
4116
4117 /*-----------------------------------------------------------------*/
4118 /* genMod - generates code for division                            */
4119 /*-----------------------------------------------------------------*/
4120 static void
4121 genMod (iCode * ic)
4122 {
4123   operand *left = IC_LEFT (ic);
4124   operand *right = IC_RIGHT (ic);
4125   operand *result = IC_RESULT (ic);
4126
4127   D(emitcode (";     genMod",""));
4128
4129   /* assign the amsops */
4130   aopOp (left, ic, FALSE);
4131   aopOp (right, ic, FALSE);
4132   aopOp (result, ic, TRUE);
4133
4134   /* special cases first */
4135   /* both are bits */
4136   if (AOP_TYPE (left) == AOP_CRY &&
4137       AOP_TYPE (right) == AOP_CRY)
4138     {
4139       genModbits (left, right, result);
4140       goto release;
4141     }
4142
4143   /* if both are of size == 1 */
4144   if (AOP_SIZE (left) == 1 &&
4145       AOP_SIZE (right) == 1)
4146     {
4147       genModOneByte (left, right, result);
4148       goto release;
4149     }
4150
4151   /* should have been converted to function call */
4152   assert (0);
4153
4154 release:
4155   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4156   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4157   freeAsmop (result, NULL, ic, TRUE);
4158 }
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genIfxJump :- will create a jump depending on the ifx           */
4162 /*-----------------------------------------------------------------*/
4163 static void
4164 genIfxJump (iCode * ic, char *jval)
4165 {
4166   symbol *jlbl;
4167   symbol *tlbl = newiTempLabel (NULL);
4168   char *inst;
4169
4170   D(emitcode (";     genIfxJump",""));
4171
4172   /* if true label then we jump if condition
4173      supplied is true */
4174   if (IC_TRUE (ic))
4175     {
4176       jlbl = IC_TRUE (ic);
4177       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4178                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4179     }
4180   else
4181     {
4182       /* false label is present */
4183       jlbl = IC_FALSE (ic);
4184       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4185                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4186     }
4187   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4188     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4189   else
4190     emitcode (inst, "%05d$", tlbl->key + 100);
4191   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4192   emitcode ("", "%05d$:", tlbl->key + 100);
4193
4194   /* mark the icode as generated */
4195   ic->generated = 1;
4196 }
4197
4198 /*-----------------------------------------------------------------*/
4199 /* genCmp :- greater or less than comparison                       */
4200 /*-----------------------------------------------------------------*/
4201 static void
4202 genCmp (operand * left, operand * right,
4203         operand * result, iCode * ifx, int sign, iCode *ic)
4204 {
4205   int size, offset = 0;
4206   unsigned long lit = 0L;
4207   bool rightInB;
4208
4209   D(emitcode (";     genCmp",""));
4210
4211   /* if left & right are bit variables */
4212   if (AOP_TYPE (left) == AOP_CRY &&
4213       AOP_TYPE (right) == AOP_CRY)
4214     {
4215       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4216       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4217     }
4218   else
4219     {
4220       /* subtract right from left if at the
4221          end the carry flag is set then we know that
4222          left is greater than right */
4223       size = max (AOP_SIZE (left), AOP_SIZE (right));
4224
4225       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4226       if ((size == 1) && !sign &&
4227           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4228         {
4229           symbol *lbl = newiTempLabel (NULL);
4230           emitcode ("cjne", "%s,%s,%05d$",
4231                     aopGet (AOP (left), offset, FALSE, FALSE),
4232                     aopGet (AOP (right), offset, FALSE, FALSE),
4233                     lbl->key + 100);
4234           emitcode ("", "%05d$:", lbl->key + 100);
4235         }
4236       else
4237         {
4238           if (AOP_TYPE (right) == AOP_LIT)
4239             {
4240               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4241               /* optimize if(x < 0) or if(x >= 0) */
4242               if (lit == 0L)
4243                 {
4244                   if (!sign)
4245                     {
4246                       CLRC;
4247                     }
4248                   else
4249                     {
4250                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4251                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4252                         {
4253                           genIfxJump (ifx, "acc.7");
4254                           return;
4255                         }
4256                       else
4257                         emitcode ("rlc", "a");
4258                     }
4259                   goto release;
4260                 }
4261             }
4262           CLRC;
4263           while (size--)
4264             {
4265               rightInB = aopGetUsesAcc(AOP (right), offset);
4266               if (rightInB)
4267                 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4268               MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4269               if (sign && size == 0)
4270                 {
4271                   emitcode ("xrl", "a,#0x80");
4272                   if (AOP_TYPE (right) == AOP_LIT)
4273                     {
4274                       unsigned long lit = (unsigned long)
4275                       floatFromVal (AOP (right)->aopu.aop_lit);
4276                       emitcode ("subb", "a,#0x%02x",
4277                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4278                     }
4279                   else
4280                     {
4281                       if (!rightInB)
4282                         emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4283                       emitcode ("xrl", "b,#0x80");
4284                       emitcode ("subb", "a,b");
4285                     }
4286                 }
4287               else
4288                 {
4289                   if (rightInB)
4290                     emitcode ("subb", "a,b");
4291                   else
4292                     emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4293                 }
4294               offset++;
4295             }
4296         }
4297     }
4298
4299 release:
4300   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4301   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4302   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4303     {
4304       outBitC (result);
4305     }
4306   else
4307     {
4308       /* if the result is used in the next
4309          ifx conditional branch then generate
4310          code a little differently */
4311       if (ifx)
4312         genIfxJump (ifx, "c");
4313       else
4314         outBitC (result);
4315       /* leave the result in acc */
4316     }
4317 }
4318
4319 /*-----------------------------------------------------------------*/
4320 /* genCmpGt :- greater than comparison                             */
4321 /*-----------------------------------------------------------------*/
4322 static void
4323 genCmpGt (iCode * ic, iCode * ifx)
4324 {
4325   operand *left, *right, *result;
4326   sym_link *letype, *retype;
4327   int sign;
4328
4329   D(emitcode (";     genCmpGt",""));
4330
4331   left = IC_LEFT (ic);
4332   right = IC_RIGHT (ic);
4333   result = IC_RESULT (ic);
4334
4335   letype = getSpec (operandType (left));
4336   retype = getSpec (operandType (right));
4337   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4338            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4339   /* assign the amsops */
4340   aopOp (left, ic, FALSE);
4341   aopOp (right, ic, FALSE);
4342   aopOp (result, ic, TRUE);
4343
4344   genCmp (right, left, result, ifx, sign,ic);
4345
4346   freeAsmop (result, NULL, ic, TRUE);
4347 }
4348
4349 /*-----------------------------------------------------------------*/
4350 /* genCmpLt - less than comparisons                                */
4351 /*-----------------------------------------------------------------*/
4352 static void
4353 genCmpLt (iCode * ic, iCode * ifx)
4354 {
4355   operand *left, *right, *result;
4356   sym_link *letype, *retype;
4357   int sign;
4358
4359   D(emitcode (";     genCmpLt",""));
4360
4361   left = IC_LEFT (ic);
4362   right = IC_RIGHT (ic);
4363   result = IC_RESULT (ic);
4364
4365   letype = getSpec (operandType (left));
4366   retype = getSpec (operandType (right));
4367   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4368            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4369   /* assign the amsops */
4370   aopOp (left, ic, FALSE);
4371   aopOp (right, ic, FALSE);
4372   aopOp (result, ic, TRUE);
4373
4374   genCmp (left, right, result, ifx, sign,ic);
4375
4376   freeAsmop (result, NULL, ic, TRUE);
4377 }
4378
4379 /*-----------------------------------------------------------------*/
4380 /* gencjneshort - compare and jump if not equal                    */
4381 /*-----------------------------------------------------------------*/
4382 static void
4383 gencjneshort (operand * left, operand * right, symbol * lbl)
4384 {
4385   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4386   int offset = 0;
4387   unsigned long lit = 0L;
4388
4389   /* if the left side is a literal or
4390      if the right is in a pointer register and left
4391      is not */
4392   if ((AOP_TYPE (left) == AOP_LIT) ||
4393       (AOP_TYPE (left) == AOP_IMMD) ||
4394       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4395     {
4396       operand *t = right;
4397       right = left;
4398       left = t;
4399     }
4400   
4401   if (AOP_TYPE (right) == AOP_LIT)
4402     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4403
4404   /* if the right side is a literal then anything goes */
4405   if (AOP_TYPE (right) == AOP_LIT &&
4406       AOP_TYPE (left) != AOP_DIR  &&
4407       AOP_TYPE (left) != AOP_IMMD)
4408     {
4409       while (size--)
4410         {
4411           emitcode ("cjne", "%s,%s,%05d$",
4412                     aopGet (AOP (left), offset, FALSE, FALSE),
4413                     aopGet (AOP (right), offset, FALSE, FALSE),
4414                     lbl->key + 100);
4415           offset++;
4416         }
4417     }
4418
4419   /* if the right side is in a register or in direct space or
4420      if the left is a pointer register & right is not */
4421   else if (AOP_TYPE (right) == AOP_REG ||
4422            AOP_TYPE (right) == AOP_DIR ||
4423            AOP_TYPE (right) == AOP_LIT ||
4424            AOP_TYPE (right) == AOP_IMMD ||
4425            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4426            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4427     {
4428       while (size--)
4429         {
4430           MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4431           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4432               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4433             emitcode ("jnz", "%05d$", lbl->key + 100);
4434           else
4435             emitcode ("cjne", "a,%s,%05d$",
4436                       aopGet (AOP (right), offset, FALSE, TRUE),
4437                       lbl->key + 100);
4438           offset++;
4439         }
4440     }
4441   else
4442     {
4443       /* right is a pointer reg need both a & b */
4444       while (size--)
4445         {
4446           char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4447           if (strcmp (l, "b"))
4448             emitcode ("mov", "b,%s", l);
4449           MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4450           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4451           offset++;
4452         }
4453     }
4454 }
4455
4456 /*-----------------------------------------------------------------*/
4457 /* gencjne - compare and jump if not equal                         */
4458 /*-----------------------------------------------------------------*/
4459 static void
4460 gencjne (operand * left, operand * right, symbol * lbl)
4461 {
4462   symbol *tlbl = newiTempLabel (NULL);
4463
4464   gencjneshort (left, right, lbl);
4465
4466   emitcode ("mov", "a,%s", one);
4467   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4468   emitcode ("", "%05d$:", lbl->key + 100);
4469   emitcode ("clr", "a");
4470   emitcode ("", "%05d$:", tlbl->key + 100);
4471 }
4472
4473 /*-----------------------------------------------------------------*/
4474 /* genCmpEq - generates code for equal to                          */
4475 /*-----------------------------------------------------------------*/
4476 static void
4477 genCmpEq (iCode * ic, iCode * ifx)
4478 {
4479   operand *left, *right, *result;
4480
4481   D(emitcode (";     genCmpEq",""));
4482
4483   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4484   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4485   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4486
4487   /* if literal, literal on the right or
4488      if the right is in a pointer register and left
4489      is not */
4490   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4491       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4492     {
4493       operand *t = IC_RIGHT (ic);
4494       IC_RIGHT (ic) = IC_LEFT (ic);
4495       IC_LEFT (ic) = t;
4496     }
4497
4498   if (ifx && !AOP_SIZE (result))
4499     {
4500       symbol *tlbl;
4501       /* if they are both bit variables */
4502       if (AOP_TYPE (left) == AOP_CRY &&
4503           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4504         {
4505           if (AOP_TYPE (right) == AOP_LIT)
4506             {
4507               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4508               if (lit == 0L)
4509                 {
4510                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4511                   emitcode ("cpl", "c");
4512                 }
4513               else if (lit == 1L)
4514                 {
4515                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4516                 }
4517               else
4518                 {
4519                   emitcode ("clr", "c");
4520                 }
4521               /* AOP_TYPE(right) == AOP_CRY */
4522             }
4523           else
4524             {
4525               symbol *lbl = newiTempLabel (NULL);
4526               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4527               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4528               emitcode ("cpl", "c");
4529               emitcode ("", "%05d$:", (lbl->key + 100));
4530             }
4531           /* if true label then we jump if condition
4532              supplied is true */
4533           tlbl = newiTempLabel (NULL);
4534           if (IC_TRUE (ifx))
4535             {
4536               emitcode ("jnc", "%05d$", tlbl->key + 100);
4537               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4538             }
4539           else
4540             {
4541               emitcode ("jc", "%05d$", tlbl->key + 100);
4542               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4543             }
4544           emitcode ("", "%05d$:", tlbl->key + 100);
4545         }
4546       else
4547         {
4548           tlbl = newiTempLabel (NULL);
4549           gencjneshort (left, right, tlbl);
4550           if (IC_TRUE (ifx))
4551             {
4552               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4553               emitcode ("", "%05d$:", tlbl->key + 100);
4554             }
4555           else
4556             {
4557               symbol *lbl = newiTempLabel (NULL);
4558               emitcode ("sjmp", "%05d$", lbl->key + 100);
4559               emitcode ("", "%05d$:", tlbl->key + 100);
4560               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4561               emitcode ("", "%05d$:", lbl->key + 100);
4562             }
4563         }
4564       /* mark the icode as generated */
4565       ifx->generated = 1;
4566       goto release;
4567     }
4568
4569   /* if they are both bit variables */
4570   if (AOP_TYPE (left) == AOP_CRY &&
4571       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4572     {
4573       if (AOP_TYPE (right) == AOP_LIT)
4574         {
4575           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4576           if (lit == 0L)
4577             {
4578               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4579               emitcode ("cpl", "c");
4580             }
4581           else if (lit == 1L)
4582             {
4583               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4584             }
4585           else
4586             {
4587               emitcode ("clr", "c");
4588             }
4589           /* AOP_TYPE(right) == AOP_CRY */
4590         }
4591       else
4592         {
4593           symbol *lbl = newiTempLabel (NULL);
4594           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4595           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4596           emitcode ("cpl", "c");
4597           emitcode ("", "%05d$:", (lbl->key + 100));
4598         }
4599       /* c = 1 if egal */
4600       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4601         {
4602           outBitC (result);
4603           goto release;
4604         }
4605       if (ifx)
4606         {
4607           genIfxJump (ifx, "c");
4608           goto release;
4609         }
4610       /* if the result is used in an arithmetic operation
4611          then put the result in place */
4612       outBitC (result);
4613     }
4614   else
4615     {
4616       gencjne (left, right, newiTempLabel (NULL));
4617       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4618         {
4619           aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4620           goto release;
4621         }
4622       if (ifx)
4623         {
4624           genIfxJump (ifx, "a");
4625           goto release;
4626         }
4627       /* if the result is used in an arithmetic operation
4628          then put the result in place */
4629       if (AOP_TYPE (result) != AOP_CRY)
4630         outAcc (result);
4631       /* leave the result in acc */
4632     }
4633
4634 release:
4635   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4636   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4637   freeAsmop (result, NULL, ic, TRUE);
4638 }
4639
4640 /*-----------------------------------------------------------------*/
4641 /* ifxForOp - returns the icode containing the ifx for operand     */
4642 /*-----------------------------------------------------------------*/
4643 static iCode *
4644 ifxForOp (operand * op, iCode * ic)
4645 {
4646   /* if true symbol then needs to be assigned */
4647   if (IS_TRUE_SYMOP (op))
4648     return NULL;
4649
4650   /* if this has register type condition and
4651      the next instruction is ifx with the same operand
4652      and live to of the operand is upto the ifx only then */
4653   if (ic->next &&
4654       ic->next->op == IFX &&
4655       IC_COND (ic->next)->key == op->key &&
4656       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4657     return ic->next;
4658
4659   return NULL;
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* hasInc - operand is incremented before any other use            */
4664 /*-----------------------------------------------------------------*/
4665 static iCode *
4666 hasInc (operand *op, iCode *ic,int osize)
4667 {
4668   sym_link *type = operandType(op);
4669   sym_link *retype = getSpec (type);
4670   iCode *lic = ic->next;
4671   int isize ;
4672   
4673   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4674   if (!IS_SYMOP(op)) return NULL;
4675
4676   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4677   if (IS_AGGREGATE(type->next)) return NULL;
4678   if (osize != (isize = getSize(type->next))) return NULL;
4679
4680   while (lic) {
4681     /* if operand of the form op = op + <sizeof *op> */
4682     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4683         isOperandEqual(IC_RESULT(lic),op) && 
4684         isOperandLiteral(IC_RIGHT(lic)) &&
4685         operandLitValue(IC_RIGHT(lic)) == isize) {
4686       return lic;
4687     }
4688     /* if the operand used or deffed */
4689     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4690       return NULL;
4691     }
4692     /* if GOTO or IFX */
4693     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4694     lic = lic->next;
4695   }
4696   return NULL;
4697 }
4698
4699 /*-----------------------------------------------------------------*/
4700 /* genAndOp - for && operation                                     */
4701 /*-----------------------------------------------------------------*/
4702 static void
4703 genAndOp (iCode * ic)
4704 {
4705   operand *left, *right, *result;
4706   symbol *tlbl;
4707
4708   D(emitcode (";     genAndOp",""));
4709
4710   /* note here that && operations that are in an
4711      if statement are taken away by backPatchLabels
4712      only those used in arthmetic operations remain */
4713   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4714   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4715   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4716
4717   /* if both are bit variables */
4718   if (AOP_TYPE (left) == AOP_CRY &&
4719       AOP_TYPE (right) == AOP_CRY)
4720     {
4721       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4722       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4723       outBitC (result);
4724     }
4725   else
4726     {
4727       tlbl = newiTempLabel (NULL);
4728       toBoolean (left);
4729       emitcode ("jz", "%05d$", tlbl->key + 100);
4730       toBoolean (right);
4731       emitcode ("", "%05d$:", tlbl->key + 100);
4732       outBitAcc (result);
4733     }
4734
4735   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4736   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4737   freeAsmop (result, NULL, ic, TRUE);
4738 }
4739
4740
4741 /*-----------------------------------------------------------------*/
4742 /* genOrOp - for || operation                                      */
4743 /*-----------------------------------------------------------------*/
4744 static void
4745 genOrOp (iCode * ic)
4746 {
4747   operand *left, *right, *result;
4748   symbol *tlbl;
4749
4750   D(emitcode (";     genOrOp",""));
4751
4752   /* note here that || operations that are in an
4753      if statement are taken away by backPatchLabels
4754      only those used in arthmetic operations remain */
4755   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4756   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4757   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4758
4759   /* if both are bit variables */
4760   if (AOP_TYPE (left) == AOP_CRY &&
4761       AOP_TYPE (right) == AOP_CRY)
4762     {
4763       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4764       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4765       outBitC (result);
4766     }
4767   else
4768     {
4769       tlbl = newiTempLabel (NULL);
4770       toBoolean (left);
4771       emitcode ("jnz", "%05d$", tlbl->key + 100);
4772       toBoolean (right);
4773       emitcode ("", "%05d$:", tlbl->key + 100);
4774       outBitAcc (result);
4775     }
4776
4777   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4778   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4779   freeAsmop (result, NULL, ic, TRUE);
4780 }
4781
4782 /*-----------------------------------------------------------------*/
4783 /* isLiteralBit - test if lit == 2^n                               */
4784 /*-----------------------------------------------------------------*/
4785 static int
4786 isLiteralBit (unsigned long lit)
4787 {
4788   unsigned long pw[32] =
4789   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4790    0x100L, 0x200L, 0x400L, 0x800L,
4791    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4792    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4793    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4794    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4795    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4796   int idx;
4797
4798   for (idx = 0; idx < 32; idx++)
4799     if (lit == pw[idx])
4800       return idx + 1;
4801   return 0;
4802 }
4803
4804 /*-----------------------------------------------------------------*/
4805 /* continueIfTrue -                                                */
4806 /*-----------------------------------------------------------------*/
4807 static void
4808 continueIfTrue (iCode * ic)
4809 {
4810   if (IC_TRUE (ic))
4811     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4812   ic->generated = 1;
4813 }
4814
4815 /*-----------------------------------------------------------------*/
4816 /* jmpIfTrue -                                                     */
4817 /*-----------------------------------------------------------------*/
4818 static void
4819 jumpIfTrue (iCode * ic)
4820 {
4821   if (!IC_TRUE (ic))
4822     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4823   ic->generated = 1;
4824 }
4825
4826 /*-----------------------------------------------------------------*/
4827 /* jmpTrueOrFalse -                                                */
4828 /*-----------------------------------------------------------------*/
4829 static void
4830 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4831 {
4832   // ugly but optimized by peephole
4833   if (IC_TRUE (ic))
4834     {
4835       symbol *nlbl = newiTempLabel (NULL);
4836       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4837       emitcode ("", "%05d$:", tlbl->key + 100);
4838       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4839       emitcode ("", "%05d$:", nlbl->key + 100);
4840     }
4841   else
4842     {
4843       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4844       emitcode ("", "%05d$:", tlbl->key + 100);
4845     }
4846   ic->generated = 1;
4847 }
4848
4849 /*-----------------------------------------------------------------*/
4850 /* genAnd  - code for and                                          */
4851 /*-----------------------------------------------------------------*/
4852 static void
4853 genAnd (iCode * ic, iCode * ifx)
4854 {
4855   operand *left, *right, *result;
4856   int size, offset = 0;
4857   unsigned long lit = 0L;
4858   int bytelit = 0;
4859   char buffer[10];
4860
4861   D(emitcode (";     genAnd",""));
4862
4863   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4864   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4865   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4866
4867 #ifdef DEBUG_TYPE
4868   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4869             AOP_TYPE (result),
4870             AOP_TYPE (left), AOP_TYPE (right));
4871   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4872             AOP_SIZE (result),
4873             AOP_SIZE (left), AOP_SIZE (right));
4874 #endif
4875
4876   /* if left is a literal & right is not then exchange them */
4877   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4878       AOP_NEEDSACC (left))
4879     {
4880       operand *tmp = right;
4881       right = left;
4882       left = tmp;
4883     }
4884
4885   /* if result = right then exchange them */
4886   if (sameRegs (AOP (result), AOP (right)))
4887     {
4888       operand *tmp = right;
4889       right = left;
4890       left = tmp;
4891     }
4892
4893   /* if right is bit then exchange them */
4894   if (AOP_TYPE (right) == AOP_CRY &&
4895       AOP_TYPE (left) != AOP_CRY)
4896     {
4897       operand *tmp = right;
4898       right = left;
4899       left = tmp;
4900     }
4901   if (AOP_TYPE (right) == AOP_LIT)
4902     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4903
4904   size = AOP_SIZE (result);
4905
4906   // if(bit & yy)
4907   // result = bit & yy;
4908   if (AOP_TYPE (left) == AOP_CRY)
4909     {
4910       // c = bit & literal;
4911       if (AOP_TYPE (right) == AOP_LIT)
4912         {
4913           if (lit & 1)
4914             {
4915               if (size && sameRegs (AOP (result), AOP (left)))
4916                 // no change
4917                 goto release;
4918               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4919             }
4920           else
4921             {
4922               // bit(result) = 0;
4923               if (size && (AOP_TYPE (result) == AOP_CRY))
4924                 {
4925                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4926                   goto release;
4927                 }
4928               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4929                 {
4930                   jumpIfTrue (ifx);
4931                   goto release;
4932                 }
4933               emitcode ("clr", "c");
4934             }
4935         }
4936       else
4937         {
4938           if (AOP_TYPE (right) == AOP_CRY)
4939             {
4940               // c = bit & bit;
4941               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4942               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4943             }
4944           else
4945             {
4946               // c = bit & val;
4947               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4948               // c = lsb
4949               emitcode ("rrc", "a");
4950               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4951             }
4952         }
4953       // bit = c
4954       // val = c
4955       if (size)
4956         outBitC (result);
4957       // if(bit & ...)
4958       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4959         genIfxJump (ifx, "c");
4960       goto release;
4961     }
4962
4963   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4964   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4965   if ((AOP_TYPE (right) == AOP_LIT) &&
4966       (AOP_TYPE (result) == AOP_CRY) &&
4967       (AOP_TYPE (left) != AOP_CRY))
4968     {
4969       int posbit = isLiteralBit (lit);
4970       /* left &  2^n */
4971       if (posbit)
4972         {
4973           posbit--;
4974           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4975           // bit = left & 2^n
4976           if (size)
4977             emitcode ("mov", "c,acc.%d", posbit & 0x07);
4978           // if(left &  2^n)
4979           else
4980             {
4981               if (ifx)
4982                 {
4983                   sprintf (buffer, "acc.%d", posbit & 0x07);
4984                   genIfxJump (ifx, buffer);
4985                 }
4986               goto release;
4987             }
4988         }
4989       else
4990         {
4991           symbol *tlbl = newiTempLabel (NULL);
4992           int sizel = AOP_SIZE (left);
4993           if (size)
4994             emitcode ("setb", "c");
4995           while (sizel--)
4996             {
4997               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4998                 {
4999                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5000                   // byte ==  2^n ?
5001                   if ((posbit = isLiteralBit (bytelit)) != 0)
5002                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5003                   else
5004                     {
5005                       if (bytelit != 0x0FFL)
5006                         emitcode ("anl", "a,%s",
5007                                   aopGet (AOP (right), offset, FALSE, TRUE));
5008                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5009                     }
5010                 }
5011               offset++;
5012             }
5013           // bit = left & literal
5014           if (size)
5015             {
5016               emitcode ("clr", "c");
5017               emitcode ("", "%05d$:", tlbl->key + 100);
5018             }
5019           // if(left & literal)
5020           else
5021             {
5022               if (ifx)
5023                 jmpTrueOrFalse (ifx, tlbl);
5024               else
5025                 emitcode ("", "%05d$:", tlbl->key + 100);
5026               goto release;
5027             }
5028         }
5029       outBitC (result);
5030       goto release;
5031     }
5032
5033   /* if left is same as result */
5034   if (sameRegs (AOP (result), AOP (left)))
5035     {
5036       for (; size--; offset++)
5037         {
5038           if (AOP_TYPE (right) == AOP_LIT)
5039             {
5040               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5041                 continue;
5042               else if (bytelit == 0)
5043                 {
5044                   aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5045                 }
5046               else if (IS_AOP_PREG (result))
5047                 {
5048                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5049                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5050                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5051                 }
5052               else
5053                 emitcode ("anl", "%s,%s",
5054                           aopGet (AOP (left), offset, FALSE, TRUE),
5055                           aopGet (AOP (right), offset, FALSE, FALSE));
5056             }
5057           else
5058             {
5059               if (AOP_TYPE (left) == AOP_ACC)
5060                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5061               else
5062                 {
5063                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5064                   if (IS_AOP_PREG (result))
5065                     {
5066                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5067                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5068
5069                     }
5070                   else
5071                     emitcode ("anl", "%s,a",
5072                               aopGet (AOP (left), offset, FALSE, TRUE));
5073                 }
5074             }
5075         }
5076     }
5077   else
5078     {
5079       // left & result in different registers
5080       if (AOP_TYPE (result) == AOP_CRY)
5081         {
5082           // result = bit
5083           // if(size), result in bit
5084           // if(!size && ifx), conditional oper: if(left & right)
5085           symbol *tlbl = newiTempLabel (NULL);
5086           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5087           if (size)
5088             emitcode ("setb", "c");
5089           while (sizer--)
5090             {
5091               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5092                 emitcode ("anl", "a,%s",
5093                           aopGet (AOP (right), offset, FALSE, FALSE));
5094               } else {
5095                 if (AOP_TYPE(left)==AOP_ACC) {
5096                   emitcode("mov", "b,a");
5097                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5098                   emitcode("anl", "a,b");
5099                 }else {
5100                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5101                   emitcode ("anl", "a,%s",
5102                             aopGet (AOP (left), offset, FALSE, FALSE));
5103                 }
5104               }
5105               emitcode ("jnz", "%05d$", tlbl->key + 100);
5106               offset++;
5107             }
5108           if (size)
5109             {
5110               CLRC;
5111               emitcode ("", "%05d$:", tlbl->key + 100);
5112               outBitC (result);
5113             }
5114           else if (ifx)
5115             jmpTrueOrFalse (ifx, tlbl);
5116           else
5117             emitcode ("", "%05d$:", tlbl->key + 100);
5118         }
5119       else
5120         {
5121           for (; (size--); offset++)
5122             {
5123               // normal case
5124               // result = left & right
5125               if (AOP_TYPE (right) == AOP_LIT)
5126                 {
5127                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5128                     {
5129                       aopPut (AOP (result),
5130                               aopGet (AOP (left), offset, FALSE, FALSE),
5131                               offset,
5132                               isOperandVolatile (result, FALSE));
5133                       continue;
5134                     }
5135                   else if (bytelit == 0)
5136                     {
5137                       /* dummy read of volatile operand */
5138                       if (isOperandVolatile (left, FALSE))
5139                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5140                       aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5141                       continue;
5142                     }
5143                 }
5144               // faster than result <- left, anl result,right
5145               // and better if result is SFR
5146               if (AOP_TYPE (left) == AOP_ACC)
5147                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5148               else
5149                 {
5150                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5151                   emitcode ("anl", "a,%s",
5152                             aopGet (AOP (left), offset, FALSE, FALSE));
5153                 }
5154               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5155             }
5156         }
5157     }
5158
5159 release:
5160   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5161   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5162   freeAsmop (result, NULL, ic, TRUE);
5163 }
5164
5165 /*-----------------------------------------------------------------*/
5166 /* genOr  - code for or                                            */
5167 /*-----------------------------------------------------------------*/
5168 static void
5169 genOr (iCode * ic, iCode * ifx)
5170 {
5171   operand *left, *right, *result;
5172   int size, offset = 0;
5173   unsigned long lit = 0L;
5174
5175   D(emitcode (";     genOr",""));
5176
5177   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5178   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5179   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5180
5181 #ifdef DEBUG_TYPE
5182   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5183             AOP_TYPE (result),
5184             AOP_TYPE (left), AOP_TYPE (right));
5185   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5186             AOP_SIZE (result),
5187             AOP_SIZE (left), AOP_SIZE (right));
5188 #endif
5189
5190   /* if left is a literal & right is not then exchange them */
5191   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5192       AOP_NEEDSACC (left))
5193     {
5194       operand *tmp = right;
5195       right = left;
5196       left = tmp;
5197     }
5198
5199   /* if result = right then exchange them */
5200   if (sameRegs (AOP (result), AOP (right)))
5201     {
5202       operand *tmp = right;
5203       right = left;
5204       left = tmp;
5205     }
5206
5207   /* if right is bit then exchange them */
5208   if (AOP_TYPE (right) == AOP_CRY &&
5209       AOP_TYPE (left) != AOP_CRY)
5210     {
5211       operand *tmp = right;
5212       right = left;
5213       left = tmp;
5214     }
5215   if (AOP_TYPE (right) == AOP_LIT)
5216     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5217
5218   size = AOP_SIZE (result);
5219
5220   // if(bit | yy)
5221   // xx = bit | yy;
5222   if (AOP_TYPE (left) == AOP_CRY)
5223     {
5224       if (AOP_TYPE (right) == AOP_LIT)
5225         {
5226           // c = bit | literal;
5227           if (lit)
5228             {
5229               // lit != 0 => result = 1
5230               if (AOP_TYPE (result) == AOP_CRY)
5231                 {
5232                   if (size)
5233                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5234                   else if (ifx)
5235                     continueIfTrue (ifx);
5236                   goto release;
5237                 }
5238               emitcode ("setb", "c");
5239             }
5240           else
5241             {
5242               // lit == 0 => result = left
5243               if (size && sameRegs (AOP (result), AOP (left)))
5244                 goto release;
5245               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5246             }
5247         }
5248       else
5249         {
5250           if (AOP_TYPE (right) == AOP_CRY)
5251             {
5252               // c = bit | bit;
5253               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5254               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5255             }
5256           else
5257             {
5258               // c = bit | val;
5259               symbol *tlbl = newiTempLabel (NULL);
5260               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5261                 emitcode ("setb", "c");
5262               emitcode ("jb", "%s,%05d$",
5263                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5264               toBoolean (right);
5265               emitcode ("jnz", "%05d$", tlbl->key + 100);
5266               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5267                 {
5268                   jmpTrueOrFalse (ifx, tlbl);
5269                   goto release;
5270                 }
5271               else
5272                 {
5273                   CLRC;
5274                   emitcode ("", "%05d$:", tlbl->key + 100);
5275                 }
5276             }
5277         }
5278       // bit = c
5279       // val = c
5280       if (size)
5281         outBitC (result);
5282       // if(bit | ...)
5283       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5284         genIfxJump (ifx, "c");
5285       goto release;
5286     }
5287
5288   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5289   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5290   if ((AOP_TYPE (right) == AOP_LIT) &&
5291       (AOP_TYPE (result) == AOP_CRY) &&
5292       (AOP_TYPE (left) != AOP_CRY))
5293     {
5294       if (lit)
5295         {
5296           // result = 1
5297           if (size)
5298             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5299           else
5300             continueIfTrue (ifx);
5301           goto release;
5302         }
5303       else
5304         {
5305           // lit = 0, result = boolean(left)
5306           if (size)
5307             emitcode ("setb", "c");
5308           toBoolean (right);
5309           if (size)
5310             {
5311               symbol *tlbl = newiTempLabel (NULL);
5312               emitcode ("jnz", "%05d$", tlbl->key + 100);
5313               CLRC;
5314               emitcode ("", "%05d$:", tlbl->key + 100);
5315             }
5316           else
5317             {
5318               genIfxJump (ifx, "a");
5319               goto release;
5320             }
5321         }
5322       outBitC (result);
5323       goto release;
5324     }
5325
5326   /* if left is same as result */
5327   if (sameRegs (AOP (result), AOP (left)))
5328     {
5329       for (; size--; offset++)
5330         {
5331           if (AOP_TYPE (right) == AOP_LIT)
5332             {
5333               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5334                 {
5335                   /* dummy read of volatile operand */
5336                   if (isOperandVolatile (left, FALSE))
5337                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5338                   else
5339                     continue;
5340                 }
5341               else if (IS_AOP_PREG (left))
5342                 {
5343                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5344                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5345                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5346                 }
5347               else
5348                 emitcode ("orl", "%s,%s",
5349                           aopGet (AOP (left), offset, FALSE, TRUE),
5350                           aopGet (AOP (right), offset, FALSE, FALSE));
5351             }
5352           else
5353             {
5354               if (AOP_TYPE (left) == AOP_ACC)
5355                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5356               else
5357                 {
5358                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5359                   if (IS_AOP_PREG (left))
5360                     {
5361                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5362                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5363                     }
5364                   else
5365                     emitcode ("orl", "%s,a",
5366                               aopGet (AOP (left), offset, FALSE, TRUE));
5367                 }
5368             }
5369         }
5370     }
5371   else
5372     {
5373       // left & result in different registers
5374       if (AOP_TYPE (result) == AOP_CRY)
5375         {
5376           // result = bit
5377           // if(size), result in bit
5378           // if(!size && ifx), conditional oper: if(left | right)
5379           symbol *tlbl = newiTempLabel (NULL);
5380           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5381           if (size)
5382             emitcode ("setb", "c");
5383           while (sizer--)
5384             {
5385               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5386                 emitcode ("orl", "a,%s",
5387                           aopGet (AOP (right), offset, FALSE, FALSE));
5388               } else {
5389                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5390                 emitcode ("orl", "a,%s",
5391                           aopGet (AOP (left), offset, FALSE, FALSE));
5392               }
5393               emitcode ("jnz", "%05d$", tlbl->key + 100);
5394               offset++;
5395             }
5396           if (size)
5397             {
5398               CLRC;
5399               emitcode ("", "%05d$:", tlbl->key + 100);
5400               outBitC (result);
5401             }
5402           else if (ifx)
5403             jmpTrueOrFalse (ifx, tlbl);
5404           else
5405             emitcode ("", "%05d$:", tlbl->key + 100);
5406         }
5407       else
5408         for (; (size--); offset++)
5409           {
5410             // normal case
5411             // result = left & right
5412             if (AOP_TYPE (right) == AOP_LIT)
5413               {
5414                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5415                   {
5416                     aopPut (AOP (result),
5417                             aopGet (AOP (left), offset, FALSE, FALSE),
5418                             offset,
5419                             isOperandVolatile (result, FALSE));
5420                     continue;
5421                   }
5422               }
5423             // faster than result <- left, anl result,right
5424             // and better if result is SFR
5425             if (AOP_TYPE (left) == AOP_ACC)
5426               emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5427             else
5428               {
5429                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5430                 emitcode ("orl", "a,%s",
5431                           aopGet (AOP (left), offset, FALSE, FALSE));
5432               }
5433             aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5434           }
5435     }
5436
5437 release:
5438   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5439   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440   freeAsmop (result, NULL, ic, TRUE);
5441 }
5442
5443 /*-----------------------------------------------------------------*/
5444 /* genXor - code for xclusive or                                   */
5445 /*-----------------------------------------------------------------*/
5446 static void
5447 genXor (iCode * ic, iCode * ifx)
5448 {
5449   operand *left, *right, *result;
5450   int size, offset = 0;
5451   unsigned long lit = 0L;
5452
5453   D(emitcode (";     genXor",""));
5454
5455   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5456   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5457   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5458
5459 #ifdef DEBUG_TYPE
5460   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5461             AOP_TYPE (result),
5462             AOP_TYPE (left), AOP_TYPE (right));
5463   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5464             AOP_SIZE (result),
5465             AOP_SIZE (left), AOP_SIZE (right));
5466 #endif
5467
5468   /* if left is a literal & right is not ||
5469      if left needs acc & right does not */
5470   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5471       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5472     {
5473       operand *tmp = right;
5474       right = left;
5475       left = tmp;
5476     }
5477
5478   /* if result = right then exchange them */
5479   if (sameRegs (AOP (result), AOP (right)))
5480     {
5481       operand *tmp = right;
5482       right = left;
5483       left = tmp;
5484     }
5485
5486   /* if right is bit then exchange them */
5487   if (AOP_TYPE (right) == AOP_CRY &&
5488       AOP_TYPE (left) != AOP_CRY)
5489     {
5490       operand *tmp = right;
5491       right = left;
5492       left = tmp;
5493     }
5494   if (AOP_TYPE (right) == AOP_LIT)
5495     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5496
5497   size = AOP_SIZE (result);
5498
5499   // if(bit ^ yy)
5500   // xx = bit ^ yy;
5501   if (AOP_TYPE (left) == AOP_CRY)
5502     {
5503       if (AOP_TYPE (right) == AOP_LIT)
5504         {
5505           // c = bit & literal;
5506           if (lit >> 1)
5507             {
5508               // lit>>1  != 0 => result = 1
5509               if (AOP_TYPE (result) == AOP_CRY)
5510                 {
5511                   if (size)
5512                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5513                   else if (ifx)
5514                     continueIfTrue (ifx);
5515                   goto release;
5516                 }
5517               emitcode ("setb", "c");
5518             }
5519           else
5520             {
5521               // lit == (0 or 1)
5522               if (lit == 0)
5523                 {
5524                   // lit == 0, result = left
5525                   if (size && sameRegs (AOP (result), AOP (left)))
5526                     goto release;
5527                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5528                 }
5529               else
5530                 {
5531                   // lit == 1, result = not(left)
5532                   if (size && sameRegs (AOP (result), AOP (left)))
5533                     {
5534                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5535                       goto release;
5536                     }
5537                   else
5538                     {
5539                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5540                       emitcode ("cpl", "c");
5541                     }
5542                 }
5543             }
5544
5545         }
5546       else
5547         {
5548           // right != literal
5549           symbol *tlbl = newiTempLabel (NULL);
5550           if (AOP_TYPE (right) == AOP_CRY)
5551             {
5552               // c = bit ^ bit;
5553               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5554             }
5555           else
5556             {
5557               int sizer = AOP_SIZE (right);
5558               // c = bit ^ val
5559               // if val>>1 != 0, result = 1
5560               emitcode ("setb", "c");
5561               while (sizer)
5562                 {
5563                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5564                   if (sizer == 1)
5565                     // test the msb of the lsb
5566                     emitcode ("anl", "a,#0xfe");
5567                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5568                   sizer--;
5569                 }
5570               // val = (0,1)
5571               emitcode ("rrc", "a");
5572             }
5573           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5574           emitcode ("cpl", "c");
5575           emitcode ("", "%05d$:", (tlbl->key + 100));
5576         }
5577       // bit = c
5578       // val = c
5579       if (size)
5580         outBitC (result);
5581       // if(bit | ...)
5582       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5583         genIfxJump (ifx, "c");
5584       goto release;
5585     }
5586
5587   if (sameRegs (AOP (result), AOP (left)))
5588     {
5589       /* if left is same as result */
5590       for (; size--; offset++)
5591         {
5592           if (AOP_TYPE (right) == AOP_LIT)
5593             {
5594               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5595                 continue;
5596               else if (IS_AOP_PREG (left))
5597                 {
5598                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5599                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5600                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5601                 }
5602               else
5603                 emitcode ("xrl", "%s,%s",
5604                           aopGet (AOP (left), offset, FALSE, TRUE),
5605                           aopGet (AOP (right), offset, FALSE, FALSE));
5606             }
5607           else
5608             {
5609               if (AOP_TYPE (left) == AOP_ACC)
5610                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5611               else
5612                 {
5613                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5614                   if (IS_AOP_PREG (left))
5615                     {
5616                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5617                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5618                     }
5619                   else
5620                     emitcode ("xrl", "%s,a",
5621                               aopGet (AOP (left), offset, FALSE, TRUE));
5622                 }
5623             }
5624         }
5625     }
5626   else
5627     {
5628       // left & result in different registers
5629       if (AOP_TYPE (result) == AOP_CRY)
5630         {
5631           // result = bit
5632           // if(size), result in bit
5633           // if(!size && ifx), conditional oper: if(left ^ right)
5634           symbol *tlbl = newiTempLabel (NULL);
5635           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5636           if (size)
5637             emitcode ("setb", "c");
5638           while (sizer--)
5639             {
5640               if ((AOP_TYPE (right) == AOP_LIT) &&
5641                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5642                 {
5643                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5644                 }
5645               else
5646                 {
5647                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5648                     emitcode ("xrl", "a,%s",
5649                               aopGet (AOP (right), offset, FALSE, FALSE));
5650                   } else {
5651                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5652                     emitcode ("xrl", "a,%s",
5653                               aopGet (AOP (left), offset, FALSE, FALSE));
5654                   }
5655                 }
5656               emitcode ("jnz", "%05d$", tlbl->key + 100);
5657               offset++;
5658             }
5659           if (size)
5660             {
5661               CLRC;
5662               emitcode ("", "%05d$:", tlbl->key + 100);
5663               outBitC (result);
5664             }
5665           else if (ifx)
5666             jmpTrueOrFalse (ifx, tlbl);
5667         }
5668       else
5669         for (; (size--); offset++)
5670           {
5671             // normal case
5672             // result = left & right
5673             if (AOP_TYPE (right) == AOP_LIT)
5674               {
5675                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5676                   {
5677                     aopPut (AOP (result),
5678                             aopGet (AOP (left), offset, FALSE, FALSE),
5679                             offset,
5680                             isOperandVolatile (result, FALSE));
5681                     continue;
5682                   }
5683               }
5684             // faster than result <- left, anl result,right
5685             // and better if result is SFR
5686             if (AOP_TYPE (left) == AOP_ACC)
5687               emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5688             else
5689               {
5690                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5691                 emitcode ("xrl", "a,%s",
5692                           aopGet (AOP (left), offset, FALSE, TRUE));
5693               }
5694             aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5695           }
5696     }
5697
5698 release:
5699   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5700   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5701   freeAsmop (result, NULL, ic, TRUE);
5702 }
5703
5704 /*-----------------------------------------------------------------*/
5705 /* genInline - write the inline code out                           */
5706 /*-----------------------------------------------------------------*/
5707 static void
5708 genInline (iCode * ic)
5709 {
5710   char *buffer, *bp, *bp1;
5711
5712   D(emitcode (";     genInline",""));
5713
5714   _G.inLine += (!options.asmpeep);
5715
5716   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5717   strcpy (buffer, IC_INLINE (ic));
5718
5719   /* emit each line as a code */
5720   while (*bp)
5721     {
5722       if (*bp == '\n')
5723         {
5724           *bp++ = '\0';
5725           emitcode (bp1, "");
5726           bp1 = bp;
5727         }
5728       else
5729         {
5730           if (*bp == ':')
5731             {
5732               bp++;
5733               *bp = '\0';
5734               bp++;
5735               emitcode (bp1, "");
5736               bp1 = bp;
5737             }
5738           else
5739             bp++;
5740         }
5741     }
5742   if (bp1 != bp)
5743     emitcode (bp1, "");
5744   /*     emitcode("",buffer); */
5745   _G.inLine -= (!options.asmpeep);
5746 }
5747
5748 /*-----------------------------------------------------------------*/
5749 /* genRRC - rotate right with carry                                */
5750 /*-----------------------------------------------------------------*/
5751 static void
5752 genRRC (iCode * ic)
5753 {
5754   operand *left, *result;
5755   int size, offset = 0;
5756   char *l;
5757
5758   D(emitcode (";     genRRC",""));
5759
5760   /* rotate right with carry */
5761   left = IC_LEFT (ic);
5762   result = IC_RESULT (ic);
5763   aopOp (left, ic, FALSE);
5764   aopOp (result, ic, FALSE);
5765
5766   /* move it to the result */
5767   size = AOP_SIZE (result);
5768   offset = size - 1;
5769   if (size == 1) { /* special case for 1 byte */
5770       l = aopGet (AOP (left), offset, FALSE, FALSE);
5771       MOVA (l);
5772       emitcode ("rr", "a");
5773       goto release;
5774   }
5775   CLRC;
5776   while (size--)
5777     {
5778       l = aopGet (AOP (left), offset, FALSE, FALSE);
5779       MOVA (l);
5780       emitcode ("rrc", "a");
5781       if (AOP_SIZE (result) > 1)
5782         aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5783     }
5784   /* now we need to put the carry into the
5785      highest order byte of the result */
5786   if (AOP_SIZE (result) > 1)
5787     {
5788       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5789       MOVA (l);
5790     }
5791   emitcode ("mov", "acc.7,c");
5792  release:
5793   aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5794   freeAsmop (left, NULL, ic, TRUE);
5795   freeAsmop (result, NULL, ic, TRUE);
5796 }
5797
5798 /*-----------------------------------------------------------------*/
5799 /* genRLC - generate code for rotate left with carry               */
5800 /*-----------------------------------------------------------------*/
5801 static void
5802 genRLC (iCode * ic)
5803 {
5804   operand *left, *result;
5805   int size, offset = 0;
5806   char *l;
5807
5808   D(emitcode (";     genRLC",""));
5809
5810   /* rotate right with carry */
5811   left = IC_LEFT (ic);
5812   result = IC_RESULT (ic);
5813   aopOp (left, ic, FALSE);
5814   aopOp (result, ic, FALSE);
5815
5816   /* move it to the result */
5817   size = AOP_SIZE (result);
5818   offset = 0;
5819   if (size--)
5820     {
5821       l = aopGet (AOP (left), offset, FALSE, FALSE);
5822       MOVA (l);
5823       if (size == 0) { /* special case for 1 byte */
5824               emitcode("rl","a");
5825               goto release;
5826       }
5827       emitcode ("add", "a,acc");
5828       if (AOP_SIZE (result) > 1)
5829         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5830       while (size--)
5831         {
5832           l = aopGet (AOP (left), offset, FALSE, FALSE);
5833           MOVA (l);
5834           emitcode ("rlc", "a");
5835           if (AOP_SIZE (result) > 1)
5836             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5837         }
5838     }
5839   /* now we need to put the carry into the
5840      highest order byte of the result */
5841   if (AOP_SIZE (result) > 1)
5842     {
5843       l = aopGet (AOP (result), 0, FALSE, FALSE);
5844       MOVA (l);
5845     }
5846   emitcode ("mov", "acc.0,c");
5847  release:
5848   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5849   freeAsmop (left, NULL, ic, TRUE);
5850   freeAsmop (result, NULL, ic, TRUE);
5851 }
5852
5853 /*-----------------------------------------------------------------*/
5854 /* genGetHbit - generates code get highest order bit               */
5855 /*-----------------------------------------------------------------*/
5856 static void
5857 genGetHbit (iCode * ic)
5858 {
5859   operand *left, *result;
5860
5861   D(emitcode (";     genGetHbit",""));
5862
5863   left = IC_LEFT (ic);
5864   result = IC_RESULT (ic);
5865   aopOp (left, ic, FALSE);
5866   aopOp (result, ic, FALSE);
5867
5868   /* get the highest order byte into a */
5869   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5870   if (AOP_TYPE (result) == AOP_CRY)
5871     {
5872       emitcode ("rlc", "a");
5873       outBitC (result);
5874     }
5875   else
5876     {
5877       emitcode ("rl", "a");
5878       emitcode ("anl", "a,#0x01");
5879       outAcc (result);
5880     }
5881
5882
5883   freeAsmop (left, NULL, ic, TRUE);
5884   freeAsmop (result, NULL, ic, TRUE);
5885 }
5886
5887 /*-----------------------------------------------------------------*/
5888 /* genSwap - generates code to swap nibbles or bytes               */
5889 /*-----------------------------------------------------------------*/
5890 static void
5891 genSwap (iCode * ic)
5892 {
5893   operand *left, *result;
5894
5895   D(emitcode (";     genSwap",""));
5896
5897   left = IC_LEFT (ic);
5898   result = IC_RESULT (ic);
5899   aopOp (left, ic, FALSE);
5900   aopOp (result, ic, FALSE);
5901   
5902   switch (AOP_SIZE (left))
5903     {
5904     case 1: /* swap nibbles in byte */
5905       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5906       emitcode ("swap", "a");
5907       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5908       break;
5909     case 2: /* swap bytes in word */
5910       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5911         {
5912           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5913           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5914                   0, isOperandVolatile (result, FALSE));
5915           aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5916         }
5917       else if (operandsEqu (left, result))
5918         {
5919           char * reg = "a";
5920           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5921           if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5922             {
5923               emitcode ("mov", "b,a");
5924               reg = "b";
5925             }
5926           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5927                   0, isOperandVolatile (result, FALSE));
5928           aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5929         }
5930       else
5931         {
5932           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5933                   0, isOperandVolatile (result, FALSE));
5934           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5935                   1, isOperandVolatile (result, FALSE));
5936         }
5937       break;
5938     default:
5939       wassertl(FALSE, "unsupported SWAP operand size");
5940     }
5941   
5942   freeAsmop (left, NULL, ic, TRUE);
5943   freeAsmop (result, NULL, ic, TRUE);
5944 }
5945
5946     
5947 /*-----------------------------------------------------------------*/
5948 /* AccRol - rotate left accumulator by known count                 */
5949 /*-----------------------------------------------------------------*/
5950 static void
5951 AccRol (int shCount)
5952 {
5953   shCount &= 0x0007;            // shCount : 0..7
5954
5955   switch (shCount)
5956     {
5957     case 0:
5958       break;
5959     case 1:
5960       emitcode ("rl", "a");
5961       break;
5962     case 2:
5963       emitcode ("rl", "a");
5964       emitcode ("rl", "a");
5965       break;
5966     case 3:
5967       emitcode ("swap", "a");
5968       emitcode ("rr", "a");
5969       break;
5970     case 4:
5971       emitcode ("swap", "a");
5972       break;
5973     case 5:
5974       emitcode ("swap", "a");
5975       emitcode ("rl", "a");
5976       break;
5977     case 6:
5978       emitcode ("rr", "a");
5979       emitcode ("rr", "a");
5980       break;
5981     case 7:
5982       emitcode ("rr", "a");
5983       break;
5984     }
5985 }
5986
5987 /*-----------------------------------------------------------------*/
5988 /* AccLsh - left shift accumulator by known count                  */
5989 /*-----------------------------------------------------------------*/
5990 static void
5991 AccLsh (int shCount)
5992 {
5993   if (shCount != 0)
5994     {
5995       if (shCount == 1)
5996         emitcode ("add", "a,acc");
5997       else if (shCount == 2)
5998         {
5999           emitcode ("add", "a,acc");
6000           emitcode ("add", "a,acc");
6001         }
6002       else
6003         {
6004           /* rotate left accumulator */
6005           AccRol (shCount);
6006           /* and kill the lower order bits */
6007           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6008         }
6009     }
6010 }
6011
6012 /*-----------------------------------------------------------------*/
6013 /* AccRsh - right shift accumulator by known count                 */
6014 /*-----------------------------------------------------------------*/
6015 static void
6016 AccRsh (int shCount)
6017 {
6018   if (shCount != 0)
6019     {
6020       if (shCount == 1)
6021         {
6022           CLRC;
6023           emitcode ("rrc", "a");
6024         }
6025       else
6026         {
6027           /* rotate right accumulator */
6028           AccRol (8 - shCount);
6029           /* and kill the higher order bits */
6030           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6031         }
6032     }
6033 }
6034
6035 /*-----------------------------------------------------------------*/
6036 /* AccSRsh - signed right shift accumulator by known count                 */
6037 /*-----------------------------------------------------------------*/
6038 static void
6039 AccSRsh (int shCount)
6040 {
6041   symbol *tlbl;
6042   if (shCount != 0)
6043     {
6044       if (shCount == 1)
6045         {
6046           emitcode ("mov", "c,acc.7");
6047           emitcode ("rrc", "a");
6048         }
6049       else if (shCount == 2)
6050         {
6051           emitcode ("mov", "c,acc.7");
6052           emitcode ("rrc", "a");
6053           emitcode ("mov", "c,acc.7");
6054           emitcode ("rrc", "a");
6055         }
6056       else
6057         {
6058           tlbl = newiTempLabel (NULL);
6059           /* rotate right accumulator */
6060           AccRol (8 - shCount);
6061           /* and kill the higher order bits */
6062           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6063           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6064           emitcode ("orl", "a,#0x%02x",
6065                     (unsigned char) ~SRMask[shCount]);
6066           emitcode ("", "%05d$:", tlbl->key + 100);
6067         }
6068     }
6069 }
6070
6071 /*-----------------------------------------------------------------*/
6072 /* shiftR1Left2Result - shift right one byte from left to result   */
6073 /*-----------------------------------------------------------------*/
6074 static void
6075 shiftR1Left2Result (operand * left, int offl,
6076                     operand * result, int offr,
6077                     int shCount, int sign)
6078 {
6079   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6080   /* shift right accumulator */
6081   if (sign)
6082     AccSRsh (shCount);
6083   else
6084     AccRsh (shCount);
6085   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6086 }
6087
6088 /*-----------------------------------------------------------------*/
6089 /* shiftL1Left2Result - shift left one byte from left to result    */
6090 /*-----------------------------------------------------------------*/
6091 static void
6092 shiftL1Left2Result (operand * left, int offl,
6093                     operand * result, int offr, int shCount)
6094 {
6095   char *l;
6096   l = aopGet (AOP (left), offl, FALSE, FALSE);
6097   MOVA (l);
6098   /* shift left accumulator */
6099   AccLsh (shCount);
6100   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6101 }
6102
6103 /*-----------------------------------------------------------------*/
6104 /* movLeft2Result - move byte from left to result                  */
6105 /*-----------------------------------------------------------------*/
6106 static void
6107 movLeft2Result (operand * left, int offl,
6108                 operand * result, int offr, int sign)
6109 {
6110   char *l;
6111   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6112     {
6113       l = aopGet (AOP (left), offl, FALSE, FALSE);
6114
6115       if (*l == '@' && (IS_AOP_PREG (result)))
6116         {
6117           emitcode ("mov", "a,%s", l);
6118           aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6119         }
6120       else
6121         {
6122           if (!sign)
6123             aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6124           else
6125             {
6126               /* MSB sign in acc.7 ! */
6127               if (getDataSize (left) == offl + 1)
6128                 {
6129                   emitcode ("mov", "a,%s", l);
6130                   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6131                 }
6132             }
6133         }
6134     }
6135 }
6136
6137 /*-----------------------------------------------------------------*/
6138 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6139 /*-----------------------------------------------------------------*/
6140 static void
6141 AccAXRrl1 (char *x)
6142 {
6143   emitcode ("rrc", "a");
6144   emitcode ("xch", "a,%s", x);
6145   emitcode ("rrc", "a");
6146   emitcode ("xch", "a,%s", x);
6147 }
6148
6149 /*-----------------------------------------------------------------*/
6150 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6151 /*-----------------------------------------------------------------*/
6152 static void
6153 AccAXLrl1 (char *x)
6154 {
6155   emitcode ("xch", "a,%s", x);
6156   emitcode ("rlc", "a");
6157   emitcode ("xch", "a,%s", x);
6158   emitcode ("rlc", "a");
6159 }
6160
6161 /*-----------------------------------------------------------------*/
6162 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6163 /*-----------------------------------------------------------------*/
6164 static void
6165 AccAXLsh1 (char *x)
6166 {
6167   emitcode ("xch", "a,%s", x);
6168   emitcode ("add", "a,acc");
6169   emitcode ("xch", "a,%s", x);
6170   emitcode ("rlc", "a");
6171 }
6172
6173 /*-----------------------------------------------------------------*/
6174 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6175 /*-----------------------------------------------------------------*/
6176 static void
6177 AccAXLsh (char *x, int shCount)
6178 {
6179   switch (shCount)
6180     {
6181     case 0:
6182       break;
6183     case 1:
6184       AccAXLsh1 (x);
6185       break;
6186     case 2:
6187       AccAXLsh1 (x);
6188       AccAXLsh1 (x);
6189       break;
6190     case 3:
6191     case 4:
6192     case 5:                     // AAAAABBB:CCCCCDDD
6193
6194       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6195
6196       emitcode ("anl", "a,#0x%02x",
6197                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6198
6199       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6200
6201       AccRol (shCount);         // DDDCCCCC:BBB00000
6202
6203       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6204
6205       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6206
6207       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6208
6209       emitcode ("anl", "a,#0x%02x",
6210                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6211
6212       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6213
6214       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6215
6216       break;
6217     case 6:                     // AAAAAABB:CCCCCCDD
6218       emitcode ("anl", "a,#0x%02x",
6219                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6220       emitcode ("mov", "c,acc.0");      // c = B
6221       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6222 #if 0 // REMOVE ME
6223       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6224       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6225 #else
6226       emitcode("rrc","a"); 
6227       emitcode("xch","a,%s", x); 
6228       emitcode("rrc","a"); 
6229       emitcode("mov","c,acc.0"); //<< get correct bit 
6230       emitcode("xch","a,%s", x); 
6231
6232       emitcode("rrc","a"); 
6233       emitcode("xch","a,%s", x); 
6234       emitcode("rrc","a"); 
6235       emitcode("xch","a,%s", x); 
6236 #endif
6237       break;
6238     case 7:                     // a:x <<= 7
6239
6240       emitcode ("anl", "a,#0x%02x",
6241                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6242
6243       emitcode ("mov", "c,acc.0");      // c = B
6244
6245       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6246
6247       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6248
6249       break;
6250     default:
6251       break;
6252     }
6253 }
6254
6255 /*-----------------------------------------------------------------*/
6256 /* AccAXRsh - right shift a:x known count (0..7)                   */
6257 /*-----------------------------------------------------------------*/
6258 static void
6259 AccAXRsh (char *x, int shCount)
6260 {
6261   switch (shCount)
6262     {
6263     case 0:
6264       break;
6265     case 1:
6266       CLRC;
6267       AccAXRrl1 (x);            // 0->a:x
6268
6269       break;
6270     case 2:
6271       CLRC;
6272       AccAXRrl1 (x);            // 0->a:x
6273
6274       CLRC;
6275       AccAXRrl1 (x);            // 0->a:x
6276
6277       break;
6278     case 3:
6279     case 4:
6280     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6281
6282       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6283
6284       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6285
6286       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6287
6288       emitcode ("anl", "a,#0x%02x",
6289                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6290
6291       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6292
6293       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6294
6295       emitcode ("anl", "a,#0x%02x",
6296                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6297
6298       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6299
6300       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6301
6302       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6303
6304       break;
6305     case 6:                     // AABBBBBB:CCDDDDDD
6306
6307       emitcode ("mov", "c,acc.7");
6308       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6309
6310       emitcode ("mov", "c,acc.7");
6311       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6312
6313       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6314
6315       emitcode ("anl", "a,#0x%02x",
6316                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6317
6318       break;
6319     case 7:                     // ABBBBBBB:CDDDDDDD
6320
6321       emitcode ("mov", "c,acc.7");      // c = A
6322
6323       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6324
6325       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6326
6327       emitcode ("anl", "a,#0x%02x",
6328                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6329
6330       break;
6331     default:
6332       break;
6333     }
6334 }
6335
6336 /*-----------------------------------------------------------------*/
6337 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6338 /*-----------------------------------------------------------------*/
6339 static void
6340 AccAXRshS (char *x, int shCount)
6341 {
6342   symbol *tlbl;
6343   switch (shCount)
6344     {
6345     case 0:
6346       break;
6347     case 1:
6348       emitcode ("mov", "c,acc.7");
6349       AccAXRrl1 (x);            // s->a:x
6350
6351       break;
6352     case 2:
6353       emitcode ("mov", "c,acc.7");
6354       AccAXRrl1 (x);            // s->a:x
6355
6356       emitcode ("mov", "c,acc.7");
6357       AccAXRrl1 (x);            // s->a:x
6358
6359       break;
6360     case 3:
6361     case 4:
6362     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6363
6364       tlbl = newiTempLabel (NULL);
6365       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6366
6367       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6368
6369       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6370
6371       emitcode ("anl", "a,#0x%02x",
6372                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6373
6374       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6375
6376       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6377
6378       emitcode ("anl", "a,#0x%02x",
6379                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6380
6381       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6382
6383       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6384
6385       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6386
6387       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6388       emitcode ("orl", "a,#0x%02x",
6389                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6390
6391       emitcode ("", "%05d$:", tlbl->key + 100);
6392       break;                    // SSSSAAAA:BBBCCCCC
6393
6394     case 6:                     // AABBBBBB:CCDDDDDD
6395
6396       tlbl = newiTempLabel (NULL);
6397       emitcode ("mov", "c,acc.7");
6398       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6399
6400       emitcode ("mov", "c,acc.7");
6401       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6402
6403       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6404
6405       emitcode ("anl", "a,#0x%02x",
6406                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6407
6408       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6409       emitcode ("orl", "a,#0x%02x",
6410                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6411
6412       emitcode ("", "%05d$:", tlbl->key + 100);
6413       break;
6414     case 7:                     // ABBBBBBB:CDDDDDDD
6415
6416       tlbl = newiTempLabel (NULL);
6417       emitcode ("mov", "c,acc.7");      // c = A
6418
6419       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6420
6421       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6422
6423       emitcode ("anl", "a,#0x%02x",
6424                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6425
6426       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6427       emitcode ("orl", "a,#0x%02x",
6428                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6429
6430       emitcode ("", "%05d$:", tlbl->key + 100);
6431       break;
6432     default:
6433       break;
6434     }
6435 }
6436
6437 /*-----------------------------------------------------------------*/
6438 /* shiftL2Left2Result - shift left two bytes from left to result   */
6439 /*-----------------------------------------------------------------*/
6440 static void
6441 shiftL2Left2Result (operand * left, int offl,
6442                     operand * result, int offr, int shCount)
6443 {
6444   if (sameRegs (AOP (result), AOP (left)) &&
6445       ((offl + MSB16) == offr))
6446     {
6447       /* don't crash result[offr] */
6448       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6449       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6450     }
6451   else
6452     {
6453       movLeft2Result (left, offl, result, offr, 0);
6454       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6455     }
6456   /* ax << shCount (x = lsb(result)) */
6457   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6458   aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6459 }
6460
6461
6462 /*-----------------------------------------------------------------*/
6463 /* shiftR2Left2Result - shift right two bytes from left to result  */
6464 /*-----------------------------------------------------------------*/
6465 static void
6466 shiftR2Left2Result (operand * left, int offl,
6467                     operand * result, int offr,
6468                     int shCount, int sign)
6469 {
6470   if (sameRegs (AOP (result), AOP (left)) &&
6471       ((offl + MSB16) == offr))
6472     {
6473       /* don't crash result[offr] */
6474       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6475       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6476     }
6477   else
6478     {
6479       movLeft2Result (left, offl, result, offr, 0);
6480       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6481     }
6482   /* a:x >> shCount (x = lsb(result)) */
6483   if (sign)
6484     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6485   else
6486     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6487   if (getDataSize (result) > 1)
6488     aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6489 }
6490
6491 /*-----------------------------------------------------------------*/
6492 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6493 /*-----------------------------------------------------------------*/
6494 static void
6495 shiftLLeftOrResult (operand * left, int offl,
6496                     operand * result, int offr, int shCount)
6497 {
6498   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6499   /* shift left accumulator */
6500   AccLsh (shCount);
6501   /* or with result */
6502   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6503   /* back to result */
6504   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6505 }
6506
6507 /*-----------------------------------------------------------------*/
6508 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6509 /*-----------------------------------------------------------------*/
6510 static void
6511 shiftRLeftOrResult (operand * left, int offl,
6512                     operand * result, int offr, int shCount)
6513 {
6514   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6515   /* shift right accumulator */
6516   AccRsh (shCount);
6517   /* or with result */
6518   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6519   /* back to result */
6520   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6521 }
6522
6523 /*-----------------------------------------------------------------*/
6524 /* genlshOne - left shift a one byte quantity by known count       */
6525 /*-----------------------------------------------------------------*/
6526 static void
6527 genlshOne (operand * result, operand * left, int shCount)
6528 {
6529   D(emitcode (";     genlshOne",""));
6530
6531   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6532 }
6533
6534 /*-----------------------------------------------------------------*/
6535 /* genlshTwo - left shift two bytes by known amount != 0           */
6536 /*-----------------------------------------------------------------*/
6537 static void
6538 genlshTwo (operand * result, operand * left, int shCount)
6539 {
6540   int size;
6541
6542   D(emitcode (";     genlshTwo",""));
6543
6544   size = getDataSize (result);
6545
6546   /* if shCount >= 8 */
6547   if (shCount >= 8)
6548     {
6549       shCount -= 8;
6550
6551       if (size > 1)
6552         {
6553           if (shCount)
6554             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6555           else
6556             movLeft2Result (left, LSB, result, MSB16, 0);
6557         }
6558       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6559     }
6560
6561   /*  1 <= shCount <= 7 */
6562   else
6563     {
6564       if (size == 1)
6565         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6566       else
6567         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6568     }
6569 }
6570
6571 /*-----------------------------------------------------------------*/
6572 /* shiftLLong - shift left one long from left to result            */
6573 /* offl = LSB or MSB16                                             */
6574 /*-----------------------------------------------------------------*/
6575 static void
6576 shiftLLong (operand * left, operand * result, int offr)
6577 {
6578   char *l;
6579   int size = AOP_SIZE (result);
6580
6581   if (size >= LSB + offr)
6582     {
6583       l = aopGet (AOP (left), LSB, FALSE, FALSE);
6584       MOVA (l);
6585       emitcode ("add", "a,acc");
6586       if (sameRegs (AOP (left), AOP (result)) &&
6587           size >= MSB16 + offr && offr != LSB)
6588         emitcode ("xch", "a,%s",
6589                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6590       else
6591         aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6592     }
6593
6594   if (size >= MSB16 + offr)
6595     {
6596       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6597         {
6598           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6599           MOVA (l);
6600         }
6601       emitcode ("rlc", "a");
6602       if (sameRegs (AOP (left), AOP (result)) &&
6603           size >= MSB24 + offr && offr != LSB)
6604         emitcode ("xch", "a,%s",
6605                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6606       else
6607         aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6608     }
6609
6610   if (size >= MSB24 + offr)
6611     {
6612       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6613         {
6614           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6615           MOVA (l);
6616         }
6617       emitcode ("rlc", "a");
6618       if (sameRegs (AOP (left), AOP (result)) &&
6619           size >= MSB32 + offr && offr != LSB)
6620         emitcode ("xch", "a,%s",
6621                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6622       else
6623         aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6624     }
6625
6626   if (size > MSB32 + offr)
6627     {
6628       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6629         {
6630           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6631           MOVA (l);
6632         }
6633       emitcode ("rlc", "a");
6634       aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6635     }
6636   if (offr != LSB)
6637     aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6638 }
6639
6640 /*-----------------------------------------------------------------*/
6641 /* genlshFour - shift four byte by a known amount != 0             */
6642 /*-----------------------------------------------------------------*/
6643 static void
6644 genlshFour (operand * result, operand * left, int shCount)
6645 {
6646   int size;
6647
6648   D(emitcode (";     genlshFour",""));
6649
6650   size = AOP_SIZE (result);
6651
6652   /* if shifting more that 3 bytes */
6653   if (shCount >= 24)
6654     {
6655       shCount -= 24;
6656       if (shCount)
6657         /* lowest order of left goes to the highest
6658            order of the destination */
6659         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6660       else
6661         movLeft2Result (left, LSB, result, MSB32, 0);
6662       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6663       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6664       aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6665       return;
6666     }
6667
6668   /* more than two bytes */
6669   else if (shCount >= 16)
6670     {
6671       /* lower order two bytes goes to higher order two bytes */
6672       shCount -= 16;
6673       /* if some more remaining */
6674       if (shCount)
6675         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6676       else
6677         {
6678           movLeft2Result (left, MSB16, result, MSB32, 0);
6679           movLeft2Result (left, LSB, result, MSB24, 0);
6680         }
6681       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6682       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6683       return;
6684     }
6685
6686   /* if more than 1 byte */
6687   else if (shCount >= 8)
6688     {
6689       /* lower order three bytes goes to higher order  three bytes */
6690       shCount -= 8;
6691       if (size == 2)
6692         {
6693           if (shCount)
6694             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6695           else
6696             movLeft2Result (left, LSB, result, MSB16, 0);
6697         }
6698       else
6699         {                       /* size = 4 */
6700           if (shCount == 0)
6701             {
6702               movLeft2Result (left, MSB24, result, MSB32, 0);
6703               movLeft2Result (left, MSB16, result, MSB24, 0);
6704               movLeft2Result (left, LSB, result, MSB16, 0);
6705               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6706             }
6707           else if (shCount == 1)
6708             shiftLLong (left, result, MSB16);
6709           else
6710             {
6711               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6712               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6713               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6714               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6715             }
6716         }
6717     }
6718
6719   /* 1 <= shCount <= 7 */
6720   else if (shCount <= 2)
6721     {
6722       shiftLLong (left, result, LSB);
6723       if (shCount == 2)
6724         shiftLLong (result, result, LSB);
6725     }
6726   /* 3 <= shCount <= 7, optimize */
6727   else
6728     {
6729       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6730       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6731       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6732     }
6733 }
6734
6735 /*-----------------------------------------------------------------*/
6736 /* genLeftShiftLiteral - left shifting by known count              */
6737 /*-----------------------------------------------------------------*/
6738 static void
6739 genLeftShiftLiteral (operand * left,
6740                      operand * right,
6741                      operand * result,
6742                      iCode * ic)
6743 {
6744   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6745   int size;
6746
6747   D(emitcode (";     genLeftShiftLiteral",""));
6748
6749   freeAsmop (right, NULL, ic, TRUE);
6750
6751   aopOp (left, ic, FALSE);
6752   aopOp (result, ic, FALSE);
6753
6754   size = getSize (operandType (result));
6755
6756 #if VIEW_SIZE
6757   emitcode ("; shift left ", "result %d, left %d", size,
6758             AOP_SIZE (left));
6759 #endif
6760
6761   /* I suppose that the left size >= result size */
6762   if (shCount == 0)
6763     {
6764       while (size--)
6765         {
6766           movLeft2Result (left, size, result, size, 0);
6767         }
6768     }
6769
6770   else if (shCount >= (size * 8))
6771     while (size--)
6772       aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6773   else
6774     {
6775       switch (size)
6776         {
6777         case 1:
6778           genlshOne (result, left, shCount);
6779           break;
6780
6781         case 2:
6782           genlshTwo (result, left, shCount);
6783           break;
6784
6785         case 4:
6786           genlshFour (result, left, shCount);
6787           break;
6788         default:
6789           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6790                   "*** ack! mystery literal shift!\n");
6791           break;
6792         }
6793     }
6794   freeAsmop (left, NULL, ic, TRUE);
6795   freeAsmop (result, NULL, ic, TRUE);
6796 }
6797
6798 /*-----------------------------------------------------------------*/
6799 /* genLeftShift - generates code for left shifting                 */
6800 /*-----------------------------------------------------------------*/
6801 static void
6802 genLeftShift (iCode * ic)
6803 {
6804   operand *left, *right, *result;
6805   int size, offset;
6806   char *l;
6807   symbol *tlbl, *tlbl1;
6808
6809   D(emitcode (";     genLeftShift",""));
6810
6811   right = IC_RIGHT (ic);
6812   left = IC_LEFT (ic);
6813   result = IC_RESULT (ic);
6814
6815   aopOp (right, ic, FALSE);
6816
6817   /* if the shift count is known then do it
6818      as efficiently as possible */
6819   if (AOP_TYPE (right) == AOP_LIT)
6820     {
6821       genLeftShiftLiteral (left, right, result, ic);
6822       return;
6823     }
6824
6825   /* shift count is unknown then we have to form
6826      a loop get the loop count in B : Note: we take
6827      only the lower order byte since shifting
6828      more that 32 bits make no sense anyway, ( the
6829      largest size of an object can be only 32 bits ) */
6830
6831   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6832   emitcode ("inc", "b");
6833   freeAsmop (right, NULL, ic, TRUE);
6834   aopOp (left, ic, FALSE);
6835   aopOp (result, ic, FALSE);
6836
6837   /* now move the left to the result if they are not the
6838      same */
6839   if (!sameRegs (AOP (left), AOP (result)) &&
6840       AOP_SIZE (result) > 1)
6841     {
6842
6843       size = AOP_SIZE (result);
6844       offset = 0;
6845       while (size--)
6846         {
6847           l = aopGet (AOP (left), offset, FALSE, TRUE);
6848           if (*l == '@' && (IS_AOP_PREG (result)))
6849             {
6850
6851               emitcode ("mov", "a,%s", l);
6852               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6853             }
6854           else
6855             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6856           offset++;
6857         }
6858     }
6859
6860   tlbl = newiTempLabel (NULL);
6861   size = AOP_SIZE (result);
6862   offset = 0;
6863   tlbl1 = newiTempLabel (NULL);
6864
6865   /* if it is only one byte then */
6866   if (size == 1)
6867     {
6868       symbol *tlbl1 = newiTempLabel (NULL);
6869
6870       l = aopGet (AOP (left), 0, FALSE, FALSE);
6871       MOVA (l);
6872       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6873       emitcode ("", "%05d$:", tlbl->key + 100);
6874       emitcode ("add", "a,acc");
6875       emitcode ("", "%05d$:", tlbl1->key + 100);
6876       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6877       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6878       goto release;
6879     }
6880
6881   reAdjustPreg (AOP (result));
6882
6883   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6884   emitcode ("", "%05d$:", tlbl->key + 100);
6885   l = aopGet (AOP (result), offset, FALSE, FALSE);
6886   MOVA (l);
6887   emitcode ("add", "a,acc");
6888   aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6889   while (--size)
6890     {
6891       l = aopGet (AOP (result), offset, FALSE, FALSE);
6892       MOVA (l);
6893       emitcode ("rlc", "a");
6894       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6895     }
6896   reAdjustPreg (AOP (result));
6897
6898   emitcode ("", "%05d$:", tlbl1->key + 100);
6899   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6900 release:
6901   freeAsmop (left, NULL, ic, TRUE);
6902   freeAsmop (result, NULL, ic, TRUE);
6903 }
6904
6905 /*-----------------------------------------------------------------*/
6906 /* genrshOne - right shift a one byte quantity by known count      */
6907 /*-----------------------------------------------------------------*/
6908 static void
6909 genrshOne (operand * result, operand * left,
6910            int shCount, int sign)
6911 {
6912   D(emitcode (";     genrshOne",""));
6913
6914   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6915 }
6916
6917 /*-----------------------------------------------------------------*/
6918 /* genrshTwo - right shift two bytes by known amount != 0          */
6919 /*-----------------------------------------------------------------*/
6920 static void
6921 genrshTwo (operand * result, operand * left,
6922            int shCount, int sign)
6923 {
6924   D(emitcode (";     genrshTwo",""));
6925
6926   /* if shCount >= 8 */
6927   if (shCount >= 8)
6928     {
6929       shCount -= 8;
6930       if (shCount)
6931         shiftR1Left2Result (left, MSB16, result, LSB,
6932                             shCount, sign);
6933       else
6934         movLeft2Result (left, MSB16, result, LSB, sign);
6935       addSign (result, MSB16, sign);
6936     }
6937
6938   /*  1 <= shCount <= 7 */
6939   else
6940     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6941 }
6942
6943 /*-----------------------------------------------------------------*/
6944 /* shiftRLong - shift right one long from left to result           */
6945 /* offl = LSB or MSB16                                             */
6946 /*-----------------------------------------------------------------*/
6947 static void
6948 shiftRLong (operand * left, int offl,
6949             operand * result, int sign)
6950 {
6951   int isSameRegs=sameRegs(AOP(left),AOP(result));
6952
6953   if (isSameRegs && offl>1) {
6954     // we are in big trouble, but this shouldn't happen
6955     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6956   }
6957
6958   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6959   
6960   if (offl==MSB16) {
6961     // shift is > 8
6962     if (sign) {
6963       emitcode ("rlc", "a");
6964       emitcode ("subb", "a,acc");
6965       if (isSameRegs)
6966         emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6967       else {
6968         aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6969         MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6970       }
6971     } else {
6972       aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6973     }
6974   }
6975
6976   if (!sign) {
6977     emitcode ("clr", "c");
6978   } else {
6979     emitcode ("mov", "c,acc.7");
6980   }
6981
6982   emitcode ("rrc", "a");
6983
6984   if (isSameRegs && offl==MSB16) {
6985     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6986   } else {
6987     aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6988     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6989   }
6990
6991   emitcode ("rrc", "a");
6992   if (isSameRegs && offl==1) {
6993     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6994   } else {
6995     aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6996     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6997   }
6998   emitcode ("rrc", "a");
6999   aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7000
7001   if (offl == LSB)
7002     {
7003       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7004       emitcode ("rrc", "a");
7005       aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7006     }
7007 }
7008
7009 /*-----------------------------------------------------------------*/
7010 /* genrshFour - shift four byte by a known amount != 0             */
7011 /*-----------------------------------------------------------------*/
7012 static void
7013 genrshFour (operand * result, operand * left,
7014             int shCount, int sign)
7015 {
7016   D(emitcode (";     genrshFour",""));
7017
7018   /* if shifting more that 3 bytes */
7019   if (shCount >= 24)
7020     {
7021       shCount -= 24;
7022       if (shCount)
7023         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7024       else
7025         movLeft2Result (left, MSB32, result, LSB, sign);
7026       addSign (result, MSB16, sign);
7027     }
7028   else if (shCount >= 16)
7029     {
7030       shCount -= 16;
7031       if (shCount)
7032         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7033       else
7034         {
7035           movLeft2Result (left, MSB24, result, LSB, 0);
7036           movLeft2Result (left, MSB32, result, MSB16, sign);
7037         }
7038       addSign (result, MSB24, sign);
7039     }
7040   else if (shCount >= 8)
7041     {
7042       shCount -= 8;
7043       if (shCount == 1)
7044         shiftRLong (left, MSB16, result, sign);
7045       else if (shCount == 0)
7046         {
7047           movLeft2Result (left, MSB16, result, LSB, 0);
7048           movLeft2Result (left, MSB24, result, MSB16, 0);
7049           movLeft2Result (left, MSB32, result, MSB24, sign);
7050           addSign (result, MSB32, sign);
7051         }
7052       else
7053         {
7054           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7055           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7056           /* the last shift is signed */
7057           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7058           addSign (result, MSB32, sign);
7059         }
7060     }
7061   else
7062     {                           /* 1 <= shCount <= 7 */
7063       if (shCount <= 2)
7064         {
7065           shiftRLong (left, LSB, result, sign);
7066           if (shCount == 2)
7067             shiftRLong (result, LSB, result, sign);
7068         }
7069       else
7070         {
7071           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7072           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7073           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7074         }
7075     }
7076 }
7077
7078 /*-----------------------------------------------------------------*/
7079 /* genRightShiftLiteral - right shifting by known count            */
7080 /*-----------------------------------------------------------------*/
7081 static void
7082 genRightShiftLiteral (operand * left,
7083                       operand * right,
7084                       operand * result,
7085                       iCode * ic,
7086                       int sign)
7087 {
7088   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7089   int size;
7090
7091   D(emitcode (";     genRightShiftLiteral",""));
7092
7093   freeAsmop (right, NULL, ic, TRUE);
7094
7095   aopOp (left, ic, FALSE);
7096   aopOp (result, ic, FALSE);
7097
7098 #if VIEW_SIZE
7099   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7100             AOP_SIZE (left));
7101 #endif
7102
7103   size = getDataSize (left);
7104   /* test the LEFT size !!! */
7105
7106   /* I suppose that the left size >= result size */
7107   if (shCount == 0)
7108     {
7109       size = getDataSize (result);
7110       while (size--)
7111         movLeft2Result (left, size, result, size, 0);
7112     }
7113
7114   else if (shCount >= (size * 8))
7115     {
7116       if (sign) {
7117         /* get sign in acc.7 */
7118         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7119       }
7120       addSign (result, LSB, sign);
7121     }
7122   else
7123     {
7124       switch (size)
7125         {
7126         case 1:
7127           genrshOne (result, left, shCount, sign);
7128           break;
7129
7130         case 2:
7131           genrshTwo (result, left, shCount, sign);
7132           break;
7133
7134         case 4:
7135           genrshFour (result, left, shCount, sign);
7136           break;
7137         default:
7138           break;
7139         }
7140     }
7141   freeAsmop (left, NULL, ic, TRUE);
7142   freeAsmop (result, NULL, ic, TRUE);
7143 }
7144
7145 /*-----------------------------------------------------------------*/
7146 /* genSignedRightShift - right shift of signed number              */
7147 /*-----------------------------------------------------------------*/
7148 static void
7149 genSignedRightShift (iCode * ic)
7150 {
7151   operand *right, *left, *result;
7152   int size, offset;
7153   char *l;
7154   symbol *tlbl, *tlbl1;
7155
7156   D(emitcode (";     genSignedRightShift",""));
7157
7158   /* we do it the hard way put the shift count in b
7159      and loop thru preserving the sign */
7160
7161   right = IC_RIGHT (ic);
7162   left = IC_LEFT (ic);
7163   result = IC_RESULT (ic);
7164
7165   aopOp (right, ic, FALSE);
7166
7167
7168   if (AOP_TYPE (right) == AOP_LIT)
7169     {
7170       genRightShiftLiteral (left, right, result, ic, 1);
7171       return;
7172     }
7173   /* shift count is unknown then we have to form
7174      a loop get the loop count in B : Note: we take
7175      only the lower order byte since shifting
7176      more that 32 bits make no sense anyway, ( the
7177      largest size of an object can be only 32 bits ) */
7178
7179   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7180   emitcode ("inc", "b");
7181   freeAsmop (right, NULL, ic, TRUE);
7182   aopOp (left, ic, FALSE);
7183   aopOp (result, ic, FALSE);
7184
7185   /* now move the left to the result if they are not the
7186      same */
7187   if (!sameRegs (AOP (left), AOP (result)) &&
7188       AOP_SIZE (result) > 1)
7189     {
7190
7191       size = AOP_SIZE (result);
7192       offset = 0;
7193       while (size--)
7194         {
7195           l = aopGet (AOP (left), offset, FALSE, TRUE);
7196           if (*l == '@' && IS_AOP_PREG (result))
7197             {
7198
7199               emitcode ("mov", "a,%s", l);
7200               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7201             }
7202           else
7203             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7204           offset++;
7205         }
7206     }
7207
7208   /* mov the highest order bit to OVR */
7209   tlbl = newiTempLabel (NULL);
7210   tlbl1 = newiTempLabel (NULL);
7211
7212   size = AOP_SIZE (result);
7213   offset = size - 1;
7214   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7215   emitcode ("rlc", "a");
7216   emitcode ("mov", "ov,c");
7217   /* if it is only one byte then */
7218   if (size == 1)
7219     {
7220       l = aopGet (AOP (left), 0, FALSE, FALSE);
7221       MOVA (l);
7222       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7223       emitcode ("", "%05d$:", tlbl->key + 100);
7224       emitcode ("mov", "c,ov");
7225       emitcode ("rrc", "a");
7226       emitcode ("", "%05d$:", tlbl1->key + 100);
7227       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7228       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7229       goto release;
7230     }
7231
7232   reAdjustPreg (AOP (result));
7233   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7234   emitcode ("", "%05d$:", tlbl->key + 100);
7235   emitcode ("mov", "c,ov");
7236   while (size--)
7237     {
7238       l = aopGet (AOP (result), offset, FALSE, FALSE);
7239       MOVA (l);
7240       emitcode ("rrc", "a");
7241       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7242     }
7243   reAdjustPreg (AOP (result));
7244   emitcode ("", "%05d$:", tlbl1->key + 100);
7245   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7246
7247 release:
7248   freeAsmop (left, NULL, ic, TRUE);
7249   freeAsmop (result, NULL, ic, TRUE);
7250 }
7251
7252 /*-----------------------------------------------------------------*/
7253 /* genRightShift - generate code for right shifting                */
7254 /*-----------------------------------------------------------------*/
7255 static void
7256 genRightShift (iCode * ic)
7257 {
7258   operand *right, *left, *result;
7259   sym_link *letype;
7260   int size, offset;
7261   char *l;
7262   symbol *tlbl, *tlbl1;
7263
7264   D(emitcode (";     genRightShift",""));
7265
7266   /* if signed then we do it the hard way preserve the
7267      sign bit moving it inwards */
7268   letype = getSpec (operandType (IC_LEFT (ic)));
7269
7270   if (!SPEC_USIGN (letype))
7271     {
7272       genSignedRightShift (ic);
7273       return;
7274     }
7275
7276   /* signed & unsigned types are treated the same : i.e. the
7277      signed is NOT propagated inwards : quoting from the
7278      ANSI - standard : "for E1 >> E2, is equivalent to division
7279      by 2**E2 if unsigned or if it has a non-negative value,
7280      otherwise the result is implementation defined ", MY definition
7281      is that the sign does not get propagated */
7282
7283   right = IC_RIGHT (ic);
7284   left = IC_LEFT (ic);
7285   result = IC_RESULT (ic);
7286
7287   aopOp (right, ic, FALSE);
7288
7289   /* if the shift count is known then do it
7290      as efficiently as possible */
7291   if (AOP_TYPE (right) == AOP_LIT)
7292     {
7293       genRightShiftLiteral (left, right, result, ic, 0);
7294       return;
7295     }
7296
7297   /* shift count is unknown then we have to form
7298      a loop get the loop count in B : Note: we take
7299      only the lower order byte since shifting
7300      more that 32 bits make no sense anyway, ( the
7301      largest size of an object can be only 32 bits ) */
7302
7303   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7304   emitcode ("inc", "b");
7305   freeAsmop (right, NULL, ic, TRUE);
7306   aopOp (left, ic, FALSE);
7307   aopOp (result, ic, FALSE);
7308
7309   /* now move the left to the result if they are not the
7310      same */
7311   if (!sameRegs (AOP (left), AOP (result)) &&
7312       AOP_SIZE (result) > 1)
7313     {
7314
7315       size = AOP_SIZE (result);
7316       offset = 0;
7317       while (size--)
7318         {
7319           l = aopGet (AOP (left), offset, FALSE, TRUE);
7320           if (*l == '@' && IS_AOP_PREG (result))
7321             {
7322
7323               emitcode ("mov", "a,%s", l);
7324               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7325             }
7326           else
7327             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7328           offset++;
7329         }
7330     }
7331
7332   tlbl = newiTempLabel (NULL);
7333   tlbl1 = newiTempLabel (NULL);
7334   size = AOP_SIZE (result);
7335   offset = size - 1;
7336
7337   /* if it is only one byte then */
7338   if (size == 1)
7339     {
7340       l = aopGet (AOP (left), 0, FALSE, FALSE);
7341       MOVA (l);
7342       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7343       emitcode ("", "%05d$:", tlbl->key + 100);
7344       CLRC;
7345       emitcode ("rrc", "a");
7346       emitcode ("", "%05d$:", tlbl1->key + 100);
7347       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7348       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7349       goto release;
7350     }
7351
7352   reAdjustPreg (AOP (result));
7353   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7354   emitcode ("", "%05d$:", tlbl->key + 100);
7355   CLRC;
7356   while (size--)
7357     {
7358       l = aopGet (AOP (result), offset, FALSE, FALSE);
7359       MOVA (l);
7360       emitcode ("rrc", "a");
7361       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7362     }
7363   reAdjustPreg (AOP (result));
7364
7365   emitcode ("", "%05d$:", tlbl1->key + 100);
7366   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7367
7368 release:
7369   freeAsmop (left, NULL, ic, TRUE);
7370   freeAsmop (result, NULL, ic, TRUE);
7371 }
7372
7373 /*-----------------------------------------------------------------*/
7374 /* emitPtrByteGet - emits code to get a byte into A through a      */
7375 /*                  pointer register (R0, R1, or DPTR). The        */
7376 /*                  original value of A can be preserved in B.     */
7377 /*-----------------------------------------------------------------*/
7378 static void
7379 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7380 {
7381   switch (p_type)
7382     {
7383     case IPOINTER:
7384     case POINTER:
7385       if (preserveAinB)
7386         emitcode ("mov", "b,a");
7387       emitcode ("mov", "a,@%s", rname);
7388       break;
7389
7390     case PPOINTER:
7391       if (preserveAinB)
7392         emitcode ("mov", "b,a");
7393       emitcode ("movx", "a,@%s", rname);
7394       break;
7395       
7396     case FPOINTER:
7397       if (preserveAinB)
7398         emitcode ("mov", "b,a");
7399       emitcode ("movx", "a,@dptr");
7400       break;
7401
7402     case CPOINTER:
7403       if (preserveAinB)
7404         emitcode ("mov", "b,a");
7405       emitcode ("clr", "a");
7406       emitcode ("movc", "a,@a+dptr");
7407       break;
7408
7409     case GPOINTER:
7410       if (preserveAinB)
7411         {
7412           emitcode ("push", "b");
7413           emitcode ("push", "acc");
7414         }
7415       emitcode ("lcall", "__gptrget");
7416       if (preserveAinB)
7417         emitcode ("pop", "b");
7418       break;
7419     }
7420 }
7421
7422 /*-----------------------------------------------------------------*/
7423 /* emitPtrByteSet - emits code to set a byte from src through a    */
7424 /*                  pointer register (R0, R1, or DPTR).            */
7425 /*-----------------------------------------------------------------*/
7426 static void
7427 emitPtrByteSet (char *rname, int p_type, char *src)
7428 {
7429   switch (p_type)
7430     {
7431     case IPOINTER:
7432     case POINTER:
7433       if (*src=='@')
7434         {
7435           MOVA (src);
7436           emitcode ("mov", "@%s,a", rname);
7437         }
7438       else
7439         emitcode ("mov", "@%s,%s", rname, src);
7440       break;
7441
7442     case PPOINTER:
7443       MOVA (src);
7444       emitcode ("movx", "@%s,a", rname);
7445       break;
7446       
7447     case FPOINTER:
7448       MOVA (src);
7449       emitcode ("movx", "@dptr,a");
7450       break;
7451
7452     case GPOINTER:
7453       MOVA (src);
7454       emitcode ("lcall", "__gptrput");
7455       break;
7456     }
7457 }
7458
7459 /*-----------------------------------------------------------------*/
7460 /* genUnpackBits - generates code for unpacking bits               */
7461 /*-----------------------------------------------------------------*/
7462 static void
7463 genUnpackBits (operand * result, char *rname, int ptype)
7464 {
7465   int offset = 0;       /* result byte offset */
7466   int rsize;            /* result size */
7467   int rlen = 0;         /* remaining bitfield length */
7468   sym_link *etype;      /* bitfield type information */
7469   int blen;             /* bitfield length */
7470   int bstr;             /* bitfield starting bit within byte */
7471
7472   D(emitcode (";     genUnpackBits",""));
7473
7474   etype = getSpec (operandType (result));
7475   rsize = getSize (operandType (result));
7476   blen = SPEC_BLEN (etype);
7477   bstr = SPEC_BSTR (etype);
7478
7479   /* If the bitfield length is less than a byte */
7480   if (blen < 8)
7481     {
7482       emitPtrByteGet (rname, ptype, FALSE);
7483       AccRsh (bstr);
7484       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7485       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7486       goto finish;
7487     }
7488
7489   /* Bit field did not fit in a byte. Copy all
7490      but the partial byte at the end.  */
7491   for (rlen=blen;rlen>=8;rlen-=8)
7492     {
7493       emitPtrByteGet (rname, ptype, FALSE);
7494       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7495       if (rlen>8)
7496         emitcode ("inc", "%s", rname);
7497     }
7498
7499   /* Handle the partial byte at the end */
7500   if (rlen)
7501     {
7502       emitPtrByteGet (rname, ptype, FALSE);
7503       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7504       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7505     }
7506
7507 finish:
7508   if (offset < rsize)
7509     {
7510       rsize -= offset;
7511       while (rsize--)
7512         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7513     }
7514 }
7515
7516
7517 /*-----------------------------------------------------------------*/
7518 /* genDataPointerGet - generates code when ptr offset is known     */
7519 /*-----------------------------------------------------------------*/
7520 static void
7521 genDataPointerGet (operand * left,
7522                    operand * result,
7523                    iCode * ic)
7524 {
7525   char *l;
7526   char buffer[256];
7527   int size, offset = 0;
7528
7529   D(emitcode (";     genDataPointerGet",""));
7530
7531   aopOp (result, ic, TRUE);
7532
7533   /* get the string representation of the name */
7534   l = aopGet (AOP (left), 0, FALSE, TRUE);
7535   size = AOP_SIZE (result);
7536   while (size--)
7537     {
7538       if (offset)
7539         sprintf (buffer, "(%s + %d)", l + 1, offset);
7540       else
7541         sprintf (buffer, "%s", l + 1);
7542       aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7543     }
7544
7545   freeAsmop (left, NULL, ic, TRUE);
7546   freeAsmop (result, NULL, ic, TRUE);
7547 }
7548
7549 /*-----------------------------------------------------------------*/
7550 /* genNearPointerGet - emitcode for near pointer fetch             */
7551 /*-----------------------------------------------------------------*/
7552 static void
7553 genNearPointerGet (operand * left,
7554                    operand * result,
7555                    iCode * ic,
7556                    iCode * pi)
7557 {
7558   asmop *aop = NULL;
7559   regs *preg = NULL;
7560   char *rname;
7561   sym_link *rtype, *retype;
7562   sym_link *ltype = operandType (left);
7563   char buffer[80];
7564
7565   D(emitcode (";     genNearPointerGet",""));
7566
7567   rtype = operandType (result);
7568   retype = getSpec (rtype);
7569
7570   aopOp (left, ic, FALSE);
7571
7572   /* if left is rematerialisable and
7573      result is not bit variable type and
7574      the left is pointer to data space i.e
7575      lower 128 bytes of space */
7576   if (AOP_TYPE (left) == AOP_IMMD &&
7577       !IS_BITVAR (retype) &&
7578       DCL_TYPE (ltype) == POINTER)
7579     {
7580       genDataPointerGet (left, result, ic);
7581       return;
7582     }
7583
7584  /* if the value is already in a pointer register
7585      then don't need anything more */
7586   if (!AOP_INPREG (AOP (left)))
7587     {
7588       if (IS_AOP_PREG (left))
7589         {
7590           // Aha, it is a pointer, just in disguise.
7591           rname = aopGet (AOP (left), 0, FALSE, FALSE);
7592           if (*rname != '@')
7593             {
7594               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7595                       __FILE__, __LINE__);
7596             }
7597           else
7598             {
7599               // Expected case.
7600               emitcode ("mov", "a%s,%s", rname + 1, rname);
7601               rname++;  // skip the '@'.
7602             }
7603         }
7604       else
7605         {
7606           /* otherwise get a free pointer register */
7607           aop = newAsmop (0);
7608           preg = getFreePtr (ic, &aop, FALSE);
7609           emitcode ("mov", "%s,%s",
7610                     preg->name,
7611                     aopGet (AOP (left), 0, FALSE, TRUE));
7612           rname = preg->name;
7613         }
7614     }
7615   else
7616     rname = aopGet (AOP (left), 0, FALSE, FALSE);
7617
7618   //aopOp (result, ic, FALSE);
7619   aopOp (result, ic, result?TRUE:FALSE);
7620
7621   /* if bitfield then unpack the bits */
7622   if (IS_BITVAR (retype))
7623     genUnpackBits (result, rname, POINTER);
7624   else
7625     {
7626       /* we have can just get the values */
7627       int size = AOP_SIZE (result);
7628       int offset = 0;
7629
7630       while (size--)
7631         {
7632           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7633             {
7634
7635               emitcode ("mov", "a,@%s", rname);
7636               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7637             }
7638           else
7639             {
7640               sprintf (buffer, "@%s", rname);
7641               aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7642             }
7643           offset++;
7644           if (size || pi)
7645             emitcode ("inc", "%s", rname);
7646         }
7647     }
7648
7649   /* now some housekeeping stuff */
7650   if (aop)       /* we had to allocate for this iCode */
7651     {
7652       if (pi) { /* post increment present */
7653         aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7654       }
7655       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7656     }
7657   else
7658     {
7659       /* we did not allocate which means left
7660          already in a pointer register, then
7661          if size > 0 && this could be used again
7662          we have to point it back to where it
7663          belongs */
7664       if ((AOP_SIZE (result) > 1 &&
7665            !OP_SYMBOL (left)->remat &&
7666            (OP_SYMBOL (left)->liveTo > ic->seq ||
7667             ic->depth)) &&
7668           !pi)
7669         {
7670           int size = AOP_SIZE (result) - 1;
7671           while (size--)
7672             emitcode ("dec", "%s", rname);
7673         }
7674     }
7675
7676   /* done */
7677   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7678   freeAsmop (left, NULL, ic, TRUE);
7679   if (pi) pi->generated = 1;
7680 }
7681
7682 /*-----------------------------------------------------------------*/
7683 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7684 /*-----------------------------------------------------------------*/
7685 static void
7686 genPagedPointerGet (operand * left,
7687                     operand * result,
7688                     iCode * ic,
7689                     iCode *pi)
7690 {
7691   asmop *aop = NULL;
7692   regs *preg = NULL;
7693   char *rname;
7694   sym_link *rtype, *retype;
7695
7696   D(emitcode (";     genPagedPointerGet",""));
7697
7698   rtype = operandType (result);
7699   retype = getSpec (rtype);
7700
7701   aopOp (left, ic, FALSE);
7702
7703   /* if the value is already in a pointer register
7704      then don't need anything more */
7705   if (!AOP_INPREG (AOP (left)))
7706     {
7707       /* otherwise get a free pointer register */
7708       aop = newAsmop (0);
7709       preg = getFreePtr (ic, &aop, FALSE);
7710       emitcode ("mov", "%s,%s",
7711                 preg->name,
7712                 aopGet (AOP (left), 0, FALSE, TRUE));
7713       rname = preg->name;
7714     }
7715   else
7716     rname = aopGet (AOP (left), 0, FALSE, FALSE);
7717
7718   aopOp (result, ic, FALSE);
7719
7720   /* if bitfield then unpack the bits */
7721   if (IS_BITVAR (retype))
7722     genUnpackBits (result, rname, PPOINTER);
7723   else
7724     {
7725       /* we have can just get the values */
7726       int size = AOP_SIZE (result);
7727       int offset = 0;
7728
7729       while (size--)
7730         {
7731
7732           emitcode ("movx", "a,@%s", rname);
7733           aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7734
7735           offset++;
7736
7737           if (size || pi)
7738             emitcode ("inc", "%s", rname);
7739         }
7740     }
7741
7742   /* now some housekeeping stuff */
7743   if (aop) /* we had to allocate for this iCode */
7744     {
7745       if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7746       freeAsmop (NULL, aop, ic, TRUE);
7747     }
7748   else
7749     {
7750       /* we did not allocate which means left
7751          already in a pointer register, then
7752          if size > 0 && this could be used again
7753          we have to point it back to where it
7754          belongs */
7755       if ((AOP_SIZE (result) > 1 &&
7756            !OP_SYMBOL (left)->remat &&
7757            (OP_SYMBOL (left)->liveTo > ic->seq ||
7758             ic->depth)) &&
7759           !pi)
7760         {
7761           int size = AOP_SIZE (result) - 1;
7762           while (size--)
7763             emitcode ("dec", "%s", rname);
7764         }
7765     }
7766
7767   /* done */
7768   freeAsmop (left, NULL, ic, TRUE);
7769   freeAsmop (result, NULL, ic, TRUE);
7770   if (pi) pi->generated = 1;
7771
7772 }
7773
7774 /*--------------------------------------------------------------------*/
7775 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7776 /*--------------------------------------------------------------------*/
7777 static void
7778 loadDptrFromOperand (operand *op, bool loadBToo)
7779 {
7780   if (AOP_TYPE (op) != AOP_STR)
7781     {
7782       /* if this is remateriazable */
7783       if (AOP_TYPE (op) == AOP_IMMD)
7784         {
7785           emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7786           if (loadBToo)
7787             {
7788               if (AOP(op)->aopu.aop_immd.from_cast_remat) 
7789                 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7790               else
7791                 {
7792                   wassertl(FALSE, "need pointerCode");
7793                   emitcode ("", "; mov b,???");
7794                   /* genPointerGet and genPointerSet originally did different
7795                   ** things for this case. Both seem wrong.
7796                   ** from genPointerGet:
7797                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
7798                   ** from genPointerSet:
7799                   **  emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7800                   */
7801                 }
7802             }
7803         }
7804       else if (AOP_TYPE (op) == AOP_DPTR)
7805         {
7806           if (loadBToo)
7807             {
7808               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7809               emitcode ("push", "acc");
7810               MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7811               emitcode ("push", "acc");
7812               emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7813               emitcode ("pop", "dph");
7814               emitcode ("pop", "dpl");
7815             }
7816           else
7817             {
7818               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7819               emitcode ("push", "acc");
7820               emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7821               emitcode ("pop", "dpl");
7822             }
7823         }
7824       else
7825         {                       /* we need to get it byte by byte */
7826           emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7827           emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7828           if (loadBToo)
7829             emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7830         }
7831     }
7832 }
7833
7834 /*-----------------------------------------------------------------*/
7835 /* genFarPointerGet - gget value from far space                    */
7836 /*-----------------------------------------------------------------*/
7837 static void
7838 genFarPointerGet (operand * left,
7839                   operand * result, iCode * ic, iCode * pi)
7840 {
7841   int size, offset;
7842   sym_link *retype = getSpec (operandType (result));
7843
7844   D(emitcode (";     genFarPointerGet",""));
7845
7846   aopOp (left, ic, FALSE);
7847   loadDptrFromOperand (left, FALSE);
7848   
7849   /* so dptr now contains the address */
7850   aopOp (result, ic, FALSE);
7851
7852   /* if bit then unpack */
7853   if (IS_BITVAR (retype))
7854     genUnpackBits (result, "dptr", FPOINTER);
7855   else
7856     {
7857       size = AOP_SIZE (result);
7858       offset = 0;
7859
7860       while (size--)
7861         {
7862           emitcode ("movx", "a,@dptr");
7863           aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7864           if (size || pi)
7865             emitcode ("inc", "dptr");
7866         }
7867     }
7868   
7869   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7870     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7871     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7872     pi->generated = 1;
7873   }
7874   freeAsmop (left, NULL, ic, TRUE);
7875   freeAsmop (result, NULL, ic, TRUE);
7876 }
7877
7878 /*-----------------------------------------------------------------*/
7879 /* genCodePointerGet - gget value from code space                  */
7880 /*-----------------------------------------------------------------*/
7881 static void
7882 genCodePointerGet (operand * left,
7883                     operand * result, iCode * ic, iCode *pi)
7884 {
7885   int size, offset;
7886   sym_link *retype = getSpec (operandType (result));
7887
7888   D(emitcode (";     genCodePointerGet",""));
7889
7890   aopOp (left, ic, FALSE);
7891   loadDptrFromOperand (left, FALSE);
7892   
7893   /* so dptr now contains the address */
7894   aopOp (result, ic, FALSE);
7895
7896   /* if bit then unpack */
7897   if (IS_BITVAR (retype))
7898     genUnpackBits (result, "dptr", CPOINTER);
7899   else
7900     {
7901       size = AOP_SIZE (result);
7902       offset = 0;
7903
7904       while (size--)
7905         {
7906           if (pi)
7907             {
7908               emitcode ("clr", "a");
7909               emitcode ("movc", "a,@a+dptr");
7910               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7911               emitcode ("inc", "dptr");
7912             }
7913           else
7914             { 
7915               emitcode ("mov", "a,#0x%02x", offset);
7916               emitcode ("movc", "a,@a+dptr");
7917               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7918             }
7919         }
7920     }
7921
7922   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7923     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7924     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7925     pi->generated = 1;
7926   }
7927   freeAsmop (left, NULL, ic, TRUE);
7928   freeAsmop (result, NULL, ic, TRUE);
7929 }
7930
7931 /*-----------------------------------------------------------------*/
7932 /* genGenPointerGet - gget value from generic pointer space        */
7933 /*-----------------------------------------------------------------*/
7934 static void
7935 genGenPointerGet (operand * left,
7936                   operand * result, iCode * ic, iCode *pi)
7937 {
7938   int size, offset;
7939   sym_link *retype = getSpec (operandType (result));
7940
7941   D(emitcode (";     genGenPointerGet",""));
7942
7943   aopOp (left, ic, FALSE);
7944   loadDptrFromOperand (left, TRUE);
7945   
7946   /* so dptr know contains the address */
7947   aopOp (result, ic, FALSE);
7948
7949   /* if bit then unpack */
7950   if (IS_BITVAR (retype))
7951     genUnpackBits (result, "dptr", GPOINTER);
7952   else
7953     {
7954       size = AOP_SIZE (result);
7955       offset = 0;
7956
7957       while (size--)
7958         {
7959           emitcode ("lcall", "__gptrget");
7960           aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7961           if (size || pi)
7962             emitcode ("inc", "dptr");
7963         }
7964     }
7965
7966   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7967     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7968     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7969     pi->generated = 1;
7970   }
7971   freeAsmop (left, NULL, ic, TRUE);
7972   freeAsmop (result, NULL, ic, TRUE);
7973 }
7974
7975 /*-----------------------------------------------------------------*/
7976 /* genPointerGet - generate code for pointer get                   */
7977 /*-----------------------------------------------------------------*/
7978 static void
7979 genPointerGet (iCode * ic, iCode *pi)
7980 {
7981   operand *left, *result;
7982   sym_link *type, *etype;
7983   int p_type;
7984
7985   D(emitcode (";     genPointerGet",""));
7986
7987   left = IC_LEFT (ic);
7988   result = IC_RESULT (ic);
7989
7990   /* depending on the type of pointer we need to
7991      move it to the correct pointer register */
7992   type = operandType (left);
7993   etype = getSpec (type);
7994   /* if left is of type of pointer then it is simple */
7995   if (IS_PTR (type) && !IS_FUNC (type->next))
7996     p_type = DCL_TYPE (type);
7997   else
7998     {
7999       /* we have to go by the storage class */
8000       p_type = PTR_TYPE (SPEC_OCLS (etype));
8001     }
8002
8003   /* special case when cast remat */
8004   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8005       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8006           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8007           type = operandType (left);
8008           p_type = DCL_TYPE (type);
8009   }
8010   /* now that we have the pointer type we assign
8011      the pointer values */
8012   switch (p_type)
8013     {
8014
8015     case POINTER:
8016     case IPOINTER:
8017       genNearPointerGet (left, result, ic, pi);
8018       break;
8019
8020     case PPOINTER:
8021       genPagedPointerGet (left, result, ic, pi);
8022       break;
8023
8024     case FPOINTER:
8025       genFarPointerGet (left, result, ic, pi);
8026       break;
8027
8028     case CPOINTER:
8029       genCodePointerGet (left, result, ic, pi);
8030       break;
8031
8032     case GPOINTER:
8033       genGenPointerGet (left, result, ic, pi);
8034       break;
8035     }
8036
8037 }
8038
8039
8040
8041 /*-----------------------------------------------------------------*/
8042 /* genPackBits - generates code for packed bit storage             */
8043 /*-----------------------------------------------------------------*/
8044 static void
8045 genPackBits (sym_link * etype,
8046              operand * right,
8047              char *rname, int p_type)
8048 {
8049   int offset = 0;       /* source byte offset */
8050   int rlen = 0;         /* remaining bitfield length */
8051   int blen;             /* bitfield length */
8052   int bstr;             /* bitfield starting bit within byte */
8053   int litval;           /* source literal value (if AOP_LIT) */
8054   unsigned char mask;   /* bitmask within current byte */
8055
8056   D(emitcode (";     genPackBits",""));
8057
8058   blen = SPEC_BLEN (etype);
8059   bstr = SPEC_BSTR (etype);
8060
8061   /* If the bitfield length is less than a byte */
8062   if (blen < 8)
8063     {
8064       mask = ((unsigned char) (0xFF << (blen + bstr)) |
8065               (unsigned char) (0xFF >> (8 - bstr)));
8066
8067       if (AOP_TYPE (right) == AOP_LIT)
8068         {
8069           /* Case with a bitfield length <8 and literal source
8070           */
8071           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8072           litval <<= bstr;
8073           litval &= (~mask) & 0xff;
8074           emitPtrByteGet (rname, p_type, FALSE);
8075           if ((mask|litval)!=0xff)
8076             emitcode ("anl","a,#0x%02x", mask);
8077           if (litval)
8078             emitcode ("orl","a,#0x%02x", litval);
8079         }
8080       else
8081         {
8082           if ((blen==1) && (p_type!=GPOINTER))
8083             {
8084               /* Case with a bitfield length == 1 and no generic pointer
8085               */
8086               if (AOP_TYPE (right) == AOP_CRY)
8087                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8088               else
8089                 {
8090                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8091                   emitcode ("rrc","a");
8092                 }
8093               emitPtrByteGet (rname, p_type, FALSE);
8094               emitcode ("mov","acc.%d,c",bstr);
8095             }
8096           else
8097             {
8098               /* Case with a bitfield length < 8 and arbitrary source
8099               */
8100               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8101               /* shift and mask source value */
8102               AccLsh (bstr);
8103               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8104
8105               /* transfer A to B and get next byte */
8106               emitPtrByteGet (rname, p_type, TRUE);
8107
8108               emitcode ("anl", "a,#0x%02x", mask);
8109               emitcode ("orl", "a,b");
8110               if (p_type == GPOINTER)
8111                 emitcode ("pop", "b");
8112            }
8113         }
8114
8115       emitPtrByteSet (rname, p_type, "a");
8116       return;
8117     }
8118
8119   /* Bit length is greater than 7 bits. In this case, copy  */
8120   /* all except the partial byte at the end                 */
8121   for (rlen=blen;rlen>=8;rlen-=8)
8122     {
8123       emitPtrByteSet (rname, p_type, 
8124                       aopGet (AOP (right), offset++, FALSE, TRUE) );
8125       if (rlen>8)
8126         emitcode ("inc", "%s", rname);
8127     }
8128
8129   /* If there was a partial byte at the end */
8130   if (rlen)
8131     {
8132       mask = (((unsigned char) -1 << rlen) & 0xff);
8133       
8134       if (AOP_TYPE (right) == AOP_LIT)
8135         {
8136           /* Case with partial byte and literal source
8137           */
8138           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8139           litval >>= (blen-rlen);
8140           litval &= (~mask) & 0xff;
8141           emitPtrByteGet (rname, p_type, FALSE);
8142           if ((mask|litval)!=0xff)
8143             emitcode ("anl","a,#0x%02x", mask);
8144           if (litval)
8145             emitcode ("orl","a,#0x%02x", litval);
8146         }
8147       else
8148         {
8149           /* Case with partial byte and arbitrary source
8150           */
8151           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8152           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8153
8154           /* transfer A to B and get next byte */
8155           emitPtrByteGet (rname, p_type, TRUE);
8156
8157           emitcode ("anl", "a,#0x%02x", mask);
8158           emitcode ("orl", "a,b");
8159           if (p_type == GPOINTER)
8160             emitcode ("pop", "b");
8161         }
8162       emitPtrByteSet (rname, p_type, "a");
8163     }
8164
8165 }
8166
8167
8168 /*-----------------------------------------------------------------*/
8169 /* genDataPointerSet - remat pointer to data space                 */
8170 /*-----------------------------------------------------------------*/
8171 static void
8172 genDataPointerSet (operand * right,
8173                    operand * result,
8174                    iCode * ic)
8175 {
8176   int size, offset = 0;
8177   char *l, buffer[256];
8178
8179   D(emitcode (";     genDataPointerSet",""));
8180
8181   aopOp (right, ic, FALSE);
8182
8183   l = aopGet (AOP (result), 0, FALSE, TRUE);
8184   size = AOP_SIZE (right);
8185   while (size--)
8186     {
8187       if (offset)
8188         sprintf (buffer, "(%s + %d)", l + 1, offset);
8189       else
8190         sprintf (buffer, "%s", l + 1);
8191       emitcode ("mov", "%s,%s", buffer,
8192                 aopGet (AOP (right), offset++, FALSE, FALSE));
8193     }
8194
8195   freeAsmop (right, NULL, ic, TRUE);
8196   freeAsmop (result, NULL, ic, TRUE);
8197 }
8198
8199 /*-----------------------------------------------------------------*/
8200 /* genNearPointerSet - emitcode for near pointer put                */
8201 /*-----------------------------------------------------------------*/
8202 static void
8203 genNearPointerSet (operand * right,
8204                    operand * result,
8205                    iCode * ic,
8206                    iCode * pi)
8207 {
8208   asmop *aop = NULL;
8209   regs *preg = NULL;
8210   char *rname, *l;
8211   sym_link *retype, *letype;
8212   sym_link *ptype = operandType (result);
8213
8214   D(emitcode (";     genNearPointerSet",""));
8215
8216   retype = getSpec (operandType (right));
8217   letype = getSpec (ptype);
8218   aopOp (result, ic, FALSE);
8219
8220   /* if the result is rematerializable &
8221      in data space & not a bit variable */
8222   if (AOP_TYPE (result) == AOP_IMMD &&
8223       DCL_TYPE (ptype) == POINTER &&
8224       !IS_BITVAR (retype) &&
8225       !IS_BITVAR (letype))
8226     {
8227       genDataPointerSet (right, result, ic);
8228       return;
8229     }
8230
8231   /* if the value is already in a pointer register
8232      then don't need anything more */
8233   if (!AOP_INPREG (AOP (result)))
8234     {
8235         if (
8236             //AOP_TYPE (result) == AOP_STK
8237             IS_AOP_PREG(result)
8238             )
8239         {
8240             // Aha, it is a pointer, just in disguise.
8241             rname = aopGet (AOP (result), 0, FALSE, FALSE);
8242             if (*rname != '@')
8243             {
8244                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8245                         __FILE__, __LINE__);
8246             }
8247             else
8248             {
8249                 // Expected case.
8250                 emitcode ("mov", "a%s,%s", rname + 1, rname);
8251                 rname++;  // skip the '@'.
8252             }
8253         }
8254         else
8255         {
8256             /* otherwise get a free pointer register */
8257             aop = newAsmop (0);
8258             preg = getFreePtr (ic, &aop, FALSE);
8259             emitcode ("mov", "%s,%s",
8260                       preg->name,
8261                       aopGet (AOP (result), 0, FALSE, TRUE));
8262             rname = preg->name;
8263         }
8264     }
8265     else
8266     {
8267         rname = aopGet (AOP (result), 0, FALSE, FALSE);
8268     }
8269
8270   aopOp (right, ic, FALSE);
8271
8272   /* if bitfield then unpack the bits */
8273   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8274     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8275   else
8276     {
8277       /* we have can just get the values */
8278       int size = AOP_SIZE (right);
8279       int offset = 0;
8280
8281       while (size--)
8282         {
8283           l = aopGet (AOP (right), offset, FALSE, TRUE);
8284           if (*l == '@')
8285             {
8286               MOVA (l);
8287               emitcode ("mov", "@%s,a", rname);
8288             }
8289           else
8290             emitcode ("mov", "@%s,%s", rname, l);
8291           if (size || pi)
8292             emitcode ("inc", "%s", rname);
8293           offset++;
8294         }
8295     }
8296
8297   /* now some housekeeping stuff */
8298   if (aop) /* we had to allocate for this iCode */
8299     {
8300       if (pi)
8301         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8302       freeAsmop (NULL, aop, ic, TRUE);
8303     }
8304   else
8305     {
8306       /* we did not allocate which means left
8307          already in a pointer register, then
8308          if size > 0 && this could be used again
8309          we have to point it back to where it
8310          belongs */
8311       if ((AOP_SIZE (right) > 1 &&
8312            !OP_SYMBOL (result)->remat &&
8313            (OP_SYMBOL (result)->liveTo > ic->seq ||
8314             ic->depth)) &&
8315           !pi)
8316         {
8317           int size = AOP_SIZE (right) - 1;
8318           while (size--)
8319             emitcode ("dec", "%s", rname);
8320         }
8321     }
8322
8323   /* done */
8324   if (pi) pi->generated = 1;
8325   freeAsmop (result, NULL, ic, TRUE);
8326   freeAsmop (right, NULL, ic, TRUE);
8327 }
8328
8329 /*-----------------------------------------------------------------*/
8330 /* genPagedPointerSet - emitcode for Paged pointer put             */
8331 /*-----------------------------------------------------------------*/
8332 static void
8333 genPagedPointerSet (operand * right,
8334                     operand * result,
8335                     iCode * ic,
8336                     iCode * pi)
8337 {
8338   asmop *aop = NULL;
8339   regs *preg = NULL;
8340   char *rname, *l;
8341   sym_link *retype, *letype;
8342
8343   D(emitcode (";     genPagedPointerSet",""));
8344
8345   retype = getSpec (operandType (right));
8346   letype = getSpec (operandType (result));
8347
8348   aopOp (result, ic, FALSE);
8349
8350   /* if the value is already in a pointer register
8351      then don't need anything more */
8352   if (!AOP_INPREG (AOP (result)))
8353     {
8354       /* otherwise get a free pointer register */
8355       aop = newAsmop (0);
8356       preg = getFreePtr (ic, &aop, FALSE);
8357       emitcode ("mov", "%s,%s",
8358                 preg->name,
8359                 aopGet (AOP (result), 0, FALSE, TRUE));
8360       rname = preg->name;
8361     }
8362   else
8363     rname = aopGet (AOP (result), 0, FALSE, FALSE);
8364
8365   aopOp (right, ic, FALSE);
8366
8367   /* if bitfield then unpack the bits */
8368   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8369     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8370   else
8371     {
8372       /* we have can just get the values */
8373       int size = AOP_SIZE (right);
8374       int offset = 0;
8375
8376       while (size--)
8377         {
8378           l = aopGet (AOP (right), offset, FALSE, TRUE);
8379
8380           MOVA (l);
8381           emitcode ("movx", "@%s,a", rname);
8382
8383           if (size || pi)
8384             emitcode ("inc", "%s", rname);
8385
8386           offset++;
8387         }
8388     }
8389
8390   /* now some housekeeping stuff */
8391   if (aop) /* we had to allocate for this iCode */
8392     {
8393       if (pi)
8394         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8395       freeAsmop (NULL, aop, ic, TRUE);
8396     }
8397   else
8398     {
8399       /* we did not allocate which means left
8400          already in a pointer register, then
8401          if size > 0 && this could be used again
8402          we have to point it back to where it
8403          belongs */
8404       if (AOP_SIZE (right) > 1 &&
8405           !OP_SYMBOL (result)->remat &&
8406           (OP_SYMBOL (result)->liveTo > ic->seq ||
8407            ic->depth))
8408         {
8409           int size = AOP_SIZE (right) - 1;
8410           while (size--)
8411             emitcode ("dec", "%s", rname);
8412         }
8413     }
8414
8415   /* done */
8416   if (pi) pi->generated = 1;
8417   freeAsmop (result, NULL, ic, TRUE);
8418   freeAsmop (right, NULL, ic, TRUE);
8419
8420
8421 }
8422
8423 /*-----------------------------------------------------------------*/
8424 /* genFarPointerSet - set value from far space                     */
8425 /*-----------------------------------------------------------------*/
8426 static void
8427 genFarPointerSet (operand * right,
8428                   operand * result, iCode * ic, iCode * pi)
8429 {
8430   int size, offset;
8431   sym_link *retype = getSpec (operandType (right));
8432   sym_link *letype = getSpec (operandType (result));
8433
8434   D(emitcode (";     genFarPointerSet",""));
8435
8436   aopOp (result, ic, FALSE);
8437   loadDptrFromOperand (result, FALSE);
8438   
8439   /* so dptr know contains the address */
8440   aopOp (right, ic, FALSE);
8441
8442   /* if bit then unpack */
8443   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8444     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8445   else
8446     {
8447       size = AOP_SIZE (right);
8448       offset = 0;
8449
8450       while (size--)
8451         {
8452           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8453           MOVA (l);
8454           emitcode ("movx", "@dptr,a");
8455           if (size || pi)
8456             emitcode ("inc", "dptr");
8457         }
8458     }
8459   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8460     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8461     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8462     pi->generated=1;
8463   }
8464   freeAsmop (result, NULL, ic, TRUE);
8465   freeAsmop (right, NULL, ic, TRUE);
8466 }
8467
8468 /*-----------------------------------------------------------------*/
8469 /* genGenPointerSet - set value from generic pointer space         */
8470 /*-----------------------------------------------------------------*/
8471 static void
8472 genGenPointerSet (operand * right,
8473                   operand * result, iCode * ic, iCode * pi)
8474 {
8475   int size, offset;
8476   sym_link *retype = getSpec (operandType (right));
8477   sym_link *letype = getSpec (operandType (result));
8478
8479   D(emitcode (";     genGenPointerSet",""));
8480
8481   aopOp (result, ic, FALSE);
8482   loadDptrFromOperand (result, TRUE);
8483   
8484   /* so dptr know contains the address */
8485   aopOp (right, ic, FALSE);
8486
8487   /* if bit then unpack */
8488   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8489     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8490   else
8491     {
8492       size = AOP_SIZE (right);
8493       offset = 0;
8494
8495       while (size--)
8496         {
8497           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8498           MOVA (l);
8499           emitcode ("lcall", "__gptrput");
8500           if (size || pi)
8501             emitcode ("inc", "dptr");
8502         }
8503     }
8504
8505   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8506     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8507     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8508     pi->generated=1;
8509   }
8510   freeAsmop (result, NULL, ic, TRUE);
8511   freeAsmop (right, NULL, ic, TRUE);
8512 }
8513
8514 /*-----------------------------------------------------------------*/
8515 /* genPointerSet - stores the value into a pointer location        */
8516 /*-----------------------------------------------------------------*/
8517 static void
8518 genPointerSet (iCode * ic, iCode *pi)
8519 {
8520   operand *right, *result;
8521   sym_link *type, *etype;
8522   int p_type;
8523
8524   D(emitcode (";     genPointerSet",""));
8525
8526   right = IC_RIGHT (ic);
8527   result = IC_RESULT (ic);
8528
8529   /* depending on the type of pointer we need to
8530      move it to the correct pointer register */
8531   type = operandType (result);
8532   etype = getSpec (type);
8533   /* if left is of type of pointer then it is simple */
8534   if (IS_PTR (type) && !IS_FUNC (type->next))
8535     {
8536       p_type = DCL_TYPE (type);
8537     }
8538   else
8539     {
8540       /* we have to go by the storage class */
8541       p_type = PTR_TYPE (SPEC_OCLS (etype));
8542     }
8543
8544   /* special case when cast remat */
8545   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8546       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8547           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8548           type = operandType (result);
8549           p_type = DCL_TYPE (type);
8550   }
8551   /* now that we have the pointer type we assign
8552      the pointer values */
8553   switch (p_type)
8554     {
8555
8556     case POINTER:
8557     case IPOINTER:
8558       genNearPointerSet (right, result, ic, pi);
8559       break;
8560
8561     case PPOINTER:
8562       genPagedPointerSet (right, result, ic, pi);
8563       break;
8564
8565     case FPOINTER:
8566       genFarPointerSet (right, result, ic, pi);
8567       break;
8568
8569     case GPOINTER:
8570       genGenPointerSet (right, result, ic, pi);
8571       break;
8572
8573     default:
8574       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
8575               "genPointerSet: illegal pointer type");
8576     }
8577
8578 }
8579
8580 /*-----------------------------------------------------------------*/
8581 /* genIfx - generate code for Ifx statement                        */
8582 /*-----------------------------------------------------------------*/
8583 static void
8584 genIfx (iCode * ic, iCode * popIc)
8585 {
8586   operand *cond = IC_COND (ic);
8587   int isbit = 0;
8588
8589   D(emitcode (";     genIfx",""));
8590
8591   aopOp (cond, ic, FALSE);
8592
8593   /* get the value into acc */
8594   if (AOP_TYPE (cond) != AOP_CRY)
8595     toBoolean (cond);
8596   else
8597     isbit = 1;
8598   /* the result is now in the accumulator */
8599   freeAsmop (cond, NULL, ic, TRUE);
8600
8601   /* if there was something to be popped then do it */
8602   if (popIc)
8603     genIpop (popIc);
8604
8605   /* if the condition is  a bit variable */
8606   if (isbit && IS_ITEMP (cond) &&
8607       SPIL_LOC (cond))
8608     genIfxJump (ic, SPIL_LOC (cond)->rname);
8609   else if (isbit && !IS_ITEMP (cond))
8610     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8611   else
8612     genIfxJump (ic, "a");
8613
8614   ic->generated = 1;
8615 }
8616
8617 /*-----------------------------------------------------------------*/
8618 /* genAddrOf - generates code for address of                       */
8619 /*-----------------------------------------------------------------*/
8620 static void
8621 genAddrOf (iCode * ic)
8622 {
8623   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8624   int size, offset;
8625
8626   D(emitcode (";     genAddrOf",""));
8627
8628   aopOp (IC_RESULT (ic), ic, FALSE);
8629
8630   /* if the operand is on the stack then we
8631      need to get the stack offset of this
8632      variable */
8633   if (sym->onStack)
8634     {
8635       /* if it has an offset then we need to compute
8636          it */
8637       if (sym->stack)
8638         {
8639           emitcode ("mov", "a,_bp");
8640           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8641                                          ((char) (sym->stack - _G.nRegsSaved)) :
8642                                          ((char) sym->stack)) & 0xff);
8643           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8644         }
8645       else
8646         {
8647           /* we can just move _bp */
8648           aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8649         }
8650       /* fill the result with zero */
8651       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8652
8653       offset = 1;
8654       while (size--)
8655         {
8656           aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8657         }
8658
8659       goto release;
8660     }
8661
8662   /* object not on stack then we need the name */
8663   size = AOP_SIZE (IC_RESULT (ic));
8664   offset = 0;
8665
8666   while (size--)
8667     {
8668       char s[SDCC_NAME_MAX];
8669       if (offset)
8670         sprintf (s, "#(%s >> %d)",
8671                  sym->rname,
8672                  offset * 8);
8673       else
8674         sprintf (s, "#%s", sym->rname);
8675       aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8676     }
8677
8678 release:
8679   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8680
8681 }
8682
8683 /*-----------------------------------------------------------------*/
8684 /* genFarFarAssign - assignment when both are in far space         */
8685 /*-----------------------------------------------------------------*/
8686 static void
8687 genFarFarAssign (operand * result, operand * right, iCode * ic)
8688 {
8689   int size = AOP_SIZE (right);
8690   int offset = 0;
8691   char *l;
8692
8693   D(emitcode (";     genFarFarAssign",""));
8694
8695   /* first push the right side on to the stack */
8696   while (size--)
8697     {
8698       l = aopGet (AOP (right), offset++, FALSE, FALSE);
8699       MOVA (l);
8700       emitcode ("push", "acc");
8701     }
8702
8703   freeAsmop (right, NULL, ic, FALSE);
8704   /* now assign DPTR to result */
8705   aopOp (result, ic, FALSE);
8706   size = AOP_SIZE (result);
8707   while (size--)
8708     {
8709       emitcode ("pop", "acc");
8710       aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8711     }
8712   freeAsmop (result, NULL, ic, FALSE);
8713
8714 }
8715
8716 /*-----------------------------------------------------------------*/
8717 /* genAssign - generate code for assignment                        */
8718 /*-----------------------------------------------------------------*/
8719 static void
8720 genAssign (iCode * ic)
8721 {
8722   operand *result, *right;
8723   int size, offset;
8724   unsigned long lit = 0L;
8725
8726   D(emitcode(";     genAssign",""));
8727
8728   result = IC_RESULT (ic);
8729   right = IC_RIGHT (ic);
8730
8731   /* if they are the same */
8732   if (operandsEqu (result, right) &&
8733       !isOperandVolatile (result, FALSE) &&
8734       !isOperandVolatile (right, FALSE))
8735     return;
8736
8737   aopOp (right, ic, FALSE);
8738
8739   /* special case both in far space */
8740   if (AOP_TYPE (right) == AOP_DPTR &&
8741       IS_TRUE_SYMOP (result) &&
8742       isOperandInFarSpace (result))
8743     {
8744
8745       genFarFarAssign (result, right, ic);
8746       return;
8747     }
8748
8749   aopOp (result, ic, TRUE);
8750
8751   /* if they are the same registers */
8752   if (sameRegs (AOP (right), AOP (result)) &&
8753       !isOperandVolatile (result, FALSE) &&
8754       !isOperandVolatile (right, FALSE))
8755     goto release;
8756
8757   /* if the result is a bit */
8758   if (AOP_TYPE (result) == AOP_CRY)
8759     {
8760
8761       /* if the right size is a literal then
8762          we know what the value is */
8763       if (AOP_TYPE (right) == AOP_LIT)
8764         {
8765           if (((int) operandLitValue (right)))
8766             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8767           else
8768             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8769           goto release;
8770         }
8771
8772       /* the right is also a bit variable */
8773       if (AOP_TYPE (right) == AOP_CRY)
8774         {
8775           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8776           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8777           goto release;
8778         }
8779
8780       /* we need to or */
8781       toBoolean (right);
8782       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8783       goto release;
8784     }
8785
8786   /* bit variables done */
8787   /* general case */
8788   size = AOP_SIZE (result);
8789   offset = 0;
8790   if (AOP_TYPE (right) == AOP_LIT)
8791     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8792   if ((size > 1) &&
8793       (AOP_TYPE (result) != AOP_REG) &&
8794       (AOP_TYPE (right) == AOP_LIT) &&
8795       !IS_FLOAT (operandType (right)) &&
8796       (lit < 256L))
8797     {
8798       emitcode ("clr", "a");
8799       while (size--)
8800         {
8801           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8802             aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8803           else
8804             aopPut (AOP (result),
8805                     aopGet (AOP (right), size, FALSE, FALSE),
8806                     size,
8807                     isOperandVolatile (result, FALSE));
8808         }
8809     }
8810   else
8811     {
8812       while (size--)
8813         {
8814           aopPut (AOP (result),
8815                   aopGet (AOP (right), offset, FALSE, FALSE),
8816                   offset,
8817                   isOperandVolatile (result, FALSE));
8818           offset++;
8819         }
8820     }
8821
8822 release:
8823   freeAsmop (right, NULL, ic, TRUE);
8824   freeAsmop (result, NULL, ic, TRUE);
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* genJumpTab - genrates code for jump table                       */
8829 /*-----------------------------------------------------------------*/
8830 static void
8831 genJumpTab (iCode * ic)
8832 {
8833   symbol *jtab;
8834   char *l;
8835
8836   D(emitcode (";     genJumpTab",""));
8837
8838   aopOp (IC_JTCOND (ic), ic, FALSE);
8839   /* get the condition into accumulator */
8840   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8841   MOVA (l);
8842   /* multiply by three */
8843   emitcode ("add", "a,acc");
8844   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8845   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8846
8847   jtab = newiTempLabel (NULL);
8848   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8849   emitcode ("jmp", "@a+dptr");
8850   emitcode ("", "%05d$:", jtab->key + 100);
8851   /* now generate the jump labels */
8852   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8853        jtab = setNextItem (IC_JTLABELS (ic)))
8854     emitcode ("ljmp", "%05d$", jtab->key + 100);
8855
8856 }
8857
8858 /*-----------------------------------------------------------------*/
8859 /* genCast - gen code for casting                                  */
8860 /*-----------------------------------------------------------------*/
8861 static void
8862 genCast (iCode * ic)
8863 {
8864   operand *result = IC_RESULT (ic);
8865   sym_link *ctype = operandType (IC_LEFT (ic));
8866   sym_link *rtype = operandType (IC_RIGHT (ic));
8867   operand *right = IC_RIGHT (ic);
8868   int size, offset;
8869
8870   D(emitcode(";     genCast",""));
8871
8872   /* if they are equivalent then do nothing */
8873   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8874     return;
8875
8876   aopOp (right, ic, FALSE);
8877   aopOp (result, ic, FALSE);
8878
8879   /* if the result is a bit (and not a bitfield) */
8880   // if (AOP_TYPE (result) == AOP_CRY)
8881   if (IS_BITVAR (OP_SYMBOL (result)->type)
8882       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8883     {
8884       /* if the right size is a literal then
8885          we know what the value is */
8886       if (AOP_TYPE (right) == AOP_LIT)
8887         {
8888           if (((int) operandLitValue (right)))
8889             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8890           else
8891             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8892
8893           goto release;
8894         }
8895
8896       /* the right is also a bit variable */
8897       if (AOP_TYPE (right) == AOP_CRY)
8898         {
8899           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8900           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8901           goto release;
8902         }
8903
8904       /* we need to or */
8905       toBoolean (right);
8906       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8907       goto release;
8908     }
8909
8910
8911   /* if they are the same size : or less */
8912   if (AOP_SIZE (result) <= AOP_SIZE (right))
8913     {
8914
8915       /* if they are in the same place */
8916       if (sameRegs (AOP (right), AOP (result)))
8917         goto release;
8918
8919       /* if they in different places then copy */
8920       size = AOP_SIZE (result);
8921       offset = 0;
8922       while (size--)
8923         {
8924           aopPut (AOP (result),
8925                   aopGet (AOP (right), offset, FALSE, FALSE),
8926                   offset,
8927                   isOperandVolatile (result, FALSE));
8928           offset++;
8929         }
8930       goto release;
8931     }
8932
8933
8934   /* if the result is of type pointer */
8935   if (IS_PTR (ctype))
8936     {
8937
8938       int p_type;
8939       sym_link *type = operandType (right);
8940       sym_link *etype = getSpec (type);
8941
8942       /* pointer to generic pointer */
8943       if (IS_GENPTR (ctype))
8944         {
8945           if (IS_PTR (type))
8946             p_type = DCL_TYPE (type);
8947           else
8948             {
8949               if (SPEC_SCLS(etype)==S_REGISTER) {
8950                 // let's assume it is a generic pointer
8951                 p_type=GPOINTER;
8952               } else {
8953                 /* we have to go by the storage class */
8954                 p_type = PTR_TYPE (SPEC_OCLS (etype));
8955               }
8956             }
8957
8958           /* the first two bytes are known */
8959           size = GPTRSIZE - 1;
8960           offset = 0;
8961           while (size--)
8962             {
8963               aopPut (AOP (result),
8964                       aopGet (AOP (right), offset, FALSE, FALSE),
8965                       offset,
8966                       isOperandVolatile (result, FALSE));
8967               offset++;
8968             }
8969           /* the last byte depending on type */
8970             {
8971                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8972                 char gpValStr[10];
8973             
8974                 if (gpVal == -1)
8975                 {
8976                     // pointerTypeToGPByte will have bitched.
8977                     exit(1);
8978                 }
8979             
8980                 sprintf(gpValStr, "#0x%d", gpVal);
8981                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8982             }       
8983           goto release;
8984         }
8985
8986       /* just copy the pointers */
8987       size = AOP_SIZE (result);
8988       offset = 0;
8989       while (size--)
8990         {
8991           aopPut (AOP (result),
8992                   aopGet (AOP (right), offset, FALSE, FALSE),
8993                   offset,
8994                   isOperandVolatile (result, FALSE));
8995           offset++;
8996         }
8997       goto release;
8998     }
8999
9000   /* so we now know that the size of destination is greater
9001      than the size of the source */
9002   /* we move to result for the size of source */
9003   size = AOP_SIZE (right);
9004   offset = 0;
9005   while (size--)
9006     {
9007       aopPut (AOP (result),
9008               aopGet (AOP (right), offset, FALSE, FALSE),
9009               offset,
9010               isOperandVolatile (result, FALSE));
9011       offset++;
9012     }
9013
9014   /* now depending on the sign of the source && destination */
9015   size = AOP_SIZE (result) - AOP_SIZE (right);
9016   /* if unsigned or not an integral type */
9017   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9018     {
9019       while (size--)
9020         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9021     }
9022   else
9023     {
9024       /* we need to extend the sign :{ */
9025       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9026                         FALSE, FALSE);
9027       MOVA (l);
9028       emitcode ("rlc", "a");
9029       emitcode ("subb", "a,acc");
9030       while (size--)
9031         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9032     }
9033
9034   /* we are done hurray !!!! */
9035
9036 release:
9037   freeAsmop (right, NULL, ic, TRUE);
9038   freeAsmop (result, NULL, ic, TRUE);
9039
9040 }
9041
9042 /*-----------------------------------------------------------------*/
9043 /* genDjnz - generate decrement & jump if not zero instrucion      */
9044 /*-----------------------------------------------------------------*/
9045 static int
9046 genDjnz (iCode * ic, iCode * ifx)
9047 {
9048   symbol *lbl, *lbl1;
9049   if (!ifx)
9050     return 0;
9051
9052   D(emitcode (";     genDjnz",""));
9053
9054   /* if the if condition has a false label
9055      then we cannot save */
9056   if (IC_FALSE (ifx))
9057     return 0;
9058
9059   /* if the minus is not of the form
9060      a = a - 1 */
9061   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9062       !IS_OP_LITERAL (IC_RIGHT (ic)))
9063     return 0;
9064
9065   if (operandLitValue (IC_RIGHT (ic)) != 1)
9066     return 0;
9067
9068   /* if the size of this greater than one then no
9069      saving */
9070   if (getSize (operandType (IC_RESULT (ic))) > 1)
9071     return 0;
9072
9073   /* otherwise we can save BIG */
9074   lbl = newiTempLabel (NULL);
9075   lbl1 = newiTempLabel (NULL);
9076
9077   aopOp (IC_RESULT (ic), ic, FALSE);
9078
9079   if (AOP_NEEDSACC(IC_RESULT(ic)))
9080   {
9081       /* If the result is accessed indirectly via
9082        * the accumulator, we must explicitly write
9083        * it back after the decrement.
9084        */
9085       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9086       
9087       if (strcmp(rByte, "a"))
9088       {
9089            /* Something is hopelessly wrong */
9090            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9091                    __FILE__, __LINE__);
9092            /* We can just give up; the generated code will be inefficient,
9093             * but what the hey.
9094             */
9095            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9096            return 0;
9097       }
9098       emitcode ("dec", "%s", rByte);
9099       aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9100       emitcode ("jnz", "%05d$", lbl->key + 100);
9101   }
9102   else if (IS_AOP_PREG (IC_RESULT (ic)))
9103     {
9104       emitcode ("dec", "%s",
9105                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9106       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9107       emitcode ("jnz", "%05d$", lbl->key + 100);
9108     }
9109   else
9110     {
9111       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9112                 lbl->key + 100);
9113     }
9114   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9115   emitcode ("", "%05d$:", lbl->key + 100);
9116   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9117   emitcode ("", "%05d$:", lbl1->key + 100);
9118
9119   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9120   ifx->generated = 1;
9121   return 1;
9122 }
9123
9124 /*-----------------------------------------------------------------*/
9125 /* genReceive - generate code for a receive iCode                  */
9126 /*-----------------------------------------------------------------*/
9127 static void
9128 genReceive (iCode * ic)
9129 {
9130     int size = getSize (operandType (IC_RESULT (ic)));
9131     int offset = 0;
9132   D(emitcode (";     genReceive",""));
9133
9134   if (ic->argreg == 1) { /* first parameter */
9135       if (isOperandInFarSpace (IC_RESULT (ic)) &&
9136           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9137            IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9138
9139           regs *tempRegs[4];
9140           int receivingA = 0;
9141           int roffset = 0;
9142               
9143           for (offset = 0; offset<size; offset++)
9144             if (!strcmp (fReturn[offset], "a"))
9145               receivingA = 1;
9146           
9147           if (!receivingA)
9148             {
9149               if (size==1 || getTempRegs(tempRegs, size-1, ic))
9150                 {
9151                   for (offset = size-1; offset>0; offset--)
9152                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9153                   emitcode("mov","a,%s", fReturn[0]);
9154                   _G.accInUse++;
9155                   aopOp (IC_RESULT (ic), ic, FALSE);
9156                   _G.accInUse--;
9157                   aopPut (AOP (IC_RESULT (ic)), "a", offset,
9158                           isOperandVolatile (IC_RESULT (ic), FALSE));
9159                   for (offset = 1; offset<size; offset++)
9160                     aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9161                             isOperandVolatile (IC_RESULT (ic), FALSE));
9162                   goto release;
9163                 }
9164             }
9165           else
9166             {
9167               if (getTempRegs(tempRegs, size, ic))
9168                 {
9169                   for (offset = 0; offset<size; offset++)
9170                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9171                   aopOp (IC_RESULT (ic), ic, FALSE);
9172                   for (offset = 0; offset<size; offset++)
9173                     aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9174                             isOperandVolatile (IC_RESULT (ic), FALSE));
9175                   goto release;
9176                 }
9177             }
9178
9179           offset = fReturnSizeMCS51 - size;
9180           while (size--) {
9181               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9182                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9183               offset++;
9184           }
9185           aopOp (IC_RESULT (ic), ic, FALSE);
9186           size = AOP_SIZE (IC_RESULT (ic));
9187           offset = 0;
9188           while (size--) {
9189               emitcode ("pop", "acc");
9190               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9191           }
9192
9193       } else {
9194           _G.accInUse++;
9195           aopOp (IC_RESULT (ic), ic, FALSE);
9196           _G.accInUse--;
9197           assignResultValue (IC_RESULT (ic));
9198       }
9199   } else { /* second receive onwards */
9200       int rb1off ;
9201       aopOp (IC_RESULT (ic), ic, FALSE);
9202       rb1off = ic->argreg;
9203       while (size--) {
9204           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9205       }
9206   }
9207
9208 release:  
9209   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9210 }
9211
9212 /*-----------------------------------------------------------------*/
9213 /* genDummyRead - generate code for dummy read of volatiles        */
9214 /*-----------------------------------------------------------------*/
9215 static void
9216 genDummyRead (iCode * ic)
9217 {
9218   operand *op;
9219   int size, offset;
9220
9221   D(emitcode(";     genDummyRead",""));
9222
9223   op = IC_RIGHT (ic);
9224   if (op && IS_SYMOP (op))
9225     {
9226       aopOp (op, ic, FALSE);
9227
9228       /* if the result is a bit */
9229       if (AOP_TYPE (op) == AOP_CRY)
9230         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9231       else
9232         {
9233           /* bit variables done */
9234           /* general case */
9235           size = AOP_SIZE (op);
9236           offset = 0;
9237           while (size--)
9238           {
9239             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9240             offset++;
9241           }
9242         }
9243
9244       freeAsmop (op, NULL, ic, TRUE);
9245     }
9246
9247   op = IC_LEFT (ic);
9248   if (op && IS_SYMOP (op))
9249     {
9250       aopOp (op, ic, FALSE);
9251
9252       /* if the result is a bit */
9253       if (AOP_TYPE (op) == AOP_CRY)
9254         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9255       else
9256         {
9257           /* bit variables done */
9258           /* general case */
9259           size = AOP_SIZE (op);
9260           offset = 0;
9261           while (size--)
9262           {
9263             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9264             offset++;
9265           }
9266         }
9267
9268       freeAsmop (op, NULL, ic, TRUE);
9269     }
9270 }
9271
9272 /*-----------------------------------------------------------------*/
9273 /* genCritical - generate code for start of a critical sequence    */
9274 /*-----------------------------------------------------------------*/
9275 static void
9276 genCritical (iCode *ic)
9277 {
9278   symbol *tlbl = newiTempLabel (NULL);
9279
9280   D(emitcode(";     genCritical",""));
9281   
9282   if (IC_RESULT (ic))
9283     aopOp (IC_RESULT (ic), ic, TRUE);
9284
9285   emitcode ("setb", "c");
9286   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9287   emitcode ("clr", "c");
9288   emitcode ("", "%05d$:", (tlbl->key + 100));
9289
9290   if (IC_RESULT (ic))
9291     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9292   else
9293     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9294
9295   if (IC_RESULT (ic))
9296     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9297 }
9298
9299 /*-----------------------------------------------------------------*/
9300 /* genEndCritical - generate code for end of a critical sequence   */
9301 /*-----------------------------------------------------------------*/
9302 static void
9303 genEndCritical (iCode *ic)
9304 {
9305   D(emitcode(";     genEndCritical",""));
9306   
9307   if (IC_RIGHT (ic))
9308     {
9309       aopOp (IC_RIGHT (ic), ic, FALSE);
9310       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9311         {
9312           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9313           emitcode ("mov", "ea,c");
9314         }
9315       else
9316         {
9317           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9318           emitcode ("rrc", "a");
9319           emitcode ("mov", "ea,c");
9320         }
9321       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9322     }
9323   else
9324     {
9325       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9326       emitcode ("mov", "ea,c");
9327     }
9328 }
9329
9330
9331 /*-----------------------------------------------------------------*/
9332 /* gen51Code - generate code for 8051 based controllers            */
9333 /*-----------------------------------------------------------------*/
9334 void
9335 gen51Code (iCode * lic)
9336 {
9337   iCode *ic;
9338   int cln = 0;
9339
9340   _G.currentFunc = NULL;
9341   lineHead = lineCurr = NULL;
9342
9343   /* print the allocation information */
9344   if (allocInfo && currFunc)
9345     printAllocInfo (currFunc, codeOutFile);
9346   /* if debug information required */
9347   if (options.debug && currFunc)
9348     {
9349       debugFile->writeFunction(currFunc);
9350       _G.debugLine = 1;
9351       if (IS_STATIC (currFunc->etype))
9352         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9353       else
9354         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9355       _G.debugLine = 0;
9356     }
9357   /* stack pointer name */
9358   if (options.useXstack)
9359     spname = "_spx";
9360   else
9361     spname = "sp";
9362
9363
9364   for (ic = lic; ic; ic = ic->next)
9365     {
9366       _G.current_iCode = ic;
9367       
9368       if (ic->lineno && cln != ic->lineno)
9369         {
9370           if (options.debug)
9371             {
9372               _G.debugLine = 1;
9373               emitcode ("", "C$%s$%d$%d$%d ==.",
9374                         FileBaseName (ic->filename), ic->lineno,
9375                         ic->level, ic->block);
9376               _G.debugLine = 0;
9377             }
9378           if (!options.noCcodeInAsm) {
9379             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
9380                       printCLine(ic->filename, ic->lineno));
9381           }
9382           cln = ic->lineno;
9383         }
9384       if (options.iCodeInAsm) {
9385         char regsInUse[80];
9386         int i;
9387
9388         for (i=0; i<8; i++) {
9389           sprintf (&regsInUse[i],
9390                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
9391         }
9392         regsInUse[i]=0;
9393         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9394       }
9395       /* if the result is marked as
9396          spilt and rematerializable or code for
9397          this has already been generated then
9398          do nothing */
9399       if (resultRemat (ic) || ic->generated)
9400         continue;
9401
9402       /* depending on the operation */
9403       switch (ic->op)
9404         {
9405         case '!':
9406           genNot (ic);
9407           break;
9408
9409         case '~':
9410           genCpl (ic);
9411           break;
9412
9413         case UNARYMINUS:
9414           genUminus (ic);
9415           break;
9416
9417         case IPUSH:
9418           genIpush (ic);
9419           break;
9420
9421         case IPOP:
9422           /* IPOP happens only when trying to restore a
9423              spilt live range, if there is an ifx statement
9424              following this pop then the if statement might
9425              be using some of the registers being popped which
9426              would destory the contents of the register so
9427              we need to check for this condition and handle it */
9428           if (ic->next &&
9429               ic->next->op == IFX &&
9430               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9431             genIfx (ic->next, ic);
9432           else
9433             genIpop (ic);
9434           break;
9435
9436         case CALL:
9437           genCall (ic);
9438           break;
9439
9440         case PCALL:
9441           genPcall (ic);
9442           break;
9443
9444         case FUNCTION:
9445           genFunction (ic);
9446           break;
9447
9448         case ENDFUNCTION:
9449           genEndFunction (ic);
9450           break;
9451
9452         case RETURN:
9453           genRet (ic);
9454           break;
9455
9456         case LABEL:
9457           genLabel (ic);
9458           break;
9459
9460         case GOTO:
9461           genGoto (ic);
9462           break;
9463
9464         case '+':
9465           genPlus (ic);
9466           break;
9467
9468         case '-':
9469           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9470             genMinus (ic);
9471           break;
9472
9473         case '*':
9474           genMult (ic);
9475           break;
9476
9477         case '/':
9478           genDiv (ic);
9479           break;
9480
9481         case '%':
9482           genMod (ic);
9483           break;
9484
9485         case '>':
9486           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9487           break;
9488
9489         case '<':
9490           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9491           break;
9492
9493         case LE_OP:
9494         case GE_OP:
9495         case NE_OP:
9496
9497           /* note these two are xlated by algebraic equivalence
9498              during parsing SDCC.y */
9499           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9500                   "got '>=' or '<=' shouldn't have come here");
9501           break;
9502
9503         case EQ_OP:
9504           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9505           break;
9506
9507         case AND_OP:
9508           genAndOp (ic);
9509           break;
9510
9511         case OR_OP:
9512           genOrOp (ic);
9513           break;
9514
9515         case '^':
9516           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9517           break;
9518
9519         case '|':
9520           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9521           break;
9522
9523         case BITWISEAND:
9524           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9525           break;
9526
9527         case INLINEASM:
9528           genInline (ic);
9529           break;
9530
9531         case RRC:
9532           genRRC (ic);
9533           break;
9534
9535         case RLC:
9536           genRLC (ic);
9537           break;
9538
9539         case GETHBIT:
9540           genGetHbit (ic);
9541           break;
9542
9543         case LEFT_OP:
9544           genLeftShift (ic);
9545           break;
9546
9547         case RIGHT_OP:
9548           genRightShift (ic);
9549           break;
9550
9551         case GET_VALUE_AT_ADDRESS:
9552           genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9553           break;
9554
9555         case '=':
9556           if (POINTER_SET (ic))
9557             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9558           else
9559             genAssign (ic);
9560           break;
9561
9562         case IFX:
9563           genIfx (ic, NULL);
9564           break;
9565
9566         case ADDRESS_OF:
9567           genAddrOf (ic);
9568           break;
9569
9570         case JUMPTABLE:
9571           genJumpTab (ic);
9572           break;
9573
9574         case CAST:
9575           genCast (ic);
9576           break;
9577
9578         case RECEIVE:
9579           genReceive (ic);
9580           break;
9581
9582         case SEND:
9583           addSet (&_G.sendSet, ic);
9584           break;
9585
9586         case DUMMY_READ_VOLATILE:
9587           genDummyRead (ic);
9588           break;
9589
9590         case CRITICAL:
9591           genCritical (ic);
9592           break;
9593
9594         case ENDCRITICAL:
9595           genEndCritical (ic);
9596           break;
9597
9598         case SWAP:
9599           genSwap (ic);
9600           break;
9601
9602         default:
9603           ic = ic;
9604         }
9605     }
9606
9607   _G.current_iCode = NULL;
9608
9609   /* now we are ready to call the
9610      peep hole optimizer */
9611   if (!options.nopeep)
9612     peepHole (&lineHead);
9613
9614   /* now do the actual printing */
9615   printLine (lineHead, codeOutFile);
9616   return;
9617 }