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