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