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