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