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