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