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