* src/mcs51/gen.c (genPointerGet, genNearPointerGet, genPagedPointerGet,
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25
26   Notes:
27   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
28       Made everything static
29 -------------------------------------------------------------------------*/
30
31 //#define D(x)
32 #define D(x) x
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "gen.h"
45
46 char *aopLiteral (value * val, int offset);
47 extern int allocInfo;
48
49 /* this is the down and dirty file with all kinds of
50    kludgy & hacky stuff. This is what it is all about
51    CODE GENERATION for a specific MCU . some of the
52    routines may be reusable, will have to see */
53
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
56 static char *spname;
57
58 char *fReturn8051[] =
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
63 {"a", "b"};
64
65 static unsigned short rbank = -1;
66
67 static struct
68   {
69     short r0Pushed;
70     short r1Pushed;
71     short 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, iCode *ifx)
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   char buffer[10];
8065
8066   D(emitcode (";     genUnpackBits",""));
8067
8068   etype = getSpec (operandType (result));
8069   rsize = getSize (operandType (result));
8070   blen = SPEC_BLEN (etype);
8071   bstr = SPEC_BSTR (etype);
8072
8073   if (ifx && blen <= 8)
8074     {
8075       emitPtrByteGet (rname, ptype, FALSE);
8076       if (blen == 1)
8077         {
8078           SNPRINTF (buffer, sizeof(buffer),
8079                     "acc.%d", bstr);
8080           genIfxJump (ifx, buffer, NULL, NULL, NULL);
8081         }
8082       else
8083         {
8084           if (blen < 8)
8085             emitcode ("anl", "a,#0x%02x",
8086                       (((unsigned char) -1) >> (8 - blen)) << bstr);
8087           genIfxJump (ifx, "a", NULL, NULL, NULL);
8088         }
8089       return;
8090     }
8091   wassert (!ifx);
8092   
8093   /* If the bitfield length is less than a byte */
8094   if (blen < 8)
8095     {
8096       emitPtrByteGet (rname, ptype, FALSE);
8097       AccRsh (bstr);
8098       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8099       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8100       goto finish;
8101     }
8102
8103   /* Bit field did not fit in a byte. Copy all
8104      but the partial byte at the end.  */
8105   for (rlen=blen;rlen>=8;rlen-=8)
8106     {
8107       emitPtrByteGet (rname, ptype, FALSE);
8108       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8109       if (rlen>8)
8110         emitcode ("inc", "%s", rname);
8111     }
8112
8113   /* Handle the partial byte at the end */
8114   if (rlen)
8115     {
8116       emitPtrByteGet (rname, ptype, FALSE);
8117       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8118       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8119     }
8120
8121 finish:
8122   if (offset < rsize)
8123     {
8124       rsize -= offset;
8125       while (rsize--)
8126         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8127     }
8128 }
8129
8130
8131 /*-----------------------------------------------------------------*/
8132 /* genDataPointerGet - generates code when ptr offset is known     */
8133 /*-----------------------------------------------------------------*/
8134 static void
8135 genDataPointerGet (operand * left,
8136                    operand * result,
8137                    iCode * ic)
8138 {
8139   char *l;
8140   char buffer[256];
8141   int size, offset = 0;
8142
8143   D(emitcode (";     genDataPointerGet",""));
8144
8145   aopOp (result, ic, TRUE);
8146
8147   /* get the string representation of the name */
8148   l = aopGet (AOP (left), 0, FALSE, TRUE);
8149   size = AOP_SIZE (result);
8150   while (size--)
8151     {
8152       if (offset)
8153         sprintf (buffer, "(%s + %d)", l + 1, offset);
8154       else
8155         sprintf (buffer, "%s", l + 1);
8156       aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8157     }
8158
8159   freeAsmop (left, NULL, ic, TRUE);
8160   freeAsmop (result, NULL, ic, TRUE);
8161 }
8162
8163 /*-----------------------------------------------------------------*/
8164 /* genNearPointerGet - emitcode for near pointer fetch             */
8165 /*-----------------------------------------------------------------*/
8166 static void
8167 genNearPointerGet (operand * left,
8168                    operand * result,
8169                    iCode * ic,
8170                    iCode * pi,
8171                    iCode * ifx)
8172 {
8173   asmop *aop = NULL;
8174   regs *preg = NULL;
8175   char *rname;
8176   sym_link *rtype, *retype;
8177   sym_link *ltype = operandType (left);
8178   char buffer[80];
8179
8180   D(emitcode (";     genNearPointerGet",""));
8181
8182   rtype = operandType (result);
8183   retype = getSpec (rtype);
8184
8185   aopOp (left, ic, FALSE);
8186
8187   /* if left is rematerialisable and
8188      result is not bitfield variable type and
8189      the left is pointer to data space i.e
8190      lower 128 bytes of space */
8191   if (AOP_TYPE (left) == AOP_IMMD &&
8192       !IS_BITFIELD (retype) &&
8193       DCL_TYPE (ltype) == POINTER)
8194     {
8195       genDataPointerGet (left, result, ic);
8196       return;
8197     }
8198
8199  /* if the value is already in a pointer register
8200      then don't need anything more */
8201   if (!AOP_INPREG (AOP (left)))
8202     {
8203       if (IS_AOP_PREG (left))
8204         {
8205           // Aha, it is a pointer, just in disguise.
8206           rname = aopGet (AOP (left), 0, FALSE, FALSE);
8207           if (*rname != '@')
8208             {
8209               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8210                       __FILE__, __LINE__);
8211             }
8212           else
8213             {
8214               // Expected case.
8215               emitcode ("mov", "a%s,%s", rname + 1, rname);
8216               rname++;  // skip the '@'.
8217             }
8218         }
8219       else
8220         {
8221           /* otherwise get a free pointer register */
8222           aop = newAsmop (0);
8223           preg = getFreePtr (ic, &aop, FALSE);
8224           emitcode ("mov", "%s,%s",
8225                     preg->name,
8226                     aopGet (AOP (left), 0, FALSE, TRUE));
8227           rname = preg->name;
8228         }
8229     }
8230   else
8231     rname = aopGet (AOP (left), 0, FALSE, FALSE);
8232
8233   //aopOp (result, ic, FALSE);
8234   aopOp (result, ic, result?TRUE:FALSE);
8235
8236   /* if bitfield then unpack the bits */
8237   if (IS_BITFIELD (retype))
8238     genUnpackBits (result, rname, POINTER, ifx);
8239   else
8240     {
8241       /* we have can just get the values */
8242       int size = AOP_SIZE (result);
8243       int offset = 0;
8244
8245       while (size--)
8246         {
8247           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8248             {
8249
8250               emitcode ("mov", "a,@%s", rname);
8251               if (!ifx)
8252                 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8253             }
8254           else
8255             {
8256               sprintf (buffer, "@%s", rname);
8257               aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8258             }
8259           offset++;
8260           if (size || pi)
8261             emitcode ("inc", "%s", rname);
8262         }
8263     }
8264
8265   /* now some housekeeping stuff */
8266   if (aop)       /* we had to allocate for this iCode */
8267     {
8268       if (pi) { /* post increment present */
8269         aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8270       }
8271       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8272     }
8273   else
8274     {
8275       /* we did not allocate which means left
8276          already in a pointer register, then
8277          if size > 0 && this could be used again
8278          we have to point it back to where it
8279          belongs */
8280       if ((AOP_SIZE (result) > 1 &&
8281            !OP_SYMBOL (left)->remat &&
8282            (OP_SYMBOL (left)->liveTo > ic->seq ||
8283             ic->depth)) &&
8284           !pi)
8285         {
8286           int size = AOP_SIZE (result) - 1;
8287           while (size--)
8288             emitcode ("dec", "%s", rname);
8289         }
8290     }
8291   
8292   if (ifx && !ifx->generated)
8293     {
8294       genIfxJump (ifx, "a", left, NULL, result);
8295     }
8296
8297   /* done */
8298   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8299   freeAsmop (left, NULL, ic, TRUE);
8300   if (pi) pi->generated = 1;
8301 }
8302
8303 /*-----------------------------------------------------------------*/
8304 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8305 /*-----------------------------------------------------------------*/
8306 static void
8307 genPagedPointerGet (operand * left,
8308                     operand * result,
8309                     iCode * ic,
8310                     iCode *pi,
8311                     iCode *ifx)
8312 {
8313   asmop *aop = NULL;
8314   regs *preg = NULL;
8315   char *rname;
8316   sym_link *rtype, *retype;
8317
8318   D(emitcode (";     genPagedPointerGet",""));
8319
8320   rtype = operandType (result);
8321   retype = getSpec (rtype);
8322
8323   aopOp (left, ic, FALSE);
8324
8325   /* if the value is already in a pointer register
8326      then don't need anything more */
8327   if (!AOP_INPREG (AOP (left)))
8328     {
8329       /* otherwise get a free pointer register */
8330       aop = newAsmop (0);
8331       preg = getFreePtr (ic, &aop, FALSE);
8332       emitcode ("mov", "%s,%s",
8333                 preg->name,
8334                 aopGet (AOP (left), 0, FALSE, TRUE));
8335       rname = preg->name;
8336     }
8337   else
8338     rname = aopGet (AOP (left), 0, FALSE, FALSE);
8339
8340   aopOp (result, ic, FALSE);
8341
8342   /* if bitfield then unpack the bits */
8343   if (IS_BITFIELD (retype))
8344     genUnpackBits (result, rname, PPOINTER, ifx);
8345   else
8346     {
8347       /* we have can just get the values */
8348       int size = AOP_SIZE (result);
8349       int offset = 0;
8350
8351       while (size--)
8352         {
8353
8354           emitcode ("movx", "a,@%s", rname);
8355           if (!ifx)
8356             aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8357
8358           offset++;
8359
8360           if (size || pi)
8361             emitcode ("inc", "%s", rname);
8362         }
8363     }
8364
8365   /* now some housekeeping stuff */
8366   if (aop) /* we had to allocate for this iCode */
8367     {
8368       if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8369       freeAsmop (NULL, aop, ic, TRUE);
8370     }
8371   else
8372     {
8373       /* we did not allocate which means left
8374          already in a pointer register, then
8375          if size > 0 && this could be used again
8376          we have to point it back to where it
8377          belongs */
8378       if ((AOP_SIZE (result) > 1 &&
8379            !OP_SYMBOL (left)->remat &&
8380            (OP_SYMBOL (left)->liveTo > ic->seq ||
8381             ic->depth)) &&
8382           !pi)
8383         {
8384           int size = AOP_SIZE (result) - 1;
8385           while (size--)
8386             emitcode ("dec", "%s", rname);
8387         }
8388     }
8389
8390   if (ifx && !ifx->generated)
8391     {
8392       genIfxJump (ifx, "a", left, NULL, result);
8393     }
8394
8395   /* done */
8396   freeAsmop (left, NULL, ic, TRUE);
8397   freeAsmop (result, NULL, ic, TRUE);
8398   if (pi) pi->generated = 1;
8399
8400 }
8401
8402 /*--------------------------------------------------------------------*/
8403 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8404 /*--------------------------------------------------------------------*/
8405 static void
8406 loadDptrFromOperand (operand *op, bool loadBToo)
8407 {
8408   if (AOP_TYPE (op) != AOP_STR)
8409     {
8410       /* if this is remateriazable */
8411       if (AOP_TYPE (op) == AOP_IMMD)
8412         {
8413           emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8414           if (loadBToo)
8415             {
8416               if (AOP(op)->aopu.aop_immd.from_cast_remat)
8417                 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8418               else
8419                 {
8420                   wassertl(FALSE, "need pointerCode");
8421                   emitcode ("", "; mov b,???");
8422                   /* genPointerGet and genPointerSet originally did different
8423                   ** things for this case. Both seem wrong.
8424                   ** from genPointerGet:
8425                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
8426                   ** from genPointerSet:
8427                   **  emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8428                   */
8429                 }
8430             }
8431         }
8432       else if (AOP_TYPE (op) == AOP_DPTR)
8433         {
8434           if (loadBToo)
8435             {
8436               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8437               emitcode ("push", "acc");
8438               MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8439               emitcode ("push", "acc");
8440               emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8441               emitcode ("pop", "dph");
8442               emitcode ("pop", "dpl");
8443             }
8444           else
8445             {
8446               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8447               emitcode ("push", "acc");
8448               emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8449               emitcode ("pop", "dpl");
8450             }
8451         }
8452       else
8453         {                       /* we need to get it byte by byte */
8454           emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8455           emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8456           if (loadBToo)
8457             emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8458         }
8459     }
8460 }
8461
8462 /*-----------------------------------------------------------------*/
8463 /* genFarPointerGet - gget value from far space                    */
8464 /*-----------------------------------------------------------------*/
8465 static void
8466 genFarPointerGet (operand * left,
8467                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
8468 {
8469   int size, offset;
8470   sym_link *retype = getSpec (operandType (result));
8471
8472   D(emitcode (";     genFarPointerGet",""));
8473
8474   aopOp (left, ic, FALSE);
8475   loadDptrFromOperand (left, FALSE);
8476
8477   /* so dptr now contains the address */
8478   aopOp (result, ic, FALSE);
8479
8480   /* if bit then unpack */
8481   if (IS_BITFIELD (retype))
8482     genUnpackBits (result, "dptr", FPOINTER, ifx);
8483   else
8484     {
8485       size = AOP_SIZE (result);
8486       offset = 0;
8487
8488       while (size--)
8489         {
8490           emitcode ("movx", "a,@dptr");
8491           if (!ifx)
8492             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8493           if (size || pi)
8494             emitcode ("inc", "dptr");
8495         }
8496
8497     }
8498   
8499   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8500     {
8501       aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8502       aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8503       pi->generated = 1;
8504     }
8505
8506   if (ifx && !ifx->generated)
8507     {
8508       genIfxJump (ifx, "a", left, NULL, result);
8509     }
8510
8511   freeAsmop (left, NULL, ic, TRUE);
8512   freeAsmop (result, NULL, ic, TRUE);
8513 }
8514
8515 /*-----------------------------------------------------------------*/
8516 /* genCodePointerGet - gget value from code space                  */
8517 /*-----------------------------------------------------------------*/
8518 static void
8519 genCodePointerGet (operand * left,
8520                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
8521 {
8522   int size, offset;
8523   sym_link *retype = getSpec (operandType (result));
8524
8525   D(emitcode (";     genCodePointerGet",""));
8526
8527   aopOp (left, ic, FALSE);
8528   loadDptrFromOperand (left, FALSE);
8529
8530   /* so dptr now contains the address */
8531   aopOp (result, ic, FALSE);
8532
8533   /* if bit then unpack */
8534   if (IS_BITFIELD (retype))
8535     genUnpackBits (result, "dptr", CPOINTER, ifx);
8536   else
8537     {
8538       size = AOP_SIZE (result);
8539       offset = 0;
8540
8541       while (size--)
8542         {
8543           if (pi)
8544             {
8545               emitcode ("clr", "a");
8546               emitcode ("movc", "a,@a+dptr");
8547               if (!ifx)
8548                 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8549               emitcode ("inc", "dptr");
8550             }
8551           else
8552             {
8553               emitcode ("mov", "a,#0x%02x", offset);
8554               emitcode ("movc", "a,@a+dptr");
8555               if (!ifx)
8556                 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8557             }
8558         }
8559     }
8560
8561   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8562     {
8563       aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8564       aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8565       pi->generated = 1;
8566     }
8567
8568   if (ifx && !ifx->generated)
8569     {
8570       genIfxJump (ifx, "a", left, NULL, result);
8571     }
8572
8573   freeAsmop (left, NULL, ic, TRUE);
8574   freeAsmop (result, NULL, ic, TRUE);
8575 }
8576
8577 /*-----------------------------------------------------------------*/
8578 /* genGenPointerGet - gget value from generic pointer space        */
8579 /*-----------------------------------------------------------------*/
8580 static void
8581 genGenPointerGet (operand * left,
8582                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
8583 {
8584   int size, offset;
8585   sym_link *retype = getSpec (operandType (result));
8586
8587   D(emitcode (";     genGenPointerGet",""));
8588
8589   aopOp (left, ic, FALSE);
8590   loadDptrFromOperand (left, TRUE);
8591
8592   /* so dptr know contains the address */
8593   aopOp (result, ic, FALSE);
8594
8595   /* if bit then unpack */
8596   if (IS_BITFIELD (retype))
8597     genUnpackBits (result, "dptr", GPOINTER, ifx);
8598   else
8599     {
8600       size = AOP_SIZE (result);
8601       offset = 0;
8602
8603       while (size--)
8604         {
8605           emitcode ("lcall", "__gptrget");
8606           if (!ifx)
8607             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8608           if (size || pi)
8609             emitcode ("inc", "dptr");
8610         }
8611     }
8612
8613   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8614     {
8615       aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8616       aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8617       pi->generated = 1;
8618     }
8619
8620   if (ifx && !ifx->generated)
8621     {
8622       genIfxJump (ifx, "a", left, NULL, result);
8623     }
8624
8625     
8626   freeAsmop (left, NULL, ic, TRUE);
8627   freeAsmop (result, NULL, ic, TRUE);
8628 }
8629
8630 /*-----------------------------------------------------------------*/
8631 /* genPointerGet - generate code for pointer get                   */
8632 /*-----------------------------------------------------------------*/
8633 static void
8634 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8635 {
8636   operand *left, *result;
8637   sym_link *type, *etype;
8638   int p_type;
8639
8640   D(emitcode (";     genPointerGet",""));
8641
8642   left = IC_LEFT (ic);
8643   result = IC_RESULT (ic);
8644   
8645   if (getSize (operandType (result))>1)
8646     ifx = NULL;
8647
8648   /* depending on the type of pointer we need to
8649      move it to the correct pointer register */
8650   type = operandType (left);
8651   etype = getSpec (type);
8652   /* if left is of type of pointer then it is simple */
8653   if (IS_PTR (type) && !IS_FUNC (type->next))
8654     p_type = DCL_TYPE (type);
8655   else
8656     {
8657       /* we have to go by the storage class */
8658       p_type = PTR_TYPE (SPEC_OCLS (etype));
8659     }
8660
8661   /* special case when cast remat */
8662   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8663       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8664           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8665           type = operandType (left);
8666           p_type = DCL_TYPE (type);
8667   }
8668   /* now that we have the pointer type we assign
8669      the pointer values */
8670   switch (p_type)
8671     {
8672
8673     case POINTER:
8674     case IPOINTER:
8675       genNearPointerGet (left, result, ic, pi, ifx);
8676       break;
8677
8678     case PPOINTER:
8679       genPagedPointerGet (left, result, ic, pi, ifx);
8680       break;
8681
8682     case FPOINTER:
8683       genFarPointerGet (left, result, ic, pi, ifx);
8684       break;
8685
8686     case CPOINTER:
8687       genCodePointerGet (left, result, ic, pi, ifx);
8688       break;
8689
8690     case GPOINTER:
8691       genGenPointerGet (left, result, ic, pi, ifx);
8692       break;
8693     }
8694
8695 }
8696
8697
8698
8699 /*-----------------------------------------------------------------*/
8700 /* genPackBits - generates code for packed bit storage             */
8701 /*-----------------------------------------------------------------*/
8702 static void
8703 genPackBits (sym_link * etype,
8704              operand * right,
8705              char *rname, int p_type)
8706 {
8707   int offset = 0;       /* source byte offset */
8708   int rlen = 0;         /* remaining bitfield length */
8709   int blen;             /* bitfield length */
8710   int bstr;             /* bitfield starting bit within byte */
8711   int litval;           /* source literal value (if AOP_LIT) */
8712   unsigned char mask;   /* bitmask within current byte */
8713
8714   D(emitcode (";     genPackBits",""));
8715
8716   blen = SPEC_BLEN (etype);
8717   bstr = SPEC_BSTR (etype);
8718
8719   /* If the bitfield length is less than a byte */
8720   if (blen < 8)
8721     {
8722       mask = ((unsigned char) (0xFF << (blen + bstr)) |
8723               (unsigned char) (0xFF >> (8 - bstr)));
8724
8725       if (AOP_TYPE (right) == AOP_LIT)
8726         {
8727           /* Case with a bitfield length <8 and literal source
8728           */
8729           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8730           litval <<= bstr;
8731           litval &= (~mask) & 0xff;
8732           emitPtrByteGet (rname, p_type, FALSE);
8733           if ((mask|litval)!=0xff)
8734             emitcode ("anl","a,#0x%02x", mask);
8735           if (litval)
8736             emitcode ("orl","a,#0x%02x", litval);
8737         }
8738       else
8739         {
8740           if ((blen==1) && (p_type!=GPOINTER))
8741             {
8742               /* Case with a bitfield length == 1 and no generic pointer
8743               */
8744               if (AOP_TYPE (right) == AOP_CRY)
8745                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8746               else
8747                 {
8748                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8749                   emitcode ("rrc","a");
8750                 }
8751               emitPtrByteGet (rname, p_type, FALSE);
8752               emitcode ("mov","acc.%d,c",bstr);
8753             }
8754           else
8755             {
8756               /* Case with a bitfield length < 8 and arbitrary source
8757               */
8758               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8759               /* shift and mask source value */
8760               AccLsh (bstr);
8761               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8762
8763               /* transfer A to B and get next byte */
8764               emitPtrByteGet (rname, p_type, TRUE);
8765
8766               emitcode ("anl", "a,#0x%02x", mask);
8767               emitcode ("orl", "a,b");
8768               if (p_type == GPOINTER)
8769                 emitcode ("pop", "b");
8770            }
8771         }
8772
8773       emitPtrByteSet (rname, p_type, "a");
8774       return;
8775     }
8776
8777   /* Bit length is greater than 7 bits. In this case, copy  */
8778   /* all except the partial byte at the end                 */
8779   for (rlen=blen;rlen>=8;rlen-=8)
8780     {
8781       emitPtrByteSet (rname, p_type,
8782                       aopGet (AOP (right), offset++, FALSE, TRUE) );
8783       if (rlen>8)
8784         emitcode ("inc", "%s", rname);
8785     }
8786
8787   /* If there was a partial byte at the end */
8788   if (rlen)
8789     {
8790       mask = (((unsigned char) -1 << rlen) & 0xff);
8791
8792       if (AOP_TYPE (right) == AOP_LIT)
8793         {
8794           /* Case with partial byte and literal source
8795           */
8796           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8797           litval >>= (blen-rlen);
8798           litval &= (~mask) & 0xff;
8799           emitPtrByteGet (rname, p_type, FALSE);
8800           if ((mask|litval)!=0xff)
8801             emitcode ("anl","a,#0x%02x", mask);
8802           if (litval)
8803             emitcode ("orl","a,#0x%02x", litval);
8804         }
8805       else
8806         {
8807           /* Case with partial byte and arbitrary source
8808           */
8809           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8810           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8811
8812           /* transfer A to B and get next byte */
8813           emitPtrByteGet (rname, p_type, TRUE);
8814
8815           emitcode ("anl", "a,#0x%02x", mask);
8816           emitcode ("orl", "a,b");
8817           if (p_type == GPOINTER)
8818             emitcode ("pop", "b");
8819         }
8820       emitPtrByteSet (rname, p_type, "a");
8821     }
8822
8823 }
8824
8825
8826 /*-----------------------------------------------------------------*/
8827 /* genDataPointerSet - remat pointer to data space                 */
8828 /*-----------------------------------------------------------------*/
8829 static void
8830 genDataPointerSet (operand * right,
8831                    operand * result,
8832                    iCode * ic)
8833 {
8834   int size, offset = 0;
8835   char *l, buffer[256];
8836
8837   D(emitcode (";     genDataPointerSet",""));
8838
8839   aopOp (right, ic, FALSE);
8840
8841   l = aopGet (AOP (result), 0, FALSE, TRUE);
8842   size = AOP_SIZE (right);
8843   while (size--)
8844     {
8845       if (offset)
8846         sprintf (buffer, "(%s + %d)", l + 1, offset);
8847       else
8848         sprintf (buffer, "%s", l + 1);
8849       emitcode ("mov", "%s,%s", buffer,
8850                 aopGet (AOP (right), offset++, FALSE, FALSE));
8851     }
8852
8853   freeAsmop (right, NULL, ic, TRUE);
8854   freeAsmop (result, NULL, ic, TRUE);
8855 }
8856
8857 /*-----------------------------------------------------------------*/
8858 /* genNearPointerSet - emitcode for near pointer put                */
8859 /*-----------------------------------------------------------------*/
8860 static void
8861 genNearPointerSet (operand * right,
8862                    operand * result,
8863                    iCode * ic,
8864                    iCode * pi)
8865 {
8866   asmop *aop = NULL;
8867   regs *preg = NULL;
8868   char *rname, *l;
8869   sym_link *retype, *letype;
8870   sym_link *ptype = operandType (result);
8871
8872   D(emitcode (";     genNearPointerSet",""));
8873
8874   retype = getSpec (operandType (right));
8875   letype = getSpec (ptype);
8876   aopOp (result, ic, FALSE);
8877
8878   /* if the result is rematerializable &
8879      in data space & not a bit variable */
8880   if (AOP_TYPE (result) == AOP_IMMD &&
8881       DCL_TYPE (ptype) == POINTER &&
8882       !IS_BITVAR (retype) &&
8883       !IS_BITVAR (letype))
8884     {
8885       genDataPointerSet (right, result, ic);
8886       return;
8887     }
8888
8889   /* if the value is already in a pointer register
8890      then don't need anything more */
8891   if (!AOP_INPREG (AOP (result)))
8892     {
8893         if (
8894             //AOP_TYPE (result) == AOP_STK
8895             IS_AOP_PREG(result)
8896             )
8897         {
8898             // Aha, it is a pointer, just in disguise.
8899             rname = aopGet (AOP (result), 0, FALSE, FALSE);
8900             if (*rname != '@')
8901             {
8902                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8903                         __FILE__, __LINE__);
8904             }
8905             else
8906             {
8907                 // Expected case.
8908                 emitcode ("mov", "a%s,%s", rname + 1, rname);
8909                 rname++;  // skip the '@'.
8910             }
8911         }
8912         else
8913         {
8914             /* otherwise get a free pointer register */
8915             aop = newAsmop (0);
8916             preg = getFreePtr (ic, &aop, FALSE);
8917             emitcode ("mov", "%s,%s",
8918                       preg->name,
8919                       aopGet (AOP (result), 0, FALSE, TRUE));
8920             rname = preg->name;
8921         }
8922     }
8923     else
8924     {
8925         rname = aopGet (AOP (result), 0, FALSE, FALSE);
8926     }
8927
8928   aopOp (right, ic, FALSE);
8929
8930   /* if bitfield then unpack the bits */
8931   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
8932     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
8933   else
8934     {
8935       /* we have can just get the values */
8936       int size = AOP_SIZE (right);
8937       int offset = 0;
8938
8939       while (size--)
8940         {
8941           l = aopGet (AOP (right), offset, FALSE, TRUE);
8942           if (*l == '@')
8943             {
8944               MOVA (l);
8945               emitcode ("mov", "@%s,a", rname);
8946             }
8947           else
8948             emitcode ("mov", "@%s,%s", rname, l);
8949           if (size || pi)
8950             emitcode ("inc", "%s", rname);
8951           offset++;
8952         }
8953     }
8954
8955   /* now some housekeeping stuff */
8956   if (aop) /* we had to allocate for this iCode */
8957     {
8958       if (pi)
8959         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8960       freeAsmop (NULL, aop, ic, TRUE);
8961     }
8962   else
8963     {
8964       /* we did not allocate which means left
8965          already in a pointer register, then
8966          if size > 0 && this could be used again
8967          we have to point it back to where it
8968          belongs */
8969       if ((AOP_SIZE (right) > 1 &&
8970            !OP_SYMBOL (result)->remat &&
8971            (OP_SYMBOL (result)->liveTo > ic->seq ||
8972             ic->depth)) &&
8973           !pi)
8974         {
8975           int size = AOP_SIZE (right) - 1;
8976           while (size--)
8977             emitcode ("dec", "%s", rname);
8978         }
8979     }
8980
8981   /* done */
8982   if (pi) pi->generated = 1;
8983   freeAsmop (result, NULL, ic, TRUE);
8984   freeAsmop (right, NULL, ic, TRUE);
8985 }
8986
8987 /*-----------------------------------------------------------------*/
8988 /* genPagedPointerSet - emitcode for Paged pointer put             */
8989 /*-----------------------------------------------------------------*/
8990 static void
8991 genPagedPointerSet (operand * right,
8992                     operand * result,
8993                     iCode * ic,
8994                     iCode * pi)
8995 {
8996   asmop *aop = NULL;
8997   regs *preg = NULL;
8998   char *rname, *l;
8999   sym_link *retype, *letype;
9000
9001   D(emitcode (";     genPagedPointerSet",""));
9002
9003   retype = getSpec (operandType (right));
9004   letype = getSpec (operandType (result));
9005
9006   aopOp (result, ic, FALSE);
9007
9008   /* if the value is already in a pointer register
9009      then don't need anything more */
9010   if (!AOP_INPREG (AOP (result)))
9011     {
9012       /* otherwise get a free pointer register */
9013       aop = newAsmop (0);
9014       preg = getFreePtr (ic, &aop, FALSE);
9015       emitcode ("mov", "%s,%s",
9016                 preg->name,
9017                 aopGet (AOP (result), 0, FALSE, TRUE));
9018       rname = preg->name;
9019     }
9020   else
9021     rname = aopGet (AOP (result), 0, FALSE, FALSE);
9022
9023   aopOp (right, ic, FALSE);
9024
9025   /* if bitfield then unpack the bits */
9026   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9027     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9028   else
9029     {
9030       /* we have can just get the values */
9031       int size = AOP_SIZE (right);
9032       int offset = 0;
9033
9034       while (size--)
9035         {
9036           l = aopGet (AOP (right), offset, FALSE, TRUE);
9037
9038           MOVA (l);
9039           emitcode ("movx", "@%s,a", rname);
9040
9041           if (size || pi)
9042             emitcode ("inc", "%s", rname);
9043
9044           offset++;
9045         }
9046     }
9047
9048   /* now some housekeeping stuff */
9049   if (aop) /* we had to allocate for this iCode */
9050     {
9051       if (pi)
9052         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9053       freeAsmop (NULL, aop, ic, TRUE);
9054     }
9055   else
9056     {
9057       /* we did not allocate which means left
9058          already in a pointer register, then
9059          if size > 0 && this could be used again
9060          we have to point it back to where it
9061          belongs */
9062       if (AOP_SIZE (right) > 1 &&
9063           !OP_SYMBOL (result)->remat &&
9064           (OP_SYMBOL (result)->liveTo > ic->seq ||
9065            ic->depth))
9066         {
9067           int size = AOP_SIZE (right) - 1;
9068           while (size--)
9069             emitcode ("dec", "%s", rname);
9070         }
9071     }
9072
9073   /* done */
9074   if (pi) pi->generated = 1;
9075   freeAsmop (result, NULL, ic, TRUE);
9076   freeAsmop (right, NULL, ic, TRUE);
9077
9078
9079 }
9080
9081 /*-----------------------------------------------------------------*/
9082 /* genFarPointerSet - set value from far space                     */
9083 /*-----------------------------------------------------------------*/
9084 static void
9085 genFarPointerSet (operand * right,
9086                   operand * result, iCode * ic, iCode * pi)
9087 {
9088   int size, offset;
9089   sym_link *retype = getSpec (operandType (right));
9090   sym_link *letype = getSpec (operandType (result));
9091
9092   D(emitcode (";     genFarPointerSet",""));
9093
9094   aopOp (result, ic, FALSE);
9095   loadDptrFromOperand (result, FALSE);
9096
9097   /* so dptr know contains the address */
9098   aopOp (right, ic, FALSE);
9099
9100   /* if bit then unpack */
9101   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9102     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9103   else
9104     {
9105       size = AOP_SIZE (right);
9106       offset = 0;
9107
9108       while (size--)
9109         {
9110           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9111           MOVA (l);
9112           emitcode ("movx", "@dptr,a");
9113           if (size || pi)
9114             emitcode ("inc", "dptr");
9115         }
9116     }
9117   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9118     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9119     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9120     pi->generated=1;
9121   }
9122   freeAsmop (result, NULL, ic, TRUE);
9123   freeAsmop (right, NULL, ic, TRUE);
9124 }
9125
9126 /*-----------------------------------------------------------------*/
9127 /* genGenPointerSet - set value from generic pointer space         */
9128 /*-----------------------------------------------------------------*/
9129 static void
9130 genGenPointerSet (operand * right,
9131                   operand * result, iCode * ic, iCode * pi)
9132 {
9133   int size, offset;
9134   sym_link *retype = getSpec (operandType (right));
9135   sym_link *letype = getSpec (operandType (result));
9136
9137   D(emitcode (";     genGenPointerSet",""));
9138
9139   aopOp (result, ic, FALSE);
9140   loadDptrFromOperand (result, TRUE);
9141
9142   /* so dptr know contains the address */
9143   aopOp (right, ic, FALSE);
9144
9145   /* if bit then unpack */
9146   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9147     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9148   else
9149     {
9150       size = AOP_SIZE (right);
9151       offset = 0;
9152
9153       while (size--)
9154         {
9155           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9156           MOVA (l);
9157           emitcode ("lcall", "__gptrput");
9158           if (size || pi)
9159             emitcode ("inc", "dptr");
9160         }
9161     }
9162
9163   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9164     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9165     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9166     pi->generated=1;
9167   }
9168   freeAsmop (result, NULL, ic, TRUE);
9169   freeAsmop (right, NULL, ic, TRUE);
9170 }
9171
9172 /*-----------------------------------------------------------------*/
9173 /* genPointerSet - stores the value into a pointer location        */
9174 /*-----------------------------------------------------------------*/
9175 static void
9176 genPointerSet (iCode * ic, iCode *pi)
9177 {
9178   operand *right, *result;
9179   sym_link *type, *etype;
9180   int p_type;
9181
9182   D(emitcode (";     genPointerSet",""));
9183
9184   right = IC_RIGHT (ic);
9185   result = IC_RESULT (ic);
9186
9187   /* depending on the type of pointer we need to
9188      move it to the correct pointer register */
9189   type = operandType (result);
9190   etype = getSpec (type);
9191   /* if left is of type of pointer then it is simple */
9192   if (IS_PTR (type) && !IS_FUNC (type->next))
9193     {
9194       p_type = DCL_TYPE (type);
9195     }
9196   else
9197     {
9198       /* we have to go by the storage class */
9199       p_type = PTR_TYPE (SPEC_OCLS (etype));
9200     }
9201
9202   /* special case when cast remat */
9203   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9204       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9205           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9206           type = operandType (result);
9207           p_type = DCL_TYPE (type);
9208   }
9209   /* now that we have the pointer type we assign
9210      the pointer values */
9211   switch (p_type)
9212     {
9213
9214     case POINTER:
9215     case IPOINTER:
9216       genNearPointerSet (right, result, ic, pi);
9217       break;
9218
9219     case PPOINTER:
9220       genPagedPointerSet (right, result, ic, pi);
9221       break;
9222
9223     case FPOINTER:
9224       genFarPointerSet (right, result, ic, pi);
9225       break;
9226
9227     case GPOINTER:
9228       genGenPointerSet (right, result, ic, pi);
9229       break;
9230
9231     default:
9232       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9233               "genPointerSet: illegal pointer type");
9234     }
9235
9236 }
9237
9238 /*-----------------------------------------------------------------*/
9239 /* genIfx - generate code for Ifx statement                        */
9240 /*-----------------------------------------------------------------*/
9241 static void
9242 genIfx (iCode * ic, iCode * popIc)
9243 {
9244   operand *cond = IC_COND (ic);
9245   int isbit = 0;
9246
9247   D(emitcode (";     genIfx",""));
9248
9249   aopOp (cond, ic, FALSE);
9250
9251   /* get the value into acc */
9252   if (AOP_TYPE (cond) != AOP_CRY)
9253     toBoolean (cond);
9254   else
9255     isbit = 1;
9256   /* the result is now in the accumulator */
9257   freeAsmop (cond, NULL, ic, TRUE);
9258
9259   /* if there was something to be popped then do it */
9260   if (popIc)
9261     genIpop (popIc);
9262
9263   /* if the condition is  a bit variable */
9264   if (isbit && IS_ITEMP (cond) &&
9265       SPIL_LOC (cond))
9266     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9267   else if (isbit && !IS_ITEMP (cond))
9268     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9269   else
9270     genIfxJump (ic, "a", NULL, NULL, NULL);
9271
9272   ic->generated = 1;
9273 }
9274
9275 /*-----------------------------------------------------------------*/
9276 /* genAddrOf - generates code for address of                       */
9277 /*-----------------------------------------------------------------*/
9278 static void
9279 genAddrOf (iCode * ic)
9280 {
9281   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9282   int size, offset;
9283
9284   D(emitcode (";     genAddrOf",""));
9285
9286   aopOp (IC_RESULT (ic), ic, FALSE);
9287
9288   /* if the operand is on the stack then we
9289      need to get the stack offset of this
9290      variable */
9291   if (sym->onStack)
9292     {
9293       /* if it has an offset then we need to compute
9294          it */
9295       if (sym->stack)
9296         {
9297           emitcode ("mov", "a,_bp");
9298           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9299                                          ((char) (sym->stack - _G.nRegsSaved)) :
9300                                          ((char) sym->stack)) & 0xff);
9301           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9302         }
9303       else
9304         {
9305           /* we can just move _bp */
9306           aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9307         }
9308       /* fill the result with zero */
9309       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9310
9311       offset = 1;
9312       while (size--)
9313         {
9314           aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9315         }
9316
9317       goto release;
9318     }
9319
9320   /* object not on stack then we need the name */
9321   size = AOP_SIZE (IC_RESULT (ic));
9322   offset = 0;
9323
9324   while (size--)
9325     {
9326       char s[SDCC_NAME_MAX];
9327       if (offset)
9328         sprintf (s, "#(%s >> %d)",
9329                  sym->rname,
9330                  offset * 8);
9331       else
9332         sprintf (s, "#%s", sym->rname);
9333       aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9334     }
9335
9336 release:
9337   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9338
9339 }
9340
9341 /*-----------------------------------------------------------------*/
9342 /* genFarFarAssign - assignment when both are in far space         */
9343 /*-----------------------------------------------------------------*/
9344 static void
9345 genFarFarAssign (operand * result, operand * right, iCode * ic)
9346 {
9347   int size = AOP_SIZE (right);
9348   int offset = 0;
9349   char *l;
9350
9351   D(emitcode (";     genFarFarAssign",""));
9352
9353   /* first push the right side on to the stack */
9354   while (size--)
9355     {
9356       l = aopGet (AOP (right), offset++, FALSE, FALSE);
9357       MOVA (l);
9358       emitcode ("push", "acc");
9359     }
9360
9361   freeAsmop (right, NULL, ic, FALSE);
9362   /* now assign DPTR to result */
9363   aopOp (result, ic, FALSE);
9364   size = AOP_SIZE (result);
9365   while (size--)
9366     {
9367       emitcode ("pop", "acc");
9368       aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9369     }
9370   freeAsmop (result, NULL, ic, FALSE);
9371
9372 }
9373
9374 /*-----------------------------------------------------------------*/
9375 /* genAssign - generate code for assignment                        */
9376 /*-----------------------------------------------------------------*/
9377 static void
9378 genAssign (iCode * ic)
9379 {
9380   operand *result, *right;
9381   int size, offset;
9382   unsigned long lit = 0L;
9383
9384   D(emitcode(";     genAssign",""));
9385
9386   result = IC_RESULT (ic);
9387   right = IC_RIGHT (ic);
9388
9389   /* if they are the same */
9390   if (operandsEqu (result, right) &&
9391       !isOperandVolatile (result, FALSE) &&
9392       !isOperandVolatile (right, FALSE))
9393     return;
9394
9395   aopOp (right, ic, FALSE);
9396
9397   /* special case both in far space */
9398   if (AOP_TYPE (right) == AOP_DPTR &&
9399       IS_TRUE_SYMOP (result) &&
9400       isOperandInFarSpace (result))
9401     {
9402
9403       genFarFarAssign (result, right, ic);
9404       return;
9405     }
9406
9407   aopOp (result, ic, TRUE);
9408
9409   /* if they are the same registers */
9410   if (sameRegs (AOP (right), AOP (result)) &&
9411       !isOperandVolatile (result, FALSE) &&
9412       !isOperandVolatile (right, FALSE))
9413     goto release;
9414
9415   /* if the result is a bit */
9416   if (AOP_TYPE (result) == AOP_CRY)
9417     {
9418
9419       /* if the right size is a literal then
9420          we know what the value is */
9421       if (AOP_TYPE (right) == AOP_LIT)
9422         {
9423           if (((int) operandLitValue (right)))
9424             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9425           else
9426             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9427           goto release;
9428         }
9429
9430       /* the right is also a bit variable */
9431       if (AOP_TYPE (right) == AOP_CRY)
9432         {
9433           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9434           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9435           goto release;
9436         }
9437
9438       /* we need to or */
9439       toBoolean (right);
9440       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9441       goto release;
9442     }
9443
9444   /* bit variables done */
9445   /* general case */
9446   size = AOP_SIZE (result);
9447   offset = 0;
9448   if (AOP_TYPE (right) == AOP_LIT)
9449     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9450   if ((size > 1) &&
9451       (AOP_TYPE (result) != AOP_REG) &&
9452       (AOP_TYPE (right) == AOP_LIT) &&
9453       !IS_FLOAT (operandType (right)) &&
9454       (lit < 256L))
9455     {
9456       emitcode ("clr", "a");
9457       while (size--)
9458         {
9459           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
9460             aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
9461           else
9462             aopPut (AOP (result),
9463                     aopGet (AOP (right), size, FALSE, FALSE),
9464                     size,
9465                     isOperandVolatile (result, FALSE));
9466         }
9467     }
9468   else
9469     {
9470       while (size--)
9471         {
9472           aopPut (AOP (result),
9473                   aopGet (AOP (right), offset, FALSE, FALSE),
9474                   offset,
9475                   isOperandVolatile (result, FALSE));
9476           offset++;
9477         }
9478     }
9479
9480 release:
9481   freeAsmop (right, NULL, ic, TRUE);
9482   freeAsmop (result, NULL, ic, TRUE);
9483 }
9484
9485 /*-----------------------------------------------------------------*/
9486 /* genJumpTab - genrates code for jump table                       */
9487 /*-----------------------------------------------------------------*/
9488 static void
9489 genJumpTab (iCode * ic)
9490 {
9491   symbol *jtab,*jtablo,*jtabhi;
9492   char *l;
9493   unsigned int count;
9494
9495   D(emitcode (";     genJumpTab",""));
9496
9497   count = elementsInSet( IC_JTLABELS (ic) );
9498
9499   if( count <= 16 )
9500     {
9501       /* this algorithm needs 9 cycles and 7 + 3*n bytes 
9502          if the switch argument is in an register. 
9503          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */ 
9504       aopOp (IC_JTCOND (ic), ic, FALSE);
9505       /* get the condition into accumulator */
9506       l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9507       MOVA (l);
9508       /* multiply by three */
9509       emitcode ("add", "a,acc");
9510       emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9511       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9512
9513       jtab = newiTempLabel (NULL);
9514       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9515       emitcode ("jmp", "@a+dptr");
9516       emitcode ("", "%05d$:", jtab->key + 100);
9517       /* now generate the jump labels */
9518       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9519            jtab = setNextItem (IC_JTLABELS (ic)))
9520         emitcode ("ljmp", "%05d$", jtab->key + 100);
9521     }
9522   else
9523     {
9524       /* this algorithm needs 14 cycles and 13 + 2*n bytes 
9525          if the switch argument is in an register. 
9526          For n>6 this algorithm may be more compact */ 
9527       jtablo = newiTempLabel (NULL);
9528       jtabhi = newiTempLabel (NULL);
9529
9530       /* get the condition into accumulator.
9531          Using b as temporary storage, if register push/pop is needed */ 
9532       aopOp (IC_JTCOND (ic), ic, FALSE);
9533       l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9534       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9535           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9536         {
9537           emitcode ("mov", "b,%s", l);
9538           l = "b";
9539         }
9540       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);            
9541       MOVA (l);      
9542       if( count <= 112 )
9543         {
9544           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9545           emitcode ("movc", "a,@a+pc");
9546           emitcode ("push", "acc");
9547
9548           MOVA (l);
9549           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9550           emitcode ("movc", "a,@a+pc");
9551           emitcode ("push", "acc");
9552         }
9553       else      
9554         {
9555           /* this scales up to n<=255, but needs two more bytes
9556              and changes dptr */
9557           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9558           emitcode ("movc", "a,@a+dptr");
9559           emitcode ("push", "acc");
9560
9561           MOVA (l);
9562           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9563           emitcode ("movc", "a,@a+dptr");
9564           emitcode ("push", "acc");
9565         }
9566
9567       emitcode ("ret", "");
9568
9569       /* now generate jump table, LSB */
9570       emitcode ("", "%05d$:", jtablo->key + 100);
9571       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9572            jtab = setNextItem (IC_JTLABELS (ic)))
9573         emitcode (".db", "%05d$", jtab->key + 100);
9574
9575       /* now generate jump table, MSB */
9576       emitcode ("", "%05d$:", jtabhi->key + 100);
9577       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9578            jtab = setNextItem (IC_JTLABELS (ic)))
9579          emitcode (".db", "%05d$>>8", jtab->key + 100);
9580     
9581     }  
9582
9583 }
9584
9585 /*-----------------------------------------------------------------*/
9586 /* genCast - gen code for casting                                  */
9587 /*-----------------------------------------------------------------*/
9588 static void
9589 genCast (iCode * ic)
9590 {
9591   operand *result = IC_RESULT (ic);
9592   sym_link *ctype = operandType (IC_LEFT (ic));
9593   sym_link *rtype = operandType (IC_RIGHT (ic));
9594   operand *right = IC_RIGHT (ic);
9595   int size, offset;
9596
9597   D(emitcode(";     genCast",""));
9598
9599   /* if they are equivalent then do nothing */
9600   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9601     return;
9602
9603   aopOp (right, ic, FALSE);
9604   aopOp (result, ic, FALSE);
9605
9606   /* if the result is a bit (and not a bitfield) */
9607   // if (AOP_TYPE (result) == AOP_CRY)
9608   if (IS_BITVAR (OP_SYMBOL (result)->type)
9609       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9610     {
9611       /* if the right size is a literal then
9612          we know what the value is */
9613       if (AOP_TYPE (right) == AOP_LIT)
9614         {
9615           if (((int) operandLitValue (right)))
9616             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9617           else
9618             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9619
9620           goto release;
9621         }
9622
9623       /* the right is also a bit variable */
9624       if (AOP_TYPE (right) == AOP_CRY)
9625         {
9626           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9627           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9628           goto release;
9629         }
9630
9631       /* we need to or */
9632       toBoolean (right);
9633       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9634       goto release;
9635     }
9636
9637
9638   /* if they are the same size : or less */
9639   if (AOP_SIZE (result) <= AOP_SIZE (right))
9640     {
9641
9642       /* if they are in the same place */
9643       if (sameRegs (AOP (right), AOP (result)))
9644         goto release;
9645
9646       /* if they in different places then copy */
9647       size = AOP_SIZE (result);
9648       offset = 0;
9649       while (size--)
9650         {
9651           aopPut (AOP (result),
9652                   aopGet (AOP (right), offset, FALSE, FALSE),
9653                   offset,
9654                   isOperandVolatile (result, FALSE));
9655           offset++;
9656         }
9657       goto release;
9658     }
9659
9660
9661   /* if the result is of type pointer */
9662   if (IS_PTR (ctype))
9663     {
9664
9665       int p_type;
9666       sym_link *type = operandType (right);
9667       sym_link *etype = getSpec (type);
9668
9669       /* pointer to generic pointer */
9670       if (IS_GENPTR (ctype))
9671         {
9672           if (IS_PTR (type))
9673             p_type = DCL_TYPE (type);
9674           else
9675             {
9676               if (SPEC_SCLS(etype)==S_REGISTER) {
9677                 // let's assume it is a generic pointer
9678                 p_type=GPOINTER;
9679               } else {
9680                 /* we have to go by the storage class */
9681                 p_type = PTR_TYPE (SPEC_OCLS (etype));
9682               }
9683             }
9684
9685           /* the first two bytes are known */
9686           size = GPTRSIZE - 1;
9687           offset = 0;
9688           while (size--)
9689             {
9690               aopPut (AOP (result),
9691                       aopGet (AOP (right), offset, FALSE, FALSE),
9692                       offset,
9693                       isOperandVolatile (result, FALSE));
9694               offset++;
9695             }
9696           /* the last byte depending on type */
9697             {
9698                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
9699                 char gpValStr[10];
9700
9701                 if (gpVal == -1)
9702                 {
9703                     // pointerTypeToGPByte will have bitched.
9704                     exit(1);
9705                 }
9706
9707                 sprintf(gpValStr, "#0x%d", gpVal);
9708                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
9709             }
9710           goto release;
9711         }
9712
9713       /* just copy the pointers */
9714       size = AOP_SIZE (result);
9715       offset = 0;
9716       while (size--)
9717         {
9718           aopPut (AOP (result),
9719                   aopGet (AOP (right), offset, FALSE, FALSE),
9720                   offset,
9721                   isOperandVolatile (result, FALSE));
9722           offset++;
9723         }
9724       goto release;
9725     }
9726
9727   /* so we now know that the size of destination is greater
9728      than the size of the source */
9729   /* we move to result for the size of source */
9730   size = AOP_SIZE (right);
9731   offset = 0;
9732   while (size--)
9733     {
9734       aopPut (AOP (result),
9735               aopGet (AOP (right), offset, FALSE, FALSE),
9736               offset,
9737               isOperandVolatile (result, FALSE));
9738       offset++;
9739     }
9740
9741   /* now depending on the sign of the source && destination */
9742   size = AOP_SIZE (result) - AOP_SIZE (right);
9743   /* if unsigned or not an integral type */
9744   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
9745     {
9746       while (size--)
9747         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
9748     }
9749   else
9750     {
9751       /* we need to extend the sign :{ */
9752       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9753                         FALSE, FALSE);
9754       MOVA (l);
9755       emitcode ("rlc", "a");
9756       emitcode ("subb", "a,acc");
9757       while (size--)
9758         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
9759     }
9760
9761   /* we are done hurray !!!! */
9762
9763 release:
9764   freeAsmop (right, NULL, ic, TRUE);
9765   freeAsmop (result, NULL, ic, TRUE);
9766
9767 }
9768
9769 /*-----------------------------------------------------------------*/
9770 /* genDjnz - generate decrement & jump if not zero instrucion      */
9771 /*-----------------------------------------------------------------*/
9772 static int
9773 genDjnz (iCode * ic, iCode * ifx)
9774 {
9775   symbol *lbl, *lbl1;
9776   if (!ifx)
9777     return 0;
9778
9779   D(emitcode (";     genDjnz",""));
9780
9781   /* if the if condition has a false label
9782      then we cannot save */
9783   if (IC_FALSE (ifx))
9784     return 0;
9785
9786   /* if the minus is not of the form
9787      a = a - 1 */
9788   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9789       !IS_OP_LITERAL (IC_RIGHT (ic)))
9790     return 0;
9791
9792   if (operandLitValue (IC_RIGHT (ic)) != 1)
9793     return 0;
9794
9795   /* if the size of this greater than one then no
9796      saving */
9797   if (getSize (operandType (IC_RESULT (ic))) > 1)
9798     return 0;
9799
9800   /* otherwise we can save BIG */
9801   lbl = newiTempLabel (NULL);
9802   lbl1 = newiTempLabel (NULL);
9803
9804   aopOp (IC_RESULT (ic), ic, FALSE);
9805
9806   if (AOP_NEEDSACC(IC_RESULT(ic)))
9807   {
9808       /* If the result is accessed indirectly via
9809        * the accumulator, we must explicitly write
9810        * it back after the decrement.
9811        */
9812       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9813
9814       if (strcmp(rByte, "a"))
9815       {
9816            /* Something is hopelessly wrong */
9817            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9818                    __FILE__, __LINE__);
9819            /* We can just give up; the generated code will be inefficient,
9820             * but what the hey.
9821             */
9822            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9823            return 0;
9824       }
9825       emitcode ("dec", "%s", rByte);
9826       aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9827       emitcode ("jnz", "%05d$", lbl->key + 100);
9828   }
9829   else if (IS_AOP_PREG (IC_RESULT (ic)))
9830     {
9831       emitcode ("dec", "%s",
9832                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9833       MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9834       emitcode ("jnz", "%05d$", lbl->key + 100);
9835     }
9836   else
9837     {
9838       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9839                 lbl->key + 100);
9840     }
9841   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9842   emitcode ("", "%05d$:", lbl->key + 100);
9843   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9844   emitcode ("", "%05d$:", lbl1->key + 100);
9845
9846   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9847   ifx->generated = 1;
9848   return 1;
9849 }
9850
9851 /*-----------------------------------------------------------------*/
9852 /* genReceive - generate code for a receive iCode                  */
9853 /*-----------------------------------------------------------------*/
9854 static void
9855 genReceive (iCode * ic)
9856 {
9857     int size = getSize (operandType (IC_RESULT (ic)));
9858     int offset = 0;
9859   D(emitcode (";     genReceive",""));
9860
9861   if (ic->argreg == 1) { /* first parameter */
9862       if (isOperandInFarSpace (IC_RESULT (ic)) &&
9863           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9864            IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9865
9866           regs *tempRegs[4];
9867           int receivingA = 0;
9868           int roffset = 0;
9869
9870           for (offset = 0; offset<size; offset++)
9871             if (!strcmp (fReturn[offset], "a"))
9872               receivingA = 1;
9873
9874           if (!receivingA)
9875             {
9876               if (size==1 || getTempRegs(tempRegs, size-1, ic))
9877                 {
9878                   for (offset = size-1; offset>0; offset--)
9879                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
9880                   emitcode("mov","a,%s", fReturn[0]);
9881                   _G.accInUse++;
9882                   aopOp (IC_RESULT (ic), ic, FALSE);
9883                   _G.accInUse--;
9884                   aopPut (AOP (IC_RESULT (ic)), "a", offset,
9885                           isOperandVolatile (IC_RESULT (ic), FALSE));
9886                   for (offset = 1; offset<size; offset++)
9887                     aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
9888                             isOperandVolatile (IC_RESULT (ic), FALSE));
9889                   goto release;
9890                 }
9891             }
9892           else
9893             {
9894               if (getTempRegs(tempRegs, size, ic))
9895                 {
9896                   for (offset = 0; offset<size; offset++)
9897                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
9898                   aopOp (IC_RESULT (ic), ic, FALSE);
9899                   for (offset = 0; offset<size; offset++)
9900                     aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
9901                             isOperandVolatile (IC_RESULT (ic), FALSE));
9902                   goto release;
9903                 }
9904             }
9905
9906           offset = fReturnSizeMCS51 - size;
9907           while (size--) {
9908               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9909                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9910               offset++;
9911           }
9912           aopOp (IC_RESULT (ic), ic, FALSE);
9913           size = AOP_SIZE (IC_RESULT (ic));
9914           offset = 0;
9915           while (size--) {
9916               emitcode ("pop", "acc");
9917               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9918           }
9919
9920       } else {
9921           _G.accInUse++;
9922           aopOp (IC_RESULT (ic), ic, FALSE);
9923           _G.accInUse--;
9924           assignResultValue (IC_RESULT (ic));
9925       }
9926   } else { /* second receive onwards */
9927       int rb1off ;
9928       aopOp (IC_RESULT (ic), ic, FALSE);
9929       rb1off = ic->argreg;
9930       while (size--) {
9931           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9932       }
9933   }
9934
9935 release:
9936   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9937 }
9938
9939 /*-----------------------------------------------------------------*/
9940 /* genDummyRead - generate code for dummy read of volatiles        */
9941 /*-----------------------------------------------------------------*/
9942 static void
9943 genDummyRead (iCode * ic)
9944 {
9945   operand *op;
9946   int size, offset;
9947
9948   D(emitcode(";     genDummyRead",""));
9949
9950   op = IC_RIGHT (ic);
9951   if (op && IS_SYMOP (op))
9952     {
9953       aopOp (op, ic, FALSE);
9954
9955       /* if the result is a bit */
9956       if (AOP_TYPE (op) == AOP_CRY)
9957         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9958       else
9959         {
9960           /* bit variables done */
9961           /* general case */
9962           size = AOP_SIZE (op);
9963           offset = 0;
9964           while (size--)
9965           {
9966             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9967             offset++;
9968           }
9969         }
9970
9971       freeAsmop (op, NULL, ic, TRUE);
9972     }
9973
9974   op = IC_LEFT (ic);
9975   if (op && IS_SYMOP (op))
9976     {
9977       aopOp (op, ic, FALSE);
9978
9979       /* if the result is a bit */
9980       if (AOP_TYPE (op) == AOP_CRY)
9981         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9982       else
9983         {
9984           /* bit variables done */
9985           /* general case */
9986           size = AOP_SIZE (op);
9987           offset = 0;
9988           while (size--)
9989           {
9990             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9991             offset++;
9992           }
9993         }
9994
9995       freeAsmop (op, NULL, ic, TRUE);
9996     }
9997 }
9998
9999 /*-----------------------------------------------------------------*/
10000 /* genCritical - generate code for start of a critical sequence    */
10001 /*-----------------------------------------------------------------*/
10002 static void
10003 genCritical (iCode *ic)
10004 {
10005   symbol *tlbl = newiTempLabel (NULL);
10006
10007   D(emitcode(";     genCritical",""));
10008
10009   if (IC_RESULT (ic))
10010     aopOp (IC_RESULT (ic), ic, TRUE);
10011
10012   emitcode ("setb", "c");
10013   emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10014   emitcode ("clr", "c");
10015   emitcode ("", "%05d$:", (tlbl->key + 100));
10016
10017   if (IC_RESULT (ic))
10018     outBitC (IC_RESULT (ic)); /* save old ea in an operand */
10019   else
10020     emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10021
10022   if (IC_RESULT (ic))
10023     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10024 }
10025
10026 /*-----------------------------------------------------------------*/
10027 /* genEndCritical - generate code for end of a critical sequence   */
10028 /*-----------------------------------------------------------------*/
10029 static void
10030 genEndCritical (iCode *ic)
10031 {
10032   D(emitcode(";     genEndCritical",""));
10033
10034   if (IC_RIGHT (ic))
10035     {
10036       aopOp (IC_RIGHT (ic), ic, FALSE);
10037       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10038         {
10039           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10040           emitcode ("mov", "ea,c");
10041         }
10042       else
10043         {
10044           MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10045           emitcode ("rrc", "a");
10046           emitcode ("mov", "ea,c");
10047         }
10048       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10049     }
10050   else
10051     {
10052       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10053       emitcode ("mov", "ea,c");
10054     }
10055 }
10056
10057 /*-----------------------------------------------------------------*/
10058 /* gen51Code - generate code for 8051 based controllers            */
10059 /*-----------------------------------------------------------------*/
10060 void
10061 gen51Code (iCode * lic)
10062 {
10063   iCode *ic;
10064   int cln = 0;
10065   /* int cseq = 0; */
10066
10067   _G.currentFunc = NULL;
10068   lineHead = lineCurr = NULL;
10069
10070   /* print the allocation information */
10071   if (allocInfo && currFunc)
10072     printAllocInfo (currFunc, codeOutFile);
10073   /* if debug information required */
10074   if (options.debug && currFunc)
10075     {
10076       debugFile->writeFunction (currFunc, lic);
10077     }
10078   /* stack pointer name */
10079   if (options.useXstack)
10080     spname = "_spx";
10081   else
10082     spname = "sp";
10083
10084
10085   for (ic = lic; ic; ic = ic->next)
10086     {
10087       _G.current_iCode = ic;
10088
10089       if (ic->lineno && cln != ic->lineno)
10090         {
10091           if (options.debug)
10092             {
10093               debugFile->writeCLine(ic);
10094             }
10095           if (!options.noCcodeInAsm) {
10096             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10097                       printCLine(ic->filename, ic->lineno));
10098           }
10099           cln = ic->lineno;
10100         }
10101       #if 0
10102       if (ic->seqPoint && ic->seqPoint != cseq)
10103         {
10104           emitcode ("", "; sequence point %d", ic->seqPoint);
10105           cseq = ic->seqPoint;
10106         }
10107       #endif
10108       if (options.iCodeInAsm) {
10109         char regsInUse[80];
10110         int i;
10111
10112         for (i=0; i<8; i++) {
10113           sprintf (&regsInUse[i],
10114                    "%c", ic->riu & (1<<i) ? i+'0' : '-');
10115         }
10116         regsInUse[i]=0;
10117         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10118       }
10119       /* if the result is marked as
10120          spilt and rematerializable or code for
10121          this has already been generated then
10122          do nothing */
10123       if (resultRemat (ic) || ic->generated)
10124         continue;
10125
10126       /* depending on the operation */
10127       switch (ic->op)
10128         {
10129         case '!':
10130           genNot (ic);
10131           break;
10132
10133         case '~':
10134           genCpl (ic);
10135           break;
10136
10137         case UNARYMINUS:
10138           genUminus (ic);
10139           break;
10140
10141         case IPUSH:
10142           genIpush (ic);
10143           break;
10144
10145         case IPOP:
10146           /* IPOP happens only when trying to restore a
10147              spilt live range, if there is an ifx statement
10148              following this pop then the if statement might
10149              be using some of the registers being popped which
10150              would destory the contents of the register so
10151              we need to check for this condition and handle it */
10152           if (ic->next &&
10153               ic->next->op == IFX &&
10154               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10155             genIfx (ic->next, ic);
10156           else
10157             genIpop (ic);
10158           break;
10159
10160         case CALL:
10161           genCall (ic);
10162           break;
10163
10164         case PCALL:
10165           genPcall (ic);
10166           break;
10167
10168         case FUNCTION:
10169           genFunction (ic);
10170           break;
10171
10172         case ENDFUNCTION:
10173           genEndFunction (ic);
10174           break;
10175
10176         case RETURN:
10177           genRet (ic);
10178           break;
10179
10180         case LABEL:
10181           genLabel (ic);
10182           break;
10183
10184         case GOTO:
10185           genGoto (ic);
10186           break;
10187
10188         case '+':
10189           genPlus (ic);
10190           break;
10191
10192         case '-':
10193           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10194             genMinus (ic);
10195           break;
10196
10197         case '*':
10198           genMult (ic);
10199           break;
10200
10201         case '/':
10202           genDiv (ic);
10203           break;
10204
10205         case '%':
10206           genMod (ic);
10207           break;
10208
10209         case '>':
10210           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10211           break;
10212
10213         case '<':
10214           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10215           break;
10216
10217         case LE_OP:
10218         case GE_OP:
10219         case NE_OP:
10220
10221           /* note these two are xlated by algebraic equivalence
10222              during parsing SDCC.y */
10223           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10224                   "got '>=' or '<=' shouldn't have come here");
10225           break;
10226
10227         case EQ_OP:
10228           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10229           break;
10230
10231         case AND_OP:
10232           genAndOp (ic);
10233           break;
10234
10235         case OR_OP:
10236           genOrOp (ic);
10237           break;
10238
10239         case '^':
10240           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10241           break;
10242
10243         case '|':
10244           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10245           break;
10246
10247         case BITWISEAND:
10248           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10249           break;
10250
10251         case INLINEASM:
10252           genInline (ic);
10253           break;
10254
10255         case RRC:
10256           genRRC (ic);
10257           break;
10258
10259         case RLC:
10260           genRLC (ic);
10261           break;
10262
10263         case GETHBIT:
10264           genGetHbit (ic);
10265           break;
10266
10267         case LEFT_OP:
10268           genLeftShift (ic);
10269           break;
10270
10271         case RIGHT_OP:
10272           genRightShift (ic);
10273           break;
10274
10275         case GET_VALUE_AT_ADDRESS:
10276           genPointerGet (ic,
10277                          hasInc (IC_LEFT (ic), ic,
10278                                  getSize (operandType (IC_RESULT (ic)))),
10279                          ifxForOp (IC_RESULT (ic), ic) );
10280           break;
10281
10282         case '=':
10283           if (POINTER_SET (ic))
10284             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10285           else
10286             genAssign (ic);
10287           break;
10288
10289         case IFX:
10290           genIfx (ic, NULL);
10291           break;
10292
10293         case ADDRESS_OF:
10294           genAddrOf (ic);
10295           break;
10296
10297         case JUMPTABLE:
10298           genJumpTab (ic);
10299           break;
10300
10301         case CAST:
10302           genCast (ic);
10303           break;
10304
10305         case RECEIVE:
10306           genReceive (ic);
10307           break;
10308
10309         case SEND:
10310           addSet (&_G.sendSet, ic);
10311           break;
10312
10313         case DUMMY_READ_VOLATILE:
10314           genDummyRead (ic);
10315           break;
10316
10317         case CRITICAL:
10318           genCritical (ic);
10319           break;
10320
10321         case ENDCRITICAL:
10322           genEndCritical (ic);
10323           break;
10324
10325         case SWAP:
10326           genSwap (ic);
10327           break;
10328
10329         default:
10330           ic = ic;
10331         }
10332     }
10333
10334   _G.current_iCode = NULL;
10335
10336   /* now we are ready to call the
10337      peep hole optimizer */
10338   if (!options.nopeep)
10339     peepHole (&lineHead);
10340
10341   /* now do the actual printing */
10342   printLine (lineHead, codeOutFile);
10343   return;
10344 }