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