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