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