src/mcs51/gen.c (genJumpTab): jumptables for more than 16 switch cases use more compa...
[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 r0InB;
72     short r1InB;
73     short accInUse;
74     short inLine;
75     short debugLine;
76     short nRegsSaved;
77     set *sendSet;
78     iCode *current_iCode;
79     symbol *currentFunc;
80   }
81 _G;
82
83 static char *rb1regs[] = {
84     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
85 };
86
87 extern int mcs51_ptrRegReq;
88 extern int mcs51_nRegs;
89 extern FILE *codeOutFile;
90 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
93                          IC_RESULT(x)->aop->type == AOP_STK )
94
95 #define MOVA(x) mova(x)  /* use function to avoid multiple eval */
96 #define CLRC    emitcode("clr","c")
97 #define SETC    emitcode("setb","c")
98
99 static lineNode *lineHead = NULL;
100 static lineNode *lineCurr = NULL;
101
102 static unsigned char SLMask[] =
103 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
104  0xE0, 0xC0, 0x80, 0x00};
105 static unsigned char SRMask[] =
106 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
107  0x07, 0x03, 0x01, 0x00};
108
109 #define LSB     0
110 #define MSB16   1
111 #define MSB24   2
112 #define MSB32   3
113
114 /*-----------------------------------------------------------------*/
115 /* emitcode - writes the code into a file : for now it is simple    */
116 /*-----------------------------------------------------------------*/
117 static void
118 emitcode (char *inst, const char *fmt,...)
119 {
120   va_list ap;
121   char lb[INITIAL_INLINEASM];
122   char *lbp = lb;
123
124   va_start (ap, fmt);
125
126   if (inst && *inst)
127     {
128       if (fmt && *fmt)
129         SNPRINTF (lb, sizeof(lb), "%s\t", inst);
130       else
131         SNPRINTF (lb, sizeof(lb), "%s", inst);
132       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
133     }
134   else
135     tvsprintf (lb, sizeof(lb), fmt, ap);
136
137   while (isspace (*lbp))
138     lbp++;
139
140   //printf ("%s\n", lb);
141
142   if (lbp && *lbp)
143     lineCurr = (lineCurr ?
144                 connectLine (lineCurr, newLineNode (lb)) :
145                 (lineHead = newLineNode (lb)));
146   lineCurr->isInline = _G.inLine;
147   lineCurr->isDebug = _G.debugLine;
148   lineCurr->ic = _G.current_iCode;
149   lineCurr->isComment = (*lbp==';');
150   va_end (ap);
151 }
152
153 /*-----------------------------------------------------------------*/
154 /* mcs51_emitDebuggerSymbol - associate the current code location  */
155 /*   with a debugger symbol                                        */
156 /*-----------------------------------------------------------------*/
157 void
158 mcs51_emitDebuggerSymbol (char * debugSym)
159 {
160   _G.debugLine = 1;
161   emitcode ("", "%s ==.", debugSym);
162   _G.debugLine = 0;
163 }
164
165 /*-----------------------------------------------------------------*/
166 /* mova - moves specified value into accumulator                   */
167 /*-----------------------------------------------------------------*/
168 static void
169 mova (const char *x)
170 {
171   /* do some early peephole optimization */
172   if (!strcmp(x, "a") || !strcmp(x, "acc"))
173     return;
174
175   emitcode("mov","a,%s", x);
176 }
177
178 /*-----------------------------------------------------------------*/
179 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
180 /*-----------------------------------------------------------------*/
181 static regs *
182 getFreePtr (iCode * ic, asmop ** aopp, bool result)
183 {
184   bool r0iu = FALSE, r1iu = FALSE;
185   bool r0ou = FALSE, r1ou = FALSE;
186
187   /* the logic: if r0 & r1 used in the instruction
188      then we are in trouble otherwise */
189
190   /* first check if r0 & r1 are used by this
191      instruction, in which case we are in trouble */
192   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
193   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
194   if (r0iu && r1iu) {
195       goto endOfWorld;
196     }
197
198   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
199   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
200
201   /* if no usage of r0 then return it */
202   if (!r0iu && !r0ou)
203     {
204       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
205       (*aopp)->type = AOP_R0;
206
207       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
208     }
209
210   /* if no usage of r1 then return it */
211   if (!r1iu && !r1ou)
212     {
213       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
214       (*aopp)->type = AOP_R1;
215
216       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
217     }
218
219   /* now we know they both have usage */
220   /* if r0 not used in this instruction */
221   if (!r0iu)
222     {
223       /* push it if not already pushed */
224       if (ic->op == IPUSH)
225         {
226           emitcode ("mov", "b,%s",
227                     mcs51_regWithIdx (R0_IDX)->dname);
228           _G.r0InB++;
229         }
230       else if (!_G.r0Pushed)
231         {
232           emitcode ("push", "%s",
233                     mcs51_regWithIdx (R0_IDX)->dname);
234           _G.r0Pushed++;
235         }
236
237       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
238       (*aopp)->type = AOP_R0;
239
240       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
241     }
242
243   /* if r1 not used then */
244
245   if (!r1iu)
246     {
247       /* push it if not already pushed */
248       if (ic->op == IPUSH)
249         {
250           emitcode ("mov", "b,%s",
251                     mcs51_regWithIdx (R1_IDX)->dname);
252           _G.r1InB++;
253         }
254       else if (!_G.r1Pushed)
255         {
256           emitcode ("push", "%s",
257                     mcs51_regWithIdx (R1_IDX)->dname);
258           _G.r1Pushed++;
259         }
260
261       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
262       (*aopp)->type = AOP_R1;
263       return mcs51_regWithIdx (R1_IDX);
264     }
265 endOfWorld:
266   /* I said end of world, but not quite end of world yet */
267   if (result) {
268     /* we can push it on the stack */
269     (*aopp)->type = AOP_STK;
270     return NULL;
271   } else {
272     /* in the case that result AND left AND right needs a pointer reg
273        we can safely use the result's */
274     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
275       (*aopp)->type = AOP_R0;
276       return mcs51_regWithIdx (R0_IDX);
277     }
278     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
279       (*aopp)->type = AOP_R1;
280       return mcs51_regWithIdx (R1_IDX);
281     }
282   }
283
284   /* now this is REALLY the end of the world */
285   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
286           "getFreePtr should never reach here");
287   exit (1);
288 }
289
290
291 /*-----------------------------------------------------------------*/
292 /* getTempRegs - initialize an array of pointers to GPR registers */
293 /*               that are not in use. Returns 1 if the requested   */
294 /*               number of registers were available, 0 otherwise.  */
295 /*-----------------------------------------------------------------*/
296 int
297 getTempRegs(regs **tempRegs, int size, iCode *ic)
298 {
299   bitVect * freeRegs;
300   int i;
301   int offset;
302
303   if (!ic)
304     ic = _G.current_iCode;
305   if (!ic)
306     return 0;
307   if (!_G.currentFunc)
308     return 0;
309
310   freeRegs = newBitVect(8);
311   bitVectSetBit (freeRegs, R2_IDX);
312   bitVectSetBit (freeRegs, R3_IDX);
313   bitVectSetBit (freeRegs, R4_IDX);
314   bitVectSetBit (freeRegs, R5_IDX);
315   bitVectSetBit (freeRegs, R6_IDX);
316   bitVectSetBit (freeRegs, R7_IDX);
317
318   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
319     {
320       bitVect * newfreeRegs;
321       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
322       freeBitVect(freeRegs);
323       freeRegs = newfreeRegs;
324     }
325   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
326
327   offset = 0;
328   for (i=0; i<freeRegs->size; i++)
329     {
330       if (bitVectBitValue(freeRegs,i))
331         tempRegs[offset++] = mcs51_regWithIdx(i);
332       if (offset>=size)
333         {
334           freeBitVect(freeRegs);
335           return 1;
336         }
337     }
338
339   freeBitVect(freeRegs);
340   return 1;
341 }
342
343
344 /*-----------------------------------------------------------------*/
345 /* newAsmop - creates a new asmOp                                  */
346 /*-----------------------------------------------------------------*/
347 static asmop *
348 newAsmop (short type)
349 {
350   asmop *aop;
351
352   aop = Safe_calloc (1, sizeof (asmop));
353   aop->type = type;
354   return aop;
355 }
356
357 /*-----------------------------------------------------------------*/
358 /* pointerCode - returns the code for a pointer type               */
359 /*-----------------------------------------------------------------*/
360 static int
361 pointerCode (sym_link * etype)
362 {
363
364   return PTR_TYPE (SPEC_OCLS (etype));
365
366 }
367
368
369 /*-----------------------------------------------------------------*/
370 /* leftRightUseAcc - returns size of accumulator use by operands   */
371 /*-----------------------------------------------------------------*/
372 static int
373 leftRightUseAcc(iCode *ic)
374 {
375   operand *op;
376   int size;
377   int accuseSize = 0;
378   int accuse = 0;
379
380   if (!ic)
381     {
382       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
383               "null iCode pointer");
384       return 0;
385     }
386
387   if (ic->op == IFX)
388     {
389       op = IC_COND (ic);
390       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
391         {
392           accuse = 1;
393           size = getSize (OP_SYMBOL (op)->type);
394           if (size>accuseSize)
395             accuseSize = size;
396         }
397     }
398   else if (ic->op == JUMPTABLE)
399     {
400       op = IC_JTCOND (ic);
401       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
402         {
403           accuse = 1;
404           size = getSize (OP_SYMBOL (op)->type);
405           if (size>accuseSize)
406             accuseSize = size;
407         }
408     }
409   else
410     {
411       op = IC_LEFT (ic);
412       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
413         {
414           accuse = 1;
415           size = getSize (OP_SYMBOL (op)->type);
416           if (size>accuseSize)
417             accuseSize = size;
418         }
419       op = IC_RIGHT (ic);
420       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
421         {
422           accuse = 1;
423           size = getSize (OP_SYMBOL (op)->type);
424           if (size>accuseSize)
425             accuseSize = size;
426         }
427     }
428
429   if (accuseSize)
430     return accuseSize;
431   else
432     return accuse;
433 }
434
435
436 /*-----------------------------------------------------------------*/
437 /* aopForSym - for a true symbol                                   */
438 /*-----------------------------------------------------------------*/
439 static asmop *
440 aopForSym (iCode * ic, symbol * sym, bool result)
441 {
442   asmop *aop;
443   memmap *space;
444
445   wassertl (ic != NULL, "Got a null iCode");
446   wassertl (sym != NULL, "Got a null symbol");
447
448   space = SPEC_OCLS (sym->etype);
449
450   /* if already has one */
451   if (sym->aop)
452     return sym->aop;
453
454   /* assign depending on the storage class */
455   /* if it is on the stack or indirectly addressable */
456   /* space we need to assign either r0 or r1 to it   */
457   if (sym->onStack || sym->iaccess)
458     {
459       sym->aop = aop = newAsmop (0);
460       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461       aop->size = getSize (sym->type);
462
463       /* now assign the address of the variable to
464          the pointer register */
465       if (aop->type != AOP_STK)
466         {
467
468           if (sym->onStack)
469             {
470               if (_G.accInUse || leftRightUseAcc (ic))
471                 emitcode ("push", "acc");
472
473               emitcode ("mov", "a,_bp");
474               emitcode ("add", "a,#0x%02x",
475                         ((sym->stack < 0) ?
476                          ((char) (sym->stack - _G.nRegsSaved)) :
477                          ((char) sym->stack)) & 0xff);
478               emitcode ("mov", "%s,a",
479                         aop->aopu.aop_ptr->name);
480
481               if (_G.accInUse || leftRightUseAcc (ic))
482                 emitcode ("pop", "acc");
483             }
484           else
485             emitcode ("mov", "%s,#%s",
486                       aop->aopu.aop_ptr->name,
487                       sym->rname);
488           aop->paged = space->paged;
489         }
490       else
491         aop->aopu.aop_stk = sym->stack;
492       return aop;
493     }
494
495   /* if in bit space */
496   if (IN_BITSPACE (space))
497     {
498       sym->aop = aop = newAsmop (AOP_CRY);
499       aop->aopu.aop_dir = sym->rname;
500       aop->size = getSize (sym->type);
501       return aop;
502     }
503   /* if it is in direct space */
504   if (IN_DIRSPACE (space))
505     {
506       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
507       //printTypeChainRaw(sym->type, NULL);
508       //printf("space = %s\n", space ? space->sname : "NULL");
509       sym->aop = aop = newAsmop (AOP_DIR);
510       aop->aopu.aop_dir = sym->rname;
511       aop->size = getSize (sym->type);
512       return aop;
513     }
514
515   /* special case for a function */
516   if (IS_FUNC (sym->type))
517     {
518       sym->aop = aop = newAsmop (AOP_IMMD);
519       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
520       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
521       aop->size = FPTRSIZE;
522       return aop;
523     }
524
525   /* only remaining is far space */
526   /* in which case DPTR gets the address */
527   sym->aop = aop = newAsmop (AOP_DPTR);
528   emitcode ("mov", "dptr,#%s", sym->rname);
529   aop->size = getSize (sym->type);
530
531   /* if it is in code space */
532   if (IN_CODESPACE (space))
533     aop->code = 1;
534
535   return aop;
536 }
537
538 /*-----------------------------------------------------------------*/
539 /* aopForRemat - rematerialzes an object                           */
540 /*-----------------------------------------------------------------*/
541 static asmop *
542 aopForRemat (symbol * sym)
543 {
544   iCode *ic = sym->rematiCode;
545   asmop *aop = newAsmop (AOP_IMMD);
546   int ptr_type=0;
547   int val = 0;
548
549   for (;;)
550     {
551       if (ic->op == '+')
552         val += (int) operandLitValue (IC_RIGHT (ic));
553       else if (ic->op == '-')
554         val -= (int) operandLitValue (IC_RIGHT (ic));
555       else if (IS_CAST_ICODE(ic)) {
556               sym_link *from_type = operandType(IC_RIGHT(ic));
557               aop->aopu.aop_immd.from_cast_remat = 1;
558               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
559               ptr_type = DCL_TYPE(from_type);
560               if (ptr_type == IPOINTER) {
561                 // bug #481053
562                 ptr_type = POINTER;
563               }
564               continue ;
565       } else break;
566
567       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
568     }
569
570   if (val)
571     sprintf (buffer, "(%s %c 0x%04x)",
572              OP_SYMBOL (IC_LEFT (ic))->rname,
573              val >= 0 ? '+' : '-',
574              abs (val) & 0xffff);
575   else
576     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
577
578   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
579   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
580   /* set immd2 field if required */
581   if (aop->aopu.aop_immd.from_cast_remat) {
582           sprintf(buffer,"#0x%02x",ptr_type);
583           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
584           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
585   }
586
587   return aop;
588 }
589
590 /*-----------------------------------------------------------------*/
591 /* regsInCommon - two operands have some registers in common       */
592 /*-----------------------------------------------------------------*/
593 static bool
594 regsInCommon (operand * op1, operand * op2)
595 {
596   symbol *sym1, *sym2;
597   int i;
598
599   /* if they have registers in common */
600   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
601     return FALSE;
602
603   sym1 = OP_SYMBOL (op1);
604   sym2 = OP_SYMBOL (op2);
605
606   if (sym1->nRegs == 0 || sym2->nRegs == 0)
607     return FALSE;
608
609   for (i = 0; i < sym1->nRegs; i++)
610     {
611       int j;
612       if (!sym1->regs[i])
613         continue;
614
615       for (j = 0; j < sym2->nRegs; j++)
616         {
617           if (!sym2->regs[j])
618             continue;
619
620           if (sym2->regs[j] == sym1->regs[i])
621             return TRUE;
622         }
623     }
624
625   return FALSE;
626 }
627
628 /*-----------------------------------------------------------------*/
629 /* operandsEqu - equivalent                                        */
630 /*-----------------------------------------------------------------*/
631 static bool
632 operandsEqu (operand * op1, operand * op2)
633 {
634   symbol *sym1, *sym2;
635
636   /* if they not symbols */
637   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
638     return FALSE;
639
640   sym1 = OP_SYMBOL (op1);
641   sym2 = OP_SYMBOL (op2);
642
643   /* if both are itemps & one is spilt
644      and the other is not then false */
645   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
646       sym1->isspilt != sym2->isspilt)
647     return FALSE;
648
649   /* if they are the same */
650   if (sym1 == sym2)
651     return TRUE;
652
653   if (sym1->rname[0] && sym2->rname[0]
654       && strcmp (sym1->rname, sym2->rname) == 0)
655     return TRUE;
656
657   /* if left is a tmp & right is not */
658   if (IS_ITEMP (op1) &&
659       !IS_ITEMP (op2) &&
660       sym1->isspilt &&
661       (sym1->usl.spillLoc == sym2))
662     return TRUE;
663
664   if (IS_ITEMP (op2) &&
665       !IS_ITEMP (op1) &&
666       sym2->isspilt &&
667       sym1->level > 0 &&
668       (sym2->usl.spillLoc == sym1))
669     return TRUE;
670
671   return FALSE;
672 }
673
674 /*-----------------------------------------------------------------*/
675 /* sameRegs - two asmops have the same registers                   */
676 /*-----------------------------------------------------------------*/
677 static bool
678 sameRegs (asmop * aop1, asmop * aop2)
679 {
680   int i;
681
682   if (aop1 == aop2)
683     return TRUE;
684
685   if (aop1->type != AOP_REG ||
686       aop2->type != AOP_REG)
687     return FALSE;
688
689   if (aop1->size != aop2->size)
690     return FALSE;
691
692   for (i = 0; i < aop1->size; i++)
693     if (aop1->aopu.aop_reg[i] !=
694         aop2->aopu.aop_reg[i])
695       return FALSE;
696
697   return TRUE;
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* aopOp - allocates an asmop for an operand  :                    */
702 /*-----------------------------------------------------------------*/
703 static void
704 aopOp (operand * op, iCode * ic, bool result)
705 {
706   asmop *aop;
707   symbol *sym;
708   int i;
709
710   if (!op)
711     return;
712
713   /* if this a literal */
714   if (IS_OP_LITERAL (op))
715     {
716       op->aop = aop = newAsmop (AOP_LIT);
717       aop->aopu.aop_lit = op->operand.valOperand;
718       aop->size = getSize (operandType (op));
719       return;
720     }
721
722   /* if already has a asmop then continue */
723   if (op->aop )
724     return;
725
726   /* if the underlying symbol has a aop */
727   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
728     {
729       op->aop = OP_SYMBOL (op)->aop;
730       return;
731     }
732
733   /* if this is a true symbol */
734   if (IS_TRUE_SYMOP (op))
735     {
736       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
737       return;
738     }
739
740   /* this is a temporary : this has
741      only four choices :
742      a) register
743      b) spillocation
744      c) rematerialize
745      d) conditional
746      e) can be a return use only */
747
748   sym = OP_SYMBOL (op);
749
750   /* if the type is a conditional */
751   if (sym->regType == REG_CND)
752     {
753       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
754       aop->size = 0;
755       return;
756     }
757
758   /* if it is spilt then two situations
759      a) is rematerialize
760      b) has a spill location */
761   if (sym->isspilt || sym->nRegs == 0)
762     {
763
764       /* rematerialize it NOW */
765       if (sym->remat)
766         {
767           sym->aop = op->aop = aop =
768             aopForRemat (sym);
769           aop->size = getSize (sym->type);
770           return;
771         }
772
773       if (sym->accuse)
774         {
775           int i;
776           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
777           aop->size = getSize (sym->type);
778           for (i = 0; i < 2; i++)
779             aop->aopu.aop_str[i] = accUse[i];
780           return;
781         }
782
783       if (sym->ruonly)
784         {
785           unsigned i;
786
787           aop = op->aop = sym->aop = newAsmop (AOP_STR);
788           aop->size = getSize (sym->type);
789           for (i = 0; i < fReturnSizeMCS51; i++)
790             aop->aopu.aop_str[i] = fReturn[i];
791           return;
792         }
793
794       if (sym->usl.spillLoc)
795         {
796           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
797             {
798               /* force a new aop if sizes differ */
799               sym->usl.spillLoc->aop = NULL;
800             }
801           sym->aop = op->aop = aop =
802                      aopForSym (ic, sym->usl.spillLoc, result);
803           aop->size = getSize (sym->type);
804           return;
805         }
806
807       /* else must be a dummy iTemp */
808       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
809       aop->size = getSize (sym->type);
810       return;
811     }
812
813   /* must be in a register */
814   sym->aop = op->aop = aop = newAsmop (AOP_REG);
815   aop->size = sym->nRegs;
816   for (i = 0; i < sym->nRegs; i++)
817     aop->aopu.aop_reg[i] = sym->regs[i];
818 }
819
820 /*-----------------------------------------------------------------*/
821 /* freeAsmop - free up the asmop given to an operand               */
822 /*----------------------------------------------------------------*/
823 static void
824 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
825 {
826   asmop *aop;
827
828   if (!op)
829     aop = aaop;
830   else
831     aop = op->aop;
832
833   if (!aop)
834     return;
835
836   if (aop->freed)
837     goto dealloc;
838
839   aop->freed = 1;
840
841   /* depending on the asmop type only three cases need work AOP_RO
842      , AOP_R1 && AOP_STK */
843   switch (aop->type)
844     {
845     case AOP_R0:
846       if (_G.r0InB)
847         {
848           emitcode ("mov", "r0,b");
849           _G.r0InB--;
850         }
851       else if (_G.r0Pushed)
852         {
853           if (pop)
854             {
855               emitcode ("pop", "ar0");
856               _G.r0Pushed--;
857             }
858         }
859       bitVectUnSetBit (ic->rUsed, R0_IDX);
860       break;
861
862     case AOP_R1:
863       if (_G.r1InB)
864         {
865           emitcode ("mov", "r1,b");
866           _G.r1InB--;
867         }
868       if (_G.r1Pushed)
869         {
870           if (pop)
871             {
872               emitcode ("pop", "ar1");
873               _G.r1Pushed--;
874             }
875         }
876       bitVectUnSetBit (ic->rUsed, R1_IDX);
877       break;
878
879     case AOP_STK:
880       {
881         int sz = aop->size;
882         int stk = aop->aopu.aop_stk + aop->size - 1;
883         bitVectUnSetBit (ic->rUsed, R0_IDX);
884         bitVectUnSetBit (ic->rUsed, R1_IDX);
885
886         getFreePtr (ic, &aop, FALSE);
887
888         if (stk)
889           {
890             emitcode ("mov", "a,_bp");
891             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
892             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
893           }
894         else
895           {
896             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
897           }
898
899         while (sz--)
900           {
901             emitcode ("pop", "acc");
902             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
903             if (!sz)
904               break;
905             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
906           }
907         op->aop = aop;
908         freeAsmop (op, NULL, ic, TRUE);
909         if (_G.r1Pushed)
910           {
911             emitcode ("pop", "ar1");
912             _G.r1Pushed--;
913           }
914
915         if (_G.r0Pushed)
916           {
917             emitcode ("pop", "ar0");
918             _G.r0Pushed--;
919           }
920       }
921     }
922
923 dealloc:
924   /* all other cases just dealloc */
925   if (op)
926     {
927       op->aop = NULL;
928       if (IS_SYMOP (op))
929         {
930           OP_SYMBOL (op)->aop = NULL;
931           /* if the symbol has a spill */
932           if (SPIL_LOC (op))
933             SPIL_LOC (op)->aop = NULL;
934         }
935     }
936 }
937
938 /*------------------------------------------------------------------*/
939 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
940 /*                      pop r0 or r1 off stack if pushed            */
941 /*------------------------------------------------------------------*/
942 static void
943 freeForBranchAsmop (operand * op)
944 {
945   asmop *aop;
946
947   if (!op)
948     return;
949
950   aop = op->aop;
951
952   if (!aop)
953     return;
954
955   if (aop->freed)
956     return;
957
958   switch (aop->type)
959     {
960     case AOP_R0:
961       if (_G.r0InB)
962         {
963           emitcode ("mov", "r0,b");
964         }
965       else if (_G.r0Pushed)
966         {
967           emitcode ("pop", "ar0");
968         }
969       break;
970
971     case AOP_R1:
972       if (_G.r1InB)
973         {
974           emitcode ("mov", "r1,b");
975         }
976       else if (_G.r1Pushed)
977         {
978           emitcode ("pop", "ar1");
979         }
980       break;
981
982     case AOP_STK:
983       {
984         int sz = aop->size;
985         int stk = aop->aopu.aop_stk + aop->size - 1;
986
987         emitcode ("mov", "b,r0");
988         if (stk)
989           {
990             emitcode ("mov", "a,_bp");
991             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
992             emitcode ("mov", "r0,a");
993           }
994         else
995           {
996             emitcode ("mov", "r0,_bp");
997           }
998
999         while (sz--)
1000           {
1001             emitcode ("pop", "acc");
1002             emitcode ("mov", "@r0,a");
1003             if (!sz)
1004               break;
1005             emitcode ("dec", "r0");
1006           }
1007         emitcode ("mov", "r0,b");
1008       }
1009     }
1010
1011 }
1012
1013 /*-----------------------------------------------------------------*/
1014 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1015 /*                 clobber the accumulator                         */
1016 /*-----------------------------------------------------------------*/
1017 static bool
1018 aopGetUsesAcc (asmop *aop, int offset)
1019 {
1020   if (offset > (aop->size - 1))
1021     return FALSE;
1022
1023   switch (aop->type)
1024     {
1025
1026     case AOP_R0:
1027     case AOP_R1:
1028       if (aop->paged)
1029         return TRUE;
1030       return FALSE;
1031     case AOP_DPTR:
1032       return TRUE;
1033     case AOP_IMMD:
1034       return FALSE;
1035     case AOP_DIR:
1036       return FALSE;
1037     case AOP_REG:
1038       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1039       return FALSE;
1040     case AOP_CRY:
1041       return TRUE;
1042     case AOP_ACC:
1043       return TRUE;
1044     case AOP_LIT:
1045       return FALSE;
1046     case AOP_STR:
1047       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1048         return TRUE;
1049       return FALSE;
1050     case AOP_DUMMY:
1051       return FALSE;
1052     default:
1053       /* Error case --- will have been caught already */
1054       wassert(0);
1055       return FALSE;
1056     }
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* aopGet - for fetching value of the aop                          */
1061 /*-----------------------------------------------------------------*/
1062 static char *
1063 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1064 {
1065   char *s = buffer;
1066   char *rs;
1067
1068   /* offset is greater than
1069      size then zero */
1070   if (offset > (aop->size - 1) &&
1071       aop->type != AOP_LIT)
1072     return zero;
1073
1074   /* depending on type */
1075   switch (aop->type)
1076     {
1077     case AOP_DUMMY:
1078       return zero;
1079
1080     case AOP_R0:
1081     case AOP_R1:
1082       /* if we need to increment it */
1083       while (offset > aop->coff)
1084         {
1085           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1086           aop->coff++;
1087         }
1088
1089       while (offset < aop->coff)
1090         {
1091           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1092           aop->coff--;
1093         }
1094
1095       aop->coff = offset;
1096       if (aop->paged)
1097         {
1098           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1099           return (dname ? "acc" : "a");
1100         }
1101       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1102       rs = Safe_calloc (1, strlen (s) + 1);
1103       strcpy (rs, s);
1104       return rs;
1105
1106     case AOP_DPTR:
1107       if (aop->code && aop->coff==0 && offset>=1) {
1108         emitcode ("mov", "a,#0x%02x", offset);
1109         emitcode ("movc", "a,@a+dptr");
1110         return (dname ? "acc" : "a");
1111       }
1112
1113       while (offset > aop->coff)
1114         {
1115           emitcode ("inc", "dptr");
1116           aop->coff++;
1117         }
1118
1119       while (offset < aop->coff)
1120         {
1121           emitcode ("lcall", "__decdptr");
1122           aop->coff--;
1123         }
1124
1125       aop->coff = offset;
1126       if (aop->code)
1127         {
1128           emitcode ("clr", "a");
1129           emitcode ("movc", "a,@a+dptr");
1130         }
1131       else
1132         {
1133           emitcode ("movx", "a,@dptr");
1134         }
1135       return (dname ? "acc" : "a");
1136
1137
1138     case AOP_IMMD:
1139       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1140               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1141       } else if (bit16)
1142         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1143       else if (offset)
1144         sprintf (s, "#(%s >> %d)",
1145                  aop->aopu.aop_immd.aop_immd1,
1146                  offset * 8);
1147       else
1148         sprintf (s, "#%s",
1149                  aop->aopu.aop_immd.aop_immd1);
1150       rs = Safe_calloc (1, strlen (s) + 1);
1151       strcpy (rs, s);
1152       return rs;
1153
1154     case AOP_DIR:
1155       if (offset)
1156         sprintf (s, "(%s + %d)",
1157                  aop->aopu.aop_dir,
1158                  offset);
1159       else
1160         sprintf (s, "%s", aop->aopu.aop_dir);
1161       rs = Safe_calloc (1, strlen (s) + 1);
1162       strcpy (rs, s);
1163       return rs;
1164
1165     case AOP_REG:
1166       if (dname)
1167         return aop->aopu.aop_reg[offset]->dname;
1168       else
1169         return aop->aopu.aop_reg[offset]->name;
1170
1171     case AOP_CRY:
1172       emitcode ("clr", "a");
1173       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1174       emitcode ("rlc", "a");
1175       return (dname ? "acc" : "a");
1176
1177     case AOP_ACC:
1178       if (!offset && dname)
1179         return "acc";
1180       return aop->aopu.aop_str[offset];
1181
1182     case AOP_LIT:
1183       return aopLiteral (aop->aopu.aop_lit, offset);
1184
1185     case AOP_STR:
1186       aop->coff = offset;
1187       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1188           dname)
1189         return "acc";
1190
1191       return aop->aopu.aop_str[offset];
1192
1193     }
1194
1195   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1196           "aopget got unsupported aop->type");
1197   exit (1);
1198 }
1199 /*-----------------------------------------------------------------*/
1200 /* aopPut - puts a string for a aop                                */
1201 /*-----------------------------------------------------------------*/
1202 static void
1203 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1204 {
1205   char *d = buffer;
1206
1207   if (aop->size && offset > (aop->size - 1))
1208     {
1209       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1210               "aopPut got offset > aop->size");
1211       exit (1);
1212     }
1213
1214   /* will assign value to value */
1215   /* depending on where it is ofcourse */
1216   switch (aop->type)
1217     {
1218     case AOP_DUMMY:
1219       MOVA (s);         /* read s in case it was volatile */
1220       break;
1221
1222     case AOP_DIR:
1223       if (offset)
1224         sprintf (d, "(%s + %d)",
1225                  aop->aopu.aop_dir, offset);
1226       else
1227         sprintf (d, "%s", aop->aopu.aop_dir);
1228
1229       if (strcmp (d, s) ||
1230           bvolatile)
1231         emitcode ("mov", "%s,%s", d, s);
1232
1233       break;
1234
1235     case AOP_REG:
1236       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1237           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1238         {
1239           if (*s == '@' ||
1240               strcmp (s, "r0") == 0 ||
1241               strcmp (s, "r1") == 0 ||
1242               strcmp (s, "r2") == 0 ||
1243               strcmp (s, "r3") == 0 ||
1244               strcmp (s, "r4") == 0 ||
1245               strcmp (s, "r5") == 0 ||
1246               strcmp (s, "r6") == 0 ||
1247               strcmp (s, "r7") == 0)
1248             emitcode ("mov", "%s,%s",
1249                       aop->aopu.aop_reg[offset]->dname, s);
1250           else
1251             emitcode ("mov", "%s,%s",
1252                       aop->aopu.aop_reg[offset]->name, s);
1253         }
1254       break;
1255
1256     case AOP_DPTR:
1257       if (aop->code)
1258         {
1259           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1260                   "aopPut writing to code space");
1261           exit (1);
1262         }
1263
1264       while (offset > aop->coff)
1265         {
1266           aop->coff++;
1267           emitcode ("inc", "dptr");
1268         }
1269
1270       while (offset < aop->coff)
1271         {
1272           aop->coff--;
1273           emitcode ("lcall", "__decdptr");
1274         }
1275
1276       aop->coff = offset;
1277
1278       /* if not in accumulater */
1279       MOVA (s);
1280
1281       emitcode ("movx", "@dptr,a");
1282       break;
1283
1284     case AOP_R0:
1285     case AOP_R1:
1286       while (offset > aop->coff)
1287         {
1288           aop->coff++;
1289           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1290         }
1291       while (offset < aop->coff)
1292         {
1293           aop->coff--;
1294           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1295         }
1296       aop->coff = offset;
1297
1298       if (aop->paged)
1299         {
1300           MOVA (s);
1301           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1302
1303         }
1304       else if (*s == '@')
1305         {
1306           MOVA (s);
1307           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1308         }
1309       else if (strcmp (s, "r0") == 0 ||
1310                strcmp (s, "r1") == 0 ||
1311                strcmp (s, "r2") == 0 ||
1312                strcmp (s, "r3") == 0 ||
1313                strcmp (s, "r4") == 0 ||
1314                strcmp (s, "r5") == 0 ||
1315                strcmp (s, "r6") == 0 ||
1316                strcmp (s, "r7") == 0)
1317         {
1318           char buffer[10];
1319           sprintf (buffer, "a%s", s);
1320           emitcode ("mov", "@%s,%s",
1321                     aop->aopu.aop_ptr->name, buffer);
1322         }
1323       else
1324         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1325
1326       break;
1327
1328     case AOP_STK:
1329       if (strcmp (s, "a") == 0)
1330         emitcode ("push", "acc");
1331       else
1332         if (*s=='@') {
1333           MOVA(s);
1334           emitcode ("push", "acc");
1335         } else {
1336           emitcode ("push", s);
1337         }
1338
1339       break;
1340
1341     case AOP_CRY:
1342       /* if bit variable */
1343       if (!aop->aopu.aop_dir)
1344         {
1345           emitcode ("clr", "a");
1346           emitcode ("rlc", "a");
1347         }
1348       else
1349         {
1350           if (s == zero)
1351             emitcode ("clr", "%s", aop->aopu.aop_dir);
1352           else if (s == one)
1353             emitcode ("setb", "%s", aop->aopu.aop_dir);
1354           else if (!strcmp (s, "c"))
1355             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1356           else
1357             {
1358               if (strcmp (s, "a"))
1359                 {
1360                   MOVA (s);
1361                 }
1362               {
1363                 /* set C, if a >= 1 */
1364                 emitcode ("add", "a,#0xff");
1365                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1366               }
1367             }
1368         }
1369       break;
1370
1371     case AOP_STR:
1372       aop->coff = offset;
1373       if (strcmp (aop->aopu.aop_str[offset], s) ||
1374           bvolatile)
1375         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1376       break;
1377
1378     case AOP_ACC:
1379       aop->coff = offset;
1380       if (!offset && (strcmp (s, "acc") == 0) &&
1381           !bvolatile)
1382         break;
1383
1384       if (strcmp (aop->aopu.aop_str[offset], s) &&
1385           !bvolatile)
1386         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1387       break;
1388
1389     default:
1390       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1391               "aopPut got unsupported aop->type");
1392       exit (1);
1393     }
1394
1395 }
1396
1397
1398 #if 0
1399 /*-----------------------------------------------------------------*/
1400 /* pointToEnd :- points to the last byte of the operand            */
1401 /*-----------------------------------------------------------------*/
1402 static void
1403 pointToEnd (asmop * aop)
1404 {
1405   int count;
1406   if (!aop)
1407     return;
1408
1409   aop->coff = count = (aop->size - 1);
1410   switch (aop->type)
1411     {
1412     case AOP_R0:
1413     case AOP_R1:
1414       while (count--)
1415         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1416       break;
1417     case AOP_DPTR:
1418       while (count--)
1419         emitcode ("inc", "dptr");
1420       break;
1421     }
1422
1423 }
1424 #endif
1425
1426 /*-----------------------------------------------------------------*/
1427 /* reAdjustPreg - points a register back to where it should        */
1428 /*-----------------------------------------------------------------*/
1429 static void
1430 reAdjustPreg (asmop * aop)
1431 {
1432   if ((aop->coff==0) || aop->size <= 1)
1433     return;
1434
1435   switch (aop->type)
1436     {
1437     case AOP_R0:
1438     case AOP_R1:
1439       while (aop->coff--)
1440         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1441       break;
1442     case AOP_DPTR:
1443       while (aop->coff--)
1444         {
1445           emitcode ("lcall", "__decdptr");
1446         }
1447       break;
1448     }
1449   aop->coff = 0;
1450 }
1451
1452 #define AOP(op) op->aop
1453 #define AOP_TYPE(op) AOP(op)->type
1454 #define AOP_SIZE(op) AOP(op)->size
1455 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1456                        AOP_TYPE(x) == AOP_R0))
1457
1458 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1459                         AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1460
1461 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1462                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1463                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1464
1465
1466 /*-----------------------------------------------------------------*/
1467 /* opIsGptr: returns non-zero if the passed operand is       */
1468 /* a generic pointer type.             */
1469 /*-----------------------------------------------------------------*/
1470 static int
1471 opIsGptr (operand * op)
1472 {
1473   sym_link *type = operandType (op);
1474
1475   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1476     {
1477       return 1;
1478     }
1479   return 0;
1480 }
1481
1482 /*-----------------------------------------------------------------*/
1483 /* getDataSize - get the operand data size                         */
1484 /*-----------------------------------------------------------------*/
1485 static int
1486 getDataSize (operand * op)
1487 {
1488   int size;
1489   size = AOP_SIZE (op);
1490   if (size == GPTRSIZE)
1491     {
1492       sym_link *type = operandType (op);
1493       if (IS_GENPTR (type))
1494         {
1495           /* generic pointer; arithmetic operations
1496            * should ignore the high byte (pointer type).
1497            */
1498           size--;
1499         }
1500     }
1501   return size;
1502 }
1503
1504 /*-----------------------------------------------------------------*/
1505 /* outAcc - output Acc                                             */
1506 /*-----------------------------------------------------------------*/
1507 static void
1508 outAcc (operand * result)
1509 {
1510   int size, offset;
1511   size = getDataSize (result);
1512   if (size)
1513     {
1514       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1515       size--;
1516       offset = 1;
1517       /* unsigned or positive */
1518       while (size--)
1519         {
1520           aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1521         }
1522     }
1523 }
1524
1525 /*-----------------------------------------------------------------*/
1526 /* outBitC - output a bit C                                        */
1527 /*-----------------------------------------------------------------*/
1528 static void
1529 outBitC (operand * result)
1530 {
1531   /* if the result is bit */
1532   if (AOP_TYPE (result) == AOP_CRY)
1533     aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1534   else
1535     {
1536       emitcode ("clr", "a");
1537       emitcode ("rlc", "a");
1538       outAcc (result);
1539     }
1540 }
1541
1542 /*-----------------------------------------------------------------*/
1543 /* toBoolean - emit code for orl a,operator(sizeop)                */
1544 /*-----------------------------------------------------------------*/
1545 static void
1546 toBoolean (operand * oper)
1547 {
1548   int size = AOP_SIZE (oper) - 1;
1549   int offset = 1;
1550   MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1551   while (size--)
1552     emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1553 }
1554
1555
1556 /*-----------------------------------------------------------------*/
1557 /* genNot - generate code for ! operation                          */
1558 /*-----------------------------------------------------------------*/
1559 static void
1560 genNot (iCode * ic)
1561 {
1562   symbol *tlbl;
1563
1564   D(emitcode (";     genNot",""));
1565
1566   /* assign asmOps to operand & result */
1567   aopOp (IC_LEFT (ic), ic, FALSE);
1568   aopOp (IC_RESULT (ic), ic, TRUE);
1569
1570   /* if in bit space then a special case */
1571   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1572     {
1573       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1574       emitcode ("cpl", "c");
1575       outBitC (IC_RESULT (ic));
1576       goto release;
1577     }
1578
1579   toBoolean (IC_LEFT (ic));
1580
1581   tlbl = newiTempLabel (NULL);
1582   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1583   emitcode ("", "%05d$:", tlbl->key + 100);
1584   outBitC (IC_RESULT (ic));
1585
1586 release:
1587   /* release the aops */
1588   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1589   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1590 }
1591
1592
1593 /*-----------------------------------------------------------------*/
1594 /* genCpl - generate code for complement                           */
1595 /*-----------------------------------------------------------------*/
1596 static void
1597 genCpl (iCode * ic)
1598 {
1599   int offset = 0;
1600   int size;
1601   symbol *tlbl;
1602
1603   D(emitcode (";     genCpl",""));
1604
1605   /* assign asmOps to operand & result */
1606   aopOp (IC_LEFT (ic), ic, FALSE);
1607   aopOp (IC_RESULT (ic), ic, TRUE);
1608
1609   /* special case if in bit space */
1610   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1611     {
1612       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1613         {
1614           /* promotion rules are responsible for this strange result: */
1615           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1616           goto release;
1617         }
1618
1619       tlbl=newiTempLabel(NULL);
1620       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1621           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1622           IS_AOP_PREG (IC_LEFT (ic)))
1623         {
1624           emitcode ("cjne", "%s,#0x01,%05d$",
1625                     aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1626                     tlbl->key + 100);
1627         }
1628       else
1629         {
1630           char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1631           MOVA (l);
1632           emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1633         }
1634       emitcode ("", "%05d$:", tlbl->key + 100);
1635       outBitC (IC_RESULT(ic));
1636       goto release;
1637     }
1638
1639   size = AOP_SIZE (IC_RESULT (ic));
1640   while (size--)
1641     {
1642       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1643       MOVA (l);
1644       emitcode ("cpl", "a");
1645       aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1646     }
1647
1648
1649 release:
1650   /* release the aops */
1651   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1652   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1653 }
1654
1655 /*-----------------------------------------------------------------*/
1656 /* genUminusFloat - unary minus for floating points                */
1657 /*-----------------------------------------------------------------*/
1658 static void
1659 genUminusFloat (operand * op, operand * result)
1660 {
1661   int size, offset = 0;
1662   char *l;
1663
1664   D(emitcode (";     genUminusFloat",""));
1665
1666   /* for this we just copy and then flip the bit */
1667
1668   size = AOP_SIZE (op) - 1;
1669
1670   while (size--)
1671     {
1672       aopPut (AOP (result),
1673               aopGet (AOP (op), offset, FALSE, FALSE),
1674               offset,
1675               isOperandVolatile (result, FALSE));
1676       offset++;
1677     }
1678
1679   l = aopGet (AOP (op), offset, FALSE, FALSE);
1680
1681   MOVA (l);
1682
1683   emitcode ("cpl", "acc.7");
1684   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1685 }
1686
1687 /*-----------------------------------------------------------------*/
1688 /* genUminus - unary minus code generation                         */
1689 /*-----------------------------------------------------------------*/
1690 static void
1691 genUminus (iCode * ic)
1692 {
1693   int offset, size;
1694   sym_link *optype, *rtype;
1695
1696
1697   D(emitcode (";     genUminus",""));
1698
1699   /* assign asmops */
1700   aopOp (IC_LEFT (ic), ic, FALSE);
1701   aopOp (IC_RESULT (ic), ic, TRUE);
1702
1703   /* if both in bit space then special
1704      case */
1705   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1706       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1707     {
1708
1709       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1710       emitcode ("cpl", "c");
1711       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1712       goto release;
1713     }
1714
1715   optype = operandType (IC_LEFT (ic));
1716   rtype = operandType (IC_RESULT (ic));
1717
1718   /* if float then do float stuff */
1719   if (IS_FLOAT (optype))
1720     {
1721       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1722       goto release;
1723     }
1724
1725   /* otherwise subtract from zero */
1726   size = AOP_SIZE (IC_LEFT (ic));
1727   offset = 0;
1728   //CLRC ;
1729   while (size--)
1730     {
1731       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1732       if (!strcmp (l, "a"))
1733         {
1734           if (offset == 0)
1735             SETC;
1736           emitcode ("cpl", "a");
1737           emitcode ("addc", "a,#0");
1738         }
1739       else
1740         {
1741           if (offset == 0)
1742             CLRC;
1743           emitcode ("clr", "a");
1744           emitcode ("subb", "a,%s", l);
1745         }
1746       aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1747     }
1748
1749   /* if any remaining bytes in the result */
1750   /* we just need to propagate the sign   */
1751   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1752     {
1753       emitcode ("rlc", "a");
1754       emitcode ("subb", "a,acc");
1755       while (size--)
1756         aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1757     }
1758
1759 release:
1760   /* release the aops */
1761   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1762   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1763 }
1764
1765 /*-----------------------------------------------------------------*/
1766 /* saveRegisters - will look for a call and save the registers     */
1767 /*-----------------------------------------------------------------*/
1768 static void
1769 saveRegisters (iCode * lic)
1770 {
1771   int i;
1772   iCode *ic;
1773   bitVect *rsave;
1774
1775   /* look for call */
1776   for (ic = lic; ic; ic = ic->next)
1777     if (ic->op == CALL || ic->op == PCALL)
1778       break;
1779
1780   if (!ic)
1781     {
1782       fprintf (stderr, "found parameter push with no function call\n");
1783       return;
1784     }
1785
1786   /* if the registers have been saved already or don't need to be then
1787      do nothing */
1788   if (ic->regsSaved)
1789     return;
1790   if (IS_SYMOP(IC_LEFT(ic)) &&
1791       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1792        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1793     return;
1794
1795   /* safe the registers in use at this time but skip the
1796      ones for the result */
1797   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1798                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1799
1800   ic->regsSaved = 1;
1801   if (options.useXstack)
1802     {
1803       if (bitVectBitValue (rsave, R0_IDX))
1804         emitcode ("mov", "b,r0");
1805       emitcode ("mov", "r0,%s", spname);
1806       for (i = 0; i < mcs51_nRegs; i++)
1807         {
1808           if (bitVectBitValue (rsave, i))
1809             {
1810               if (i == R0_IDX)
1811                 emitcode ("mov", "a,b");
1812               else
1813                 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1814               emitcode ("movx", "@r0,a");
1815               emitcode ("inc", "r0");
1816             }
1817         }
1818       emitcode ("mov", "%s,r0", spname);
1819       if (bitVectBitValue (rsave, R0_IDX))
1820         emitcode ("mov", "r0,b");
1821     }
1822   else
1823     for (i = 0; i < mcs51_nRegs; i++)
1824       {
1825         if (bitVectBitValue (rsave, i))
1826           emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1827       }
1828 }
1829
1830 /*-----------------------------------------------------------------*/
1831 /* unsaveRegisters - pop the pushed registers                      */
1832 /*-----------------------------------------------------------------*/
1833 static void
1834 unsaveRegisters (iCode * ic)
1835 {
1836   int i;
1837   bitVect *rsave;
1838
1839   /* restore the registers in use at this time but skip the
1840      ones for the result */
1841   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1842                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1843
1844   if (options.useXstack)
1845     {
1846       emitcode ("mov", "r0,%s", spname);
1847       for (i = mcs51_nRegs; i >= 0; i--)
1848         {
1849           if (bitVectBitValue (rsave, i))
1850             {
1851               emitcode ("dec", "r0");
1852               emitcode ("movx", "a,@r0");
1853               if (i == R0_IDX)
1854                 emitcode ("mov", "b,a");
1855               else
1856                 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1857             }
1858
1859         }
1860       emitcode ("mov", "%s,r0", spname);
1861       if (bitVectBitValue (rsave, R0_IDX))
1862         emitcode ("mov", "r0,b");
1863     }
1864   else
1865     for (i = mcs51_nRegs; i >= 0; i--)
1866       {
1867         if (bitVectBitValue (rsave, i))
1868           emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1869       }
1870
1871 }
1872
1873
1874 /*-----------------------------------------------------------------*/
1875 /* pushSide -                */
1876 /*-----------------------------------------------------------------*/
1877 static void
1878 pushSide (operand * oper, int size)
1879 {
1880   int offset = 0;
1881   while (size--)
1882     {
1883       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1884       if (AOP_TYPE (oper) != AOP_REG &&
1885           AOP_TYPE (oper) != AOP_DIR &&
1886           strcmp (l, "a"))
1887         {
1888           MOVA (l);
1889           emitcode ("push", "acc");
1890         }
1891       else
1892         emitcode ("push", "%s", l);
1893     }
1894 }
1895
1896 /*-----------------------------------------------------------------*/
1897 /* assignResultValue -               */
1898 /*-----------------------------------------------------------------*/
1899 static void
1900 assignResultValue (operand * oper)
1901 {
1902   int offset = 0;
1903   int size = AOP_SIZE (oper);
1904   while (size--)
1905     {
1906       aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1907       offset++;
1908     }
1909 }
1910
1911
1912 /*-----------------------------------------------------------------*/
1913 /* genXpush - pushes onto the external stack                       */
1914 /*-----------------------------------------------------------------*/
1915 static void
1916 genXpush (iCode * ic)
1917 {
1918   asmop *aop = newAsmop (0);
1919   regs *r;
1920   int size, offset = 0;
1921
1922   D(emitcode (";     genXpush",""));
1923
1924   aopOp (IC_LEFT (ic), ic, FALSE);
1925   r = getFreePtr (ic, &aop, FALSE);
1926
1927
1928   emitcode ("mov", "%s,_spx", r->name);
1929
1930   size = AOP_SIZE (IC_LEFT (ic));
1931   while (size--)
1932     {
1933
1934       char *l = aopGet (AOP (IC_LEFT (ic)),
1935                         offset++, FALSE, FALSE);
1936       MOVA (l);
1937       emitcode ("movx", "@%s,a", r->name);
1938       emitcode ("inc", "%s", r->name);
1939
1940     }
1941
1942
1943   emitcode ("mov", "_spx,%s", r->name);
1944
1945   freeAsmop (NULL, aop, ic, TRUE);
1946   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1947 }
1948
1949 /*-----------------------------------------------------------------*/
1950 /* genIpush - genrate code for pushing this gets a little complex  */
1951 /*-----------------------------------------------------------------*/
1952 static void
1953 genIpush (iCode * ic)
1954 {
1955   int size, offset = 0;
1956   char *l;
1957
1958   D(emitcode (";     genIpush",""));
1959
1960   /* if this is not a parm push : ie. it is spill push
1961      and spill push is always done on the local stack */
1962   if (!ic->parmPush)
1963     {
1964
1965       /* and the item is spilt then do nothing */
1966       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1967         return;
1968
1969       aopOp (IC_LEFT (ic), ic, FALSE);
1970       size = AOP_SIZE (IC_LEFT (ic));
1971       /* push it on the stack */
1972       while (size--)
1973         {
1974           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1975           if (*l == '#')
1976             {
1977               MOVA (l);
1978               l = "acc";
1979             }
1980           emitcode ("push", "%s", l);
1981         }
1982       return;
1983     }
1984
1985   /* this is a paramter push: in this case we call
1986      the routine to find the call and save those
1987      registers that need to be saved */
1988   saveRegisters (ic);
1989
1990   /* if use external stack then call the external
1991      stack pushing routine */
1992   if (options.useXstack)
1993     {
1994       genXpush (ic);
1995       return;
1996     }
1997
1998   /* then do the push */
1999   aopOp (IC_LEFT (ic), ic, FALSE);
2000
2001
2002   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2003   size = AOP_SIZE (IC_LEFT (ic));
2004
2005   while (size--)
2006     {
2007       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2008       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2009           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2010           strcmp (l, "a"))
2011         {
2012           MOVA (l);
2013           emitcode ("push", "acc");
2014         }
2015       else
2016         emitcode ("push", "%s", l);
2017     }
2018
2019   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2020 }
2021
2022 /*-----------------------------------------------------------------*/
2023 /* genIpop - recover the registers: can happen only for spilling   */
2024 /*-----------------------------------------------------------------*/
2025 static void
2026 genIpop (iCode * ic)
2027 {
2028   int size, offset;
2029
2030   D(emitcode (";     genIpop",""));
2031
2032   /* if the temp was not pushed then */
2033   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2034     return;
2035
2036   aopOp (IC_LEFT (ic), ic, FALSE);
2037   size = AOP_SIZE (IC_LEFT (ic));
2038   offset = (size - 1);
2039   while (size--)
2040     emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2041                                    FALSE, TRUE));
2042
2043   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2044 }
2045
2046 /*-----------------------------------------------------------------*/
2047 /* unsaveRBank - restores the resgister bank from stack            */
2048 /*-----------------------------------------------------------------*/
2049 static void
2050 unsaveRBank (int bank, iCode * ic, bool popPsw)
2051 {
2052   int i;
2053   asmop *aop = NULL;
2054   regs *r = NULL;
2055
2056   if (options.useXstack)
2057   {
2058       if (!ic)
2059       {
2060           /* Assume r0 is available for use. */
2061           r = mcs51_regWithIdx (R0_IDX);;
2062       }
2063       else
2064       {
2065           aop = newAsmop (0);
2066           r = getFreePtr (ic, &aop, FALSE);
2067       }
2068       emitcode ("mov", "%s,_spx", r->name);
2069   }
2070
2071   if (popPsw)
2072     {
2073       if (options.useXstack)
2074       {
2075           emitcode ("movx", "a,@%s", r->name);
2076           emitcode ("mov", "psw,a");
2077           emitcode ("dec", "%s", r->name);
2078         }
2079       else
2080       {
2081         emitcode ("pop", "psw");
2082       }
2083     }
2084
2085   for (i = (mcs51_nRegs - 1); i >= 0; i--)
2086     {
2087       if (options.useXstack)
2088         {
2089           emitcode ("movx", "a,@%s", r->name);
2090           emitcode ("mov", "(%s+%d),a",
2091                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2092           emitcode ("dec", "%s", r->name);
2093
2094         }
2095       else
2096         emitcode ("pop", "(%s+%d)",
2097                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2098     }
2099
2100   if (options.useXstack)
2101     {
2102       emitcode ("mov", "_spx,%s", r->name);
2103     }
2104
2105   if (aop)
2106   {
2107       freeAsmop (NULL, aop, ic, TRUE);
2108   }
2109 }
2110
2111 /*-----------------------------------------------------------------*/
2112 /* saveRBank - saves an entire register bank on the stack          */
2113 /*-----------------------------------------------------------------*/
2114 static void
2115 saveRBank (int bank, iCode * ic, bool pushPsw)
2116 {
2117   int i;
2118   asmop *aop = NULL;
2119   regs *r = NULL;
2120
2121   if (options.useXstack)
2122     {
2123       if (!ic)
2124       {
2125           /* Assume r0 is available for use. */
2126           r = mcs51_regWithIdx (R0_IDX);;
2127       }
2128       else
2129       {
2130           aop = newAsmop (0);
2131           r = getFreePtr (ic, &aop, FALSE);
2132       }
2133       emitcode ("mov", "%s,_spx", r->name);
2134     }
2135
2136   for (i = 0; i < mcs51_nRegs; i++)
2137     {
2138       if (options.useXstack)
2139         {
2140           emitcode ("inc", "%s", r->name);
2141           emitcode ("mov", "a,(%s+%d)",
2142                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2143           emitcode ("movx", "@%s,a", r->name);
2144         }
2145       else
2146         emitcode ("push", "(%s+%d)",
2147                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2148     }
2149
2150   if (pushPsw)
2151     {
2152       if (options.useXstack)
2153         {
2154           emitcode ("mov", "a,psw");
2155           emitcode ("movx", "@%s,a", r->name);
2156           emitcode ("inc", "%s", r->name);
2157           emitcode ("mov", "_spx,%s", r->name);
2158
2159         }
2160       else
2161       {
2162         emitcode ("push", "psw");
2163       }
2164
2165       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2166     }
2167
2168     if (aop)
2169     {
2170         freeAsmop (NULL, aop, ic, TRUE);
2171     }
2172
2173   if (ic)
2174   {
2175       ic->bankSaved = 1;
2176   }
2177 }
2178
2179 /*-----------------------------------------------------------------*/
2180 /* genSend - gen code for SEND                                     */
2181 /*-----------------------------------------------------------------*/
2182 static void genSend(set *sendSet)
2183 {
2184     iCode *sic;
2185     int rb1_count = 0 ;
2186
2187     for (sic = setFirstItem (_G.sendSet); sic;
2188          sic = setNextItem (_G.sendSet)) {
2189           int size, offset = 0;
2190           aopOp (IC_LEFT (sic), sic, FALSE);
2191           size = AOP_SIZE (IC_LEFT (sic));
2192
2193           if (sic->argreg == 1) {
2194               while (size--) {
2195                   char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2196                                     FALSE, FALSE);
2197                   if (strcmp (l, fReturn[offset]))
2198                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2199                   offset++;
2200               }
2201               rb1_count = 0;
2202           } else {
2203               while (size--) {
2204                   emitcode ("mov","b1_%d,%s",rb1_count++,
2205                             aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2206               }
2207           }
2208           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2209     }
2210 }
2211
2212 /*-----------------------------------------------------------------*/
2213 /* genCall - generates a call statement                            */
2214 /*-----------------------------------------------------------------*/
2215 static void
2216 genCall (iCode * ic)
2217 {
2218   sym_link *dtype;
2219 //  bool restoreBank = FALSE;
2220   bool swapBanks = FALSE;
2221
2222   D(emitcode(";     genCall",""));
2223
2224   dtype = operandType (IC_LEFT (ic));
2225   /* if send set is not empty the assign */
2226   if (_G.sendSet)
2227     {
2228         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2229             genSend(reverseSet(_G.sendSet));
2230         } else {
2231             genSend(_G.sendSet);
2232         }
2233
2234       _G.sendSet = NULL;
2235     }
2236
2237   /* if we are calling a not _naked function that is not using
2238      the same register bank then we need to save the
2239      destination registers on the stack */
2240   dtype = operandType (IC_LEFT (ic));
2241   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2242       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2243        !IFFUNC_ISISR (dtype))
2244   {
2245       swapBanks = TRUE;
2246   }
2247
2248   /* if caller saves & we have not saved then */
2249   if (!ic->regsSaved)
2250       saveRegisters (ic);
2251
2252   if (swapBanks)
2253   {
2254         emitcode ("mov", "psw,#0x%02x",
2255            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2256   }
2257
2258   /* make the call */
2259   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2260                             OP_SYMBOL (IC_LEFT (ic))->rname :
2261                             OP_SYMBOL (IC_LEFT (ic))->name));
2262
2263   if (swapBanks)
2264   {
2265        emitcode ("mov", "psw,#0x%02x",
2266           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2267   }
2268
2269   /* if we need assign a result value */
2270   if ((IS_ITEMP (IC_RESULT (ic)) &&
2271        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2272         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2273         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2274       IS_TRUE_SYMOP (IC_RESULT (ic)))
2275     {
2276
2277       _G.accInUse++;
2278       aopOp (IC_RESULT (ic), ic, FALSE);
2279       _G.accInUse--;
2280
2281       assignResultValue (IC_RESULT (ic));
2282
2283       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2284     }
2285
2286   /* adjust the stack for parameters if
2287      required */
2288   if (ic->parmBytes)
2289     {
2290       int i;
2291       if (ic->parmBytes > 3)
2292         {
2293           emitcode ("mov", "a,%s", spname);
2294           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2295           emitcode ("mov", "%s,a", spname);
2296         }
2297       else
2298         for (i = 0; i < ic->parmBytes; i++)
2299           emitcode ("dec", "%s", spname);
2300     }
2301
2302   /* if we hade saved some registers then unsave them */
2303   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2304     unsaveRegisters (ic);
2305
2306 //  /* if register bank was saved then pop them */
2307 //  if (restoreBank)
2308 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2309 }
2310
2311 /*-----------------------------------------------------------------*/
2312 /* -10l - generates a call by pointer statement                */
2313 /*-----------------------------------------------------------------*/
2314 static void
2315 genPcall (iCode * ic)
2316 {
2317   sym_link *dtype;
2318   symbol *rlbl = newiTempLabel (NULL);
2319 //  bool restoreBank=FALSE;
2320   bool swapBanks = FALSE;
2321
2322   D(emitcode(";     genPCall",""));
2323
2324   /* if caller saves & we have not saved then */
2325   if (!ic->regsSaved)
2326     saveRegisters (ic);
2327
2328   /* if we are calling a not _naked function that is not using
2329      the same register bank then we need to save the
2330      destination registers on the stack */
2331   dtype = operandType (IC_LEFT (ic))->next;
2332   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2333       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2334       !IFFUNC_ISISR (dtype))
2335   {
2336 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2337 //    restoreBank=TRUE;
2338       swapBanks = TRUE;
2339       // need caution message to user here
2340   }
2341
2342   /* push the return address on to the stack */
2343   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2344   emitcode ("push", "acc");
2345   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2346   emitcode ("push", "acc");
2347
2348   /* now push the calling address */
2349   aopOp (IC_LEFT (ic), ic, FALSE);
2350
2351   pushSide (IC_LEFT (ic), FPTRSIZE);
2352
2353   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2354
2355   /* if send set is not empty the assign */
2356   if (_G.sendSet)
2357     {
2358         genSend(reverseSet(_G.sendSet));
2359         _G.sendSet = NULL;
2360     }
2361
2362   if (swapBanks)
2363   {
2364         emitcode ("mov", "psw,#0x%02x",
2365            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2366   }
2367
2368   /* make the call */
2369   emitcode ("ret", "");
2370   emitcode ("", "%05d$:", (rlbl->key + 100));
2371
2372
2373   if (swapBanks)
2374   {
2375        emitcode ("mov", "psw,#0x%02x",
2376           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2377   }
2378
2379   /* if we need assign a result value */
2380   if ((IS_ITEMP (IC_RESULT (ic)) &&
2381        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2382         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2383       IS_TRUE_SYMOP (IC_RESULT (ic)))
2384     {
2385
2386       _G.accInUse++;
2387       aopOp (IC_RESULT (ic), ic, FALSE);
2388       _G.accInUse--;
2389
2390       assignResultValue (IC_RESULT (ic));
2391
2392       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2393     }
2394
2395   /* adjust the stack for parameters if
2396      required */
2397   if (ic->parmBytes)
2398     {
2399       int i;
2400       if (ic->parmBytes > 3)
2401         {
2402           emitcode ("mov", "a,%s", spname);
2403           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2404           emitcode ("mov", "%s,a", spname);
2405         }
2406       else
2407         for (i = 0; i < ic->parmBytes; i++)
2408           emitcode ("dec", "%s", spname);
2409
2410     }
2411
2412 //  /* if register bank was saved then unsave them */
2413 //  if (restoreBank)
2414 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2415
2416   /* if we hade saved some registers then
2417      unsave them */
2418   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2419     unsaveRegisters (ic);
2420 }
2421
2422 /*-----------------------------------------------------------------*/
2423 /* resultRemat - result  is rematerializable                       */
2424 /*-----------------------------------------------------------------*/
2425 static int
2426 resultRemat (iCode * ic)
2427 {
2428   if (SKIP_IC (ic) || ic->op == IFX)
2429     return 0;
2430
2431   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2432     {
2433       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2434       if (sym->remat && !POINTER_SET (ic))
2435         return 1;
2436     }
2437
2438   return 0;
2439 }
2440
2441 #if defined(__BORLANDC__) || defined(_MSC_VER)
2442 #define STRCASECMP stricmp
2443 #else
2444 #define STRCASECMP strcasecmp
2445 #endif
2446
2447 /*-----------------------------------------------------------------*/
2448 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2449 /*-----------------------------------------------------------------*/
2450 static int
2451 regsCmp(void *p1, void *p2)
2452 {
2453   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2454 }
2455
2456 static bool
2457 inExcludeList (char *s)
2458 {
2459   const char *p = setFirstItem(options.excludeRegsSet);
2460
2461   if (p == NULL || STRCASECMP(p, "none") == 0)
2462     return FALSE;
2463
2464
2465   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2466 }
2467
2468 /*-----------------------------------------------------------------*/
2469 /* genFunction - generated code for function entry                 */
2470 /*-----------------------------------------------------------------*/
2471 static void
2472 genFunction (iCode * ic)
2473 {
2474   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2475   sym_link *ftype;
2476   bool   switchedPSW = FALSE;
2477   int calleesaves_saved_register = -1;
2478   int stackAdjust = sym->stack;
2479   int accIsFree = sym->recvSize < 4;
2480   iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2481
2482   _G.nRegsSaved = 0;
2483   /* create the function header */
2484   emitcode (";", "-----------------------------------------");
2485   emitcode (";", " function %s", sym->name);
2486   emitcode (";", "-----------------------------------------");
2487
2488   emitcode ("", "%s:", sym->rname);
2489   ftype = operandType (IC_LEFT (ic));
2490   _G.currentFunc = sym;
2491
2492   if (IFFUNC_ISNAKED(ftype))
2493   {
2494       emitcode(";", "naked function: no prologue.");
2495       return;
2496   }
2497
2498   /* here we need to generate the equates for the
2499      register bank if required */
2500   if (FUNC_REGBANK (ftype) != rbank)
2501     {
2502       int i;
2503
2504       rbank = FUNC_REGBANK (ftype);
2505       for (i = 0; i < mcs51_nRegs; i++)
2506         {
2507           if (strcmp (regs8051[i].base, "0") == 0)
2508             emitcode ("", "%s = 0x%02x",
2509                       regs8051[i].dname,
2510                       8 * rbank + regs8051[i].offset);
2511           else
2512             emitcode ("", "%s = %s + 0x%02x",
2513                       regs8051[i].dname,
2514                       regs8051[i].base,
2515                       8 * rbank + regs8051[i].offset);
2516         }
2517     }
2518
2519   /* if this is an interrupt service routine then
2520      save acc, b, dpl, dph  */
2521   if (IFFUNC_ISISR (sym->type))
2522     {
2523
2524       if (!inExcludeList ("acc"))
2525         emitcode ("push", "acc");
2526       if (!inExcludeList ("b"))
2527         emitcode ("push", "b");
2528       if (!inExcludeList ("dpl"))
2529         emitcode ("push", "dpl");
2530       if (!inExcludeList ("dph"))
2531         emitcode ("push", "dph");
2532       /* if this isr has no bank i.e. is going to
2533          run with bank 0 , then we need to save more
2534          registers :-) */
2535       if (!FUNC_REGBANK (sym->type))
2536         {
2537
2538           /* if this function does not call any other
2539              function then we can be economical and
2540              save only those registers that are used */
2541           if (!IFFUNC_HASFCALL(sym->type))
2542             {
2543               int i;
2544
2545               /* if any registers used */
2546               if (sym->regsUsed)
2547                 {
2548                   /* save the registers used */
2549                   for (i = 0; i < sym->regsUsed->size; i++)
2550                     {
2551                       if (bitVectBitValue (sym->regsUsed, i))
2552                         emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2553                     }
2554                 }
2555             }
2556           else
2557             {
2558
2559               /* this function has a function call. We cannot
2560                  determines register usage so we will have to push the
2561                  entire bank */
2562                 saveRBank (0, ic, FALSE);
2563                 if (options.parms_in_bank1) {
2564                     int i;
2565                     for (i=0; i < 8 ; i++ ) {
2566                         emitcode ("push","%s",rb1regs[i]);
2567                     }
2568                 }
2569             }
2570         }
2571         else
2572         {
2573             /* This ISR uses a non-zero bank.
2574              *
2575              * We assume that the bank is available for our
2576              * exclusive use.
2577              *
2578              * However, if this ISR calls a function which uses some
2579              * other bank, we must save that bank entirely.
2580              */
2581             unsigned long banksToSave = 0;
2582
2583             if (IFFUNC_HASFCALL(sym->type))
2584             {
2585
2586 #define MAX_REGISTER_BANKS 4
2587
2588                 iCode *i;
2589                 int ix;
2590
2591                 for (i = ic; i; i = i->next)
2592                 {
2593                     if (i->op == ENDFUNCTION)
2594                     {
2595                         /* we got to the end OK. */
2596                         break;
2597                     }
2598
2599                     if (i->op == CALL)
2600                     {
2601                         sym_link *dtype;
2602
2603                         dtype = operandType (IC_LEFT(i));
2604                         if (dtype
2605                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2606                         {
2607                              /* Mark this bank for saving. */
2608                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2609                              {
2610                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2611                              }
2612                              else
2613                              {
2614                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2615                              }
2616
2617                              /* And note that we don't need to do it in
2618                               * genCall.
2619                               */
2620                              i->bankSaved = 1;
2621                         }
2622                     }
2623                     if (i->op == PCALL)
2624                     {
2625                         /* This is a mess; we have no idea what
2626                          * register bank the called function might
2627                          * use.
2628                          *
2629                          * The only thing I can think of to do is
2630                          * throw a warning and hope.
2631                          */
2632                         werror(W_FUNCPTR_IN_USING_ISR);
2633                     }
2634                 }
2635
2636                 if (banksToSave && options.useXstack)
2637                 {
2638                     /* Since we aren't passing it an ic,
2639                      * saveRBank will assume r0 is available to abuse.
2640                      *
2641                      * So switch to our (trashable) bank now, so
2642                      * the caller's R0 isn't trashed.
2643                      */
2644                     emitcode ("push", "psw");
2645                     emitcode ("mov", "psw,#0x%02x",
2646                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2647                     switchedPSW = TRUE;
2648                 }
2649
2650                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2651                 {
2652                      if (banksToSave & (1 << ix))
2653                      {
2654                          saveRBank(ix, NULL, FALSE);
2655                      }
2656                 }
2657             }
2658             // TODO: this needs a closer look
2659             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2660         }
2661
2662       /* Set the register bank to the desired value if nothing else */
2663       /* has done so yet. */
2664       if (!switchedPSW)
2665         {
2666           emitcode ("push", "psw");
2667           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2668         }
2669     }
2670   else
2671     {
2672       /* This is a non-ISR function. The caller has already switched register */
2673       /* banks, if necessary, so just handle the callee-saves option. */
2674
2675       /* if callee-save to be used for this function
2676          then save the registers being used in this function */
2677       if (IFFUNC_CALLEESAVES(sym->type))
2678         {
2679           int i;
2680
2681           /* if any registers used */
2682           if (sym->regsUsed)
2683             {
2684               /* save the registers used */
2685               for (i = 0; i < sym->regsUsed->size; i++)
2686                 {
2687                   if (bitVectBitValue (sym->regsUsed, i))
2688                     {
2689                       /* remember one saved register for later usage */
2690                       if (calleesaves_saved_register < 0)
2691                         calleesaves_saved_register = i;
2692                       emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2693                       _G.nRegsSaved++;
2694                     }
2695                 }
2696             }
2697         }
2698     }
2699
2700
2701   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2702     {
2703
2704       if (options.useXstack)
2705         {
2706           if (!accIsFree)
2707             emitcode ("push", "acc");
2708           emitcode ("mov", "r0,%s", spname);
2709           emitcode ("mov", "a,_bp");
2710           emitcode ("movx", "@r0,a");
2711           emitcode ("inc", "%s", spname);
2712           if (!accIsFree)
2713             emitcode ("pop", "acc");
2714         }
2715       else
2716         {
2717           /* set up the stack */
2718           emitcode ("push", "_bp");     /* save the callers stack  */
2719         }
2720       emitcode ("mov", "_bp,%s", spname);
2721     }
2722
2723   /* For some cases it is worthwhile to perform a RECEIVE iCode */
2724   /* before setting up the stack frame completely. */
2725   if (ric && ric->argreg == 1 && IC_RESULT (ric))
2726     {
2727       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2728
2729       if (rsym->isitmp)
2730         {
2731           if (rsym && rsym->regType == REG_CND)
2732             rsym = NULL;
2733           if (rsym && (rsym->accuse || rsym->ruonly))
2734             rsym = NULL;
2735           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2736             rsym = rsym->usl.spillLoc;
2737         }
2738
2739       /* If the RECEIVE operand immediately spills to the first entry on the */
2740       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2741       /* rather than the usual @r0/r1 machinations. */
2742       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2743         {
2744           int ofs;
2745
2746           _G.current_iCode = ric;
2747           D(emitcode (";     genReceive",""));
2748           for (ofs=0; ofs < sym->recvSize; ofs++)
2749             {
2750               if (!strcmp (fReturn[ofs], "a"))
2751                 emitcode ("push", "acc");
2752               else
2753                 emitcode ("push", fReturn[ofs]);
2754             }
2755           stackAdjust -= sym->recvSize;
2756           if (stackAdjust<0)
2757             {
2758               assert (stackAdjust>=0);
2759               stackAdjust = 0;
2760             }
2761           _G.current_iCode = ic;
2762           ric->generated = 1;
2763           accIsFree = 1;
2764         }
2765       /* If the RECEIVE operand is 4 registers, we can do the moves now */
2766       /* to free up the accumulator. */
2767       else if (rsym && rsym->nRegs && sym->recvSize == 4)
2768         {
2769           int ofs;
2770
2771           _G.current_iCode = ric;
2772           D(emitcode (";     genReceive",""));
2773           for (ofs=0; ofs < sym->recvSize; ofs++)
2774             {
2775               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2776             }
2777           _G.current_iCode = ic;
2778           ric->generated = 1;
2779           accIsFree = 1;
2780         }
2781     }
2782
2783   /* adjust the stack for the function */
2784   if (stackAdjust)
2785     {
2786
2787       int i = stackAdjust;
2788       if (i > 256)
2789         werror (W_STACK_OVERFLOW, sym->name);
2790
2791       if (i > 3 && accIsFree)
2792         {
2793
2794           emitcode ("mov", "a,sp");
2795           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796           emitcode ("mov", "sp,a");
2797
2798         }
2799       else if (i > 5)
2800         {
2801           /* The accumulator is not free, so we will need another register */
2802           /* to clobber. No need to worry about a possible conflict with */
2803           /* the above early RECEIVE optimizations since they would have */
2804           /* freed the accumulator if they were generated. */
2805
2806           if (IFFUNC_CALLEESAVES(sym->type))
2807             {
2808               /* if it's a callee-saves function we need a saved register */
2809               if (calleesaves_saved_register >= 0)
2810                 {
2811                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2812                   emitcode ("mov", "a,sp");
2813                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2814                   emitcode ("mov", "sp,a");
2815                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2816                 }
2817               else
2818                 /* do it the hard way */
2819                 while (i--)
2820                   emitcode ("inc", "sp");
2821             }
2822           else
2823             {
2824               /* not callee-saves, we can clobber r0 */
2825               emitcode ("mov", "r0,a");
2826               emitcode ("mov", "a,sp");
2827               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2828               emitcode ("mov", "sp,a");
2829               emitcode ("mov", "a,r0");
2830             }
2831         }
2832       else
2833         while (i--)
2834           emitcode ("inc", "sp");
2835     }
2836
2837   if (sym->xstack)
2838     {
2839
2840       if (!accIsFree)
2841         emitcode ("push", "acc");
2842       emitcode ("mov", "a,_spx");
2843       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2844       emitcode ("mov", "_spx,a");
2845       if (!accIsFree)
2846         emitcode ("pop", "acc");
2847     }
2848
2849   /* if critical function then turn interrupts off */
2850   if (IFFUNC_ISCRITICAL (ftype))
2851     {
2852       symbol *tlbl = newiTempLabel (NULL);
2853       emitcode ("setb", "c");
2854       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2855       emitcode ("clr", "c");
2856       emitcode ("", "%05d$:", (tlbl->key + 100));
2857       emitcode ("push", "psw"); /* save old ea via c in psw */
2858     }
2859 }
2860
2861 /*-----------------------------------------------------------------*/
2862 /* genEndFunction - generates epilogue for functions               */
2863 /*-----------------------------------------------------------------*/
2864 static void
2865 genEndFunction (iCode * ic)
2866 {
2867   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2868   lineNode *lnp = lineCurr;
2869   bitVect *regsUsed;
2870   bitVect *regsUsedPrologue;
2871   bitVect *regsUnneeded;
2872   int idx;
2873
2874   _G.currentFunc = NULL;
2875   if (IFFUNC_ISNAKED(sym->type))
2876   {
2877       emitcode(";", "naked function: no epilogue.");
2878       if (options.debug && currFunc)
2879         debugFile->writeEndFunction (currFunc, ic, 0);
2880       return;
2881   }
2882
2883   if (IFFUNC_ISCRITICAL (sym->type))
2884     {
2885       emitcode ("pop", "psw"); /* restore ea via c in psw */
2886       emitcode ("mov", "ea,c");
2887     }
2888
2889   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2890     {
2891       emitcode ("mov", "%s,_bp", spname);
2892     }
2893
2894   /* if use external stack but some variables were
2895      added to the local stack then decrement the
2896      local stack */
2897   if (options.useXstack && sym->stack)
2898     {
2899       emitcode ("mov", "a,sp");
2900       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2901       emitcode ("mov", "sp,a");
2902     }
2903
2904
2905   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2906     {
2907       if (options.useXstack)
2908         {
2909           emitcode ("mov", "r0,%s", spname);
2910           emitcode ("movx", "a,@r0");
2911           emitcode ("mov", "_bp,a");
2912           emitcode ("dec", "%s", spname);
2913         }
2914       else
2915         {
2916           emitcode ("pop", "_bp");
2917         }
2918     }
2919
2920   /* restore the register bank  */
2921   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2922   {
2923     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2924      || !options.useXstack)
2925     {
2926         /* Special case of ISR using non-zero bank with useXstack
2927          * is handled below.
2928          */
2929         emitcode ("pop", "psw");
2930     }
2931   }
2932
2933   if (IFFUNC_ISISR (sym->type))
2934     {
2935
2936       /* now we need to restore the registers */
2937       /* if this isr has no bank i.e. is going to
2938          run with bank 0 , then we need to save more
2939          registers :-) */
2940       if (!FUNC_REGBANK (sym->type))
2941         {
2942           /* if this function does not call any other
2943              function then we can be economical and
2944              save only those registers that are used */
2945           if (!IFFUNC_HASFCALL(sym->type))
2946             {
2947               int i;
2948
2949               /* if any registers used */
2950               if (sym->regsUsed)
2951                 {
2952                   /* save the registers used */
2953                   for (i = sym->regsUsed->size; i >= 0; i--)
2954                     {
2955                       if (bitVectBitValue (sym->regsUsed, i))
2956                         emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2957                     }
2958                 }
2959             }
2960           else
2961             {
2962               if (options.parms_in_bank1) {
2963                   int i;
2964                   for (i = 7 ; i >= 0 ; i-- ) {
2965                       emitcode ("pop","%s",rb1regs[i]);
2966                   }
2967               }
2968               /* this function has  a function call cannot
2969                  determines register usage so we will have to pop the
2970                  entire bank */
2971               unsaveRBank (0, ic, FALSE);
2972             }
2973         }
2974         else
2975         {
2976             /* This ISR uses a non-zero bank.
2977              *
2978              * Restore any register banks saved by genFunction
2979              * in reverse order.
2980              */
2981             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2982             int ix;
2983
2984             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2985             {
2986                 if (savedBanks & (1 << ix))
2987                 {
2988                     unsaveRBank(ix, NULL, FALSE);
2989                 }
2990             }
2991
2992             if (options.useXstack)
2993             {
2994                 /* Restore bank AFTER calling unsaveRBank,
2995                  * since it can trash r0.
2996                  */
2997                 emitcode ("pop", "psw");
2998             }
2999         }
3000
3001       if (!inExcludeList ("dph"))
3002         emitcode ("pop", "dph");
3003       if (!inExcludeList ("dpl"))
3004         emitcode ("pop", "dpl");
3005       if (!inExcludeList ("b"))
3006         emitcode ("pop", "b");
3007       if (!inExcludeList ("acc"))
3008         emitcode ("pop", "acc");
3009
3010       /* if debug then send end of function */
3011       if (options.debug && currFunc)
3012         {
3013           debugFile->writeEndFunction (currFunc, ic, 1);
3014         }
3015
3016       emitcode ("reti", "");
3017     }
3018   else
3019     {
3020       if (IFFUNC_CALLEESAVES(sym->type))
3021         {
3022           int i;
3023
3024           /* if any registers used */
3025           if (sym->regsUsed)
3026             {
3027               /* save the registers used */
3028               for (i = sym->regsUsed->size; i >= 0; i--)
3029                 {
3030                   if (bitVectBitValue (sym->regsUsed, i) ||
3031                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3032                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3033                 }
3034             }
3035           else if (mcs51_ptrRegReq)
3036             {
3037               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3038               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3039             }
3040
3041         }
3042
3043       /* if debug then send end of function */
3044       if (options.debug && currFunc)
3045         {
3046           debugFile->writeEndFunction (currFunc, ic, 1);
3047         }
3048
3049       emitcode ("ret", "");
3050     }
3051
3052   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3053     return;
3054
3055   /* If this was an interrupt handler using bank 0 that called another */
3056   /* function, then all registers must be saved; nothing to optimized. */
3057   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3058       && !FUNC_REGBANK(sym->type))
3059     return;
3060
3061   /* There are no push/pops to optimize if not callee-saves or ISR */
3062   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3063     return;
3064
3065   /* If there were stack parameters, we cannot optimize without also    */
3066   /* fixing all of the stack offsets; this is too dificult to consider. */
3067   if (FUNC_HASSTACKPARM(sym->type))
3068     return;
3069
3070   /* Compute the registers actually used */
3071   regsUsed = newBitVect (mcs51_nRegs);
3072   regsUsedPrologue = newBitVect (mcs51_nRegs);
3073   while (lnp)
3074     {
3075       if (lnp->ic && lnp->ic->op == FUNCTION)
3076         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3077       else
3078         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3079
3080       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3081           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3082         break;
3083       if (!lnp->prev)
3084         break;
3085       lnp = lnp->prev;
3086     }
3087
3088   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3089       && !bitVectBitValue (regsUsed, CND_IDX))
3090     {
3091       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3092       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3093           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3094         bitVectUnSetBit (regsUsed, CND_IDX);
3095     }
3096   else
3097     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3098
3099   /* If this was an interrupt handler that called another function */
3100   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3101   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3102     {
3103       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3104       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3105       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3106       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3107       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3108     }
3109
3110   /* Remove the unneeded push/pops */
3111   regsUnneeded = newBitVect (mcs51_nRegs);
3112   while (lnp)
3113     {
3114       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3115         {
3116           if (!strncmp(lnp->line, "push", 4))
3117             {
3118               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3119               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3120                 {
3121                   connectLine (lnp->prev, lnp->next);
3122                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3123                 }
3124             }
3125           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3126             {
3127               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3128               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3129                 {
3130                   connectLine (lnp->prev, lnp->next);
3131                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3132                 }
3133             }
3134         }
3135       lnp = lnp->next;
3136     }
3137
3138   for (idx = 0; idx < regsUnneeded->size; idx++)
3139     if (bitVectBitValue (regsUnneeded, idx))
3140       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3141
3142   freeBitVect (regsUnneeded);
3143   freeBitVect (regsUsed);
3144   freeBitVect (regsUsedPrologue);
3145 }
3146
3147 /*-----------------------------------------------------------------*/
3148 /* genRet - generate code for return statement                     */
3149 /*-----------------------------------------------------------------*/
3150 static void
3151 genRet (iCode * ic)
3152 {
3153   int size, offset = 0, pushed = 0;
3154
3155   D(emitcode (";     genRet",""));
3156
3157   /* if we have no return value then
3158      just generate the "ret" */
3159   if (!IC_LEFT (ic))
3160     goto jumpret;
3161
3162   /* we have something to return then
3163      move the return value into place */
3164   aopOp (IC_LEFT (ic), ic, FALSE);
3165   size = AOP_SIZE (IC_LEFT (ic));
3166
3167   while (size--)
3168     {
3169       char *l;
3170       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3171         {
3172           /* #NOCHANGE */
3173           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3174                       FALSE, TRUE);
3175           emitcode ("push", "%s", l);
3176           pushed++;
3177         }
3178       else
3179         {
3180           l = aopGet (AOP (IC_LEFT (ic)), offset,
3181                       FALSE, FALSE);
3182           if (strcmp (fReturn[offset], l))
3183             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3184         }
3185     }
3186
3187   if (pushed)
3188     {
3189       while (pushed)
3190         {
3191           pushed--;
3192           if (strcmp (fReturn[pushed], "a"))
3193             emitcode ("pop", fReturn[pushed]);
3194           else
3195             emitcode ("pop", "acc");
3196         }
3197     }
3198   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3199
3200 jumpret:
3201   /* generate a jump to the return label
3202      if the next is not the return statement */
3203   if (!(ic->next && ic->next->op == LABEL &&
3204         IC_LABEL (ic->next) == returnLabel))
3205
3206     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3207
3208 }
3209
3210 /*-----------------------------------------------------------------*/
3211 /* genLabel - generates a label                                    */
3212 /*-----------------------------------------------------------------*/
3213 static void
3214 genLabel (iCode * ic)
3215 {
3216   /* special case never generate */
3217   if (IC_LABEL (ic) == entryLabel)
3218     return;
3219
3220   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /* genGoto - generates a ljmp                                      */
3225 /*-----------------------------------------------------------------*/
3226 static void
3227 genGoto (iCode * ic)
3228 {
3229   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3230 }
3231
3232 /*-----------------------------------------------------------------*/
3233 /* findLabelBackwards: walks back through the iCode chain looking  */
3234 /* for the given label. Returns number of iCode instructions     */
3235 /* between that label and given ic.          */
3236 /* Returns zero if label not found.          */
3237 /*-----------------------------------------------------------------*/
3238 static int
3239 findLabelBackwards (iCode * ic, int key)
3240 {
3241   int count = 0;
3242
3243   while (ic->prev)
3244     {
3245       ic = ic->prev;
3246       count++;
3247
3248       /* If we have any pushes or pops, we cannot predict the distance.
3249          I don't like this at all, this should be dealt with in the
3250          back-end */
3251       if (ic->op == IPUSH || ic->op == IPOP) {
3252         return 0;
3253       }
3254
3255       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3256         {
3257           return count;
3258         }
3259     }
3260
3261   return 0;
3262 }
3263
3264 /*-----------------------------------------------------------------*/
3265 /* genPlusIncr :- does addition with increment if possible         */
3266 /*-----------------------------------------------------------------*/
3267 static bool
3268 genPlusIncr (iCode * ic)
3269 {
3270   unsigned int icount;
3271   unsigned int size = getDataSize (IC_RESULT (ic));
3272
3273   /* will try to generate an increment */
3274   /* if the right side is not a literal
3275      we cannot */
3276   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3277     return FALSE;
3278
3279   /* if the literal value of the right hand side
3280      is greater than 4 then it is not worth it */
3281   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3282     return FALSE;
3283
3284   D(emitcode (";     genPlusIncr",""));
3285
3286   /* if increment >=16 bits in register or direct space */
3287   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3288       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3289       (size > 1) &&
3290       (icount == 1))
3291     {
3292       symbol *tlbl;
3293       int emitTlbl;
3294       int labelRange;
3295
3296       /* If the next instruction is a goto and the goto target
3297        * is < 10 instructions previous to this, we can generate
3298        * jumps straight to that target.
3299        */
3300       if (ic->next && ic->next->op == GOTO
3301           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3302           && labelRange <= 10)
3303         {
3304           emitcode (";", "tail increment optimized");
3305           tlbl = IC_LABEL (ic->next);
3306           emitTlbl = 0;
3307         }
3308       else
3309         {
3310           tlbl = newiTempLabel (NULL);
3311           emitTlbl = 1;
3312         }
3313       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3314       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3315           IS_AOP_PREG (IC_RESULT (ic)))
3316         emitcode ("cjne", "%s,#0x00,%05d$",
3317                   aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3318                   tlbl->key + 100);
3319       else
3320         {
3321           emitcode ("clr", "a");
3322           emitcode ("cjne", "a,%s,%05d$",
3323                     aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3324                     tlbl->key + 100);
3325         }
3326
3327       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3328       if (size > 2)
3329         {
3330           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3331               IS_AOP_PREG (IC_RESULT (ic)))
3332             emitcode ("cjne", "%s,#0x00,%05d$",
3333                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3334                       tlbl->key + 100);
3335           else
3336             emitcode ("cjne", "a,%s,%05d$",
3337                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3338                       tlbl->key + 100);
3339
3340           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3341         }
3342       if (size > 3)
3343         {
3344           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3345               IS_AOP_PREG (IC_RESULT (ic)))
3346             emitcode ("cjne", "%s,#0x00,%05d$",
3347                       aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3348                       tlbl->key + 100);
3349           else
3350             {
3351               emitcode ("cjne", "a,%s,%05d$",
3352                         aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3353                         tlbl->key + 100);
3354             }
3355           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3356         }
3357
3358       if (emitTlbl)
3359         {
3360           emitcode ("", "%05d$:", tlbl->key + 100);
3361         }
3362       return TRUE;
3363     }
3364
3365   /* if the sizes are greater than 1 then we cannot */
3366   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3367       AOP_SIZE (IC_LEFT (ic)) > 1)
3368     return FALSE;
3369
3370   /* we can if the aops of the left & result match or
3371      if they are in registers and the registers are the
3372      same */
3373   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3374     {
3375
3376       if (icount > 3)
3377         {
3378           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3379           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3380           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3381         }
3382       else
3383         {
3384
3385           while (icount--)
3386             emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3387         }
3388
3389       return TRUE;
3390     }
3391
3392   return FALSE;
3393 }
3394
3395 /*-----------------------------------------------------------------*/
3396 /* outBitAcc - output a bit in acc                                 */
3397 /*-----------------------------------------------------------------*/
3398 static void
3399 outBitAcc (operand * result)
3400 {
3401   symbol *tlbl = newiTempLabel (NULL);
3402   /* if the result is a bit */
3403   if (AOP_TYPE (result) == AOP_CRY)
3404     {
3405       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3406     }
3407   else
3408     {
3409       emitcode ("jz", "%05d$", tlbl->key + 100);
3410       emitcode ("mov", "a,%s", one);
3411       emitcode ("", "%05d$:", tlbl->key + 100);
3412       outAcc (result);
3413     }
3414 }
3415
3416 /*-----------------------------------------------------------------*/
3417 /* genPlusBits - generates code for addition of two bits           */
3418 /*-----------------------------------------------------------------*/
3419 static void
3420 genPlusBits (iCode * ic)
3421 {
3422   D(emitcode (";     genPlusBits",""));
3423
3424   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3425     {
3426       symbol *lbl = newiTempLabel (NULL);
3427       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3428       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3429       emitcode ("cpl", "c");
3430       emitcode ("", "%05d$:", (lbl->key + 100));
3431       outBitC (IC_RESULT (ic));
3432     }
3433   else
3434     {
3435       emitcode ("clr", "a");
3436       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3437       emitcode ("rlc", "a");
3438       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3439       emitcode ("addc", "a,#0x00");
3440       outAcc (IC_RESULT (ic));
3441     }
3442 }
3443
3444 #if 0
3445 /* This is the original version of this code.
3446
3447  * This is being kept around for reference,
3448  * because I am not entirely sure I got it right...
3449  */
3450 static void
3451 adjustArithmeticResult (iCode * ic)
3452 {
3453   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3454       AOP_SIZE (IC_LEFT (ic)) == 3 &&
3455       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3456     aopPut (AOP (IC_RESULT (ic)),
3457             aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3458             2,
3459             isOperandVolatile (IC_RESULT (ic), FALSE));
3460
3461   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3462       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3463       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3464     aopPut (AOP (IC_RESULT (ic)),
3465             aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3466             2,
3467             isOperandVolatile (IC_RESULT (ic), FALSE));
3468
3469   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3470       AOP_SIZE (IC_LEFT (ic)) < 3 &&
3471       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3472       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3473       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3474     {
3475       char buffer[5];
3476       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3477       aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3478     }
3479 }
3480 #else
3481 /* This is the pure and virtuous version of this code.
3482  * I'm pretty certain it's right, but not enough to toss the old
3483  * code just yet...
3484  */
3485 static void
3486 adjustArithmeticResult (iCode * ic)
3487 {
3488   if (opIsGptr (IC_RESULT (ic)) &&
3489       opIsGptr (IC_LEFT (ic)) &&
3490       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3491     {
3492       aopPut (AOP (IC_RESULT (ic)),
3493               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3494               GPTRSIZE - 1,
3495               isOperandVolatile (IC_RESULT (ic), FALSE));
3496     }
3497
3498   if (opIsGptr (IC_RESULT (ic)) &&
3499       opIsGptr (IC_RIGHT (ic)) &&
3500       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3501     {
3502       aopPut (AOP (IC_RESULT (ic)),
3503               aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3504               GPTRSIZE - 1,
3505               isOperandVolatile (IC_RESULT (ic), FALSE));
3506     }
3507
3508   if (opIsGptr (IC_RESULT (ic)) &&
3509       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3510       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3511       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3512       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3513     {
3514       char buffer[5];
3515       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3516       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3517     }
3518 }
3519 #endif
3520
3521 /*-----------------------------------------------------------------*/
3522 /* genPlus - generates code for addition                           */
3523 /*-----------------------------------------------------------------*/
3524 static void
3525 genPlus (iCode * ic)
3526 {
3527   int size, offset = 0;
3528   int skip_bytes = 0;
3529   char *add = "add";
3530   asmop *leftOp, *rightOp;
3531   operand * op;
3532
3533   /* special cases :- */
3534
3535   D(emitcode (";     genPlus",""));
3536
3537   aopOp (IC_LEFT (ic), ic, FALSE);
3538   aopOp (IC_RIGHT (ic), ic, FALSE);
3539   aopOp (IC_RESULT (ic), ic, TRUE);
3540
3541   /* if literal, literal on the right or
3542      if left requires ACC or right is already
3543      in ACC */
3544   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3545       (AOP_NEEDSACC (IC_LEFT (ic))) ||
3546       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3547     {
3548       operand *t = IC_RIGHT (ic);
3549       IC_RIGHT (ic) = IC_LEFT (ic);
3550       IC_LEFT (ic) = t;
3551     }
3552
3553   /* if both left & right are in bit
3554      space */
3555   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3556       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3557     {
3558       genPlusBits (ic);
3559       goto release;
3560     }
3561
3562   /* if left in bit space & right literal */
3563   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3564       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3565     {
3566       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3567       /* if result in bit space */
3568       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3569         {
3570           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3571             emitcode ("cpl", "c");
3572           outBitC (IC_RESULT (ic));
3573         }
3574       else
3575         {
3576           size = getDataSize (IC_RESULT (ic));
3577           while (size--)
3578             {
3579               MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3580               emitcode ("addc", "a,#00");
3581               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3582             }
3583         }
3584       goto release;
3585     }
3586
3587   /* if I can do an increment instead
3588      of add then GOOD for ME */
3589   if (genPlusIncr (ic) == TRUE)
3590     goto release;
3591
3592   size = getDataSize (IC_RESULT (ic));
3593   leftOp = AOP(IC_LEFT(ic));
3594   rightOp = AOP(IC_RIGHT(ic));
3595   op=IC_LEFT(ic);
3596
3597   /* if this is an add for an array access
3598      at a 256 byte boundary */
3599   if ( 2 == size
3600        && AOP_TYPE (op) == AOP_IMMD
3601        && IS_SYMOP (op)
3602        && IS_SPEC (OP_SYM_ETYPE (op))
3603        && SPEC_ABSA (OP_SYM_ETYPE (op))
3604        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3605      )
3606     {
3607       D(emitcode (";     genPlus aligned array",""));
3608       aopPut (AOP (IC_RESULT (ic)),
3609               aopGet (rightOp, 0, FALSE, FALSE),
3610               0,
3611               isOperandVolatile (IC_RESULT (ic), FALSE));
3612
3613       if( 1 == getDataSize (IC_RIGHT (ic)) )
3614         {
3615           aopPut (AOP (IC_RESULT (ic)),
3616                   aopGet (leftOp, 1, FALSE, FALSE),
3617                   1,
3618                   isOperandVolatile (IC_RESULT (ic), FALSE));
3619         }
3620       else
3621         {
3622           MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3623           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3624           aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3625         }
3626       goto release;
3627     }
3628
3629   /* if the lower bytes of a literal are zero skip the addition */
3630   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3631     {
3632        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3633               (skip_bytes+1 < size))
3634          {
3635            skip_bytes++;
3636          }
3637        if (skip_bytes)
3638          D(emitcode (";     genPlus shortcut",""));
3639     }
3640
3641   while (size--)
3642     {
3643       if( offset >= skip_bytes )
3644         {
3645           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3646             {
3647               emitcode("mov", "b,a");
3648               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
3649               emitcode("xch", "a,b");
3650               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3651               emitcode (add, "a,b");
3652             }
3653           else if (aopGetUsesAcc (leftOp, offset))
3654             {
3655               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3656               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3657             }
3658           else
3659             {
3660               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3661               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3662             }
3663           aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3664           add = "addc";  /* further adds must propagate carry */
3665         }
3666       else
3667         {
3668           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3669               isOperandVolatile (IC_RESULT (ic), FALSE))
3670             {
3671               /* just move */
3672               aopPut (AOP (IC_RESULT (ic)),
3673                       aopGet (leftOp, offset, FALSE, FALSE),
3674                       offset,
3675                       isOperandVolatile (IC_RESULT (ic), FALSE));
3676             }
3677         }
3678       offset++;
3679     }
3680
3681   adjustArithmeticResult (ic);
3682
3683 release:
3684   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3685   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3686   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3687 }
3688
3689 /*-----------------------------------------------------------------*/
3690 /* genMinusDec :- does subtraction with deccrement if possible     */
3691 /*-----------------------------------------------------------------*/
3692 static bool
3693 genMinusDec (iCode * ic)
3694 {
3695   unsigned int icount;
3696   unsigned int size = getDataSize (IC_RESULT (ic));
3697
3698   /* will try to generate an increment */
3699   /* if the right side is not a literal
3700      we cannot */
3701   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3702     return FALSE;
3703
3704   /* if the literal value of the right hand side
3705      is greater than 4 then it is not worth it */
3706   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3707     return FALSE;
3708
3709   D(emitcode (";     genMinusDec",""));
3710
3711   /* if decrement >=16 bits in register or direct space */
3712   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3713       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3714       (size > 1) &&
3715       (icount == 1))
3716     {
3717       symbol *tlbl;
3718       int emitTlbl;
3719       int labelRange;
3720
3721       /* If the next instruction is a goto and the goto target
3722        * is <= 10 instructions previous to this, we can generate
3723        * jumps straight to that target.
3724        */
3725       if (ic->next && ic->next->op == GOTO
3726           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3727           && labelRange <= 10)
3728         {
3729           emitcode (";", "tail decrement optimized");
3730           tlbl = IC_LABEL (ic->next);
3731           emitTlbl = 0;
3732         }
3733       else
3734         {
3735           tlbl = newiTempLabel (NULL);
3736           emitTlbl = 1;
3737         }
3738
3739       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3740       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3741           IS_AOP_PREG (IC_RESULT (ic)))
3742         emitcode ("cjne", "%s,#0xff,%05d$"
3743                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3744                   ,tlbl->key + 100);
3745       else
3746         {
3747           emitcode ("mov", "a,#0xff");
3748           emitcode ("cjne", "a,%s,%05d$"
3749                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3750                     ,tlbl->key + 100);
3751         }
3752       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3753       if (size > 2)
3754         {
3755           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3756               IS_AOP_PREG (IC_RESULT (ic)))
3757             emitcode ("cjne", "%s,#0xff,%05d$"
3758                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3759                       ,tlbl->key + 100);
3760           else
3761             {
3762               emitcode ("cjne", "a,%s,%05d$"
3763                         ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3764                         ,tlbl->key + 100);
3765             }
3766           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3767         }
3768       if (size > 3)
3769         {
3770           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3771               IS_AOP_PREG (IC_RESULT (ic)))
3772             emitcode ("cjne", "%s,#0xff,%05d$"
3773                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3774                       ,tlbl->key + 100);
3775           else
3776             {
3777               emitcode ("cjne", "a,%s,%05d$"
3778                         ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3779                         ,tlbl->key + 100);
3780             }
3781           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3782         }
3783       if (emitTlbl)
3784         {
3785           emitcode ("", "%05d$:", tlbl->key + 100);
3786         }
3787       return TRUE;
3788     }
3789
3790   /* if the sizes are greater than 1 then we cannot */
3791   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3792       AOP_SIZE (IC_LEFT (ic)) > 1)
3793     return FALSE;
3794
3795   /* we can if the aops of the left & result match or
3796      if they are in registers and the registers are the
3797      same */
3798   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3799     {
3800
3801       while (icount--)
3802         emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3803
3804       return TRUE;
3805     }
3806
3807   return FALSE;
3808 }
3809
3810 /*-----------------------------------------------------------------*/
3811 /* addSign - complete with sign                                    */
3812 /*-----------------------------------------------------------------*/
3813 static void
3814 addSign (operand * result, int offset, int sign)
3815 {
3816   int size = (getDataSize (result) - offset);
3817   if (size > 0)
3818     {
3819       if (sign)
3820         {
3821           emitcode ("rlc", "a");
3822           emitcode ("subb", "a,acc");
3823           while (size--)
3824             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3825         }
3826       else
3827         while (size--)
3828           aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3829     }
3830 }
3831
3832 /*-----------------------------------------------------------------*/
3833 /* genMinusBits - generates code for subtraction  of two bits      */
3834 /*-----------------------------------------------------------------*/
3835 static void
3836 genMinusBits (iCode * ic)
3837 {
3838   symbol *lbl = newiTempLabel (NULL);
3839
3840   D(emitcode (";     genMinusBits",""));
3841
3842   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3843     {
3844       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3845       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3846       emitcode ("cpl", "c");
3847       emitcode ("", "%05d$:", (lbl->key + 100));
3848       outBitC (IC_RESULT (ic));
3849     }
3850   else
3851     {
3852       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3853       emitcode ("subb", "a,acc");
3854       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3855       emitcode ("inc", "a");
3856       emitcode ("", "%05d$:", (lbl->key + 100));
3857       aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3858       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3859     }
3860 }
3861
3862 /*-----------------------------------------------------------------*/
3863 /* genMinus - generates code for subtraction                       */
3864 /*-----------------------------------------------------------------*/
3865 static void
3866 genMinus (iCode * ic)
3867 {
3868   int size, offset = 0;
3869
3870   D(emitcode (";     genMinus",""));
3871
3872   aopOp (IC_LEFT (ic), ic, FALSE);
3873   aopOp (IC_RIGHT (ic), ic, FALSE);
3874   aopOp (IC_RESULT (ic), ic, TRUE);
3875
3876   /* special cases :- */
3877   /* if both left & right are in bit space */
3878   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3879       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3880     {
3881       genMinusBits (ic);
3882       goto release;
3883     }
3884
3885   /* if I can do an decrement instead
3886      of subtract then GOOD for ME */
3887   if (genMinusDec (ic) == TRUE)
3888     goto release;
3889
3890   size = getDataSize (IC_RESULT (ic));
3891
3892   /* if literal, add a,#-lit, else normal subb */
3893   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3894     {
3895       unsigned long lit = 0L;
3896
3897       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3898       lit = -(long) lit;
3899
3900       while (size--)
3901         {
3902           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3903           /* first add without previous c */
3904           if (!offset) {
3905             if (!size && lit== (unsigned long) -1) {
3906               emitcode ("dec", "a");
3907             } else {
3908               emitcode ("add", "a,#0x%02x",
3909                         (unsigned int) (lit & 0x0FFL));
3910             }
3911           } else {
3912             emitcode ("addc", "a,#0x%02x",
3913                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3914           }
3915           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3916         }
3917     }
3918   else
3919     {
3920       asmop *leftOp, *rightOp;
3921
3922       leftOp = AOP(IC_LEFT(ic));
3923       rightOp = AOP(IC_RIGHT(ic));
3924
3925       while (size--)
3926         {
3927           if (aopGetUsesAcc(rightOp, offset)) {
3928             wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3929             MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3930             if (offset == 0) {
3931               emitcode( "setb", "c");
3932             }
3933             emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3934             emitcode("cpl", "a");
3935           } else {
3936             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3937             if (offset == 0)
3938               CLRC;
3939             emitcode ("subb", "a,%s",
3940                       aopGet(rightOp, offset, FALSE, TRUE));
3941           }
3942
3943           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3944         }
3945     }
3946
3947
3948   adjustArithmeticResult (ic);
3949
3950 release:
3951   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3952   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3953   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3954 }
3955
3956
3957 /*-----------------------------------------------------------------*/
3958 /* genMultbits :- multiplication of bits                           */
3959 /*-----------------------------------------------------------------*/
3960 static void
3961 genMultbits (operand * left,
3962              operand * right,
3963              operand * result)
3964 {
3965   D(emitcode (";     genMultbits",""));
3966
3967   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3968   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3969   outBitC (result);
3970 }
3971
3972 /*-----------------------------------------------------------------*/
3973 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3974 /*-----------------------------------------------------------------*/
3975 static void
3976 genMultOneByte (operand * left,
3977                 operand * right,
3978                 operand * result)
3979 {
3980   symbol *lbl;
3981   int size = AOP_SIZE (result);
3982   bool runtimeSign, compiletimeSign;
3983   bool lUnsigned, rUnsigned;
3984
3985   D(emitcode (";     genMultOneByte",""));
3986
3987   if (size < 1 || size > 2)
3988     {
3989       /* this should never happen */
3990       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3991                AOP_SIZE(result), __FILE__, lineno);
3992       exit (1);
3993     }
3994
3995   /* (if two literals: the value is computed before) */
3996   /* if one literal, literal on the right */
3997   if (AOP_TYPE (left) == AOP_LIT)
3998     {
3999       operand *t = right;
4000       right = left;
4001       left = t;
4002       /* emitcode (";", "swapped left and right"); */
4003     }
4004   /* if no literal, unsigned on the right: shorter code */
4005   if (   AOP_TYPE (right) != AOP_LIT
4006       && SPEC_USIGN (getSpec (operandType (left))))
4007     {
4008       operand *t = right;
4009       right = left;
4010       left = t;
4011     }
4012
4013   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4014   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4015
4016   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4017                    no need to take care about the signedness! */
4018       || (lUnsigned && rUnsigned))
4019     {
4020       /* just an unsigned 8 * 8 = 8 multiply
4021          or 8u * 8u = 16u */
4022       /* emitcode (";","unsigned"); */
4023       /* TODO: check for accumulator clash between left & right aops? */
4024
4025       if (AOP_TYPE (right) == AOP_LIT)
4026         {
4027           /* moving to accumulator first helps peepholes */
4028           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4029           emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4030         }
4031       else
4032         {
4033           emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4034           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4035         }
4036
4037       emitcode ("mul", "ab");
4038       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4039       if (size == 2)
4040         aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4041       return;
4042     }
4043
4044   /* we have to do a signed multiply */
4045   /* emitcode (";", "signed"); */
4046
4047   /* now sign adjust for both left & right */
4048
4049   /* let's see what's needed: */
4050   /* apply negative sign during runtime */
4051   runtimeSign = FALSE;
4052   /* negative sign from literals */
4053   compiletimeSign = FALSE;
4054
4055   if (!lUnsigned)
4056     {
4057       if (AOP_TYPE(left) == AOP_LIT)
4058         {
4059           /* signed literal */
4060           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4061           if (val < 0)
4062             compiletimeSign = TRUE;
4063         }
4064       else
4065         /* signed but not literal */
4066         runtimeSign = TRUE;
4067     }
4068
4069   if (!rUnsigned)
4070     {
4071       if (AOP_TYPE(right) == AOP_LIT)
4072         {
4073           /* signed literal */
4074           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4075           if (val < 0)
4076             compiletimeSign ^= TRUE;
4077         }
4078       else
4079         /* signed but not literal */
4080         runtimeSign = TRUE;
4081     }
4082
4083   /* initialize F0, which stores the runtime sign */
4084   if (runtimeSign)
4085     {
4086       if (compiletimeSign)
4087         emitcode ("setb", "F0"); /* set sign flag */
4088       else
4089         emitcode ("clr", "F0"); /* reset sign flag */
4090     }
4091
4092   /* save the signs of the operands */
4093   if (AOP_TYPE(right) == AOP_LIT)
4094     {
4095       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4096
4097       if (!rUnsigned && val < 0)
4098         emitcode ("mov", "b,#0x%02x", -val);
4099       else
4100         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4101     }
4102   else /* ! literal */
4103     {
4104       if (rUnsigned)  /* emitcode (";", "signed"); */
4105
4106         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4107       else
4108         {
4109           MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4110           lbl = newiTempLabel (NULL);
4111           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4112           emitcode ("cpl", "F0"); /* complement sign flag */
4113           emitcode ("cpl", "a");  /* 2's complement */
4114           emitcode ("inc", "a");
4115           emitcode ("", "%05d$:", (lbl->key + 100));
4116           emitcode ("mov", "b,a");
4117         }
4118     }
4119
4120   if (AOP_TYPE(left) == AOP_LIT)
4121     {
4122       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4123
4124       if (!lUnsigned && val < 0)
4125         emitcode ("mov", "a,#0x%02x", -val);
4126       else
4127         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4128     }
4129   else /* ! literal */
4130     {
4131       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4132
4133       if (!lUnsigned)
4134         {
4135           lbl = newiTempLabel (NULL);
4136           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4137           emitcode ("cpl", "F0"); /* complement sign flag */
4138           emitcode ("cpl", "a"); /* 2's complement */
4139           emitcode ("inc", "a");
4140           emitcode ("", "%05d$:", (lbl->key + 100));
4141         }
4142     }
4143
4144   /* now the multiplication */
4145   emitcode ("mul", "ab");
4146   if (runtimeSign || compiletimeSign)
4147     {
4148       lbl = newiTempLabel (NULL);
4149       if (runtimeSign)
4150         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4151       emitcode ("cpl", "a"); /* lsb 2's complement */
4152       if (size != 2)
4153         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4154       else
4155         {
4156           emitcode ("add", "a,#1"); /* this sets carry flag */
4157           emitcode ("xch", "a,b");
4158           emitcode ("cpl", "a"); /* msb 2's complement */
4159           emitcode ("addc", "a,#0");
4160           emitcode ("xch", "a,b");
4161         }
4162       emitcode ("", "%05d$:", (lbl->key + 100));
4163     }
4164   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4165   if (size == 2)
4166     aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4167 }
4168
4169 /*-----------------------------------------------------------------*/
4170 /* genMult - generates code for multiplication                     */
4171 /*-----------------------------------------------------------------*/
4172 static void
4173 genMult (iCode * ic)
4174 {
4175   operand *left = IC_LEFT (ic);
4176   operand *right = IC_RIGHT (ic);
4177   operand *result = IC_RESULT (ic);
4178
4179   D(emitcode (";     genMult",""));
4180
4181   /* assign the amsops */
4182   aopOp (left, ic, FALSE);
4183   aopOp (right, ic, FALSE);
4184   aopOp (result, ic, TRUE);
4185
4186   /* special cases first */
4187   /* both are bits */
4188   if (AOP_TYPE (left) == AOP_CRY &&
4189       AOP_TYPE (right) == AOP_CRY)
4190     {
4191       genMultbits (left, right, result);
4192       goto release;
4193     }
4194
4195   /* if both are of size == 1 */
4196 #if 0 // one of them can be a sloc shared with the result
4197     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4198 #else
4199   if (getSize(operandType(left)) == 1 &&
4200       getSize(operandType(right)) == 1)
4201 #endif
4202     {
4203       genMultOneByte (left, right, result);
4204       goto release;
4205     }
4206
4207   /* should have been converted to function call */
4208     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4209              getSize(OP_SYMBOL(right)->type));
4210   assert (0);
4211
4212 release:
4213   freeAsmop (result, NULL, ic, TRUE);
4214   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4215   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4216 }
4217
4218 /*-----------------------------------------------------------------*/
4219 /* genDivbits :- division of bits                                  */
4220 /*-----------------------------------------------------------------*/
4221 static void
4222 genDivbits (operand * left,
4223             operand * right,
4224             operand * result)
4225 {
4226
4227   char *l;
4228
4229   D(emitcode (";     genDivbits",""));
4230
4231   /* the result must be bit */
4232   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4233   l = aopGet (AOP (left), 0, FALSE, FALSE);
4234
4235   MOVA (l);
4236
4237   emitcode ("div", "ab");
4238   emitcode ("rrc", "a");
4239   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4240 }
4241
4242 /*-----------------------------------------------------------------*/
4243 /* genDivOneByte : 8 bit division                                  */
4244 /*-----------------------------------------------------------------*/
4245 static void
4246 genDivOneByte (operand * left,
4247                operand * right,
4248                operand * result)
4249 {
4250   bool lUnsigned, rUnsigned;
4251   bool runtimeSign, compiletimeSign;
4252   symbol *lbl;
4253   int size, offset;
4254
4255   D(emitcode (";     genDivOneByte",""));
4256
4257   /* Why is it necessary that genDivOneByte() can return an int result?
4258      Have a look at:
4259
4260         volatile unsigned char uc;
4261         volatile signed char sc1, sc2;
4262         volatile int i;
4263
4264         uc  = 255;
4265         sc1 = -1;
4266         i = uc / sc1;
4267
4268      Or:
4269
4270         sc1 = -128;
4271         sc2 = -1;
4272         i = sc1 / sc2;
4273
4274      In all cases a one byte result would overflow, the following cast to int
4275      would return the wrong result.
4276
4277      Two possible solution:
4278         a) cast operands to int, if ((unsigned) / (signed)) or
4279            ((signed) / (signed))
4280         b) return an 16 bit signed int; this is what we're doing here!
4281   */
4282
4283   size = AOP_SIZE (result) - 1;
4284   offset = 1;
4285   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4286   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4287
4288   /* signed or unsigned */
4289   if (lUnsigned && rUnsigned)
4290     {
4291       /* unsigned is easy */
4292       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4293       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4294       emitcode ("div", "ab");
4295       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4296       while (size--)
4297         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4298       return;
4299     }
4300
4301   /* signed is a little bit more difficult */
4302
4303   /* now sign adjust for both left & right */
4304
4305   /* let's see what's needed: */
4306   /* apply negative sign during runtime */
4307   runtimeSign = FALSE;
4308   /* negative sign from literals */
4309   compiletimeSign = FALSE;
4310
4311   if (!lUnsigned)
4312     {
4313       if (AOP_TYPE(left) == AOP_LIT)
4314         {
4315           /* signed literal */
4316           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4317           if (val < 0)
4318             compiletimeSign = TRUE;
4319         }
4320       else
4321         /* signed but not literal */
4322         runtimeSign = TRUE;
4323     }
4324
4325   if (!rUnsigned)
4326     {
4327       if (AOP_TYPE(right) == AOP_LIT)
4328         {
4329           /* signed literal */
4330           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4331           if (val < 0)
4332             compiletimeSign ^= TRUE;
4333         }
4334       else
4335         /* signed but not literal */
4336         runtimeSign = TRUE;
4337     }
4338
4339   /* initialize F0, which stores the runtime sign */
4340   if (runtimeSign)
4341     {
4342       if (compiletimeSign)
4343         emitcode ("setb", "F0"); /* set sign flag */
4344       else
4345         emitcode ("clr", "F0"); /* reset sign flag */
4346     }
4347
4348   /* save the signs of the operands */
4349   if (AOP_TYPE(right) == AOP_LIT)
4350     {
4351       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4352
4353       if (!rUnsigned && val < 0)
4354         emitcode ("mov", "b,#0x%02x", -val);
4355       else
4356         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4357     }
4358   else /* ! literal */
4359     {
4360       if (rUnsigned)
4361         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4362       else
4363         {
4364           MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4365           lbl = newiTempLabel (NULL);
4366           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4367           emitcode ("cpl", "F0"); /* complement sign flag */
4368           emitcode ("cpl", "a");  /* 2's complement */
4369           emitcode ("inc", "a");
4370           emitcode ("", "%05d$:", (lbl->key + 100));
4371           emitcode ("mov", "b,a");
4372         }
4373     }
4374
4375   if (AOP_TYPE(left) == AOP_LIT)
4376     {
4377       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4378
4379       if (!lUnsigned && val < 0)
4380         emitcode ("mov", "a,#0x%02x", -val);
4381       else
4382         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4383     }
4384   else /* ! literal */
4385     {
4386       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4387
4388       if (!lUnsigned)
4389         {
4390           lbl = newiTempLabel (NULL);
4391           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4392           emitcode ("cpl", "F0"); /* complement sign flag */
4393           emitcode ("cpl", "a");  /* 2's complement */
4394           emitcode ("inc", "a");
4395           emitcode ("", "%05d$:", (lbl->key + 100));
4396         }
4397     }
4398
4399   /* now the division */
4400   emitcode ("div", "ab");
4401
4402   if (runtimeSign || compiletimeSign)
4403     {
4404       lbl = newiTempLabel (NULL);
4405       if (runtimeSign)
4406         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4407       emitcode ("cpl", "a"); /* lsb 2's complement */
4408       emitcode ("inc", "a");
4409       emitcode ("", "%05d$:", (lbl->key + 100));
4410
4411       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4412       if (size > 0)
4413         {
4414           /* msb is 0x00 or 0xff depending on the sign */
4415           if (runtimeSign)
4416             {
4417               emitcode ("mov", "c,F0");
4418               emitcode ("subb", "a,acc");
4419               while (size--)
4420                 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4421             }
4422           else /* compiletimeSign */
4423             while (size--)
4424               aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4425         }
4426     }
4427   else
4428     {
4429       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4430       while (size--)
4431         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4432     }
4433 }
4434
4435 /*-----------------------------------------------------------------*/
4436 /* genDiv - generates code for division                            */
4437 /*-----------------------------------------------------------------*/
4438 static void
4439 genDiv (iCode * ic)
4440 {
4441   operand *left = IC_LEFT (ic);
4442   operand *right = IC_RIGHT (ic);
4443   operand *result = IC_RESULT (ic);
4444
4445   D(emitcode (";     genDiv",""));
4446
4447   /* assign the amsops */
4448   aopOp (left, ic, FALSE);
4449   aopOp (right, ic, FALSE);
4450   aopOp (result, ic, TRUE);
4451
4452   /* special cases first */
4453   /* both are bits */
4454   if (AOP_TYPE (left) == AOP_CRY &&
4455       AOP_TYPE (right) == AOP_CRY)
4456     {
4457       genDivbits (left, right, result);
4458       goto release;
4459     }
4460
4461   /* if both are of size == 1 */
4462   if (AOP_SIZE (left) == 1 &&
4463       AOP_SIZE (right) == 1)
4464     {
4465       genDivOneByte (left, right, result);
4466       goto release;
4467     }
4468
4469   /* should have been converted to function call */
4470   assert (0);
4471 release:
4472   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4474   freeAsmop (result, NULL, ic, TRUE);
4475 }
4476
4477 /*-----------------------------------------------------------------*/
4478 /* genModbits :- modulus of bits                                   */
4479 /*-----------------------------------------------------------------*/
4480 static void
4481 genModbits (operand * left,
4482             operand * right,
4483             operand * result)
4484 {
4485
4486   char *l;
4487
4488   D(emitcode (";     genModbits",""));
4489
4490   /* the result must be bit */
4491   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4492   l = aopGet (AOP (left), 0, FALSE, FALSE);
4493
4494   MOVA (l);
4495
4496   emitcode ("div", "ab");
4497   emitcode ("mov", "a,b");
4498   emitcode ("rrc", "a");
4499   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4500 }
4501
4502 /*-----------------------------------------------------------------*/
4503 /* genModOneByte : 8 bit modulus                                   */
4504 /*-----------------------------------------------------------------*/
4505 static void
4506 genModOneByte (operand * left,
4507                operand * right,
4508                operand * result)
4509 {
4510   bool lUnsigned, rUnsigned;
4511   bool runtimeSign, compiletimeSign;
4512   symbol *lbl;
4513   int size, offset;
4514
4515   D(emitcode (";     genModOneByte",""));
4516
4517   size = AOP_SIZE (result) - 1;
4518   offset = 1;
4519   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4520   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4521
4522   /* signed or unsigned */
4523   if (lUnsigned && rUnsigned)
4524     {
4525       /* unsigned is easy */
4526       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4527       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4528       emitcode ("div", "ab");
4529       aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4530       while (size--)
4531         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4532       return;
4533     }
4534
4535   /* signed is a little bit more difficult */
4536
4537   /* now sign adjust for both left & right */
4538
4539   /* modulus: sign of the right operand has no influence on the result! */
4540   if (AOP_TYPE(right) == AOP_LIT)
4541     {
4542       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4543
4544       if (!rUnsigned && val < 0)
4545         emitcode ("mov", "b,#0x%02x", -val);
4546       else
4547         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4548     }
4549   else /* not literal */
4550     {
4551       if (rUnsigned)
4552         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4553       else
4554         {
4555           MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4556           lbl = newiTempLabel (NULL);
4557           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4558           emitcode ("cpl", "a"); /* 2's complement */
4559           emitcode ("inc", "a");
4560           emitcode ("", "%05d$:", (lbl->key + 100));
4561           emitcode ("mov", "b,a");
4562         }
4563     }
4564
4565   /* let's see what's needed: */
4566   /* apply negative sign during runtime */
4567   runtimeSign = FALSE;
4568   /* negative sign from literals */
4569   compiletimeSign = FALSE;
4570
4571   /* sign adjust left side */
4572   if (AOP_TYPE(left) == AOP_LIT)
4573     {
4574       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4575
4576       if (!lUnsigned && val < 0)
4577         {
4578           compiletimeSign = TRUE; /* set sign flag */
4579           emitcode ("mov", "a,#0x%02x", -val);
4580         }
4581       else
4582         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4583     }
4584   else /* ! literal */
4585     {
4586       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4587
4588       if (!lUnsigned)
4589         {
4590           runtimeSign = TRUE;
4591           emitcode ("clr", "F0"); /* clear sign flag */
4592
4593           lbl = newiTempLabel (NULL);
4594           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4595           emitcode ("setb", "F0"); /* set sign flag */
4596           emitcode ("cpl", "a");   /* 2's complement */
4597           emitcode ("inc", "a");
4598           emitcode ("", "%05d$:", (lbl->key + 100));
4599         }
4600     }
4601
4602   /* now the modulus */
4603   emitcode ("div", "ab");
4604
4605   if (runtimeSign || compiletimeSign)
4606     {
4607       emitcode ("mov", "a,b");
4608       lbl = newiTempLabel (NULL);
4609       if (runtimeSign)
4610         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4611       emitcode ("cpl", "a"); /* 2's complement */
4612       emitcode ("inc", "a");
4613       emitcode ("", "%05d$:", (lbl->key + 100));
4614
4615       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4616       if (size > 0)
4617         {
4618           /* msb is 0x00 or 0xff depending on the sign */
4619           if (runtimeSign)
4620             {
4621               emitcode ("mov", "c,F0");
4622               emitcode ("subb", "a,acc");
4623               while (size--)
4624                 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4625             }
4626           else /* compiletimeSign */
4627             while (size--)
4628               aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4629         }
4630     }
4631   else
4632     {
4633       aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4634       while (size--)
4635         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4636     }
4637 }
4638
4639 /*-----------------------------------------------------------------*/
4640 /* genMod - generates code for division                            */
4641 /*-----------------------------------------------------------------*/
4642 static void
4643 genMod (iCode * ic)
4644 {
4645   operand *left = IC_LEFT (ic);
4646   operand *right = IC_RIGHT (ic);
4647   operand *result = IC_RESULT (ic);
4648
4649   D(emitcode (";     genMod",""));
4650
4651   /* assign the amsops */
4652   aopOp (left, ic, FALSE);
4653   aopOp (right, ic, FALSE);
4654   aopOp (result, ic, TRUE);
4655
4656   /* special cases first */
4657   /* both are bits */
4658   if (AOP_TYPE (left) == AOP_CRY &&
4659       AOP_TYPE (right) == AOP_CRY)
4660     {
4661       genModbits (left, right, result);
4662       goto release;
4663     }
4664
4665   /* if both are of size == 1 */
4666   if (AOP_SIZE (left) == 1 &&
4667       AOP_SIZE (right) == 1)
4668     {
4669       genModOneByte (left, right, result);
4670       goto release;
4671     }
4672
4673   /* should have been converted to function call */
4674   assert (0);
4675
4676 release:
4677   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4678   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679   freeAsmop (result, NULL, ic, TRUE);
4680 }
4681
4682 /*-----------------------------------------------------------------*/
4683 /* genIfxJump :- will create a jump depending on the ifx           */
4684 /*-----------------------------------------------------------------*/
4685 static void
4686 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4687 {
4688   symbol *jlbl;
4689   symbol *tlbl = newiTempLabel (NULL);
4690   char *inst;
4691
4692   D(emitcode (";     genIfxJump",""));
4693
4694   /* if true label then we jump if condition
4695      supplied is true */
4696   if (IC_TRUE (ic))
4697     {
4698       jlbl = IC_TRUE (ic);
4699       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4700                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4701     }
4702   else
4703     {
4704       /* false label is present */
4705       jlbl = IC_FALSE (ic);
4706       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4707                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4708     }
4709   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4710     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4711   else
4712     emitcode (inst, "%05d$", tlbl->key + 100);
4713   freeForBranchAsmop (result);
4714   freeForBranchAsmop (right);
4715   freeForBranchAsmop (left);
4716   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4717   emitcode ("", "%05d$:", tlbl->key + 100);
4718
4719   /* mark the icode as generated */
4720   ic->generated = 1;
4721 }
4722
4723 /*-----------------------------------------------------------------*/
4724 /* genCmp :- greater or less than comparison                       */
4725 /*-----------------------------------------------------------------*/
4726 static void
4727 genCmp (operand * left, operand * right,
4728         operand * result, iCode * ifx, int sign, iCode *ic)
4729 {
4730   int size, offset = 0;
4731   unsigned long lit = 0L;
4732   bool rightInB;
4733
4734   D(emitcode (";     genCmp",""));
4735
4736   /* if left & right are bit variables */
4737   if (AOP_TYPE (left) == AOP_CRY &&
4738       AOP_TYPE (right) == AOP_CRY)
4739     {
4740       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4741       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4742     }
4743   else
4744     {
4745       /* subtract right from left if at the
4746          end the carry flag is set then we know that
4747          left is greater than right */
4748       size = max (AOP_SIZE (left), AOP_SIZE (right));
4749
4750       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4751       if ((size == 1) && !sign &&
4752           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4753         {
4754           symbol *lbl = newiTempLabel (NULL);
4755           emitcode ("cjne", "%s,%s,%05d$",
4756                     aopGet (AOP (left), offset, FALSE, FALSE),
4757                     aopGet (AOP (right), offset, FALSE, FALSE),
4758                     lbl->key + 100);
4759           emitcode ("", "%05d$:", lbl->key + 100);
4760         }
4761       else
4762         {
4763           if (AOP_TYPE (right) == AOP_LIT)
4764             {
4765               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4766               /* optimize if(x < 0) or if(x >= 0) */
4767               if (lit == 0L)
4768                 {
4769                   if (!sign)
4770                     {
4771                       CLRC;
4772                     }
4773                   else
4774                     {
4775                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4776                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4777                         {
4778                           genIfxJump (ifx, "acc.7", left, right, result);
4779                           freeAsmop (right, NULL, ic, TRUE);
4780                           freeAsmop (left, NULL, ic, TRUE);
4781
4782                           return;
4783                         }
4784                       else
4785                         emitcode ("rlc", "a");
4786                     }
4787                   goto release;
4788                 }
4789             }
4790           CLRC;
4791           while (size--)
4792             {
4793               rightInB = aopGetUsesAcc(AOP (right), offset);
4794               if (rightInB)
4795                 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4796               MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4797               if (sign && size == 0)
4798                 {
4799                   emitcode ("xrl", "a,#0x80");
4800                   if (AOP_TYPE (right) == AOP_LIT)
4801                     {
4802                       unsigned long lit = (unsigned long)
4803                       floatFromVal (AOP (right)->aopu.aop_lit);
4804                       emitcode ("subb", "a,#0x%02x",
4805                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4806                     }
4807                   else
4808                     {
4809                       if (!rightInB)
4810                         emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4811                       emitcode ("xrl", "b,#0x80");
4812                       emitcode ("subb", "a,b");
4813                     }
4814                 }
4815               else
4816                 {
4817                   if (rightInB)
4818                     emitcode ("subb", "a,b");
4819                   else
4820                     emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4821                 }
4822               offset++;
4823             }
4824         }
4825     }
4826
4827 release:
4828   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4830   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4831     {
4832       outBitC (result);
4833     }
4834   else
4835     {
4836       /* if the result is used in the next
4837          ifx conditional branch then generate
4838          code a little differently */
4839       if (ifx)
4840         genIfxJump (ifx, "c", NULL, NULL, result);
4841       else
4842         outBitC (result);
4843       /* leave the result in acc */
4844     }
4845 }
4846
4847 /*-----------------------------------------------------------------*/
4848 /* genCmpGt :- greater than comparison                             */
4849 /*-----------------------------------------------------------------*/
4850 static void
4851 genCmpGt (iCode * ic, iCode * ifx)
4852 {
4853   operand *left, *right, *result;
4854   sym_link *letype, *retype;
4855   int sign;
4856
4857   D(emitcode (";     genCmpGt",""));
4858
4859   left = IC_LEFT (ic);
4860   right = IC_RIGHT (ic);
4861   result = IC_RESULT (ic);
4862
4863   letype = getSpec (operandType (left));
4864   retype = getSpec (operandType (right));
4865   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4866            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4867   /* assign the amsops */
4868   aopOp (left, ic, FALSE);
4869   aopOp (right, ic, FALSE);
4870   aopOp (result, ic, TRUE);
4871
4872   genCmp (right, left, result, ifx, sign,ic);
4873
4874   freeAsmop (result, NULL, ic, TRUE);
4875 }
4876
4877 /*-----------------------------------------------------------------*/
4878 /* genCmpLt - less than comparisons                                */
4879 /*-----------------------------------------------------------------*/
4880 static void
4881 genCmpLt (iCode * ic, iCode * ifx)
4882 {
4883   operand *left, *right, *result;
4884   sym_link *letype, *retype;
4885   int sign;
4886
4887   D(emitcode (";     genCmpLt",""));
4888
4889   left = IC_LEFT (ic);
4890   right = IC_RIGHT (ic);
4891   result = IC_RESULT (ic);
4892
4893   letype = getSpec (operandType (left));
4894   retype = getSpec (operandType (right));
4895   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
4896            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
4897   /* assign the amsops */
4898   aopOp (left, ic, FALSE);
4899   aopOp (right, ic, FALSE);
4900   aopOp (result, ic, TRUE);
4901
4902   genCmp (left, right, result, ifx, sign,ic);
4903
4904   freeAsmop (result, NULL, ic, TRUE);
4905 }
4906
4907 /*-----------------------------------------------------------------*/
4908 /* gencjneshort - compare and jump if not equal                    */
4909 /*-----------------------------------------------------------------*/
4910 static void
4911 gencjneshort (operand * left, operand * right, symbol * lbl)
4912 {
4913   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4914   int offset = 0;
4915   unsigned long lit = 0L;
4916
4917   /* if the left side is a literal or
4918      if the right is in a pointer register and left
4919      is not */
4920   if ((AOP_TYPE (left) == AOP_LIT) ||
4921       (AOP_TYPE (left) == AOP_IMMD) ||
4922       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4923     {
4924       operand *t = right;
4925       right = left;
4926       left = t;
4927     }
4928
4929   if (AOP_TYPE (right) == AOP_LIT)
4930     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4931
4932   /* if the right side is a literal then anything goes */
4933   if (AOP_TYPE (right) == AOP_LIT &&
4934       AOP_TYPE (left) != AOP_DIR  &&
4935       AOP_TYPE (left) != AOP_IMMD)
4936     {
4937       while (size--)
4938         {
4939           emitcode ("cjne", "%s,%s,%05d$",
4940                     aopGet (AOP (left), offset, FALSE, FALSE),
4941                     aopGet (AOP (right), offset, FALSE, FALSE),
4942                     lbl->key + 100);
4943           offset++;
4944         }
4945     }
4946
4947   /* if the right side is in a register or in direct space or
4948      if the left is a pointer register & right is not */
4949   else if (AOP_TYPE (right) == AOP_REG ||
4950            AOP_TYPE (right) == AOP_DIR ||
4951            AOP_TYPE (right) == AOP_LIT ||
4952            AOP_TYPE (right) == AOP_IMMD ||
4953            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4954            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4955     {
4956       while (size--)
4957         {
4958           MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4959           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4960               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4961             emitcode ("jnz", "%05d$", lbl->key + 100);
4962           else
4963             emitcode ("cjne", "a,%s,%05d$",
4964                       aopGet (AOP (right), offset, FALSE, TRUE),
4965                       lbl->key + 100);
4966           offset++;
4967         }
4968     }
4969   else
4970     {
4971       /* right is a pointer reg need both a & b */
4972       while (size--)
4973         {
4974           char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4975           if (strcmp (l, "b"))
4976             emitcode ("mov", "b,%s", l);
4977           MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4978           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4979           offset++;
4980         }
4981     }
4982 }
4983
4984 /*-----------------------------------------------------------------*/
4985 /* gencjne - compare and jump if not equal                         */
4986 /*-----------------------------------------------------------------*/
4987 static void
4988 gencjne (operand * left, operand * right, symbol * lbl)
4989 {
4990   symbol *tlbl = newiTempLabel (NULL);
4991
4992   gencjneshort (left, right, lbl);
4993
4994   emitcode ("mov", "a,%s", one);
4995   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4996   emitcode ("", "%05d$:", lbl->key + 100);
4997   emitcode ("clr", "a");
4998   emitcode ("", "%05d$:", tlbl->key + 100);
4999 }
5000
5001 /*-----------------------------------------------------------------*/
5002 /* genCmpEq - generates code for equal to                          */
5003 /*-----------------------------------------------------------------*/
5004 static void
5005 genCmpEq (iCode * ic, iCode * ifx)
5006 {
5007   operand *left, *right, *result;
5008
5009   D(emitcode (";     genCmpEq",""));
5010
5011   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5012   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5013   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5014
5015   /* if literal, literal on the right or
5016      if the right is in a pointer register and left
5017      is not */
5018   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5019       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5020     {
5021       operand *t = IC_RIGHT (ic);
5022       IC_RIGHT (ic) = IC_LEFT (ic);
5023       IC_LEFT (ic) = t;
5024     }
5025
5026   if (ifx && !AOP_SIZE (result))
5027     {
5028       symbol *tlbl;
5029       /* if they are both bit variables */
5030       if (AOP_TYPE (left) == AOP_CRY &&
5031           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5032         {
5033           if (AOP_TYPE (right) == AOP_LIT)
5034             {
5035               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5036               if (lit == 0L)
5037                 {
5038                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5039                   emitcode ("cpl", "c");
5040                 }
5041               else if (lit == 1L)
5042                 {
5043                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5044                 }
5045               else
5046                 {
5047                   emitcode ("clr", "c");
5048                 }
5049               /* AOP_TYPE(right) == AOP_CRY */
5050             }
5051           else
5052             {
5053               symbol *lbl = newiTempLabel (NULL);
5054               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5055               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5056               emitcode ("cpl", "c");
5057               emitcode ("", "%05d$:", (lbl->key + 100));
5058             }
5059           /* if true label then we jump if condition
5060              supplied is true */
5061           tlbl = newiTempLabel (NULL);
5062           if (IC_TRUE (ifx))
5063             {
5064               emitcode ("jnc", "%05d$", tlbl->key + 100);
5065               freeForBranchAsmop (result);
5066               freeForBranchAsmop (right);
5067               freeForBranchAsmop (left);
5068               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5069             }
5070           else
5071             {
5072               emitcode ("jc", "%05d$", tlbl->key + 100);
5073               freeForBranchAsmop (result);
5074               freeForBranchAsmop (right);
5075               freeForBranchAsmop (left);
5076               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5077             }
5078           emitcode ("", "%05d$:", tlbl->key + 100);
5079         }
5080       else
5081         {
5082           tlbl = newiTempLabel (NULL);
5083           gencjneshort (left, right, tlbl);
5084           if (IC_TRUE (ifx))
5085             {
5086               freeForBranchAsmop (result);
5087               freeForBranchAsmop (right);
5088               freeForBranchAsmop (left);
5089               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5090               emitcode ("", "%05d$:", tlbl->key + 100);
5091             }
5092           else
5093             {
5094               symbol *lbl = newiTempLabel (NULL);
5095               emitcode ("sjmp", "%05d$", lbl->key + 100);
5096               emitcode ("", "%05d$:", tlbl->key + 100);
5097               freeForBranchAsmop (result);
5098               freeForBranchAsmop (right);
5099               freeForBranchAsmop (left);
5100               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5101               emitcode ("", "%05d$:", lbl->key + 100);
5102             }
5103         }
5104       /* mark the icode as generated */
5105       ifx->generated = 1;
5106       goto release;
5107     }
5108
5109   /* if they are both bit variables */
5110   if (AOP_TYPE (left) == AOP_CRY &&
5111       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5112     {
5113       if (AOP_TYPE (right) == AOP_LIT)
5114         {
5115           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5116           if (lit == 0L)
5117             {
5118               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5119               emitcode ("cpl", "c");
5120             }
5121           else if (lit == 1L)
5122             {
5123               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5124             }
5125           else
5126             {
5127               emitcode ("clr", "c");
5128             }
5129           /* AOP_TYPE(right) == AOP_CRY */
5130         }
5131       else
5132         {
5133           symbol *lbl = newiTempLabel (NULL);
5134           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5135           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5136           emitcode ("cpl", "c");
5137           emitcode ("", "%05d$:", (lbl->key + 100));
5138         }
5139       /* c = 1 if egal */
5140       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5141         {
5142           outBitC (result);
5143           goto release;
5144         }
5145       if (ifx)
5146         {
5147           genIfxJump (ifx, "c", left, right, result);
5148           goto release;
5149         }
5150       /* if the result is used in an arithmetic operation
5151          then put the result in place */
5152       outBitC (result);
5153     }
5154   else
5155     {
5156       gencjne (left, right, newiTempLabel (NULL));
5157       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5158         {
5159           aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5160           goto release;
5161         }
5162       if (ifx)
5163         {
5164           genIfxJump (ifx, "a", left, right, result);
5165           goto release;
5166         }
5167       /* if the result is used in an arithmetic operation
5168          then put the result in place */
5169       if (AOP_TYPE (result) != AOP_CRY)
5170         outAcc (result);
5171       /* leave the result in acc */
5172     }
5173
5174 release:
5175   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5176   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5177   freeAsmop (result, NULL, ic, TRUE);
5178 }
5179
5180 /*-----------------------------------------------------------------*/
5181 /* ifxForOp - returns the icode containing the ifx for operand     */
5182 /*-----------------------------------------------------------------*/
5183 static iCode *
5184 ifxForOp (operand * op, iCode * ic)
5185 {
5186   /* if true symbol then needs to be assigned */
5187   if (IS_TRUE_SYMOP (op))
5188     return NULL;
5189
5190   /* if this has register type condition and
5191      the next instruction is ifx with the same operand
5192      and live to of the operand is upto the ifx only then */
5193   if (ic->next &&
5194       ic->next->op == IFX &&
5195       IC_COND (ic->next)->key == op->key &&
5196       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5197     return ic->next;
5198
5199   return NULL;
5200 }
5201
5202 /*-----------------------------------------------------------------*/
5203 /* hasInc - operand is incremented before any other use            */
5204 /*-----------------------------------------------------------------*/
5205 static iCode *
5206 hasInc (operand *op, iCode *ic,int osize)
5207 {
5208   sym_link *type = operandType(op);
5209   sym_link *retype = getSpec (type);
5210   iCode *lic = ic->next;
5211   int isize ;
5212
5213   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5214   if (!IS_SYMOP(op)) return NULL;
5215
5216   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5217   if (IS_AGGREGATE(type->next)) return NULL;
5218   if (osize != (isize = getSize(type->next))) return NULL;
5219
5220   while (lic) {
5221     /* if operand of the form op = op + <sizeof *op> */
5222     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5223         isOperandEqual(IC_RESULT(lic),op) &&
5224         isOperandLiteral(IC_RIGHT(lic)) &&
5225         operandLitValue(IC_RIGHT(lic)) == isize) {
5226       return lic;
5227     }
5228     /* if the operand used or deffed */
5229     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5230       return NULL;
5231     }
5232     /* if GOTO or IFX */
5233     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5234     lic = lic->next;
5235   }
5236   return NULL;
5237 }
5238
5239 /*-----------------------------------------------------------------*/
5240 /* genAndOp - for && operation                                     */
5241 /*-----------------------------------------------------------------*/
5242 static void
5243 genAndOp (iCode * ic)
5244 {
5245   operand *left, *right, *result;
5246   symbol *tlbl;
5247
5248   D(emitcode (";     genAndOp",""));
5249
5250   /* note here that && operations that are in an
5251      if statement are taken away by backPatchLabels
5252      only those used in arthmetic operations remain */
5253   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5254   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5255   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5256
5257   /* if both are bit variables */
5258   if (AOP_TYPE (left) == AOP_CRY &&
5259       AOP_TYPE (right) == AOP_CRY)
5260     {
5261       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5262       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5263       outBitC (result);
5264     }
5265   else
5266     {
5267       tlbl = newiTempLabel (NULL);
5268       toBoolean (left);
5269       emitcode ("jz", "%05d$", tlbl->key + 100);
5270       toBoolean (right);
5271       emitcode ("", "%05d$:", tlbl->key + 100);
5272       outBitAcc (result);
5273     }
5274
5275   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5276   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5277   freeAsmop (result, NULL, ic, TRUE);
5278 }
5279
5280
5281 /*-----------------------------------------------------------------*/
5282 /* genOrOp - for || operation                                      */
5283 /*-----------------------------------------------------------------*/
5284 static void
5285 genOrOp (iCode * ic)
5286 {
5287   operand *left, *right, *result;
5288   symbol *tlbl;
5289
5290   D(emitcode (";     genOrOp",""));
5291
5292   /* note here that || operations that are in an
5293      if statement are taken away by backPatchLabels
5294      only those used in arthmetic operations remain */
5295   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5296   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5297   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5298
5299   /* if both are bit variables */
5300   if (AOP_TYPE (left) == AOP_CRY &&
5301       AOP_TYPE (right) == AOP_CRY)
5302     {
5303       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5304       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5305       outBitC (result);
5306     }
5307   else
5308     {
5309       tlbl = newiTempLabel (NULL);
5310       toBoolean (left);
5311       emitcode ("jnz", "%05d$", tlbl->key + 100);
5312       toBoolean (right);
5313       emitcode ("", "%05d$:", tlbl->key + 100);
5314       outBitAcc (result);
5315     }
5316
5317   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5318   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5319   freeAsmop (result, NULL, ic, TRUE);
5320 }
5321
5322 /*-----------------------------------------------------------------*/
5323 /* isLiteralBit - test if lit == 2^n                               */
5324 /*-----------------------------------------------------------------*/
5325 static int
5326 isLiteralBit (unsigned long lit)
5327 {
5328   unsigned long pw[32] =
5329   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5330    0x100L, 0x200L, 0x400L, 0x800L,
5331    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5332    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5333    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5334    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5335    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5336   int idx;
5337
5338   for (idx = 0; idx < 32; idx++)
5339     if (lit == pw[idx])
5340       return idx + 1;
5341   return 0;
5342 }
5343
5344 /*-----------------------------------------------------------------*/
5345 /* continueIfTrue -                                                */
5346 /*-----------------------------------------------------------------*/
5347 static void
5348 continueIfTrue (iCode * ic)
5349 {
5350   if (IC_TRUE (ic))
5351     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5352   ic->generated = 1;
5353 }
5354
5355 /*-----------------------------------------------------------------*/
5356 /* jmpIfTrue -                                                     */
5357 /*-----------------------------------------------------------------*/
5358 static void
5359 jumpIfTrue (iCode * ic)
5360 {
5361   if (!IC_TRUE (ic))
5362     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5363   ic->generated = 1;
5364 }
5365
5366 /*-----------------------------------------------------------------*/
5367 /* jmpTrueOrFalse -                                                */
5368 /*-----------------------------------------------------------------*/
5369 static void
5370 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5371 {
5372   // ugly but optimized by peephole
5373   if (IC_TRUE (ic))
5374     {
5375       symbol *nlbl = newiTempLabel (NULL);
5376       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5377       emitcode ("", "%05d$:", tlbl->key + 100);
5378       freeForBranchAsmop (result);
5379       freeForBranchAsmop (right);
5380       freeForBranchAsmop (left);
5381       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5382       emitcode ("", "%05d$:", nlbl->key + 100);
5383     }
5384   else
5385     {
5386       freeForBranchAsmop (result);
5387       freeForBranchAsmop (right);
5388       freeForBranchAsmop (left);
5389       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5390       emitcode ("", "%05d$:", tlbl->key + 100);
5391     }
5392   ic->generated = 1;
5393 }
5394
5395 /*-----------------------------------------------------------------*/
5396 /* genAnd  - code for and                                          */
5397 /*-----------------------------------------------------------------*/
5398 static void
5399 genAnd (iCode * ic, iCode * ifx)
5400 {
5401   operand *left, *right, *result;
5402   int size, offset = 0;
5403   unsigned long lit = 0L;
5404   int bytelit = 0;
5405   char buffer[10];
5406
5407   D(emitcode (";     genAnd",""));
5408
5409   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5410   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5411   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5412
5413 #ifdef DEBUG_TYPE
5414   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5415             AOP_TYPE (result),
5416             AOP_TYPE (left), AOP_TYPE (right));
5417   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5418             AOP_SIZE (result),
5419             AOP_SIZE (left), AOP_SIZE (right));
5420 #endif
5421
5422   /* if left is a literal & right is not then exchange them */
5423   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5424       AOP_NEEDSACC (left))
5425     {
5426       operand *tmp = right;
5427       right = left;
5428       left = tmp;
5429     }
5430
5431   /* if result = right then exchange left and right */
5432   if (sameRegs (AOP (result), AOP (right)))
5433     {
5434       operand *tmp = right;
5435       right = left;
5436       left = tmp;
5437     }
5438
5439   /* if right is bit then exchange them */
5440   if (AOP_TYPE (right) == AOP_CRY &&
5441       AOP_TYPE (left) != AOP_CRY)
5442     {
5443       operand *tmp = right;
5444       right = left;
5445       left = tmp;
5446     }
5447   if (AOP_TYPE (right) == AOP_LIT)
5448     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5449
5450   size = AOP_SIZE (result);
5451
5452   // if(bit & yy)
5453   // result = bit & yy;
5454   if (AOP_TYPE (left) == AOP_CRY)
5455     {
5456       // c = bit & literal;
5457       if (AOP_TYPE (right) == AOP_LIT)
5458         {
5459           if (lit & 1)
5460             {
5461               if (size && sameRegs (AOP (result), AOP (left)))
5462                 // no change
5463                 goto release;
5464               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5465             }
5466           else
5467             {
5468               // bit(result) = 0;
5469               if (size && (AOP_TYPE (result) == AOP_CRY))
5470                 {
5471                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5472                   goto release;
5473                 }
5474               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5475                 {
5476                   jumpIfTrue (ifx);
5477                   goto release;
5478                 }
5479               emitcode ("clr", "c");
5480             }
5481         }
5482       else
5483         {
5484           if (AOP_TYPE (right) == AOP_CRY)
5485             {
5486               // c = bit & bit;
5487               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5488               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5489             }
5490           else
5491             {
5492               // c = bit & val;
5493               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5494               // c = lsb
5495               emitcode ("rrc", "a");
5496               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5497             }
5498         }
5499       // bit = c
5500       // val = c
5501       if (size)
5502         outBitC (result);
5503       // if(bit & ...)
5504       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5505         genIfxJump (ifx, "c", left, right, result);
5506       goto release;
5507     }
5508
5509   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5510   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5511   if ((AOP_TYPE (right) == AOP_LIT) &&
5512       (AOP_TYPE (result) == AOP_CRY) &&
5513       (AOP_TYPE (left) != AOP_CRY))
5514     {
5515       int posbit = isLiteralBit (lit);
5516       /* left &  2^n */
5517       if (posbit)
5518         {
5519           posbit--;
5520           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5521           // bit = left & 2^n
5522           if (size)
5523             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5524           // if(left &  2^n)
5525           else
5526             {
5527               if (ifx)
5528                 {
5529                   SNPRINTF (buffer, sizeof(buffer),
5530                             "acc.%d", posbit & 0x07);
5531                   genIfxJump (ifx, buffer, left, right, result);
5532                 }
5533               else 
5534                 {// what is this case? just found it in ds390/gen.c
5535                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5536                 }
5537               goto release;
5538             }
5539         }
5540       else
5541         {
5542           symbol *tlbl = newiTempLabel (NULL);
5543           int sizel = AOP_SIZE (left);
5544           if (size)
5545             emitcode ("setb", "c");
5546           while (sizel--)
5547             {
5548               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5549                 {
5550                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5551                   // byte ==  2^n ?
5552                   if ((posbit = isLiteralBit (bytelit)) != 0)
5553                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5554                   else
5555                     {
5556                       if (bytelit != 0x0FFL)
5557                         emitcode ("anl", "a,%s",
5558                                   aopGet (AOP (right), offset, FALSE, TRUE));
5559                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5560                     }
5561                 }
5562               offset++;
5563             }
5564           // bit = left & literal
5565           if (size)
5566             {
5567               emitcode ("clr", "c");
5568               emitcode ("", "%05d$:", tlbl->key + 100);
5569             }
5570           // if(left & literal)
5571           else
5572             {
5573               if (ifx)
5574                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5575               else
5576                 emitcode ("", "%05d$:", tlbl->key + 100);
5577               goto release;
5578             }
5579         }
5580       outBitC (result);
5581       goto release;
5582     }
5583
5584   /* if left is same as result */
5585   if (sameRegs (AOP (result), AOP (left)))
5586     {
5587       for (; size--; offset++)
5588         {
5589           if (AOP_TYPE (right) == AOP_LIT)
5590             {
5591               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5592               if (bytelit == 0x0FF)
5593                 {
5594                   /* dummy read of volatile operand */
5595                   if (isOperandVolatile (left, FALSE))
5596                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5597                   else
5598                 continue;
5599                 }
5600               else if (bytelit == 0)
5601                 {
5602                   aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5603                 }
5604               else if (IS_AOP_PREG (result))
5605                 {
5606                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5607                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5608                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5609                 }
5610               else
5611                 emitcode ("anl", "%s,%s",
5612                           aopGet (AOP (left), offset, FALSE, TRUE),
5613                           aopGet (AOP (right), offset, FALSE, FALSE));
5614             }
5615           else
5616             {
5617               if (AOP_TYPE (left) == AOP_ACC)
5618                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5619               else
5620                 {
5621                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5622                   if (IS_AOP_PREG (result))
5623                     {
5624                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5625                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5626                     }
5627                   else
5628                     emitcode ("anl", "%s,a",
5629                               aopGet (AOP (left), offset, FALSE, TRUE));
5630                 }
5631             }
5632         }
5633     }
5634   else
5635     {
5636       // left & result in different registers
5637       if (AOP_TYPE (result) == AOP_CRY)
5638         {
5639           // result = bit
5640           // if(size), result in bit
5641           // if(!size && ifx), conditional oper: if(left & right)
5642           symbol *tlbl = newiTempLabel (NULL);
5643           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5644           if (size)
5645             emitcode ("setb", "c");
5646           while (sizer--)
5647             {
5648               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5649                 emitcode ("anl", "a,%s",
5650                           aopGet (AOP (right), offset, FALSE, FALSE));
5651               } else {
5652                 if (AOP_TYPE(left)==AOP_ACC) {
5653                   emitcode("mov", "b,a");
5654                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5655                   emitcode("anl", "a,b");
5656                 }else {
5657                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5658                   emitcode ("anl", "a,%s",
5659                             aopGet (AOP (left), offset, FALSE, FALSE));
5660                 }
5661               }
5662               emitcode ("jnz", "%05d$", tlbl->key + 100);
5663               offset++;
5664             }
5665           if (size)
5666             {
5667               CLRC;
5668               emitcode ("", "%05d$:", tlbl->key + 100);
5669               outBitC (result);
5670             }
5671           else if (ifx)
5672             jmpTrueOrFalse (ifx, tlbl, left, right, result);
5673           else
5674             emitcode ("", "%05d$:", tlbl->key + 100);
5675         }
5676       else
5677         {
5678           for (; (size--); offset++)
5679             {
5680               // normal case
5681               // result = left & right
5682               if (AOP_TYPE (right) == AOP_LIT)
5683                 {
5684                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5685                   if (bytelit == 0x0FF)
5686                     {
5687                       aopPut (AOP (result),
5688                               aopGet (AOP (left), offset, FALSE, FALSE),
5689                               offset,
5690                               isOperandVolatile (result, FALSE));
5691                       continue;
5692                     }
5693                   else if (bytelit == 0)
5694                     {
5695                       /* dummy read of volatile operand */
5696                       if (isOperandVolatile (left, FALSE))
5697                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5698                       aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5699                       continue;
5700                     }
5701                 }
5702               // faster than result <- left, anl result,right
5703               // and better if result is SFR
5704               if (AOP_TYPE (left) == AOP_ACC)
5705                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5706               else
5707                 {
5708                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5709                   emitcode ("anl", "a,%s",
5710                             aopGet (AOP (left), offset, FALSE, FALSE));
5711                 }
5712               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5713             }
5714         }
5715     }
5716
5717 release:
5718   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5719   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5720   freeAsmop (result, NULL, ic, TRUE);
5721 }
5722
5723 /*-----------------------------------------------------------------*/
5724 /* genOr  - code for or                                            */
5725 /*-----------------------------------------------------------------*/
5726 static void
5727 genOr (iCode * ic, iCode * ifx)
5728 {
5729   operand *left, *right, *result;
5730   int size, offset = 0;
5731   unsigned long lit = 0L;
5732   int bytelit = 0;
5733
5734   D(emitcode (";     genOr",""));
5735
5736   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5737   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5738   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5739
5740 #ifdef DEBUG_TYPE
5741   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5742             AOP_TYPE (result),
5743             AOP_TYPE (left), AOP_TYPE (right));
5744   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5745             AOP_SIZE (result),
5746             AOP_SIZE (left), AOP_SIZE (right));
5747 #endif
5748
5749   /* if left is a literal & right is not then exchange them */
5750   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5751       AOP_NEEDSACC (left))
5752     {
5753       operand *tmp = right;
5754       right = left;
5755       left = tmp;
5756     }
5757
5758   /* if result = right then exchange them */
5759   if (sameRegs (AOP (result), AOP (right)))
5760     {
5761       operand *tmp = right;
5762       right = left;
5763       left = tmp;
5764     }
5765
5766   /* if right is bit then exchange them */
5767   if (AOP_TYPE (right) == AOP_CRY &&
5768       AOP_TYPE (left) != AOP_CRY)
5769     {
5770       operand *tmp = right;
5771       right = left;
5772       left = tmp;
5773     }
5774   if (AOP_TYPE (right) == AOP_LIT)
5775     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5776
5777   size = AOP_SIZE (result);
5778
5779   // if(bit | yy)
5780   // xx = bit | yy;
5781   if (AOP_TYPE (left) == AOP_CRY)
5782     {
5783       if (AOP_TYPE (right) == AOP_LIT)
5784         {
5785           // c = bit | literal;
5786           if (lit)
5787             {
5788               // lit != 0 => result = 1
5789               if (AOP_TYPE (result) == AOP_CRY)
5790                 {
5791                   if (size)
5792                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5793                   else if (ifx)
5794                     continueIfTrue (ifx);
5795                   goto release;
5796                 }
5797               emitcode ("setb", "c");
5798             }
5799           else
5800             {
5801               // lit == 0 => result = left
5802               if (size && sameRegs (AOP (result), AOP (left)))
5803                 goto release;
5804               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5805             }
5806         }
5807       else
5808         {
5809           if (AOP_TYPE (right) == AOP_CRY)
5810             {
5811               // c = bit | bit;
5812               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5813               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5814             }
5815           else
5816             {
5817               // c = bit | val;
5818               symbol *tlbl = newiTempLabel (NULL);
5819               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5820                 emitcode ("setb", "c");
5821               emitcode ("jb", "%s,%05d$",
5822                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5823               toBoolean (right);
5824               emitcode ("jnz", "%05d$", tlbl->key + 100);
5825               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5826                 {
5827                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
5828                   goto release;
5829                 }
5830               else
5831                 {
5832                   CLRC;
5833                   emitcode ("", "%05d$:", tlbl->key + 100);
5834                 }
5835             }
5836         }
5837       // bit = c
5838       // val = c
5839       if (size)
5840         outBitC (result);
5841       // if(bit | ...)
5842       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5843         genIfxJump (ifx, "c", left, right, result);
5844       goto release;
5845     }
5846
5847   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5848   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5849   if ((AOP_TYPE (right) == AOP_LIT) &&
5850       (AOP_TYPE (result) == AOP_CRY) &&
5851       (AOP_TYPE (left) != AOP_CRY))
5852     {
5853       if (lit)
5854         {
5855           // result = 1
5856           if (size)
5857             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5858           else
5859             continueIfTrue (ifx);
5860           goto release;
5861         }
5862       else
5863         {
5864           // lit = 0, result = boolean(left)
5865           if (size)
5866             emitcode ("setb", "c");
5867           toBoolean (right);
5868           if (size)
5869             {
5870               symbol *tlbl = newiTempLabel (NULL);
5871               emitcode ("jnz", "%05d$", tlbl->key + 100);
5872               CLRC;
5873               emitcode ("", "%05d$:", tlbl->key + 100);
5874             }
5875           else
5876             {
5877               genIfxJump (ifx, "a", left, right, result);
5878               goto release;
5879             }
5880         }
5881       outBitC (result);
5882       goto release;
5883     }
5884
5885   /* if left is same as result */
5886   if (sameRegs (AOP (result), AOP (left)))
5887     {
5888       for (; size--; offset++)
5889         {
5890           if (AOP_TYPE (right) == AOP_LIT)
5891             {
5892               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5893               if (bytelit == 0)
5894                 {
5895                   /* dummy read of volatile operand */
5896                   if (isOperandVolatile (left, FALSE))
5897                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5898                   else
5899                     continue;
5900                 }
5901               else if (bytelit == 0x0FF)
5902                 {
5903                   aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
5904                 }
5905               else if (IS_AOP_PREG (left))
5906                 {
5907                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5908                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5909                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5910                 }
5911               else
5912                 {
5913                   emitcode ("orl", "%s,%s",
5914                             aopGet (AOP (left), offset, FALSE, TRUE),
5915                             aopGet (AOP (right), offset, FALSE, FALSE));
5916                 }
5917             }
5918           else
5919             {
5920               if (AOP_TYPE (left) == AOP_ACC)
5921                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5922               else
5923                 {
5924                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5925                   if (IS_AOP_PREG (left))
5926                     {
5927                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5928                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5929                     }
5930                   else
5931                     {
5932                       emitcode ("orl", "%s,a",
5933                                 aopGet (AOP (left), offset, FALSE, TRUE));
5934                     }
5935                 }
5936             }
5937         }
5938     }
5939   else
5940     {
5941       // left & result in different registers
5942       if (AOP_TYPE (result) == AOP_CRY)
5943         {
5944           // result = bit
5945           // if(size), result in bit
5946           // if(!size && ifx), conditional oper: if(left | right)
5947           symbol *tlbl = newiTempLabel (NULL);
5948           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5949           if (size)
5950             emitcode ("setb", "c");
5951           while (sizer--)
5952             {
5953               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5954                 emitcode ("orl", "a,%s",
5955                           aopGet (AOP (right), offset, FALSE, FALSE));
5956               } else {
5957                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5958                 emitcode ("orl", "a,%s",
5959                           aopGet (AOP (left), offset, FALSE, FALSE));
5960               }
5961               emitcode ("jnz", "%05d$", tlbl->key + 100);
5962               offset++;
5963             }
5964           if (size)
5965             {
5966               CLRC;
5967               emitcode ("", "%05d$:", tlbl->key + 100);
5968               outBitC (result);
5969             }
5970           else if (ifx)
5971             jmpTrueOrFalse (ifx, tlbl, left, right, result);
5972           else
5973             emitcode ("", "%05d$:", tlbl->key + 100);
5974         }
5975       else
5976         {
5977           for (; (size--); offset++)
5978             {
5979               // normal case
5980               // result = left | right
5981               if (AOP_TYPE (right) == AOP_LIT)
5982                 {
5983                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5984                   if (bytelit == 0)
5985                     {
5986                       aopPut (AOP (result),
5987                               aopGet (AOP (left), offset, FALSE, FALSE),
5988                               offset,
5989                               isOperandVolatile (result, FALSE));
5990                       continue;
5991                     }
5992                   else if (bytelit == 0x0FF)
5993                     {
5994                       /* dummy read of volatile operand */
5995                       if (isOperandVolatile (left, FALSE))
5996                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5997                       aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
5998                       continue;
5999                     }
6000                 }
6001               // faster than result <- left, anl result,right
6002               // and better if result is SFR
6003               if (AOP_TYPE (left) == AOP_ACC)
6004                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6005               else
6006                 {
6007                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6008                   emitcode ("orl", "a,%s",
6009                             aopGet (AOP (left), offset, FALSE, FALSE));
6010                 }
6011               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6012             }
6013         }
6014     }
6015
6016 release:
6017   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6018   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019   freeAsmop (result, NULL, ic, TRUE);
6020 }
6021
6022 /*-----------------------------------------------------------------*/
6023 /* genXor - code for xclusive or                                   */
6024 /*-----------------------------------------------------------------*/
6025 static void
6026 genXor (iCode * ic, iCode * ifx)
6027 {
6028   operand *left, *right, *result;
6029   int size, offset = 0;
6030   unsigned long lit = 0L;
6031   int bytelit = 0;
6032
6033   D(emitcode (";     genXor",""));
6034
6035   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6036   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6037   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6038
6039 #ifdef DEBUG_TYPE
6040   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6041             AOP_TYPE (result),
6042             AOP_TYPE (left), AOP_TYPE (right));
6043   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6044             AOP_SIZE (result),
6045             AOP_SIZE (left), AOP_SIZE (right));
6046 #endif
6047
6048   /* if left is a literal & right is not ||
6049      if left needs acc & right does not */
6050   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6051       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6052     {
6053       operand *tmp = right;
6054       right = left;
6055       left = tmp;
6056     }
6057
6058   /* if result = right then exchange them */
6059   if (sameRegs (AOP (result), AOP (right)))
6060     {
6061       operand *tmp = right;
6062       right = left;
6063       left = tmp;
6064     }
6065
6066   /* if right is bit then exchange them */
6067   if (AOP_TYPE (right) == AOP_CRY &&
6068       AOP_TYPE (left) != AOP_CRY)
6069     {
6070       operand *tmp = right;
6071       right = left;
6072       left = tmp;
6073     }
6074   if (AOP_TYPE (right) == AOP_LIT)
6075     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6076
6077   size = AOP_SIZE (result);
6078
6079   // if(bit ^ yy)
6080   // xx = bit ^ yy;
6081   if (AOP_TYPE (left) == AOP_CRY)
6082     {
6083       if (AOP_TYPE (right) == AOP_LIT)
6084         {
6085           // c = bit & literal;
6086           if (lit >> 1)
6087             {
6088               // lit>>1  != 0 => result = 1
6089               if (AOP_TYPE (result) == AOP_CRY)
6090                 {
6091                   if (size)
6092                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6093                   else if (ifx)
6094                     continueIfTrue (ifx);
6095                   goto release;
6096                 }
6097               emitcode ("setb", "c");
6098             }
6099           else
6100             {
6101               // lit == (0 or 1)
6102               if (lit == 0)
6103                 {
6104                   // lit == 0, result = left
6105                   if (size && sameRegs (AOP (result), AOP (left)))
6106                     goto release;
6107                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6108                 }
6109               else
6110                 {
6111                   // lit == 1, result = not(left)
6112                   if (size && sameRegs (AOP (result), AOP (left)))
6113                     {
6114                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6115                       goto release;
6116                     }
6117                   else
6118                     {
6119                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6120                       emitcode ("cpl", "c");
6121                     }
6122                 }
6123             }
6124
6125         }
6126       else
6127         {
6128           // right != literal
6129           symbol *tlbl = newiTempLabel (NULL);
6130           if (AOP_TYPE (right) == AOP_CRY)
6131             {
6132               // c = bit ^ bit;
6133               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6134             }
6135           else
6136             {
6137               int sizer = AOP_SIZE (right);
6138               // c = bit ^ val
6139               // if val>>1 != 0, result = 1
6140               emitcode ("setb", "c");
6141               while (sizer)
6142                 {
6143                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6144                   if (sizer == 1)
6145                     // test the msb of the lsb
6146                     emitcode ("anl", "a,#0xfe");
6147                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6148                   sizer--;
6149                 }
6150               // val = (0,1)
6151               emitcode ("rrc", "a");
6152             }
6153           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6154           emitcode ("cpl", "c");
6155           emitcode ("", "%05d$:", (tlbl->key + 100));
6156         }
6157       // bit = c
6158       // val = c
6159       if (size)
6160         outBitC (result);
6161       // if(bit | ...)
6162       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6163         genIfxJump (ifx, "c", left, right, result);
6164       goto release;
6165     }
6166
6167   /* if left is same as result */
6168   if (sameRegs (AOP (result), AOP (left)))
6169     {
6170       for (; size--; offset++)
6171         {
6172           if (AOP_TYPE (right) == AOP_LIT)
6173             {
6174               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6175               if (bytelit == 0)
6176                 {
6177                   /* dummy read of volatile operand */
6178                   if (isOperandVolatile (left, FALSE))
6179                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6180                   else
6181                 continue;
6182                 }
6183               else if (IS_AOP_PREG (left))
6184                 {
6185                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6186                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6187                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6188                 }
6189               else
6190                 {
6191                   emitcode ("xrl", "%s,%s",
6192                             aopGet (AOP (left), offset, FALSE, TRUE),
6193                             aopGet (AOP (right), offset, FALSE, FALSE));
6194                 }
6195             }
6196           else
6197             {
6198               if (AOP_TYPE (left) == AOP_ACC)
6199                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6200               else
6201                 {
6202                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6203                   if (IS_AOP_PREG (left))
6204                     {
6205                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6206                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6207                     }
6208                   else
6209                     emitcode ("xrl", "%s,a",
6210                               aopGet (AOP (left), offset, FALSE, TRUE));
6211                 }
6212             }
6213         }
6214     }
6215   else
6216     {
6217       // left & result in different registers
6218       if (AOP_TYPE (result) == AOP_CRY)
6219         {
6220           // result = bit
6221           // if(size), result in bit
6222           // if(!size && ifx), conditional oper: if(left ^ right)
6223           symbol *tlbl = newiTempLabel (NULL);
6224           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6225           if (size)
6226             emitcode ("setb", "c");
6227           while (sizer--)
6228             {
6229               if ((AOP_TYPE (right) == AOP_LIT) &&
6230                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6231                 {
6232                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6233                 }
6234               else
6235                 {
6236                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6237                     emitcode ("xrl", "a,%s",
6238                               aopGet (AOP (right), offset, FALSE, FALSE));
6239                   } else {
6240                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6241                     emitcode ("xrl", "a,%s",
6242                               aopGet (AOP (left), offset, FALSE, FALSE));
6243                   }
6244                 }
6245               emitcode ("jnz", "%05d$", tlbl->key + 100);
6246               offset++;
6247             }
6248           if (size)
6249             {
6250               CLRC;
6251               emitcode ("", "%05d$:", tlbl->key + 100);
6252               outBitC (result);
6253             }
6254           else if (ifx)
6255             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6256         }
6257       else
6258         {
6259           for (; (size--); offset++)
6260             {
6261               // normal case
6262               // result = left & right
6263               if (AOP_TYPE (right) == AOP_LIT)
6264                 {
6265                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6266                   if (bytelit == 0)
6267                     {
6268                       aopPut (AOP (result),
6269                               aopGet (AOP (left), offset, FALSE, FALSE),
6270                               offset,
6271                               isOperandVolatile (result, FALSE));
6272                       continue;
6273                     }
6274                 }
6275               // faster than result <- left, anl result,right
6276               // and better if result is SFR
6277               if (AOP_TYPE (left) == AOP_ACC)
6278                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6279               else
6280                 {
6281                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6282                   emitcode ("xrl", "a,%s",
6283                             aopGet (AOP (left), offset, FALSE, TRUE));
6284                 }
6285               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6286             }
6287         }
6288     }
6289
6290 release:
6291   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6292   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6293   freeAsmop (result, NULL, ic, TRUE);
6294 }
6295
6296 /*-----------------------------------------------------------------*/
6297 /* genInline - write the inline code out                           */
6298 /*-----------------------------------------------------------------*/
6299 static void
6300 genInline (iCode * ic)
6301 {
6302   char *buffer, *bp, *bp1;
6303
6304   D(emitcode (";     genInline",""));
6305
6306   _G.inLine += (!options.asmpeep);
6307
6308   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6309   strcpy (buffer, IC_INLINE (ic));
6310
6311   /* emit each line as a code */
6312   while (*bp)
6313     {
6314       if (*bp == '\n')
6315         {
6316           *bp++ = '\0';
6317           emitcode (bp1, "");
6318           bp1 = bp;
6319         }
6320       else
6321         {
6322           /* Add \n for labels, not dirs such as c:\mydir */
6323           if ( (*bp == ':') && (isspace(bp[1])) )
6324             {
6325               bp++;
6326               *bp = '\0';
6327               bp++;
6328               emitcode (bp1, "");
6329               bp1 = bp;
6330             }
6331           else
6332             bp++;
6333         }
6334     }
6335   if (bp1 != bp)
6336     emitcode (bp1, "");
6337   /*     emitcode("",buffer); */
6338   _G.inLine -= (!options.asmpeep);
6339 }
6340
6341 /*-----------------------------------------------------------------*/
6342 /* genRRC - rotate right with carry                                */
6343 /*-----------------------------------------------------------------*/
6344 static void
6345 genRRC (iCode * ic)
6346 {
6347   operand *left, *result;
6348   int size, offset = 0;
6349   char *l;
6350
6351   D(emitcode (";     genRRC",""));
6352
6353   /* rotate right with carry */
6354   left = IC_LEFT (ic);
6355   result = IC_RESULT (ic);
6356   aopOp (left, ic, FALSE);
6357   aopOp (result, ic, FALSE);
6358
6359   /* move it to the result */
6360   size = AOP_SIZE (result);
6361   offset = size - 1;
6362   if (size == 1) { /* special case for 1 byte */
6363       l = aopGet (AOP (left), offset, FALSE, FALSE);
6364       MOVA (l);
6365       emitcode ("rr", "a");
6366       goto release;
6367   }
6368   CLRC;
6369   while (size--)
6370     {
6371       l = aopGet (AOP (left), offset, FALSE, FALSE);
6372       MOVA (l);
6373       emitcode ("rrc", "a");
6374       if (AOP_SIZE (result) > 1)
6375         aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6376     }
6377   /* now we need to put the carry into the
6378      highest order byte of the result */
6379   if (AOP_SIZE (result) > 1)
6380     {
6381       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6382       MOVA (l);
6383     }
6384   emitcode ("mov", "acc.7,c");
6385  release:
6386   aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6387   freeAsmop (left, NULL, ic, TRUE);
6388   freeAsmop (result, NULL, ic, TRUE);
6389 }
6390
6391 /*-----------------------------------------------------------------*/
6392 /* genRLC - generate code for rotate left with carry               */
6393 /*-----------------------------------------------------------------*/
6394 static void
6395 genRLC (iCode * ic)
6396 {
6397   operand *left, *result;
6398   int size, offset = 0;
6399   char *l;
6400
6401   D(emitcode (";     genRLC",""));
6402
6403   /* rotate right with carry */
6404   left = IC_LEFT (ic);
6405   result = IC_RESULT (ic);
6406   aopOp (left, ic, FALSE);
6407   aopOp (result, ic, FALSE);
6408
6409   /* move it to the result */
6410   size = AOP_SIZE (result);
6411   offset = 0;
6412   if (size--)
6413     {
6414       l = aopGet (AOP (left), offset, FALSE, FALSE);
6415       MOVA (l);
6416       if (size == 0) { /* special case for 1 byte */
6417               emitcode("rl","a");
6418               goto release;
6419       }
6420       emitcode ("add", "a,acc");
6421       if (AOP_SIZE (result) > 1)
6422         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6423       while (size--)
6424         {
6425           l = aopGet (AOP (left), offset, FALSE, FALSE);
6426           MOVA (l);
6427           emitcode ("rlc", "a");
6428           if (AOP_SIZE (result) > 1)
6429             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6430         }
6431     }
6432   /* now we need to put the carry into the
6433      highest order byte of the result */
6434   if (AOP_SIZE (result) > 1)
6435     {
6436       l = aopGet (AOP (result), 0, FALSE, FALSE);
6437       MOVA (l);
6438     }
6439   emitcode ("mov", "acc.0,c");
6440  release:
6441   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6442   freeAsmop (left, NULL, ic, TRUE);
6443   freeAsmop (result, NULL, ic, TRUE);
6444 }
6445
6446 /*-----------------------------------------------------------------*/
6447 /* genGetHbit - generates code get highest order bit               */
6448 /*-----------------------------------------------------------------*/
6449 static void
6450 genGetHbit (iCode * ic)
6451 {
6452   operand *left, *result;
6453
6454   D(emitcode (";     genGetHbit",""));
6455
6456   left = IC_LEFT (ic);
6457   result = IC_RESULT (ic);
6458   aopOp (left, ic, FALSE);
6459   aopOp (result, ic, FALSE);
6460
6461   /* get the highest order byte into a */
6462   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6463   if (AOP_TYPE (result) == AOP_CRY)
6464     {
6465       emitcode ("rlc", "a");
6466       outBitC (result);
6467     }
6468   else
6469     {
6470       emitcode ("rl", "a");
6471       emitcode ("anl", "a,#0x01");
6472       outAcc (result);
6473     }
6474
6475
6476   freeAsmop (left, NULL, ic, TRUE);
6477   freeAsmop (result, NULL, ic, TRUE);
6478 }
6479
6480 /*-----------------------------------------------------------------*/
6481 /* genSwap - generates code to swap nibbles or bytes               */
6482 /*-----------------------------------------------------------------*/
6483 static void
6484 genSwap (iCode * ic)
6485 {
6486   operand *left, *result;
6487
6488   D(emitcode (";     genSwap",""));
6489
6490   left = IC_LEFT (ic);
6491   result = IC_RESULT (ic);
6492   aopOp (left, ic, FALSE);
6493   aopOp (result, ic, FALSE);
6494
6495   switch (AOP_SIZE (left))
6496     {
6497     case 1: /* swap nibbles in byte */
6498       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6499       emitcode ("swap", "a");
6500       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6501       break;
6502     case 2: /* swap bytes in word */
6503       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6504         {
6505           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6506           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6507                   0, isOperandVolatile (result, FALSE));
6508           aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6509         }
6510       else if (operandsEqu (left, result))
6511         {
6512           char * reg = "a";
6513           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6514           if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6515             {
6516               emitcode ("mov", "b,a");
6517               reg = "b";
6518             }
6519           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6520                   0, isOperandVolatile (result, FALSE));
6521           aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6522         }
6523       else
6524         {
6525           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6526                   0, isOperandVolatile (result, FALSE));
6527           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6528                   1, isOperandVolatile (result, FALSE));
6529         }
6530       break;
6531     default:
6532       wassertl(FALSE, "unsupported SWAP operand size");
6533     }
6534
6535   freeAsmop (left, NULL, ic, TRUE);
6536   freeAsmop (result, NULL, ic, TRUE);
6537 }
6538
6539
6540 /*-----------------------------------------------------------------*/
6541 /* AccRol - rotate left accumulator by known count                 */
6542 /*-----------------------------------------------------------------*/
6543 static void
6544 AccRol (int shCount)
6545 {
6546   shCount &= 0x0007;            // shCount : 0..7
6547
6548   switch (shCount)
6549     {
6550     case 0:
6551       break;
6552     case 1:
6553       emitcode ("rl", "a");
6554       break;
6555     case 2:
6556       emitcode ("rl", "a");
6557       emitcode ("rl", "a");
6558       break;
6559     case 3:
6560       emitcode ("swap", "a");
6561       emitcode ("rr", "a");
6562       break;
6563     case 4:
6564       emitcode ("swap", "a");
6565       break;
6566     case 5:
6567       emitcode ("swap", "a");
6568       emitcode ("rl", "a");
6569       break;
6570     case 6:
6571       emitcode ("rr", "a");
6572       emitcode ("rr", "a");
6573       break;
6574     case 7:
6575       emitcode ("rr", "a");
6576       break;
6577     }
6578 }
6579
6580 /*-----------------------------------------------------------------*/
6581 /* AccLsh - left shift accumulator by known count                  */
6582 /*-----------------------------------------------------------------*/
6583 static void
6584 AccLsh (int shCount)
6585 {
6586   if (shCount != 0)
6587     {
6588       if (shCount == 1)
6589         emitcode ("add", "a,acc");
6590       else if (shCount == 2)
6591         {
6592           emitcode ("add", "a,acc");
6593           emitcode ("add", "a,acc");
6594         }
6595       else
6596         {
6597           /* rotate left accumulator */
6598           AccRol (shCount);
6599           /* and kill the lower order bits */
6600           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6601         }
6602     }
6603 }
6604
6605 /*-----------------------------------------------------------------*/
6606 /* AccRsh - right shift accumulator by known count                 */
6607 /*-----------------------------------------------------------------*/
6608 static void
6609 AccRsh (int shCount)
6610 {
6611   if (shCount != 0)
6612     {
6613       if (shCount == 1)
6614         {
6615           CLRC;
6616           emitcode ("rrc", "a");
6617         }
6618       else
6619         {
6620           /* rotate right accumulator */
6621           AccRol (8 - shCount);
6622           /* and kill the higher order bits */
6623           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6624         }
6625     }
6626 }
6627
6628 /*-----------------------------------------------------------------*/
6629 /* AccSRsh - signed right shift accumulator by known count                 */
6630 /*-----------------------------------------------------------------*/
6631 static void
6632 AccSRsh (int shCount)
6633 {
6634   symbol *tlbl;
6635   if (shCount != 0)
6636     {
6637       if (shCount == 1)
6638         {
6639           emitcode ("mov", "c,acc.7");
6640           emitcode ("rrc", "a");
6641         }
6642       else if (shCount == 2)
6643         {
6644           emitcode ("mov", "c,acc.7");
6645           emitcode ("rrc", "a");
6646           emitcode ("mov", "c,acc.7");
6647           emitcode ("rrc", "a");
6648         }
6649       else
6650         {
6651           tlbl = newiTempLabel (NULL);
6652           /* rotate right accumulator */
6653           AccRol (8 - shCount);
6654           /* and kill the higher order bits */
6655           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6656           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6657           emitcode ("orl", "a,#0x%02x",
6658                     (unsigned char) ~SRMask[shCount]);
6659           emitcode ("", "%05d$:", tlbl->key + 100);
6660         }
6661     }
6662 }
6663
6664 /*-----------------------------------------------------------------*/
6665 /* shiftR1Left2Result - shift right one byte from left to result   */
6666 /*-----------------------------------------------------------------*/
6667 static void
6668 shiftR1Left2Result (operand * left, int offl,
6669                     operand * result, int offr,
6670                     int shCount, int sign)
6671 {
6672   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6673   /* shift right accumulator */
6674   if (sign)
6675     AccSRsh (shCount);
6676   else
6677     AccRsh (shCount);
6678   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6679 }
6680
6681 /*-----------------------------------------------------------------*/
6682 /* shiftL1Left2Result - shift left one byte from left to result    */
6683 /*-----------------------------------------------------------------*/
6684 static void
6685 shiftL1Left2Result (operand * left, int offl,
6686                     operand * result, int offr, int shCount)
6687 {
6688   char *l;
6689   l = aopGet (AOP (left), offl, FALSE, FALSE);
6690   MOVA (l);
6691   /* shift left accumulator */
6692   AccLsh (shCount);
6693   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6694 }
6695
6696 /*-----------------------------------------------------------------*/
6697 /* movLeft2Result - move byte from left to result                  */
6698 /*-----------------------------------------------------------------*/
6699 static void
6700 movLeft2Result (operand * left, int offl,
6701                 operand * result, int offr, int sign)
6702 {
6703   char *l;
6704   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6705     {
6706       l = aopGet (AOP (left), offl, FALSE, FALSE);
6707
6708       if (*l == '@' && (IS_AOP_PREG (result)))
6709         {
6710           emitcode ("mov", "a,%s", l);
6711           aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6712         }
6713       else
6714         {
6715           if (!sign)
6716             aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6717           else
6718             {
6719               /* MSB sign in acc.7 ! */
6720               if (getDataSize (left) == offl + 1)
6721                 {
6722                   emitcode ("mov", "a,%s", l);
6723                   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6724                 }
6725             }
6726         }
6727     }
6728 }
6729
6730 /*-----------------------------------------------------------------*/
6731 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6732 /*-----------------------------------------------------------------*/
6733 static void
6734 AccAXRrl1 (char *x)
6735 {
6736   emitcode ("rrc", "a");
6737   emitcode ("xch", "a,%s", x);
6738   emitcode ("rrc", "a");
6739   emitcode ("xch", "a,%s", x);
6740 }
6741
6742 /*-----------------------------------------------------------------*/
6743 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6744 /*-----------------------------------------------------------------*/
6745 static void
6746 AccAXLrl1 (char *x)
6747 {
6748   emitcode ("xch", "a,%s", x);
6749   emitcode ("rlc", "a");
6750   emitcode ("xch", "a,%s", x);
6751   emitcode ("rlc", "a");
6752 }
6753
6754 /*-----------------------------------------------------------------*/
6755 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6756 /*-----------------------------------------------------------------*/
6757 static void
6758 AccAXLsh1 (char *x)
6759 {
6760   emitcode ("xch", "a,%s", x);
6761   emitcode ("add", "a,acc");
6762   emitcode ("xch", "a,%s", x);
6763   emitcode ("rlc", "a");
6764 }
6765
6766 /*-----------------------------------------------------------------*/
6767 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6768 /*-----------------------------------------------------------------*/
6769 static void
6770 AccAXLsh (char *x, int shCount)
6771 {
6772   switch (shCount)
6773     {
6774     case 0:
6775       break;
6776     case 1:
6777       AccAXLsh1 (x);
6778       break;
6779     case 2:
6780       AccAXLsh1 (x);
6781       AccAXLsh1 (x);
6782       break;
6783     case 3:
6784     case 4:
6785     case 5:                     // AAAAABBB:CCCCCDDD
6786
6787       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6788
6789       emitcode ("anl", "a,#0x%02x",
6790                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6791
6792       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6793
6794       AccRol (shCount);         // DDDCCCCC:BBB00000
6795
6796       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6797
6798       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6799
6800       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6801
6802       emitcode ("anl", "a,#0x%02x",
6803                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6804
6805       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6806
6807       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6808
6809       break;
6810     case 6:                     // AAAAAABB:CCCCCCDD
6811       emitcode ("anl", "a,#0x%02x",
6812                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6813       emitcode ("mov", "c,acc.0");      // c = B
6814       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6815 #if 0 // REMOVE ME
6816       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6817       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6818 #else
6819       emitcode("rrc","a");
6820       emitcode("xch","a,%s", x);
6821       emitcode("rrc","a");
6822       emitcode("mov","c,acc.0"); //<< get correct bit
6823       emitcode("xch","a,%s", x);
6824
6825       emitcode("rrc","a");
6826       emitcode("xch","a,%s", x);
6827       emitcode("rrc","a");
6828       emitcode("xch","a,%s", x);
6829 #endif
6830       break;
6831     case 7:                     // a:x <<= 7
6832
6833       emitcode ("anl", "a,#0x%02x",
6834                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6835
6836       emitcode ("mov", "c,acc.0");      // c = B
6837
6838       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6839
6840       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6841
6842       break;
6843     default:
6844       break;
6845     }
6846 }
6847
6848 /*-----------------------------------------------------------------*/
6849 /* AccAXRsh - right shift a:x known count (0..7)                   */
6850 /*-----------------------------------------------------------------*/
6851 static void
6852 AccAXRsh (char *x, int shCount)
6853 {
6854   switch (shCount)
6855     {
6856     case 0:
6857       break;
6858     case 1:
6859       CLRC;
6860       AccAXRrl1 (x);            // 0->a:x
6861
6862       break;
6863     case 2:
6864       CLRC;
6865       AccAXRrl1 (x);            // 0->a:x
6866
6867       CLRC;
6868       AccAXRrl1 (x);            // 0->a:x
6869
6870       break;
6871     case 3:
6872     case 4:
6873     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6874
6875       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6876
6877       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6878
6879       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6880
6881       emitcode ("anl", "a,#0x%02x",
6882                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6883
6884       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6885
6886       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6887
6888       emitcode ("anl", "a,#0x%02x",
6889                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6890
6891       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6892
6893       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6894
6895       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6896
6897       break;
6898     case 6:                     // AABBBBBB:CCDDDDDD
6899
6900       emitcode ("mov", "c,acc.7");
6901       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6902
6903       emitcode ("mov", "c,acc.7");
6904       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6905
6906       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6907
6908       emitcode ("anl", "a,#0x%02x",
6909                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6910
6911       break;
6912     case 7:                     // ABBBBBBB:CDDDDDDD
6913
6914       emitcode ("mov", "c,acc.7");      // c = A
6915
6916       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6917
6918       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6919
6920       emitcode ("anl", "a,#0x%02x",
6921                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6922
6923       break;
6924     default:
6925       break;
6926     }
6927 }
6928
6929 /*-----------------------------------------------------------------*/
6930 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6931 /*-----------------------------------------------------------------*/
6932 static void
6933 AccAXRshS (char *x, int shCount)
6934 {
6935   symbol *tlbl;
6936   switch (shCount)
6937     {
6938     case 0:
6939       break;
6940     case 1:
6941       emitcode ("mov", "c,acc.7");
6942       AccAXRrl1 (x);            // s->a:x
6943
6944       break;
6945     case 2:
6946       emitcode ("mov", "c,acc.7");
6947       AccAXRrl1 (x);            // s->a:x
6948
6949       emitcode ("mov", "c,acc.7");
6950       AccAXRrl1 (x);            // s->a:x
6951
6952       break;
6953     case 3:
6954     case 4:
6955     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6956
6957       tlbl = newiTempLabel (NULL);
6958       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6959
6960       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6961
6962       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6963
6964       emitcode ("anl", "a,#0x%02x",
6965                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6966
6967       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6968
6969       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6970
6971       emitcode ("anl", "a,#0x%02x",
6972                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6973
6974       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6975
6976       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6977
6978       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6979
6980       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6981       emitcode ("orl", "a,#0x%02x",
6982                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6983
6984       emitcode ("", "%05d$:", tlbl->key + 100);
6985       break;                    // SSSSAAAA:BBBCCCCC
6986
6987     case 6:                     // AABBBBBB:CCDDDDDD
6988
6989       tlbl = newiTempLabel (NULL);
6990       emitcode ("mov", "c,acc.7");
6991       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6992
6993       emitcode ("mov", "c,acc.7");
6994       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6995
6996       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6997
6998       emitcode ("anl", "a,#0x%02x",
6999                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7000
7001       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7002       emitcode ("orl", "a,#0x%02x",
7003                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7004
7005       emitcode ("", "%05d$:", tlbl->key + 100);
7006       break;
7007     case 7:                     // ABBBBBBB:CDDDDDDD
7008
7009       tlbl = newiTempLabel (NULL);
7010       emitcode ("mov", "c,acc.7");      // c = A
7011
7012       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7013
7014       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7015
7016       emitcode ("anl", "a,#0x%02x",
7017                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7018
7019       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7020       emitcode ("orl", "a,#0x%02x",
7021                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7022
7023       emitcode ("", "%05d$:", tlbl->key + 100);
7024       break;
7025     default:
7026       break;
7027     }
7028 }
7029
7030 /*-----------------------------------------------------------------*/
7031 /* shiftL2Left2Result - shift left two bytes from left to result   */
7032 /*-----------------------------------------------------------------*/
7033 static void
7034 shiftL2Left2Result (operand * left, int offl,
7035                     operand * result, int offr, int shCount)
7036 {
7037   if (sameRegs (AOP (result), AOP (left)) &&
7038       ((offl + MSB16) == offr))
7039     {
7040       /* don't crash result[offr] */
7041       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7042       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7043     }
7044   else
7045     {
7046       movLeft2Result (left, offl, result, offr, 0);
7047       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7048     }
7049   /* ax << shCount (x = lsb(result)) */
7050   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7051   aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7052 }
7053
7054
7055 /*-----------------------------------------------------------------*/
7056 /* shiftR2Left2Result - shift right two bytes from left to result  */
7057 /*-----------------------------------------------------------------*/
7058 static void
7059 shiftR2Left2Result (operand * left, int offl,
7060                     operand * result, int offr,
7061                     int shCount, int sign)
7062 {
7063   if (sameRegs (AOP (result), AOP (left)) &&
7064       ((offl + MSB16) == offr))
7065     {
7066       /* don't crash result[offr] */
7067       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7068       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7069     }
7070   else
7071     {
7072       movLeft2Result (left, offl, result, offr, 0);
7073       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7074     }
7075   /* a:x >> shCount (x = lsb(result)) */
7076   if (sign)
7077     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7078   else
7079     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7080   if (getDataSize (result) > 1)
7081     aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7082 }
7083
7084 /*-----------------------------------------------------------------*/
7085 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7086 /*-----------------------------------------------------------------*/
7087 static void
7088 shiftLLeftOrResult (operand * left, int offl,
7089                     operand * result, int offr, int shCount)
7090 {
7091   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7092   /* shift left accumulator */
7093   AccLsh (shCount);
7094   /* or with result */
7095   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7096   /* back to result */
7097   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7098 }
7099
7100 /*-----------------------------------------------------------------*/
7101 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7102 /*-----------------------------------------------------------------*/
7103 static void
7104 shiftRLeftOrResult (operand * left, int offl,
7105                     operand * result, int offr, int shCount)
7106 {
7107   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7108   /* shift right accumulator */
7109   AccRsh (shCount);
7110   /* or with result */
7111   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7112   /* back to result */
7113   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7114 }
7115
7116 /*-----------------------------------------------------------------*/
7117 /* genlshOne - left shift a one byte quantity by known count       */
7118 /*-----------------------------------------------------------------*/
7119 static void
7120 genlshOne (operand * result, operand * left, int shCount)
7121 {
7122   D(emitcode (";     genlshOne",""));
7123
7124   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7125 }
7126
7127 /*-----------------------------------------------------------------*/
7128 /* genlshTwo - left shift two bytes by known amount != 0           */
7129 /*-----------------------------------------------------------------*/
7130 static void
7131 genlshTwo (operand * result, operand * left, int shCount)
7132 {
7133   int size;
7134
7135   D(emitcode (";     genlshTwo",""));
7136
7137   size = getDataSize (result);
7138
7139   /* if shCount >= 8 */
7140   if (shCount >= 8)
7141     {
7142       shCount -= 8;
7143
7144       if (size > 1)
7145         {
7146           if (shCount)
7147             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7148           else
7149             movLeft2Result (left, LSB, result, MSB16, 0);
7150         }
7151       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7152     }
7153
7154   /*  1 <= shCount <= 7 */
7155   else
7156     {
7157       if (size == 1)
7158         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7159       else
7160         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7161     }
7162 }
7163
7164 /*-----------------------------------------------------------------*/
7165 /* shiftLLong - shift left one long from left to result            */
7166 /* offl = LSB or MSB16                                             */
7167 /*-----------------------------------------------------------------*/
7168 static void
7169 shiftLLong (operand * left, operand * result, int offr)
7170 {
7171   char *l;
7172   int size = AOP_SIZE (result);
7173
7174   if (size >= LSB + offr)
7175     {
7176       l = aopGet (AOP (left), LSB, FALSE, FALSE);
7177       MOVA (l);
7178       emitcode ("add", "a,acc");
7179       if (sameRegs (AOP (left), AOP (result)) &&
7180           size >= MSB16 + offr && offr != LSB)
7181         emitcode ("xch", "a,%s",
7182                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7183       else
7184         aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7185     }
7186
7187   if (size >= MSB16 + offr)
7188     {
7189       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7190         {
7191           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7192           MOVA (l);
7193         }
7194       emitcode ("rlc", "a");
7195       if (sameRegs (AOP (left), AOP (result)) &&
7196           size >= MSB24 + offr && offr != LSB)
7197         emitcode ("xch", "a,%s",
7198                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7199       else
7200         aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7201     }
7202
7203   if (size >= MSB24 + offr)
7204     {
7205       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7206         {
7207           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7208           MOVA (l);
7209         }
7210       emitcode ("rlc", "a");
7211       if (sameRegs (AOP (left), AOP (result)) &&
7212           size >= MSB32 + offr && offr != LSB)
7213         emitcode ("xch", "a,%s",
7214                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7215       else
7216         aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7217     }
7218
7219   if (size > MSB32 + offr)
7220     {
7221       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7222         {
7223           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7224           MOVA (l);
7225         }
7226       emitcode ("rlc", "a");
7227       aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7228     }
7229   if (offr != LSB)
7230     aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7231 }
7232
7233 /*-----------------------------------------------------------------*/
7234 /* genlshFour - shift four byte by a known amount != 0             */
7235 /*-----------------------------------------------------------------*/
7236 static void
7237 genlshFour (operand * result, operand * left, int shCount)
7238 {
7239   int size;
7240
7241   D(emitcode (";     genlshFour",""));
7242
7243   size = AOP_SIZE (result);
7244
7245   /* if shifting more that 3 bytes */
7246   if (shCount >= 24)
7247     {
7248       shCount -= 24;
7249       if (shCount)
7250         /* lowest order of left goes to the highest
7251            order of the destination */
7252         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7253       else
7254         movLeft2Result (left, LSB, result, MSB32, 0);
7255       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7256       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7257       aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7258       return;
7259     }
7260
7261   /* more than two bytes */
7262   else if (shCount >= 16)
7263     {
7264       /* lower order two bytes goes to higher order two bytes */
7265       shCount -= 16;
7266       /* if some more remaining */
7267       if (shCount)
7268         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7269       else
7270         {
7271           movLeft2Result (left, MSB16, result, MSB32, 0);
7272           movLeft2Result (left, LSB, result, MSB24, 0);
7273         }
7274       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7275       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7276       return;
7277     }
7278
7279   /* if more than 1 byte */
7280   else if (shCount >= 8)
7281     {
7282       /* lower order three bytes goes to higher order  three bytes */
7283       shCount -= 8;
7284       if (size == 2)
7285         {
7286           if (shCount)
7287             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7288           else
7289             movLeft2Result (left, LSB, result, MSB16, 0);
7290         }
7291       else
7292         {                       /* size = 4 */
7293           if (shCount == 0)
7294             {
7295               movLeft2Result (left, MSB24, result, MSB32, 0);
7296               movLeft2Result (left, MSB16, result, MSB24, 0);
7297               movLeft2Result (left, LSB, result, MSB16, 0);
7298               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7299             }
7300           else if (shCount == 1)
7301             shiftLLong (left, result, MSB16);
7302           else
7303             {
7304               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7305               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7306               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7307               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7308             }
7309         }
7310     }
7311
7312   /* 1 <= shCount <= 7 */
7313   else if (shCount <= 2)
7314     {
7315       shiftLLong (left, result, LSB);
7316       if (shCount == 2)
7317         shiftLLong (result, result, LSB);
7318     }
7319   /* 3 <= shCount <= 7, optimize */
7320   else
7321     {
7322       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7323       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7324       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7325     }
7326 }
7327
7328 /*-----------------------------------------------------------------*/
7329 /* genLeftShiftLiteral - left shifting by known count              */
7330 /*-----------------------------------------------------------------*/
7331 static void
7332 genLeftShiftLiteral (operand * left,
7333                      operand * right,
7334                      operand * result,
7335                      iCode * ic)
7336 {
7337   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7338   int size;
7339
7340   D(emitcode (";     genLeftShiftLiteral",""));
7341
7342   freeAsmop (right, NULL, ic, TRUE);
7343
7344   aopOp (left, ic, FALSE);
7345   aopOp (result, ic, FALSE);
7346
7347   size = getSize (operandType (result));
7348
7349 #if VIEW_SIZE
7350   emitcode ("; shift left ", "result %d, left %d", size,
7351             AOP_SIZE (left));
7352 #endif
7353
7354   /* I suppose that the left size >= result size */
7355   if (shCount == 0)
7356     {
7357       while (size--)
7358         {
7359           movLeft2Result (left, size, result, size, 0);
7360         }
7361     }
7362
7363   else if (shCount >= (size * 8))
7364     while (size--)
7365       aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7366   else
7367     {
7368       switch (size)
7369         {
7370         case 1:
7371           genlshOne (result, left, shCount);
7372           break;
7373
7374         case 2:
7375           genlshTwo (result, left, shCount);
7376           break;
7377
7378         case 4:
7379           genlshFour (result, left, shCount);
7380           break;
7381         default:
7382           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7383                   "*** ack! mystery literal shift!\n");
7384           break;
7385         }
7386     }
7387   freeAsmop (left, NULL, ic, TRUE);
7388   freeAsmop (result, NULL, ic, TRUE);
7389 }
7390
7391 /*-----------------------------------------------------------------*/
7392 /* genLeftShift - generates code for left shifting                 */
7393 /*-----------------------------------------------------------------*/
7394 static void
7395 genLeftShift (iCode * ic)
7396 {
7397   operand *left, *right, *result;
7398   int size, offset;
7399   char *l;
7400   symbol *tlbl, *tlbl1;
7401
7402   D(emitcode (";     genLeftShift",""));
7403
7404   right = IC_RIGHT (ic);
7405   left = IC_LEFT (ic);
7406   result = IC_RESULT (ic);
7407
7408   aopOp (right, ic, FALSE);
7409
7410   /* if the shift count is known then do it
7411      as efficiently as possible */
7412   if (AOP_TYPE (right) == AOP_LIT)
7413     {
7414       genLeftShiftLiteral (left, right, result, ic);
7415       return;
7416     }
7417
7418   /* shift count is unknown then we have to form
7419      a loop get the loop count in B : Note: we take
7420      only the lower order byte since shifting
7421      more that 32 bits make no sense anyway, ( the
7422      largest size of an object can be only 32 bits ) */
7423
7424   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7425   emitcode ("inc", "b");
7426   freeAsmop (right, NULL, ic, TRUE);
7427   aopOp (left, ic, FALSE);
7428   aopOp (result, ic, FALSE);
7429
7430   /* now move the left to the result if they are not the
7431      same */
7432   if (!sameRegs (AOP (left), AOP (result)) &&
7433       AOP_SIZE (result) > 1)
7434     {
7435
7436       size = AOP_SIZE (result);
7437       offset = 0;
7438       while (size--)
7439         {
7440           l = aopGet (AOP (left), offset, FALSE, TRUE);
7441           if (*l == '@' && (IS_AOP_PREG (result)))
7442             {
7443
7444               emitcode ("mov", "a,%s", l);
7445               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7446             }
7447           else
7448             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7449           offset++;
7450         }
7451     }
7452
7453   tlbl = newiTempLabel (NULL);
7454   size = AOP_SIZE (result);
7455   offset = 0;
7456   tlbl1 = newiTempLabel (NULL);
7457
7458   /* if it is only one byte then */
7459   if (size == 1)
7460     {
7461       symbol *tlbl1 = newiTempLabel (NULL);
7462
7463       l = aopGet (AOP (left), 0, FALSE, FALSE);
7464       MOVA (l);
7465       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7466       emitcode ("", "%05d$:", tlbl->key + 100);
7467       emitcode ("add", "a,acc");
7468       emitcode ("", "%05d$:", tlbl1->key + 100);
7469       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7470       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7471       goto release;
7472     }
7473
7474   reAdjustPreg (AOP (result));
7475
7476   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7477   emitcode ("", "%05d$:", tlbl->key + 100);
7478   l = aopGet (AOP (result), offset, FALSE, FALSE);
7479   MOVA (l);
7480   emitcode ("add", "a,acc");
7481   aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7482   while (--size)
7483     {
7484       l = aopGet (AOP (result), offset, FALSE, FALSE);
7485       MOVA (l);
7486       emitcode ("rlc", "a");
7487       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7488     }
7489   reAdjustPreg (AOP (result));
7490
7491   emitcode ("", "%05d$:", tlbl1->key + 100);
7492   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7493 release:
7494   freeAsmop (left, NULL, ic, TRUE);
7495   freeAsmop (result, NULL, ic, TRUE);
7496 }
7497
7498 /*-----------------------------------------------------------------*/
7499 /* genrshOne - right shift a one byte quantity by known count      */
7500 /*-----------------------------------------------------------------*/
7501 static void
7502 genrshOne (operand * result, operand * left,
7503            int shCount, int sign)
7504 {
7505   D(emitcode (";     genrshOne",""));
7506
7507   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7508 }
7509
7510 /*-----------------------------------------------------------------*/
7511 /* genrshTwo - right shift two bytes by known amount != 0          */
7512 /*-----------------------------------------------------------------*/
7513 static void
7514 genrshTwo (operand * result, operand * left,
7515            int shCount, int sign)
7516 {
7517   D(emitcode (";     genrshTwo",""));
7518
7519   /* if shCount >= 8 */
7520   if (shCount >= 8)
7521     {
7522       shCount -= 8;
7523       if (shCount)
7524         shiftR1Left2Result (left, MSB16, result, LSB,
7525                             shCount, sign);
7526       else
7527         movLeft2Result (left, MSB16, result, LSB, sign);
7528       addSign (result, MSB16, sign);
7529     }
7530
7531   /*  1 <= shCount <= 7 */
7532   else
7533     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7534 }
7535
7536 /*-----------------------------------------------------------------*/
7537 /* shiftRLong - shift right one long from left to result           */
7538 /* offl = LSB or MSB16                                             */
7539 /*-----------------------------------------------------------------*/
7540 static void
7541 shiftRLong (operand * left, int offl,
7542             operand * result, int sign)
7543 {
7544   int isSameRegs=sameRegs(AOP(left),AOP(result));
7545
7546   if (isSameRegs && offl>1) {
7547     // we are in big trouble, but this shouldn't happen
7548     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7549   }
7550
7551   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7552
7553   if (offl==MSB16) {
7554     // shift is > 8
7555     if (sign) {
7556       emitcode ("rlc", "a");
7557       emitcode ("subb", "a,acc");
7558       if (isSameRegs)
7559         emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7560       else {
7561         aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7562         MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7563       }
7564     } else {
7565       aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7566     }
7567   }
7568
7569   if (!sign) {
7570     emitcode ("clr", "c");
7571   } else {
7572     emitcode ("mov", "c,acc.7");
7573   }
7574
7575   emitcode ("rrc", "a");
7576
7577   if (isSameRegs && offl==MSB16) {
7578     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7579   } else {
7580     aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7581     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7582   }
7583
7584   emitcode ("rrc", "a");
7585   if (isSameRegs && offl==1) {
7586     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7587   } else {
7588     aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7589     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7590   }
7591   emitcode ("rrc", "a");
7592   aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7593
7594   if (offl == LSB)
7595     {
7596       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7597       emitcode ("rrc", "a");
7598       aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7599     }
7600 }
7601
7602 /*-----------------------------------------------------------------*/
7603 /* genrshFour - shift four byte by a known amount != 0             */
7604 /*-----------------------------------------------------------------*/
7605 static void
7606 genrshFour (operand * result, operand * left,
7607             int shCount, int sign)
7608 {
7609   D(emitcode (";     genrshFour",""));
7610
7611   /* if shifting more that 3 bytes */
7612   if (shCount >= 24)
7613     {
7614       shCount -= 24;
7615       if (shCount)
7616         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7617       else
7618         movLeft2Result (left, MSB32, result, LSB, sign);
7619       addSign (result, MSB16, sign);
7620     }
7621   else if (shCount >= 16)
7622     {
7623       shCount -= 16;
7624       if (shCount)
7625         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7626       else
7627         {
7628           movLeft2Result (left, MSB24, result, LSB, 0);
7629           movLeft2Result (left, MSB32, result, MSB16, sign);
7630         }
7631       addSign (result, MSB24, sign);
7632     }
7633   else if (shCount >= 8)
7634     {
7635       shCount -= 8;
7636       if (shCount == 1)
7637         shiftRLong (left, MSB16, result, sign);
7638       else if (shCount == 0)
7639         {
7640           movLeft2Result (left, MSB16, result, LSB, 0);
7641           movLeft2Result (left, MSB24, result, MSB16, 0);
7642           movLeft2Result (left, MSB32, result, MSB24, sign);
7643           addSign (result, MSB32, sign);
7644         }
7645       else
7646         {
7647           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7648           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7649           /* the last shift is signed */
7650           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7651           addSign (result, MSB32, sign);
7652         }
7653     }
7654   else
7655     {                           /* 1 <= shCount <= 7 */
7656       if (shCount <= 2)
7657         {
7658           shiftRLong (left, LSB, result, sign);
7659           if (shCount == 2)
7660             shiftRLong (result, LSB, result, sign);
7661         }
7662       else
7663         {
7664           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7665           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7666           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7667         }
7668     }
7669 }
7670
7671 /*-----------------------------------------------------------------*/
7672 /* genRightShiftLiteral - right shifting by known count            */
7673 /*-----------------------------------------------------------------*/
7674 static void
7675 genRightShiftLiteral (operand * left,
7676                       operand * right,
7677                       operand * result,
7678                       iCode * ic,
7679                       int sign)
7680 {
7681   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7682   int size;
7683
7684   D(emitcode (";     genRightShiftLiteral",""));
7685
7686   freeAsmop (right, NULL, ic, TRUE);
7687
7688   aopOp (left, ic, FALSE);
7689   aopOp (result, ic, FALSE);
7690
7691 #if VIEW_SIZE
7692   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7693             AOP_SIZE (left));
7694 #endif
7695
7696   size = getDataSize (left);
7697   /* test the LEFT size !!! */
7698
7699   /* I suppose that the left size >= result size */
7700   if (shCount == 0)
7701     {
7702       size = getDataSize (result);
7703       while (size--)
7704         movLeft2Result (left, size, result, size, 0);
7705     }
7706
7707   else if (shCount >= (size * 8))
7708     {
7709       if (sign) {
7710         /* get sign in acc.7 */
7711         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7712       }
7713       addSign (result, LSB, sign);
7714     }
7715   else
7716     {
7717       switch (size)
7718         {
7719         case 1:
7720           genrshOne (result, left, shCount, sign);
7721           break;
7722
7723         case 2:
7724           genrshTwo (result, left, shCount, sign);
7725           break;
7726
7727         case 4:
7728           genrshFour (result, left, shCount, sign);
7729           break;
7730         default:
7731           break;
7732         }
7733     }
7734   freeAsmop (left, NULL, ic, TRUE);
7735   freeAsmop (result, NULL, ic, TRUE);
7736 }
7737
7738 /*-----------------------------------------------------------------*/
7739 /* genSignedRightShift - right shift of signed number              */
7740 /*-----------------------------------------------------------------*/
7741 static void
7742 genSignedRightShift (iCode * ic)
7743 {
7744   operand *right, *left, *result;
7745   int size, offset;
7746   char *l;
7747   symbol *tlbl, *tlbl1;
7748
7749   D(emitcode (";     genSignedRightShift",""));
7750
7751   /* we do it the hard way put the shift count in b
7752      and loop thru preserving the sign */
7753
7754   right = IC_RIGHT (ic);
7755   left = IC_LEFT (ic);
7756   result = IC_RESULT (ic);
7757
7758   aopOp (right, ic, FALSE);
7759
7760
7761   if (AOP_TYPE (right) == AOP_LIT)
7762     {
7763       genRightShiftLiteral (left, right, result, ic, 1);
7764       return;
7765     }
7766   /* shift count is unknown then we have to form
7767      a loop get the loop count in B : Note: we take
7768      only the lower order byte since shifting
7769      more that 32 bits make no sense anyway, ( the
7770      largest size of an object can be only 32 bits ) */
7771
7772   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7773   emitcode ("inc", "b");
7774   freeAsmop (right, NULL, ic, TRUE);
7775   aopOp (left, ic, FALSE);
7776   aopOp (result, ic, FALSE);
7777
7778   /* now move the left to the result if they are not the
7779      same */
7780   if (!sameRegs (AOP (left), AOP (result)) &&
7781       AOP_SIZE (result) > 1)
7782     {
7783
7784       size = AOP_SIZE (result);
7785       offset = 0;
7786       while (size--)
7787         {
7788           l = aopGet (AOP (left), offset, FALSE, TRUE);
7789           if (*l == '@' && IS_AOP_PREG (result))
7790             {
7791
7792               emitcode ("mov", "a,%s", l);
7793               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7794             }
7795           else
7796             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7797           offset++;
7798         }
7799     }
7800
7801   /* mov the highest order bit to OVR */
7802   tlbl = newiTempLabel (NULL);
7803   tlbl1 = newiTempLabel (NULL);
7804
7805   size = AOP_SIZE (result);
7806   offset = size - 1;
7807   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
7808   emitcode ("rlc", "a");
7809   emitcode ("mov", "ov,c");
7810   /* if it is only one byte then */
7811   if (size == 1)
7812     {
7813       l = aopGet (AOP (left), 0, FALSE, FALSE);
7814       MOVA (l);
7815       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7816       emitcode ("", "%05d$:", tlbl->key + 100);
7817       emitcode ("mov", "c,ov");
7818       emitcode ("rrc", "a");
7819       emitcode ("", "%05d$:", tlbl1->key + 100);
7820       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7821       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7822       goto release;
7823     }
7824
7825   reAdjustPreg (AOP (result));
7826   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7827   emitcode ("", "%05d$:", tlbl->key + 100);
7828   emitcode ("mov", "c,ov");
7829   while (size--)
7830     {
7831       l = aopGet (AOP (result), offset, FALSE, FALSE);
7832       MOVA (l);
7833       emitcode ("rrc", "a");
7834       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7835     }
7836   reAdjustPreg (AOP (result));
7837   emitcode ("", "%05d$:", tlbl1->key + 100);
7838   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7839
7840 release:
7841   freeAsmop (left, NULL, ic, TRUE);
7842   freeAsmop (result, NULL, ic, TRUE);
7843 }
7844
7845 /*-----------------------------------------------------------------*/
7846 /* genRightShift - generate code for right shifting                */
7847 /*-----------------------------------------------------------------*/
7848 static void
7849 genRightShift (iCode * ic)
7850 {
7851   operand *right, *left, *result;
7852   sym_link *letype;
7853   int size, offset;
7854   char *l;
7855   symbol *tlbl, *tlbl1;
7856
7857   D(emitcode (";     genRightShift",""));
7858
7859   /* if signed then we do it the hard way preserve the
7860      sign bit moving it inwards */
7861   letype = getSpec (operandType (IC_LEFT (ic)));
7862
7863   if (!SPEC_USIGN (letype))
7864     {
7865       genSignedRightShift (ic);
7866       return;
7867     }
7868
7869   /* signed & unsigned types are treated the same : i.e. the
7870      signed is NOT propagated inwards : quoting from the
7871      ANSI - standard : "for E1 >> E2, is equivalent to division
7872      by 2**E2 if unsigned or if it has a non-negative value,
7873      otherwise the result is implementation defined ", MY definition
7874      is that the sign does not get propagated */
7875
7876   right = IC_RIGHT (ic);
7877   left = IC_LEFT (ic);
7878   result = IC_RESULT (ic);
7879
7880   aopOp (right, ic, FALSE);
7881
7882   /* if the shift count is known then do it
7883      as efficiently as possible */
7884   if (AOP_TYPE (right) == AOP_LIT)
7885     {
7886       genRightShiftLiteral (left, right, result, ic, 0);
7887       return;
7888     }
7889
7890   /* shift count is unknown then we have to form
7891      a loop get the loop count in B : Note: we take
7892      only the lower order byte since shifting
7893      more that 32 bits make no sense anyway, ( the
7894      largest size of an object can be only 32 bits ) */
7895
7896   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7897   emitcode ("inc", "b");
7898   freeAsmop (right, NULL, ic, TRUE);
7899   aopOp (left, ic, FALSE);
7900   aopOp (result, ic, FALSE);
7901
7902   /* now move the left to the result if they are not the
7903      same */
7904   if (!sameRegs (AOP (left), AOP (result)) &&
7905       AOP_SIZE (result) > 1)
7906     {
7907
7908       size = AOP_SIZE (result);
7909       offset = 0;
7910       while (size--)
7911         {
7912           l = aopGet (AOP (left), offset, FALSE, TRUE);
7913           if (*l == '@' && IS_AOP_PREG (result))
7914             {
7915
7916               emitcode ("mov", "a,%s", l);
7917               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7918             }
7919           else
7920             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7921           offset++;
7922         }
7923     }
7924
7925   tlbl = newiTempLabel (NULL);
7926   tlbl1 = newiTempLabel (NULL);
7927   size = AOP_SIZE (result);
7928   offset = size - 1;
7929
7930   /* if it is only one byte then */
7931   if (size == 1)
7932     {
7933       l = aopGet (AOP (left), 0, FALSE, FALSE);
7934       MOVA (l);
7935       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7936       emitcode ("", "%05d$:", tlbl->key + 100);
7937       CLRC;
7938       emitcode ("rrc", "a");
7939       emitcode ("", "%05d$:", tlbl1->key + 100);
7940       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7941       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7942       goto release;
7943     }
7944
7945   reAdjustPreg (AOP (result));
7946   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7947   emitcode ("", "%05d$:", tlbl->key + 100);
7948   CLRC;
7949   while (size--)
7950     {
7951       l = aopGet (AOP (result), offset, FALSE, FALSE);
7952       MOVA (l);
7953       emitcode ("rrc", "a");
7954       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7955     }
7956   reAdjustPreg (AOP (result));
7957
7958   emitcode ("", "%05d$:", tlbl1->key + 100);
7959   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7960
7961 release:
7962   freeAsmop (left, NULL, ic, TRUE);
7963   freeAsmop (result, NULL, ic, TRUE);
7964 }
7965
7966 /*-----------------------------------------------------------------*/
7967 /* emitPtrByteGet - emits code to get a byte into A through a      */
7968 /*                  pointer register (R0, R1, or DPTR). The        */
7969 /*                  original value of A can be preserved in B.     */
7970 /*-----------------------------------------------------------------*/
7971 static void
7972 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7973 {
7974   switch (p_type)
7975     {
7976     case IPOINTER:
7977     case POINTER:
7978       if (preserveAinB)
7979         emitcode ("mov", "b,a");
7980       emitcode ("mov", "a,@%s", rname);
7981       break;
7982
7983     case PPOINTER:
7984       if (preserveAinB)
7985         emitcode ("mov", "b,a");
7986       emitcode ("movx", "a,@%s", rname);
7987       break;
7988
7989     case FPOINTER:
7990       if (preserveAinB)
7991         emitcode ("mov", "b,a");
7992       emitcode ("movx", "a,@dptr");
7993       break;
7994
7995     case CPOINTER:
7996       if (preserveAinB)
7997         emitcode ("mov", "b,a");
7998       emitcode ("clr", "a");
7999       emitcode ("movc", "a,@a+dptr");
8000       break;
8001
8002     case GPOINTER:
8003       if (preserveAinB)
8004         {
8005           emitcode ("push", "b");
8006           emitcode ("push", "acc");
8007         }
8008       emitcode ("lcall", "__gptrget");
8009       if (preserveAinB)
8010         emitcode ("pop", "b");
8011       break;
8012     }
8013 }
8014
8015 /*-----------------------------------------------------------------*/
8016 /* emitPtrByteSet - emits code to set a byte from src through a    */
8017 /*                  pointer register (R0, R1, or DPTR).            */
8018 /*-----------------------------------------------------------------*/
8019 static void
8020 emitPtrByteSet (char *rname, int p_type, char *src)
8021 {
8022   switch (p_type)
8023     {
8024     case IPOINTER:
8025     case POINTER:
8026       if (*src=='@')
8027         {
8028           MOVA (src);
8029           emitcode ("mov", "@%s,a", rname);
8030         }
8031       else
8032         emitcode ("mov", "@%s,%s", rname, src);
8033       break;
8034
8035     case PPOINTER:
8036       MOVA (src);
8037       emitcode ("movx", "@%s,a", rname);
8038       break;
8039
8040     case FPOINTER:
8041       MOVA (src);
8042       emitcode ("movx", "@dptr,a");
8043       break;
8044
8045     case GPOINTER:
8046       MOVA (src);
8047       emitcode ("lcall", "__gptrput");
8048       break;
8049     }
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* genUnpackBits - generates code for unpacking bits               */
8054 /*-----------------------------------------------------------------*/
8055 static void
8056 genUnpackBits (operand * result, char *rname, int ptype)
8057 {
8058   int offset = 0;       /* result byte offset */
8059   int rsize;            /* result size */
8060   int rlen = 0;         /* remaining bitfield length */
8061   sym_link *etype;      /* bitfield type information */
8062   int blen;             /* bitfield length */
8063   int bstr;             /* bitfield starting bit within byte */
8064
8065   D(emitcode (";     genUnpackBits",""));
8066
8067   etype = getSpec (operandType (result));
8068   rsize = getSize (operandType (result));
8069   blen = SPEC_BLEN (etype);
8070   bstr = SPEC_BSTR (etype);
8071
8072   /* If the bitfield length is less than a byte */
8073   if (blen < 8)
8074     {
8075       emitPtrByteGet (rname, ptype, FALSE);
8076       AccRsh (bstr);
8077       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8078       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8079       goto finish;
8080     }
8081
8082   /* Bit field did not fit in a byte. Copy all
8083      but the partial byte at the end.  */
8084   for (rlen=blen;rlen>=8;rlen-=8)
8085     {
8086       emitPtrByteGet (rname, ptype, FALSE);
8087       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8088       if (rlen>8)
8089         emitcode ("inc", "%s", rname);
8090     }
8091
8092   /* Handle the partial byte at the end */
8093   if (rlen)
8094     {
8095       emitPtrByteGet (rname, ptype, FALSE);
8096       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8097       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8098     }
8099
8100 finish:
8101   if (offset < rsize)
8102     {
8103       rsize -= offset;
8104       while (rsize--)
8105         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8106     }
8107 }
8108
8109
8110 /*-----------------------------------------------------------------*/
8111 /* genDataPointerGet - generates code when ptr offset is known     */
8112 /*-----------------------------------------------------------------*/
8113 static void
8114 genDataPointerGet (operand * left,
8115                    operand * result,
8116                    iCode * ic)
8117 {
8118   char *l;
8119   char buffer[256];
8120   int size, offset = 0;
8121
8122   D(emitcode (";     genDataPointerGet",""));
8123
8124   aopOp (result, ic, TRUE);
8125
8126   /* get the string representation of the name */
8127   l = aopGet (AOP (left), 0, FALSE, TRUE);
8128   size = AOP_SIZE (result);
8129   while (size--)
8130     {
8131       if (offset)
8132         sprintf (buffer, "(%s + %d)", l + 1, offset);
8133       else
8134         sprintf (buffer, "%s", l + 1);
8135       aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8136     }
8137
8138   freeAsmop (left, NULL, ic, TRUE);
8139   freeAsmop (result, NULL, ic, TRUE);
8140 }
8141
8142 /*-----------------------------------------------------------------*/
8143 /* genNearPointerGet - emitcode for near pointer fetch             */
8144 /*-----------------------------------------------------------------*/
8145 static void
8146 genNearPointerGet (operand * left,
8147                    operand * result,
8148                    iCode * ic,
8149                    iCode * pi)
8150 {
8151   asmop *aop = NULL;
8152   regs *preg = NULL;
8153   char *rname;
8154   sym_link *rtype, *retype;
8155   sym_link *ltype = operandType (left);
8156   char buffer[80];
8157
8158   D(emitcode (";     genNearPointerGet",""));
8159
8160   rtype = operandType (result);
8161   retype = getSpec (rtype);
8162
8163   aopOp (left, ic, FALSE);
8164
8165   /* if left is rematerialisable and
8166      result is not bitfield variable type and
8167      the left is pointer to data space i.e
8168      lower 128 bytes of space */
8169   if (AOP_TYPE (left) == AOP_IMMD &&
8170       !IS_BITFIELD (retype) &&
8171       DCL_TYPE (ltype) == POINTER)
8172     {
8173       genDataPointerGet (left, result, ic);
8174       return;
8175     }
8176
8177  /* if the value is already in a pointer register
8178      then don't need anything more */
8179   if (!AOP_INPREG (AOP (left)))
8180     {
8181       if (IS_AOP_PREG (left))
8182         {
8183           // Aha, it is a pointer, just in disguise.
8184           rname = aopGet (AOP (left), 0, FALSE, FALSE);
8185           if (*rname != '@')
8186             {
8187               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8188                       __FILE__, __LINE__);
8189             }
8190           else
8191             {
8192               // Expected case.
8193               emitcode ("mov", "a%s,%s", rname + 1, rname);
8194               rname++;  // skip the '@'.
8195             }
8196         }
8197       else
8198         {
8199           /* otherwise get a free pointer register */
8200           aop = newAsmop (0);
8201           preg = getFreePtr (ic, &aop, FALSE);
8202           emitcode ("mov", "%s,%s",
8203                     preg->name,
8204                     aopGet (AOP (left), 0, FALSE, TRUE));
8205           rname = preg->name;
8206         }
8207     }
8208   else
8209     rname = aopGet (AOP (left), 0, FALSE, FALSE);
8210
8211   //aopOp (result, ic, FALSE);
8212   aopOp (result, ic, result?TRUE:FALSE);
8213
8214   /* if bitfield then unpack the bits */
8215   if (IS_BITFIELD (retype))
8216     genUnpackBits (result, rname, POINTER);
8217   else
8218     {
8219       /* we have can just get the values */
8220       int size = AOP_SIZE (result);
8221       int offset = 0;
8222
8223       while (size--)
8224         {
8225           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8226             {
8227
8228               emitcode ("mov", "a,@%s", rname);
8229               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8230             }
8231           else
8232             {
8233               sprintf (buffer, "@%s", rname);
8234               aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8235             }
8236           offset++;
8237           if (size || pi)
8238             emitcode ("inc", "%s", rname);
8239         }
8240     }
8241
8242   /* now some housekeeping stuff */
8243   if (aop)       /* we had to allocate for this iCode */
8244     {
8245       if (pi) { /* post increment present */
8246         aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8247       }
8248       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8249     }
8250   else
8251     {
8252       /* we did not allocate which means left
8253          already in a pointer register, then
8254          if size > 0 && this could be used again
8255          we have to point it back to where it
8256          belongs */
8257       if ((AOP_SIZE (result) > 1 &&
8258            !OP_SYMBOL (left)->remat &&
8259            (OP_SYMBOL (left)->liveTo > ic->seq ||
8260             ic->depth)) &&
8261           !pi)
8262         {
8263           int size = AOP_SIZE (result) - 1;
8264           while (size--)
8265             emitcode ("dec", "%s", rname);
8266         }
8267     }
8268
8269   /* done */
8270   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8271   freeAsmop (left, NULL, ic, TRUE);
8272   if (pi) pi->generated = 1;
8273 }
8274
8275 /*-----------------------------------------------------------------*/
8276 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8277 /*-----------------------------------------------------------------*/
8278 static void
8279 genPagedPointerGet (operand * left,
8280                     operand * result,
8281                     iCode * ic,
8282                     iCode *pi)
8283 {
8284   asmop *aop = NULL;
8285   regs *preg = NULL;
8286   char *rname;
8287   sym_link *rtype, *retype;
8288
8289   D(emitcode (";     genPagedPointerGet",""));
8290
8291   rtype = operandType (result);
8292   retype = getSpec (rtype);
8293
8294   aopOp (left, ic, FALSE);
8295
8296   /* if the value is already in a pointer register
8297      then don't need anything more */
8298   if (!AOP_INPREG (AOP (left)))
8299     {
8300       /* otherwise get a free pointer register */
8301       aop = newAsmop (0);
8302       preg = getFreePtr (ic, &aop, FALSE);
8303       emitcode ("mov", "%s,%s",
8304                 preg->name,
8305                 aopGet (AOP (left), 0, FALSE, TRUE));
8306       rname = preg->name;
8307     }
8308   else
8309     rname = aopGet (AOP (left), 0, FALSE, FALSE);
8310
8311   aopOp (result, ic, FALSE);
8312
8313   /* if bitfield then unpack the bits */
8314   if (IS_BITFIELD (retype))
8315     genUnpackBits (result, rname, PPOINTER);
8316   else
8317     {
8318       /* we have can just get the values */
8319       int size = AOP_SIZE (result);
8320       int offset = 0;
8321
8322       while (size--)
8323         {
8324
8325           emitcode ("movx", "a,@%s", rname);
8326           aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8327
8328           offset++;
8329
8330           if (size || pi)
8331             emitcode ("inc", "%s", rname);
8332         }
8333     }
8334
8335   /* now some housekeeping stuff */
8336   if (aop) /* we had to allocate for this iCode */
8337     {
8338       if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8339       freeAsmop (NULL, aop, ic, TRUE);
8340     }
8341   else
8342     {
8343       /* we did not allocate which means left
8344          already in a pointer register, then
8345          if size > 0 && this could be used again
8346          we have to point it back to where it
8347          belongs */
8348       if ((AOP_SIZE (result) > 1 &&
8349            !OP_SYMBOL (left)->remat &&
8350            (OP_SYMBOL (left)->liveTo > ic->seq ||
8351             ic->depth)) &&
8352           !pi)
8353         {
8354           int size = AOP_SIZE (result) - 1;
8355           while (size--)
8356             emitcode ("dec", "%s", rname);
8357         }
8358     }
8359
8360   /* done */
8361   freeAsmop (left, NULL, ic, TRUE);
8362   freeAsmop (result, NULL, ic, TRUE);
8363   if (pi) pi->generated = 1;
8364
8365 }
8366
8367 /*--------------------------------------------------------------------*/
8368 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8369 /*--------------------------------------------------------------------*/
8370 static void
8371 loadDptrFromOperand (operand *op, bool loadBToo)
8372 {
8373   if (AOP_TYPE (op) != AOP_STR)
8374     {
8375       /* if this is remateriazable */
8376       if (AOP_TYPE (op) == AOP_IMMD)
8377         {
8378           emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8379           if (loadBToo)
8380             {
8381               if (AOP(op)->aopu.aop_immd.from_cast_remat)
8382                 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8383               else
8384                 {
8385                   wassertl(FALSE, "need pointerCode");
8386                   emitcode ("", "; mov b,???");
8387                   /* genPointerGet and genPointerSet originally did different
8388                   ** things for this case. Both seem wrong.
8389                   ** from genPointerGet:
8390                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
8391                   ** from genPointerSet:
8392                   **  emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8393                   */
8394                 }
8395             }
8396         }
8397       else if (AOP_TYPE (op) == AOP_DPTR)
8398         {
8399           if (loadBToo)
8400             {
8401               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8402               emitcode ("push", "acc");
8403               MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8404               emitcode ("push", "acc");
8405               emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8406               emitcode ("pop", "dph");
8407               emitcode ("pop", "dpl");
8408             }
8409           else
8410             {
8411               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8412               emitcode ("push", "acc");
8413               emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8414               emitcode ("pop", "dpl");
8415             }
8416         }
8417       else
8418         {                       /* we need to get it byte by byte */
8419           emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8420           emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8421           if (loadBToo)
8422             emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8423         }
8424     }
8425 }
8426
8427 /*-----------------------------------------------------------------*/
8428 /* genFarPointerGet - gget value from far space                    */
8429 /*-----------------------------------------------------------------*/
8430 static void
8431 genFarPointerGet (operand * left,
8432                   operand * result, iCode * ic, iCode * pi)
8433 {
8434   int size, offset;
8435   sym_link *retype = getSpec (operandType (result));
8436
8437   D(emitcode (";     genFarPointerGet",""));
8438
8439   aopOp (left, ic, FALSE);
8440   loadDptrFromOperand (left, FALSE);
8441
8442   /* so dptr now contains the address */
8443   aopOp (result, ic, FALSE);
8444
8445   /* if bit then unpack */
8446   if (IS_BITFIELD (retype))
8447     genUnpackBits (result, "dptr", FPOINTER);
8448   else
8449     {
8450       size = AOP_SIZE (result);
8451       offset = 0;
8452
8453       while (size--)
8454         {
8455           emitcode ("movx", "a,@dptr");
8456           aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8457           if (size || pi)
8458             emitcode ("inc", "dptr");
8459         }
8460     }
8461
8462   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8463     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8464     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8465     pi->generated = 1;
8466   }
8467   freeAsmop (left, NULL, ic, TRUE);
8468   freeAsmop (result, NULL, ic, TRUE);
8469 }
8470
8471 /*-----------------------------------------------------------------*/
8472 /* genCodePointerGet - gget value from code space                  */
8473 /*-----------------------------------------------------------------*/
8474 static void
8475 genCodePointerGet (operand * left,
8476                     operand * result, iCode * ic, iCode *pi)
8477 {
8478   int size, offset;
8479   sym_link *retype = getSpec (operandType (result));
8480
8481   D(emitcode (";     genCodePointerGet",""));
8482
8483   aopOp (left, ic, FALSE);
8484   loadDptrFromOperand (left, FALSE);
8485
8486   /* so dptr now contains the address */
8487   aopOp (result, ic, FALSE);
8488
8489   /* if bit then unpack */
8490   if (IS_BITFIELD (retype))
8491     genUnpackBits (result, "dptr", CPOINTER);
8492   else
8493     {
8494       size = AOP_SIZE (result);
8495       offset = 0;
8496
8497       while (size--)
8498         {
8499           if (pi)
8500             {
8501               emitcode ("clr", "a");
8502               emitcode ("movc", "a,@a+dptr");
8503               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8504               emitcode ("inc", "dptr");
8505             }
8506           else
8507             {
8508               emitcode ("mov", "a,#0x%02x", offset);
8509               emitcode ("movc", "a,@a+dptr");
8510               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8511             }
8512         }
8513     }
8514
8515   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8516     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8517     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8518     pi->generated = 1;
8519   }
8520   freeAsmop (left, NULL, ic, TRUE);
8521   freeAsmop (result, NULL, ic, TRUE);
8522 }
8523
8524 /*-----------------------------------------------------------------*/
8525 /* genGenPointerGet - gget value from generic pointer space        */
8526 /*-----------------------------------------------------------------*/
8527 static void
8528 genGenPointerGet (operand * left,
8529                   operand * result, iCode * ic, iCode *pi)
8530 {
8531   int size, offset;
8532   sym_link *retype = getSpec (operandType (result));
8533
8534   D(emitcode (";     genGenPointerGet",""));
8535
8536   aopOp (left, ic, FALSE);
8537   loadDptrFromOperand (left, TRUE);
8538
8539   /* so dptr know contains the address */
8540   aopOp (result, ic, FALSE);
8541
8542   /* if bit then unpack */
8543   if (IS_BITFIELD (retype))
8544     genUnpackBits (result, "dptr", GPOINTER);
8545   else
8546     {
8547       size = AOP_SIZE (result);
8548       offset = 0;
8549
8550       while (size--)
8551         {
8552           emitcode ("lcall", "__gptrget");
8553           aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8554           if (size || pi)
8555             emitcode ("inc", "dptr");
8556         }
8557     }
8558
8559   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
8560     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8561     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8562     pi->generated = 1;
8563   }
8564   freeAsmop (left, NULL, ic, TRUE);
8565   freeAsmop (result, NULL, ic, TRUE);
8566 }
8567
8568 /*-----------------------------------------------------------------*/
8569 /* genPointerGet - generate code for pointer get                   */
8570 /*-----------------------------------------------------------------*/
8571 static void
8572 genPointerGet (iCode * ic, iCode *pi)
8573 {
8574   operand *left, *result;
8575   sym_link *type, *etype;
8576   int p_type;
8577
8578   D(emitcode (";     genPointerGet",""));
8579
8580   left = IC_LEFT (ic);
8581   result = IC_RESULT (ic);
8582
8583   /* depending on the type of pointer we need to
8584      move it to the correct pointer register */
8585   type = operandType (left);
8586   etype = getSpec (type);
8587   /* if left is of type of pointer then it is simple */
8588   if (IS_PTR (type) && !IS_FUNC (type->next))
8589     p_type = DCL_TYPE (type);
8590   else
8591     {
8592       /* we have to go by the storage class */
8593       p_type = PTR_TYPE (SPEC_OCLS (etype));
8594     }
8595
8596   /* special case when cast remat */
8597   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8598       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8599           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8600           type = operandType (left);
8601           p_type = DCL_TYPE (type);
8602   }
8603   /* now that we have the pointer type we assign
8604      the pointer values */
8605   switch (p_type)
8606     {
8607
8608     case POINTER:
8609     case IPOINTER:
8610       genNearPointerGet (left, result, ic, pi);
8611       break;
8612
8613     case PPOINTER:
8614       genPagedPointerGet (left, result, ic, pi);
8615       break;
8616
8617     case FPOINTER:
8618       genFarPointerGet (left, result, ic, pi);
8619       break;
8620
8621     case CPOINTER:
8622       genCodePointerGet (left, result, ic, pi);
8623       break;
8624
8625     case GPOINTER:
8626       genGenPointerGet (left, result, ic, pi);
8627       break;
8628     }
8629
8630 }
8631
8632
8633
8634 /*-----------------------------------------------------------------*/
8635 /* genPackBits - generates code for packed bit storage             */
8636 /*-----------------------------------------------------------------*/
8637 static void
8638 genPackBits (sym_link * etype,
8639              operand * right,
8640              char *rname, int p_type)
8641 {
8642   int offset = 0;       /* source byte offset */
8643   int rlen = 0;         /* remaining bitfield length */
8644   int blen;             /* bitfield length */
8645   int bstr;             /* bitfield starting bit within byte */
8646   int litval;           /* source literal value (if AOP_LIT) */
8647   unsigned char mask;   /* bitmask within current byte */
8648
8649   D(emitcode (";     genPackBits",""));
8650
8651   blen = SPEC_BLEN (etype);
8652   bstr = SPEC_BSTR (etype);
8653
8654   /* If the bitfield length is less than a byte */
8655   if (blen < 8)
8656     {
8657       mask = ((unsigned char) (0xFF << (blen + bstr)) |
8658               (unsigned char) (0xFF >> (8 - bstr)));
8659
8660       if (AOP_TYPE (right) == AOP_LIT)
8661         {
8662           /* Case with a bitfield length <8 and literal source
8663           */
8664           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8665           litval <<= bstr;
8666           litval &= (~mask) & 0xff;
8667           emitPtrByteGet (rname, p_type, FALSE);
8668           if ((mask|litval)!=0xff)
8669             emitcode ("anl","a,#0x%02x", mask);
8670           if (litval)
8671             emitcode ("orl","a,#0x%02x", litval);
8672         }
8673       else
8674         {
8675           if ((blen==1) && (p_type!=GPOINTER))
8676             {
8677               /* Case with a bitfield length == 1 and no generic pointer
8678               */
8679               if (AOP_TYPE (right) == AOP_CRY)
8680                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8681               else
8682                 {
8683                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8684                   emitcode ("rrc","a");
8685                 }
8686               emitPtrByteGet (rname, p_type, FALSE);
8687               emitcode ("mov","acc.%d,c",bstr);
8688             }
8689           else
8690             {
8691               /* Case with a bitfield length < 8 and arbitrary source
8692               */
8693               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8694               /* shift and mask source value */
8695               AccLsh (bstr);
8696               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8697
8698               /* transfer A to B and get next byte */
8699               emitPtrByteGet (rname, p_type, TRUE);
8700
8701               emitcode ("anl", "a,#0x%02x", mask);
8702               emitcode ("orl", "a,b");
8703               if (p_type == GPOINTER)
8704                 emitcode ("pop", "b");
8705            }
8706         }
8707
8708       emitPtrByteSet (rname, p_type, "a");
8709       return;
8710     }
8711
8712   /* Bit length is greater than 7 bits. In this case, copy  */
8713   /* all except the partial byte at the end                 */
8714   for (rlen=blen;rlen>=8;rlen-=8)
8715     {
8716       emitPtrByteSet (rname, p_type,
8717                       aopGet (AOP (right), offset++, FALSE, TRUE) );
8718       if (rlen>8)
8719         emitcode ("inc", "%s", rname);
8720     }
8721
8722   /* If there was a partial byte at the end */
8723   if (rlen)
8724     {
8725       mask = (((unsigned char) -1 << rlen) & 0xff);
8726
8727       if (AOP_TYPE (right) == AOP_LIT)
8728         {
8729           /* Case with partial byte and literal source
8730           */
8731           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8732           litval >>= (blen-rlen);
8733           litval &= (~mask) & 0xff;
8734           emitPtrByteGet (rname, p_type, FALSE);
8735           if ((mask|litval)!=0xff)
8736             emitcode ("anl","a,#0x%02x", mask);
8737           if (litval)
8738             emitcode ("orl","a,#0x%02x", litval);
8739         }
8740       else
8741         {
8742           /* Case with partial byte and arbitrary source
8743           */
8744           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8745           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8746
8747           /* transfer A to B and get next byte */
8748           emitPtrByteGet (rname, p_type, TRUE);
8749
8750           emitcode ("anl", "a,#0x%02x", mask);
8751           emitcode ("orl", "a,b");
8752           if (p_type == GPOINTER)
8753             emitcode ("pop", "b");
8754         }
8755       emitPtrByteSet (rname, p_type, "a");
8756     }
8757
8758 }
8759
8760
8761 /*-----------------------------------------------------------------*/
8762 /* genDataPointerSet - remat pointer to data space                 */
8763 /*-----------------------------------------------------------------*/
8764 static void
8765 genDataPointerSet (operand * right,
8766                    operand * result,
8767                    iCode * ic)
8768 {
8769   int size, offset = 0;
8770   char *l, buffer[256];
8771
8772   D(emitcode (";     genDataPointerSet",""));
8773
8774   aopOp (right, ic, FALSE);
8775
8776   l = aopGet (AOP (result), 0, FALSE, TRUE);
8777   size = AOP_SIZE (right);
8778   while (size--)
8779     {
8780       if (offset)
8781         sprintf (buffer, "(%s + %d)", l + 1, offset);
8782       else
8783         sprintf (buffer, "%s", l + 1);
8784       emitcode ("mov", "%s,%s", buffer,
8785                 aopGet (AOP (right), offset++, FALSE, FALSE));
8786     }
8787
8788   freeAsmop (right, NULL, ic, TRUE);
8789   freeAsmop (result, NULL, ic, TRUE);
8790 }
8791
8792 /*-----------------------------------------------------------------*/
8793 /* genNearPointerSet - emitcode for near pointer put                */
8794 /*-----------------------------------------------------------------*/
8795 static void
8796 genNearPointerSet (operand * right,
8797                    operand * result,
8798                    iCode * ic,
8799                    iCode * pi)
8800 {
8801   asmop *aop = NULL;
8802   regs *preg = NULL;
8803   char *rname, *l;
8804   sym_link *retype, *letype;
8805   sym_link *ptype = operandType (result);
8806
8807   D(emitcode (";     genNearPointerSet",""));
8808
8809   retype = getSpec (operandType (right));
8810   letype = getSpec (ptype);
8811   aopOp (result, ic, FALSE);
8812
8813   /* if the result is rematerializable &
8814      in data space & not a bit variable */
8815   if (AOP_TYPE (result) == AOP_IMMD &&
8816       DCL_TYPE (ptype) == POINTER &&
8817       !IS_BITVAR (retype) &&
8818       !IS_BITVAR (letype))
8819     {
8820       genDataPointerSet (right, result, ic);
8821       return;
8822     }
8823
8824   /* if the value is already in a pointer register
8825      then don't need anything more */
8826   if (!AOP_INPREG (AOP (result)))
8827     {
8828         if (
8829             //AOP_TYPE (result) == AOP_STK
8830             IS_AOP_PREG(result)
8831             )
8832         {
8833             // Aha, it is a pointer, just in disguise.
8834             rname = aopGet (AOP (result), 0, FALSE, FALSE);
8835             if (*rname != '@')
8836             {
8837                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8838                         __FILE__, __LINE__);
8839             }
8840             else
8841             {
8842                 // Expected case.
8843                 emitcode ("mov", "a%s,%s", rname + 1, rname);
8844                 rname++;  // skip the '@'.
8845             }
8846         }
8847         else
8848         {
8849             /* otherwise get a free pointer register */
8850             aop = newAsmop (0);
8851             preg = getFreePtr (ic, &aop, FALSE);
8852             emitcode ("mov", "%s,%s",
8853                       preg->name,
8854                       aopGet (AOP (result), 0, FALSE, TRUE));
8855             rname = preg->name;
8856         }
8857     }
8858     else
8859     {
8860         rname = aopGet (AOP (result), 0, FALSE, FALSE);
8861     }
8862
8863   aopOp (right, ic, FALSE);
8864
8865   /* if bitfield then unpack the bits */
8866   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8867     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8868   else
8869     {
8870       /* we have can just get the values */
8871       int size = AOP_SIZE (right);
8872       int offset = 0;
8873
8874       while (size--)
8875         {
8876           l = aopGet (AOP (right), offset, FALSE, TRUE);
8877           if (*l == '@')
8878             {
8879               MOVA (l);
8880               emitcode ("mov", "@%s,a", rname);
8881             }
8882           else
8883             emitcode ("mov", "@%s,%s", rname, l);
8884           if (size || pi)
8885             emitcode ("inc", "%s", rname);
8886           offset++;
8887         }
8888     }
8889
8890   /* now some housekeeping stuff */
8891   if (aop) /* we had to allocate for this iCode */
8892     {
8893       if (pi)
8894         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8895       freeAsmop (NULL, aop, ic, TRUE);
8896     }
8897   else
8898     {
8899       /* we did not allocate which means left
8900          already in a pointer register, then
8901          if size > 0 && this could be used again
8902          we have to point it back to where it
8903          belongs */
8904       if ((AOP_SIZE (right) > 1 &&
8905            !OP_SYMBOL (result)->remat &&
8906            (OP_SYMBOL (result)->liveTo > ic->seq ||
8907             ic->depth)) &&
8908           !pi)
8909         {
8910           int size = AOP_SIZE (right) - 1;
8911           while (size--)
8912             emitcode ("dec", "%s", rname);
8913         }
8914     }
8915
8916   /* done */
8917   if (pi) pi->generated = 1;
8918   freeAsmop (result, NULL, ic, TRUE);
8919   freeAsmop (right, NULL, ic, TRUE);
8920 }
8921
8922 /*-----------------------------------------------------------------*/
8923 /* genPagedPointerSet - emitcode for Paged pointer put             */
8924 /*-----------------------------------------------------------------*/
8925 static void
8926 genPagedPointerSet (operand * right,
8927                     operand * result,
8928                     iCode * ic,
8929                     iCode * pi)
8930 {
8931   asmop *aop = NULL;
8932   regs *preg = NULL;
8933   char *rname, *l;
8934   sym_link *retype, *letype;
8935
8936   D(emitcode (";     genPagedPointerSet",""));
8937
8938   retype = getSpec (operandType (right));
8939   letype = getSpec (operandType (result));
8940
8941   aopOp (result, ic, FALSE);
8942
8943   /* if the value is already in a pointer register
8944      then don't need anything more */
8945   if (!AOP_INPREG (AOP (result)))
8946     {
8947       /* otherwise get a free pointer register */
8948       aop = newAsmop (0);
8949       preg = getFreePtr (ic, &aop, FALSE);
8950       emitcode ("mov", "%s,%s",
8951                 preg->name,
8952                 aopGet (AOP (result), 0, FALSE, TRUE));
8953       rname = preg->name;
8954     }
8955   else
8956     rname = aopGet (AOP (result), 0, FALSE, FALSE);
8957
8958   aopOp (right, ic, FALSE);
8959
8960   /* if bitfield then unpack the bits */
8961   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8962     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
8963   else
8964     {
8965       /* we have can just get the values */
8966       int size = AOP_SIZE (right);
8967       int offset = 0;
8968
8969       while (size--)
8970         {
8971           l = aopGet (AOP (right), offset, FALSE, TRUE);
8972
8973           MOVA (l);
8974           emitcode ("movx", "@%s,a", rname);
8975
8976           if (size || pi)
8977             emitcode ("inc", "%s", rname);
8978
8979           offset++;
8980         }
8981     }
8982
8983   /* now some housekeeping stuff */
8984   if (aop) /* we had to allocate for this iCode */
8985     {
8986       if (pi)
8987         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8988       freeAsmop (NULL, aop, ic, TRUE);
8989     }
8990   else
8991     {
8992       /* we did not allocate which means left
8993          already in a pointer register, then
8994          if size > 0 && this could be used again
8995          we have to point it back to where it
8996          belongs */
8997       if (AOP_SIZE (right) > 1 &&
8998           !OP_SYMBOL (result)->remat &&
8999           (OP_SYMBOL (result)->liveTo > ic->seq ||
9000            ic->depth))
9001         {
9002           int size = AOP_SIZE (right) - 1;
9003           while (size--)
9004             emitcode ("dec", "%s", rname);
9005         }
9006     }
9007
9008   /* done */
9009   if (pi) pi->generated = 1;
9010   freeAsmop (result, NULL, ic, TRUE);
9011   freeAsmop (right, NULL, ic, TRUE);
9012
9013
9014 }
9015
9016 /*-----------------------------------------------------------------*/
9017 /* genFarPointerSet - set value from far space                     */
9018 /*-----------------------------------------------------------------*/
9019 static void
9020 genFarPointerSet (operand * right,
9021                   operand * result, iCode * ic, iCode * pi)
9022 {
9023   int size, offset;
9024   sym_link *retype = getSpec (operandType (right));
9025   sym_link *letype = getSpec (operandType (result));
9026
9027   D(emitcode (";     genFarPointerSet",""));
9028
9029   aopOp (result, ic, FALSE);
9030   loadDptrFromOperand (result, FALSE);
9031
9032   /* so dptr know contains the address */
9033   aopOp (right, ic, FALSE);
9034
9035   /* if bit then unpack */
9036   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9037     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9038   else
9039     {
9040       size = AOP_SIZE (right);
9041       offset = 0;
9042
9043       while (size--)
9044         {
9045           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9046           MOVA (l);
9047           emitcode ("movx", "@dptr,a");
9048           if (size || pi)
9049             emitcode ("inc", "dptr");
9050         }
9051     }
9052   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9053     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9054     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9055     pi->generated=1;
9056   }
9057   freeAsmop (result, NULL, ic, TRUE);
9058   freeAsmop (right, NULL, ic, TRUE);
9059 }
9060
9061 /*-----------------------------------------------------------------*/
9062 /* genGenPointerSet - set value from generic pointer space         */
9063 /*-----------------------------------------------------------------*/
9064 static void
9065 genGenPointerSet (operand * right,
9066                   operand * result, iCode * ic, iCode * pi)
9067 {
9068   int size, offset;
9069   sym_link *retype = getSpec (operandType (right));
9070   sym_link *letype = getSpec (operandType (result));
9071
9072   D(emitcode (";     genGenPointerSet",""));
9073
9074   aopOp (result, ic, FALSE);
9075   loadDptrFromOperand (result, TRUE);
9076
9077   /* so dptr know contains the address */
9078   aopOp (right, ic, FALSE);
9079
9080   /* if bit then unpack */
9081   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9082     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9083   else
9084     {
9085       size = AOP_SIZE (right);
9086       offset = 0;
9087
9088       while (size--)
9089         {
9090           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9091           MOVA (l);
9092           emitcode ("lcall", "__gptrput");
9093           if (size || pi)
9094             emitcode ("inc", "dptr");
9095         }
9096     }
9097
9098   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9099     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9100     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9101     pi->generated=1;
9102   }
9103   freeAsmop (result, NULL, ic, TRUE);
9104   freeAsmop (right, NULL, ic, TRUE);
9105 }
9106
9107 /*-----------------------------------------------------------------*/
9108 /* genPointerSet - stores the value into a pointer location        */
9109 /*-----------------------------------------------------------------*/
9110 static void
9111 genPointerSet (iCode * ic, iCode *pi)
9112 {
9113   operand *right, *result;
9114   sym_link *type, *etype;
9115   int p_type;
9116
9117   D(emitcode (";     genPointerSet",""));
9118
9119   right = IC_RIGHT (ic);
9120   result = IC_RESULT (ic);
9121
9122   /* depending on the type of pointer we need to
9123      move it to the correct pointer register */
9124   type = operandType (result);
9125   etype = getSpec (type);
9126   /* if left is of type of pointer then it is simple */
9127   if (IS_PTR (type) && !IS_FUNC (type->next))
9128     {
9129       p_type = DCL_TYPE (type);
9130     }
9131   else
9132     {
9133       /* we have to go by the storage class */
9134       p_type = PTR_TYPE (SPEC_OCLS (etype));
9135     }
9136
9137   /* special case when cast remat */
9138   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9139       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9140           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9141           type = operandType (result);
9142           p_type = DCL_TYPE (type);
9143   }
9144   /* now that we have the pointer type we assign
9145      the pointer values */
9146   switch (p_type)
9147     {
9148
9149     case POINTER:
9150     case IPOINTER:
9151       genNearPointerSet (right, result, ic, pi);
9152       break;
9153
9154     case PPOINTER:
9155       genPagedPointerSet (right, result, ic, pi);
9156       break;
9157
9158     case FPOINTER:
9159       genFarPointerSet (right, result, ic, pi);
9160       break;
9161
9162     case GPOINTER:
9163       genGenPointerSet (right, result, ic, pi);
9164       break;
9165
9166     default:
9167       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9168               "genPointerSet: illegal pointer type");
9169     }
9170
9171 }
9172
9173 /*-----------------------------------------------------------------*/
9174 /* genIfx - generate code for Ifx statement                        */
9175 /*-----------------------------------------------------------------*/
9176 static void
9177 genIfx (iCode * ic, iCode * popIc)
9178 {
9179   operand *cond = IC_COND (ic);
9180   int isbit = 0;
9181
9182   D(emitcode (";     genIfx",""));
9183
9184   aopOp (cond, ic, FALSE);
9185
9186   /* get the value into acc */
9187   if (AOP_TYPE (cond) != AOP_CRY)
9188     toBoolean (cond);
9189   else
9190     isbit = 1;
9191   /* the result is now in the accumulator */
9192   freeAsmop (cond, NULL, ic, TRUE);
9193
9194   /* if there was something to be popped then do it */
9195   if (popIc)
9196     genIpop (popIc);
9197
9198   /* if the condition is  a bit variable */
9199   if (isbit && IS_ITEMP (cond) &&
9200       SPIL_LOC (cond))
9201     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9202   else if (isbit && !IS_ITEMP (cond))
9203     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9204   else
9205     genIfxJump (ic, "a", NULL, NULL, NULL);
9206
9207   ic->generated = 1;
9208 }
9209
9210 /*-----------------------------------------------------------------*/
9211 /* genAddrOf - generates code for address of                       */
9212 /*-----------------------------------------------------------------*/
9213 static void
9214 genAddrOf (iCode * ic)
9215 {
9216   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9217   int size, offset;
9218
9219   D(emitcode (";     genAddrOf",""));
9220
9221   aopOp (IC_RESULT (ic), ic, FALSE);
9222
9223   /* if the operand is on the stack then we
9224      need to get the stack offset of this
9225      variable */
9226   if (sym->onStack)
9227     {
9228       /* if it has an offset then we need to compute
9229          it */
9230       if (sym->stack)
9231         {
9232           emitcode ("mov", "a,_bp");
9233           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9234                                          ((char) (sym->stack - _G.nRegsSaved)) :
9235                                          ((char) sym->stack)) & 0xff);
9236           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9237         }
9238       else
9239         {
9240           /* we can just move _bp */
9241           aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9242         }
9243       /* fill the result with zero */
9244       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9245
9246       offset = 1;
9247       while (size--)
9248         {
9249           aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9250         }
9251
9252       goto release;
9253     }
9254
9255   /* object not on stack then we need the name */
9256   size = AOP_SIZE (IC_RESULT (ic));
9257   offset = 0;
9258
9259   while (size--)
9260     {
9261       char s[SDCC_NAME_MAX];
9262       if (offset)
9263         sprintf (s, "#(%s >> %d)",
9264                  sym->rname,
9265                  offset * 8);
9266       else
9267         sprintf (s, "#%s", sym->rname);
9268       aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9269     }
9270
9271 release:
9272   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9273
9274 }
9275
9276 /*-----------------------------------------------------------------*/
9277 /* genFarFarAssign - assignment when both are in far space         */
9278 /*-----------------------------------------------------------------*/
9279 static void
9280 genFarFarAssign (operand * result, operand * right, iCode * ic)
9281 {
9282   int size = AOP_SIZE (right);
9283   int offset = 0;
9284   char *l;
9285
9286   D(emitcode (";     genFarFarAssign",""));
9287
9288   /* first push the right side on to the stack */
9289   while (size--)
9290     {
9291       l = aopGet (AOP (right), offset++, FALSE, FALSE);
9292       MOVA (l);
9293       emitcode ("push", "acc");
9294     }
9295
9296   freeAsmop (right, NULL, ic, FALSE);
9297   /* now assign DPTR to result */
9298   aopOp (result, ic, FALSE);
9299   size = AOP_SIZE (result);
9300   while (size--)
9301     {
9302       emitcode ("pop", "acc");
9303       aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9304     }
9305   freeAsmop (result, NULL, ic, FALSE);
9306
9307 }
9308
9309 /*-----------------------------------------------------------------*/
9310 /* genAssign - generate code for assignment                        */
9311 /*-----------------------------------------------------------------*/
9312 static void
9313 genAssign (iCode * ic)
9314 {
9315   operand *result, *right;
9316   int size, offset;
9317   unsigned long lit = 0L;
9318
9319   D(emitcode(";     genAssign",""));
9320
9321   result = IC_RESULT (ic);
9322   right = IC_RIGHT (ic);
9323
9324   /* if they are the same */
9325   if (operandsEqu (result, right) &&
9326       !isOperandVolatile (result, FALSE) &&
9327       !isOperandVolatile (right, FALSE))
9328     return;
9329
9330   aopOp (right, ic, FALSE);
9331
9332   /* special case both in far space */
9333   if (AOP_TYPE (right) == AOP_DPTR &&
9334       IS_TRUE_SYMOP (result) &&
9335       isOperandInFarSpace (result))
9336     {
9337
9338       genFarFarAssign (result, right, ic);
9339       return;
9340     }
9341
9342   aopOp (result, ic, TRUE);
9343
9344   /* if they are the same registers */
9345   if (sameRegs (AOP (right), AOP (result)) &&
9346       !isOperandVolatile (result, FALSE) &&
9347       !isOperandVolatile (right, FALSE))
9348     goto release;
9349
9350   /* if the result is a bit */
9351   if (AOP_TYPE (result) == AOP_CRY)
9352     {
9353
9354       /* if the right size is a literal then
9355          we know what the value is */
9356       if (AOP_TYPE (right) == AOP_LIT)
9357         {
9358           if (((int) operandLitValue (right)))
9359             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9360           else
9361             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9362           goto release;
9363         }
9364
9365       /* the right is also a bit variable */
9366       if (AOP_TYPE (right) == AOP_CRY)
9367         {
9368           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9369           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9370           goto release;
9371         }
9372
9373       /* we need to or */
9374       toBoolean (right);
9375       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9376       goto release;
9377     }
9378
9379   /* bit variables done */
9380   /* general case */
9381   size = AOP_SIZE (result);
9382   offset = 0;
9383   if (AOP_TYPE (right) == AOP_LIT)
9384     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9385   if ((size > 1) &&
9386       (AOP_TYPE (result) != AOP_REG) &&
9387       (AOP_TYPE (right) == AOP_LIT) &&
9388       !IS_FLOAT (operandType (right)) &&
9389       (lit < 256L))
9390     {
9391       emitcode ("clr", "a");
9392       while (size--)
9393         {
9394           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9395             aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9396           else
9397             aopPut (AOP (result),
9398                     aopGet (AOP (right), size, FALSE, FALSE),
9399                     size,
9400                     isOperandVolatile (result, FALSE));
9401         }
9402     }
9403   else
9404     {
9405       while (size--)
9406         {
9407           aopPut (AOP (result),
9408                   aopGet (AOP (right), offset, FALSE, FALSE),
9409                   offset,
9410                   isOperandVolatile (result, FALSE));
9411           offset++;
9412         }
9413     }
9414
9415 release:
9416   freeAsmop (right, NULL, ic, TRUE);
9417   freeAsmop (result, NULL, ic, TRUE);
9418 }
9419
9420 /*-----------------------------------------------------------------*/
9421 /* genJumpTab - genrates code for jump table                       */
9422 /*-----------------------------------------------------------------*/
9423 static void
9424 genJumpTab (iCode * ic)
9425 {
9426   symbol *jtab,*jtablo,*jtabhi;
9427   char *l;
9428   unsigned int count;
9429
9430   D(emitcode (";     genJumpTab",""));
9431
9432   count = elementsInSet( IC_JTLABELS (ic) );
9433
9434   if( count <= 16 )
9435     {
9436       /* this algorithm needs 9 cycles and 7 + 3*n bytes 
9437          if the switch argument is in an register. 
9438          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */ 
9439       aopOp (IC_JTCOND (ic), ic, FALSE);
9440       /* get the condition into accumulator */
9441       l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9442       MOVA (l);
9443       /* multiply by three */
9444       emitcode ("add", "a,acc");
9445       emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9446       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9447
9448       jtab = newiTempLabel (NULL);
9449       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9450       emitcode ("jmp", "@a+dptr");
9451       emitcode ("", "%05d$:", jtab->key + 100);
9452       /* now generate the jump labels */
9453       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9454            jtab = setNextItem (IC_JTLABELS (ic)))
9455         emitcode ("ljmp", "%05d$", jtab->key + 100);
9456     }
9457   else
9458     {
9459       /* this algorithm needs 14 cycles and 13 + 2*n bytes 
9460          if the switch argument is in an register. 
9461          For n>6 this algorithm may be more compact */ 
9462       jtablo = newiTempLabel (NULL);
9463       jtabhi = newiTempLabel (NULL);
9464
9465       /* get the condition into accumulator.
9466          Using b as temporary storage, if register push/pop is needed */ 
9467       aopOp (IC_JTCOND (ic), ic, FALSE);
9468       l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9469       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9470           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9471         {
9472           emitcode ("mov", "b,%s", l);
9473           l = "b";
9474         }
9475       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);            
9476       MOVA (l);      
9477       if( count <= 112 )
9478         {
9479           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9480           emitcode ("movc", "a,@a+pc");
9481           emitcode ("push", "acc");
9482
9483           MOVA (l);
9484           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9485           emitcode ("movc", "a,@a+pc");
9486           emitcode ("push", "acc");
9487         }
9488       else      
9489         {
9490           /* this scales up to n<=255, but needs two more bytes
9491              and changes dptr */
9492           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9493           emitcode ("movc", "a,@a+dptr");
9494           emitcode ("push", "acc");
9495
9496           MOVA (l);
9497           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9498           emitcode ("movc", "a,@a+dptr");
9499           emitcode ("push", "acc");
9500         }
9501
9502       emitcode ("ret", "");
9503
9504       /* now generate jump table, LSB */
9505       emitcode ("", "%05d$:", jtablo->key + 100);
9506       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9507            jtab = setNextItem (IC_JTLABELS (ic)))
9508         emitcode (".db", "%05d$", jtab->key + 100);
9509
9510       /* now generate jump table, MSB */
9511       emitcode ("", "%05d$:", jtabhi->key + 100);
9512       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9513            jtab = setNextItem (IC_JTLABELS (ic)))
9514          emitcode (".db", "%05d$>>8", jtab->key + 100);
9515     
9516     }  
9517
9518 }
9519
9520 /*-----------------------------------------------------------------*/
9521 /* genCast - gen code for casting                                  */
9522 /*-----------------------------------------------------------------*/
9523 static void
9524 genCast (iCode * ic)
9525 {
9526   operand *result = IC_RESULT (ic);
9527   sym_link *ctype = operandType (IC_LEFT (ic));
9528   sym_link *rtype = operandType (IC_RIGHT (ic));
9529   operand *right = IC_RIGHT (ic);
9530   int size, offset;
9531
9532   D(emitcode(";     genCast",""));
9533
9534   /* if they are equivalent then do nothing */
9535   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9536     return;
9537
9538   aopOp (right, ic, FALSE);
9539   aopOp (result, ic, FALSE);
9540
9541   /* if the result is a bit (and not a bitfield) */
9542   // if (AOP_TYPE (result) == AOP_CRY)
9543   if (IS_BITVAR (OP_SYMBOL (result)->type)
9544       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9545     {
9546       /* if the right size is a literal then
9547          we know what the value is */
9548       if (AOP_TYPE (right) == AOP_LIT)
9549         {
9550           if (((int) operandLitValue (right)))
9551             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9552           else
9553             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9554
9555           goto release;
9556         }
9557
9558       /* the right is also a bit variable */
9559       if (AOP_TYPE (right) == AOP_CRY)
9560         {
9561           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9562           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9563           goto release;
9564         }
9565
9566       /* we need to or */
9567       toBoolean (right);
9568       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9569       goto release;
9570     }
9571
9572
9573   /* if they are the same size : or less */
9574   if (AOP_SIZE (result) <= AOP_SIZE (right))
9575     {
9576
9577       /* if they are in the same place */
9578       if (sameRegs (AOP (right), AOP (result)))
9579         goto release;
9580
9581       /* if they in different places then copy */
9582       size = AOP_SIZE (result);
9583       offset = 0;
9584       while (size--)
9585         {
9586           aopPut (AOP (result),
9587                   aopGet (AOP (right), offset, FALSE, FALSE),
9588                   offset,
9589                   isOperandVolatile (result, FALSE));
9590           offset++;
9591         }
9592       goto release;
9593     }
9594
9595
9596   /* if the result is of type pointer */
9597   if (IS_PTR (ctype))
9598     {
9599
9600       int p_type;
9601       sym_link *type = operandType (right);
9602       sym_link *etype = getSpec (type);
9603
9604       /* pointer to generic pointer */
9605       if (IS_GENPTR (ctype))
9606         {
9607           if (IS_PTR (type))
9608             p_type = DCL_TYPE (type);
9609           else
9610             {
9611               if (SPEC_SCLS(etype)==S_REGISTER) {
9612                 // let's assume it is a generic pointer
9613                 p_type=GPOINTER;
9614               } else {
9615                 /* we have to go by the storage class */
9616                 p_type = PTR_TYPE (SPEC_OCLS (etype));
9617               }
9618             }
9619
9620           /* the first two bytes are known */
9621           size = GPTRSIZE - 1;
9622           offset = 0;
9623           while (size--)
9624             {
9625               aopPut (AOP (result),
9626                       aopGet (AOP (right), offset, FALSE, FALSE),
9627                       offset,
9628                       isOperandVolatile (result, FALSE));
9629               offset++;
9630             }
9631           /* the last byte depending on type */
9632             {
9633                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9634                 char gpValStr[10];
9635
9636                 if (gpVal == -1)
9637                 {
9638                     // pointerTypeToGPByte will have bitched.
9639                     exit(1);
9640                 }
9641
9642                 sprintf(gpValStr, "#0x%d", gpVal);
9643                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9644             }
9645           goto release;
9646         }
9647
9648       /* just copy the pointers */
9649       size = AOP_SIZE (result);
9650       offset = 0;
9651       while (size--)
9652         {
9653           aopPut (AOP (result),
9654                   aopGet (AOP (right), offset, FALSE, FALSE),
9655                   offset,
9656                   isOperandVolatile (result, FALSE));
9657           offset++;
9658         }
9659       goto release;
9660     }
9661
9662   /* so we now know that the size of destination is greater
9663      than the size of the source */
9664   /* we move to result for the size of source */
9665   size = AOP_SIZE (right);
9666   offset = 0;
9667   while (size--)
9668     {
9669       aopPut (AOP (result),
9670               aopGet (AOP (right), offset, FALSE, FALSE),
9671               offset,
9672               isOperandVolatile (result, FALSE));
9673       offset++;
9674     }
9675
9676   /* now depending on the sign of the source && destination */
9677   size = AOP_SIZE (result) - AOP_SIZE (right);
9678   /* if unsigned or not an integral type */
9679   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9680     {
9681       while (size--)
9682         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9683     }
9684   else
9685     {
9686       /* we need to extend the sign :{ */
9687       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9688                         FALSE, FALSE);
9689       MOVA (l);
9690       emitcode ("rlc", "a");
9691       emitcode ("subb", "a,acc");
9692       while (size--)
9693         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9694     }
9695
9696   /* we are done hurray !!!! */
9697
9698 release:
9699   freeAsmop (right, NULL, ic, TRUE);
9700   freeAsmop (result, NULL, ic, TRUE);
9701
9702 }
9703
9704 /*-----------------------------------------------------------------*/
9705 /* genDjnz - generate decrement & jump if not zero instrucion      */
9706 /*-----------------------------------------------------------------*/
9707 static int
9708 genDjnz (iCode * ic, iCode * ifx)
9709 {
9710   symbol *lbl, *lbl1;
9711   if (!ifx)
9712     return 0;
9713
9714   D(emitcode (";     genDjnz",""));
9715
9716   /* if the if condition has a false label
9717      then we cannot save */
9718   if (IC_FALSE (ifx))
9719     return 0;
9720
9721   /* if the minus is not of the form
9722      a = a - 1 */
9723   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9724       !IS_OP_LITERAL (IC_RIGHT (ic)))
9725     return 0;
9726
9727   if (operandLitValue (IC_RIGHT (ic)) != 1)
9728     return 0;
9729
9730   /* if the size of this greater than one then no
9731      saving */
9732   if (getSize (operandType (IC_RESULT (ic))) > 1)
9733     return 0;
9734
9735   /* otherwise we can save BIG */
9736   lbl = newiTempLabel (NULL);
9737   lbl1 = newiTempLabel (NULL);
9738
9739   aopOp (IC_RESULT (ic), ic, FALSE);
9740
9741   if (AOP_NEEDSACC(IC_RESULT(ic)))
9742   {
9743       /* If the result is accessed indirectly via
9744        * the accumulator, we must explicitly write
9745        * it back after the decrement.
9746        */
9747       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9748
9749       if (strcmp(rByte, "a"))
9750       {
9751            /* Something is hopelessly wrong */
9752            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9753                    __FILE__, __LINE__);
9754            /* We can just give up; the generated code will be inefficient,
9755             * but what the hey.
9756             */
9757            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9758            return 0;
9759       }
9760       emitcode ("dec", "%s", rByte);
9761       aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9762       emitcode ("jnz", "%05d$", lbl->key + 100);
9763   }
9764   else if (IS_AOP_PREG (IC_RESULT (ic)))
9765     {
9766       emitcode ("dec", "%s",
9767                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9768       MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9769       emitcode ("jnz", "%05d$", lbl->key + 100);
9770     }
9771   else
9772     {
9773       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9774                 lbl->key + 100);
9775     }
9776   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9777   emitcode ("", "%05d$:", lbl->key + 100);
9778   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9779   emitcode ("", "%05d$:", lbl1->key + 100);
9780
9781   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9782   ifx->generated = 1;
9783   return 1;
9784 }
9785
9786 /*-----------------------------------------------------------------*/
9787 /* genReceive - generate code for a receive iCode                  */
9788 /*-----------------------------------------------------------------*/
9789 static void
9790 genReceive (iCode * ic)
9791 {
9792     int size = getSize (operandType (IC_RESULT (ic)));
9793     int offset = 0;
9794   D(emitcode (";     genReceive",""));
9795
9796   if (ic->argreg == 1) { /* first parameter */
9797       if (isOperandInFarSpace (IC_RESULT (ic)) &&
9798           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9799            IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9800
9801           regs *tempRegs[4];
9802           int receivingA = 0;
9803           int roffset = 0;
9804
9805           for (offset = 0; offset<size; offset++)
9806             if (!strcmp (fReturn[offset], "a"))
9807               receivingA = 1;
9808
9809           if (!receivingA)
9810             {
9811               if (size==1 || getTempRegs(tempRegs, size-1, ic))
9812                 {
9813                   for (offset = size-1; offset>0; offset--)
9814                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9815                   emitcode("mov","a,%s", fReturn[0]);
9816                   _G.accInUse++;
9817                   aopOp (IC_RESULT (ic), ic, FALSE);
9818                   _G.accInUse--;
9819                   aopPut (AOP (IC_RESULT (ic)), "a", offset,
9820                           isOperandVolatile (IC_RESULT (ic), FALSE));
9821                   for (offset = 1; offset<size; offset++)
9822                     aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9823                             isOperandVolatile (IC_RESULT (ic), FALSE));
9824                   goto release;
9825                 }
9826             }
9827           else
9828             {
9829               if (getTempRegs(tempRegs, size, ic))
9830                 {
9831                   for (offset = 0; offset<size; offset++)
9832                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9833                   aopOp (IC_RESULT (ic), ic, FALSE);
9834                   for (offset = 0; offset<size; offset++)
9835                     aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9836                             isOperandVolatile (IC_RESULT (ic), FALSE));
9837                   goto release;
9838                 }
9839             }
9840
9841           offset = fReturnSizeMCS51 - size;
9842           while (size--) {
9843               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9844                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9845               offset++;
9846           }
9847           aopOp (IC_RESULT (ic), ic, FALSE);
9848           size = AOP_SIZE (IC_RESULT (ic));
9849           offset = 0;
9850           while (size--) {
9851               emitcode ("pop", "acc");
9852               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9853           }
9854
9855       } else {
9856           _G.accInUse++;
9857           aopOp (IC_RESULT (ic), ic, FALSE);
9858           _G.accInUse--;
9859           assignResultValue (IC_RESULT (ic));
9860       }
9861   } else { /* second receive onwards */
9862       int rb1off ;
9863       aopOp (IC_RESULT (ic), ic, FALSE);
9864       rb1off = ic->argreg;
9865       while (size--) {
9866           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9867       }
9868   }
9869
9870 release:
9871   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9872 }
9873
9874 /*-----------------------------------------------------------------*/
9875 /* genDummyRead - generate code for dummy read of volatiles        */
9876 /*-----------------------------------------------------------------*/
9877 static void
9878 genDummyRead (iCode * ic)
9879 {
9880   operand *op;
9881   int size, offset;
9882
9883   D(emitcode(";     genDummyRead",""));
9884
9885   op = IC_RIGHT (ic);
9886   if (op && IS_SYMOP (op))
9887     {
9888       aopOp (op, ic, FALSE);
9889
9890       /* if the result is a bit */
9891       if (AOP_TYPE (op) == AOP_CRY)
9892         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9893       else
9894         {
9895           /* bit variables done */
9896           /* general case */
9897           size = AOP_SIZE (op);
9898           offset = 0;
9899           while (size--)
9900           {
9901             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9902             offset++;
9903           }
9904         }
9905
9906       freeAsmop (op, NULL, ic, TRUE);
9907     }
9908
9909   op = IC_LEFT (ic);
9910   if (op && IS_SYMOP (op))
9911     {
9912       aopOp (op, ic, FALSE);
9913
9914       /* if the result is a bit */
9915       if (AOP_TYPE (op) == AOP_CRY)
9916         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9917       else
9918         {
9919           /* bit variables done */
9920           /* general case */
9921           size = AOP_SIZE (op);
9922           offset = 0;
9923           while (size--)
9924           {
9925             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9926             offset++;
9927           }
9928         }
9929
9930       freeAsmop (op, NULL, ic, TRUE);
9931     }
9932 }
9933
9934 /*-----------------------------------------------------------------*/
9935 /* genCritical - generate code for start of a critical sequence    */
9936 /*-----------------------------------------------------------------*/
9937 static void
9938 genCritical (iCode *ic)
9939 {
9940   symbol *tlbl = newiTempLabel (NULL);
9941
9942   D(emitcode(";     genCritical",""));
9943
9944   if (IC_RESULT (ic))
9945     aopOp (IC_RESULT (ic), ic, TRUE);
9946
9947   emitcode ("setb", "c");
9948   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9949   emitcode ("clr", "c");
9950   emitcode ("", "%05d$:", (tlbl->key + 100));
9951
9952   if (IC_RESULT (ic))
9953     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9954   else
9955     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9956
9957   if (IC_RESULT (ic))
9958     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9959 }
9960
9961 /*-----------------------------------------------------------------*/
9962 /* genEndCritical - generate code for end of a critical sequence   */
9963 /*-----------------------------------------------------------------*/
9964 static void
9965 genEndCritical (iCode *ic)
9966 {
9967   D(emitcode(";     genEndCritical",""));
9968
9969   if (IC_RIGHT (ic))
9970     {
9971       aopOp (IC_RIGHT (ic), ic, FALSE);
9972       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9973         {
9974           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9975           emitcode ("mov", "ea,c");
9976         }
9977       else
9978         {
9979           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9980           emitcode ("rrc", "a");
9981           emitcode ("mov", "ea,c");
9982         }
9983       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9984     }
9985   else
9986     {
9987       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9988       emitcode ("mov", "ea,c");
9989     }
9990 }
9991
9992 /*-----------------------------------------------------------------*/
9993 /* gen51Code - generate code for 8051 based controllers            */
9994 /*-----------------------------------------------------------------*/
9995 void
9996 gen51Code (iCode * lic)
9997 {
9998   iCode *ic;
9999   int cln = 0;
10000   /* int cseq = 0; */
10001
10002   _G.currentFunc = NULL;
10003   lineHead = lineCurr = NULL;
10004
10005   /* print the allocation information */
10006   if (allocInfo && currFunc)
10007     printAllocInfo (currFunc, codeOutFile);
10008   /* if debug information required */
10009   if (options.debug && currFunc)
10010     {
10011       debugFile->writeFunction (currFunc, lic);
10012     }
10013   /* stack pointer name */
10014   if (options.useXstack)
10015     spname = "_spx";
10016   else
10017     spname = "sp";
10018
10019
10020   for (ic = lic; ic; ic = ic->next)
10021     {
10022       _G.current_iCode = ic;
10023
10024       if (ic->lineno && cln != ic->lineno)
10025         {
10026           if (options.debug)
10027             {
10028               debugFile->writeCLine(ic);
10029             }
10030           if (!options.noCcodeInAsm) {
10031             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10032                       printCLine(ic->filename, ic->lineno));
10033           }
10034           cln = ic->lineno;
10035         }
10036       #if 0
10037       if (ic->seqPoint && ic->seqPoint != cseq)
10038         {
10039           emitcode ("", "; sequence point %d", ic->seqPoint);
10040           cseq = ic->seqPoint;
10041         }
10042       #endif
10043       if (options.iCodeInAsm) {
10044         char regsInUse[80];
10045         int i;
10046
10047         for (i=0; i<8; i++) {
10048           sprintf (&regsInUse[i],
10049                    "%c", ic->riu & (1<<i) ? i+'0' : '-');
10050         }
10051         regsInUse[i]=0;
10052         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10053       }
10054       /* if the result is marked as
10055          spilt and rematerializable or code for
10056          this has already been generated then
10057          do nothing */
10058       if (resultRemat (ic) || ic->generated)
10059         continue;
10060
10061       /* depending on the operation */
10062       switch (ic->op)
10063         {
10064         case '!':
10065           genNot (ic);
10066           break;
10067
10068         case '~':
10069           genCpl (ic);
10070           break;
10071
10072         case UNARYMINUS:
10073           genUminus (ic);
10074           break;
10075
10076         case IPUSH:
10077           genIpush (ic);
10078           break;
10079
10080         case IPOP:
10081           /* IPOP happens only when trying to restore a
10082              spilt live range, if there is an ifx statement
10083              following this pop then the if statement might
10084              be using some of the registers being popped which
10085              would destory the contents of the register so
10086              we need to check for this condition and handle it */
10087           if (ic->next &&
10088               ic->next->op == IFX &&
10089               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10090             genIfx (ic->next, ic);
10091           else
10092             genIpop (ic);
10093           break;
10094
10095         case CALL:
10096           genCall (ic);
10097           break;
10098
10099         case PCALL:
10100           genPcall (ic);
10101           break;
10102
10103         case FUNCTION:
10104           genFunction (ic);
10105           break;
10106
10107         case ENDFUNCTION:
10108           genEndFunction (ic);
10109           break;
10110
10111         case RETURN:
10112           genRet (ic);
10113           break;
10114
10115         case LABEL:
10116           genLabel (ic);
10117           break;
10118
10119         case GOTO:
10120           genGoto (ic);
10121           break;
10122
10123         case '+':
10124           genPlus (ic);
10125           break;
10126
10127         case '-':
10128           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10129             genMinus (ic);
10130           break;
10131
10132         case '*':
10133           genMult (ic);
10134           break;
10135
10136         case '/':
10137           genDiv (ic);
10138           break;
10139
10140         case '%':
10141           genMod (ic);
10142           break;
10143
10144         case '>':
10145           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10146           break;
10147
10148         case '<':
10149           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10150           break;
10151
10152         case LE_OP:
10153         case GE_OP:
10154         case NE_OP:
10155
10156           /* note these two are xlated by algebraic equivalence
10157              during parsing SDCC.y */
10158           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10159                   "got '>=' or '<=' shouldn't have come here");
10160           break;
10161
10162         case EQ_OP:
10163           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10164           break;
10165
10166         case AND_OP:
10167           genAndOp (ic);
10168           break;
10169
10170         case OR_OP:
10171           genOrOp (ic);
10172           break;
10173
10174         case '^':
10175           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10176           break;
10177
10178         case '|':
10179           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10180           break;
10181
10182         case BITWISEAND:
10183           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10184           break;
10185
10186         case INLINEASM:
10187           genInline (ic);
10188           break;
10189
10190         case RRC:
10191           genRRC (ic);
10192           break;
10193
10194         case RLC:
10195           genRLC (ic);
10196           break;
10197
10198         case GETHBIT:
10199           genGetHbit (ic);
10200           break;
10201
10202         case LEFT_OP:
10203           genLeftShift (ic);
10204           break;
10205
10206         case RIGHT_OP:
10207           genRightShift (ic);
10208           break;
10209
10210         case GET_VALUE_AT_ADDRESS:
10211           genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
10212           break;
10213
10214         case '=':
10215           if (POINTER_SET (ic))
10216             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10217           else
10218             genAssign (ic);
10219           break;
10220
10221         case IFX:
10222           genIfx (ic, NULL);
10223           break;
10224
10225         case ADDRESS_OF:
10226           genAddrOf (ic);
10227           break;
10228
10229         case JUMPTABLE:
10230           genJumpTab (ic);
10231           break;
10232
10233         case CAST:
10234           genCast (ic);
10235           break;
10236
10237         case RECEIVE:
10238           genReceive (ic);
10239           break;
10240
10241         case SEND:
10242           addSet (&_G.sendSet, ic);
10243           break;
10244
10245         case DUMMY_READ_VOLATILE:
10246           genDummyRead (ic);
10247           break;
10248
10249         case CRITICAL:
10250           genCritical (ic);
10251           break;
10252
10253         case ENDCRITICAL:
10254           genEndCritical (ic);
10255           break;
10256
10257         case SWAP:
10258           genSwap (ic);
10259           break;
10260
10261         default:
10262           ic = ic;
10263         }
10264     }
10265
10266   _G.current_iCode = NULL;
10267
10268   /* now we are ready to call the
10269      peep hole optimizer */
10270   if (!options.nopeep)
10271     peepHole (&lineHead);
10272
10273   /* now do the actual printing */
10274   printLine (lineHead, codeOutFile);
10275   return;
10276 }