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