more enhancements for avr & some bug fixes
[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 += (int) operandLitValue (IC_RIGHT (ic));
389       else if (ic->op == '-')
390         val -= (int) 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           unsigned 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 = (unsigned int) 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, iCode *ic)
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   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3708   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3709   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3710     {
3711       outBitC (result);
3712     }
3713   else
3714     {
3715       /* if the result is used in the next
3716          ifx conditional branch then generate
3717          code a little differently */
3718       if (ifx)
3719         genIfxJump (ifx, "c");
3720       else
3721         outBitC (result);
3722       /* leave the result in acc */
3723     }
3724 }
3725
3726 /*-----------------------------------------------------------------*/
3727 /* genCmpGt :- greater than comparison                             */
3728 /*-----------------------------------------------------------------*/
3729 static void
3730 genCmpGt (iCode * ic, iCode * ifx)
3731 {
3732   operand *left, *right, *result;
3733   sym_link *letype, *retype;
3734   int sign;
3735
3736   left = IC_LEFT (ic);
3737   right = IC_RIGHT (ic);
3738   result = IC_RESULT (ic);
3739
3740   letype = getSpec (operandType (left));
3741   retype = getSpec (operandType (right));
3742   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3743   /* assign the amsops */
3744   aopOp (left, ic, FALSE);
3745   aopOp (right, ic, FALSE);
3746   aopOp (result, ic, TRUE);
3747
3748   genCmp (right, left, result, ifx, sign,ic);
3749
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,ic);
3777
3778   freeAsmop (result, NULL, ic, TRUE);
3779 }
3780
3781 /*-----------------------------------------------------------------*/
3782 /* gencjneshort - compare and jump if not equal                    */
3783 /*-----------------------------------------------------------------*/
3784 static void
3785 gencjneshort (operand * left, operand * right, symbol * lbl)
3786 {
3787   int size = max (AOP_SIZE (left), AOP_SIZE (right));
3788   int offset = 0;
3789   unsigned long lit = 0L;
3790
3791   /* if the left side is a literal or
3792      if the right is in a pointer register and left
3793      is not */
3794   if ((AOP_TYPE (left) == AOP_LIT) ||
3795       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3796     {
3797       operand *t = right;
3798       right = left;
3799       left = t;
3800     }
3801   if (AOP_TYPE (right) == AOP_LIT)
3802     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3803
3804   /* if the right side is a literal then anything goes */
3805   if (AOP_TYPE (right) == AOP_LIT &&
3806       AOP_TYPE (left) != AOP_DIR)
3807     {
3808       while (size--)
3809         {
3810           emitcode ("cjne", "%s,%s,%05d$",
3811                     aopGet (AOP (left), offset, FALSE, FALSE),
3812                     aopGet (AOP (right), offset, FALSE, FALSE),
3813                     lbl->key + 100);
3814           offset++;
3815         }
3816     }
3817
3818   /* if the right side is in a register or in direct space or
3819      if the left is a pointer register & right is not */
3820   else if (AOP_TYPE (right) == AOP_REG ||
3821            AOP_TYPE (right) == AOP_DIR ||
3822            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3823            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3824     {
3825       while (size--)
3826         {
3827           MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3828           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3829               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3830             emitcode ("jnz", "%05d$", lbl->key + 100);
3831           else
3832             emitcode ("cjne", "a,%s,%05d$",
3833                       aopGet (AOP (right), offset, FALSE, TRUE),
3834                       lbl->key + 100);
3835           offset++;
3836         }
3837     }
3838   else
3839     {
3840       /* right is a pointer reg need both a & b */
3841       while (size--)
3842         {
3843           char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3844           if (strcmp (l, "b"))
3845             emitcode ("mov", "b,%s", l);
3846           MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3847           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3848           offset++;
3849         }
3850     }
3851 }
3852
3853 /*-----------------------------------------------------------------*/
3854 /* gencjne - compare and jump if not equal                         */
3855 /*-----------------------------------------------------------------*/
3856 static void
3857 gencjne (operand * left, operand * right, symbol * lbl)
3858 {
3859   symbol *tlbl = newiTempLabel (NULL);
3860
3861   gencjneshort (left, right, lbl);
3862
3863   emitcode ("mov", "a,%s", one);
3864   emitcode ("sjmp", "%05d$", tlbl->key + 100);
3865   emitcode ("", "%05d$:", lbl->key + 100);
3866   emitcode ("clr", "a");
3867   emitcode ("", "%05d$:", tlbl->key + 100);
3868 }
3869
3870 /*-----------------------------------------------------------------*/
3871 /* genCmpEq - generates code for equal to                          */
3872 /*-----------------------------------------------------------------*/
3873 static void
3874 genCmpEq (iCode * ic, iCode * ifx)
3875 {
3876   operand *left, *right, *result;
3877
3878   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
3879   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
3880   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
3881
3882   /* if literal, literal on the right or
3883      if the right is in a pointer register and left
3884      is not */
3885   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3886       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3887     {
3888       operand *t = IC_RIGHT (ic);
3889       IC_RIGHT (ic) = IC_LEFT (ic);
3890       IC_LEFT (ic) = t;
3891     }
3892
3893   if (ifx && !AOP_SIZE (result))
3894     {
3895       symbol *tlbl;
3896       /* if they are both bit variables */
3897       if (AOP_TYPE (left) == AOP_CRY &&
3898           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3899         {
3900           if (AOP_TYPE (right) == AOP_LIT)
3901             {
3902               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3903               if (lit == 0L)
3904                 {
3905                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3906                   emitcode ("cpl", "c");
3907                 }
3908               else if (lit == 1L)
3909                 {
3910                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3911                 }
3912               else
3913                 {
3914                   emitcode ("clr", "c");
3915                 }
3916               /* AOP_TYPE(right) == AOP_CRY */
3917             }
3918           else
3919             {
3920               symbol *lbl = newiTempLabel (NULL);
3921               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3922               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3923               emitcode ("cpl", "c");
3924               emitcode ("", "%05d$:", (lbl->key + 100));
3925             }
3926           /* if true label then we jump if condition
3927              supplied is true */
3928           tlbl = newiTempLabel (NULL);
3929           if (IC_TRUE (ifx))
3930             {
3931               emitcode ("jnc", "%05d$", tlbl->key + 100);
3932               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3933             }
3934           else
3935             {
3936               emitcode ("jc", "%05d$", tlbl->key + 100);
3937               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3938             }
3939           emitcode ("", "%05d$:", tlbl->key + 100);
3940         }
3941       else
3942         {
3943           tlbl = newiTempLabel (NULL);
3944           gencjneshort (left, right, tlbl);
3945           if (IC_TRUE (ifx))
3946             {
3947               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
3948               emitcode ("", "%05d$:", tlbl->key + 100);
3949             }
3950           else
3951             {
3952               symbol *lbl = newiTempLabel (NULL);
3953               emitcode ("sjmp", "%05d$", lbl->key + 100);
3954               emitcode ("", "%05d$:", tlbl->key + 100);
3955               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
3956               emitcode ("", "%05d$:", lbl->key + 100);
3957             }
3958         }
3959       /* mark the icode as generated */
3960       ifx->generated = 1;
3961       goto release;
3962     }
3963
3964   /* if they are both bit variables */
3965   if (AOP_TYPE (left) == AOP_CRY &&
3966       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
3967     {
3968       if (AOP_TYPE (right) == AOP_LIT)
3969         {
3970           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3971           if (lit == 0L)
3972             {
3973               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3974               emitcode ("cpl", "c");
3975             }
3976           else if (lit == 1L)
3977             {
3978               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3979             }
3980           else
3981             {
3982               emitcode ("clr", "c");
3983             }
3984           /* AOP_TYPE(right) == AOP_CRY */
3985         }
3986       else
3987         {
3988           symbol *lbl = newiTempLabel (NULL);
3989           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3990           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
3991           emitcode ("cpl", "c");
3992           emitcode ("", "%05d$:", (lbl->key + 100));
3993         }
3994       /* c = 1 if egal */
3995       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3996         {
3997           outBitC (result);
3998           goto release;
3999         }
4000       if (ifx)
4001         {
4002           genIfxJump (ifx, "c");
4003           goto release;
4004         }
4005       /* if the result is used in an arithmetic operation
4006          then put the result in place */
4007       outBitC (result);
4008     }
4009   else
4010     {
4011       gencjne (left, right, newiTempLabel (NULL));
4012       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4013         {
4014           aopPut (AOP (result), "a", 0);
4015           goto release;
4016         }
4017       if (ifx)
4018         {
4019           genIfxJump (ifx, "a");
4020           goto release;
4021         }
4022       /* if the result is used in an arithmetic operation
4023          then put the result in place */
4024       if (AOP_TYPE (result) != AOP_CRY)
4025         outAcc (result);
4026       /* leave the result in acc */
4027     }
4028
4029 release:
4030   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4031   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4032   freeAsmop (result, NULL, ic, TRUE);
4033 }
4034
4035 /*-----------------------------------------------------------------*/
4036 /* ifxForOp - returns the icode containing the ifx for operand     */
4037 /*-----------------------------------------------------------------*/
4038 static iCode *
4039 ifxForOp (operand * op, iCode * ic)
4040 {
4041   /* if true symbol then needs to be assigned */
4042   if (IS_TRUE_SYMOP (op))
4043     return NULL;
4044
4045   /* if this has register type condition and
4046      the next instruction is ifx with the same operand
4047      and live to of the operand is upto the ifx only then */
4048   if (ic->next &&
4049       ic->next->op == IFX &&
4050       IC_COND (ic->next)->key == op->key &&
4051       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4052     return ic->next;
4053
4054   return NULL;
4055 }
4056
4057 /*-----------------------------------------------------------------*/
4058 /* hasInc - operand is incremented before any other use            */
4059 /*-----------------------------------------------------------------*/
4060 static iCode *
4061 hasInc (operand *op, iCode *ic)
4062 {
4063   sym_link *type = operandType(op);
4064   sym_link *retype = getSpec (type);
4065   iCode *lic = ic->next;
4066   int isize ;
4067   
4068   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4069   isize = getSize(type->next);
4070   while (lic) {
4071     /* if operand of the form op = op + <sizeof *op> */
4072     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4073         isOperandEqual(IC_RESULT(lic),op) && 
4074         isOperandLiteral(IC_RIGHT(lic)) &&
4075         operandLitValue(IC_RIGHT(lic)) == isize) {
4076       return lic;
4077     }
4078     /* if the operand used or deffed */
4079     if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4080       return NULL;
4081     }
4082     lic = lic->next;
4083   }
4084   return NULL;
4085 }
4086
4087 /*-----------------------------------------------------------------*/
4088 /* genAndOp - for && operation                                     */
4089 /*-----------------------------------------------------------------*/
4090 static void
4091 genAndOp (iCode * ic)
4092 {
4093   operand *left, *right, *result;
4094   symbol *tlbl;
4095
4096   /* note here that && operations that are in an
4097      if statement are taken away by backPatchLabels
4098      only those used in arthmetic operations remain */
4099   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4100   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4101   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4102
4103   /* if both are bit variables */
4104   if (AOP_TYPE (left) == AOP_CRY &&
4105       AOP_TYPE (right) == AOP_CRY)
4106     {
4107       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4108       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4109       outBitC (result);
4110     }
4111   else
4112     {
4113       tlbl = newiTempLabel (NULL);
4114       toBoolean (left);
4115       emitcode ("jz", "%05d$", tlbl->key + 100);
4116       toBoolean (right);
4117       emitcode ("", "%05d$:", tlbl->key + 100);
4118       outBitAcc (result);
4119     }
4120
4121   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4122   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4123   freeAsmop (result, NULL, ic, TRUE);
4124 }
4125
4126
4127 /*-----------------------------------------------------------------*/
4128 /* genOrOp - for || operation                                      */
4129 /*-----------------------------------------------------------------*/
4130 static void
4131 genOrOp (iCode * ic)
4132 {
4133   operand *left, *right, *result;
4134   symbol *tlbl;
4135
4136   /* note here that || operations that are in an
4137      if statement are taken away by backPatchLabels
4138      only those used in arthmetic operations remain */
4139   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4140   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4141   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4142
4143   /* if both are bit variables */
4144   if (AOP_TYPE (left) == AOP_CRY &&
4145       AOP_TYPE (right) == AOP_CRY)
4146     {
4147       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4148       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4149       outBitC (result);
4150     }
4151   else
4152     {
4153       tlbl = newiTempLabel (NULL);
4154       toBoolean (left);
4155       emitcode ("jnz", "%05d$", tlbl->key + 100);
4156       toBoolean (right);
4157       emitcode ("", "%05d$:", tlbl->key + 100);
4158       outBitAcc (result);
4159     }
4160
4161   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4162   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4163   freeAsmop (result, NULL, ic, TRUE);
4164 }
4165
4166 /*-----------------------------------------------------------------*/
4167 /* isLiteralBit - test if lit == 2^n                               */
4168 /*-----------------------------------------------------------------*/
4169 static int
4170 isLiteralBit (unsigned long lit)
4171 {
4172   unsigned long pw[32] =
4173   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4174    0x100L, 0x200L, 0x400L, 0x800L,
4175    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4176    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4177    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4178    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4179    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4180   int idx;
4181
4182   for (idx = 0; idx < 32; idx++)
4183     if (lit == pw[idx])
4184       return idx + 1;
4185   return 0;
4186 }
4187
4188 /*-----------------------------------------------------------------*/
4189 /* continueIfTrue -                                                */
4190 /*-----------------------------------------------------------------*/
4191 static void
4192 continueIfTrue (iCode * ic)
4193 {
4194   if (IC_TRUE (ic))
4195     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4196   ic->generated = 1;
4197 }
4198
4199 /*-----------------------------------------------------------------*/
4200 /* jmpIfTrue -                                                     */
4201 /*-----------------------------------------------------------------*/
4202 static void
4203 jumpIfTrue (iCode * ic)
4204 {
4205   if (!IC_TRUE (ic))
4206     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4207   ic->generated = 1;
4208 }
4209
4210 /*-----------------------------------------------------------------*/
4211 /* jmpTrueOrFalse -                                                */
4212 /*-----------------------------------------------------------------*/
4213 static void
4214 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4215 {
4216   // ugly but optimized by peephole
4217   if (IC_TRUE (ic))
4218     {
4219       symbol *nlbl = newiTempLabel (NULL);
4220       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4221       emitcode ("", "%05d$:", tlbl->key + 100);
4222       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4223       emitcode ("", "%05d$:", nlbl->key + 100);
4224     }
4225   else
4226     {
4227       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4228       emitcode ("", "%05d$:", tlbl->key + 100);
4229     }
4230   ic->generated = 1;
4231 }
4232
4233 /*-----------------------------------------------------------------*/
4234 /* genAnd  - code for and                                          */
4235 /*-----------------------------------------------------------------*/
4236 static void
4237 genAnd (iCode * ic, iCode * ifx)
4238 {
4239   operand *left, *right, *result;
4240   int size, offset = 0;
4241   unsigned long lit = 0L;
4242   int bytelit = 0;
4243   char buffer[10];
4244
4245   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4246   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4247   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4248
4249 #ifdef DEBUG_TYPE
4250   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4251             AOP_TYPE (result),
4252             AOP_TYPE (left), AOP_TYPE (right));
4253   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4254             AOP_SIZE (result),
4255             AOP_SIZE (left), AOP_SIZE (right));
4256 #endif
4257
4258   /* if left is a literal & right is not then exchange them */
4259   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4260       AOP_NEEDSACC (left))
4261     {
4262       operand *tmp = right;
4263       right = left;
4264       left = tmp;
4265     }
4266
4267   /* if result = right then exchange them */
4268   if (sameRegs (AOP (result), AOP (right)))
4269     {
4270       operand *tmp = right;
4271       right = left;
4272       left = tmp;
4273     }
4274
4275   /* if right is bit then exchange them */
4276   if (AOP_TYPE (right) == AOP_CRY &&
4277       AOP_TYPE (left) != AOP_CRY)
4278     {
4279       operand *tmp = right;
4280       right = left;
4281       left = tmp;
4282     }
4283   if (AOP_TYPE (right) == AOP_LIT)
4284     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4285
4286   size = AOP_SIZE (result);
4287
4288   // if(bit & yy)
4289   // result = bit & yy;
4290   if (AOP_TYPE (left) == AOP_CRY)
4291     {
4292       // c = bit & literal;
4293       if (AOP_TYPE (right) == AOP_LIT)
4294         {
4295           if (lit & 1)
4296             {
4297               if (size && sameRegs (AOP (result), AOP (left)))
4298                 // no change
4299                 goto release;
4300               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4301             }
4302           else
4303             {
4304               // bit(result) = 0;
4305               if (size && (AOP_TYPE (result) == AOP_CRY))
4306                 {
4307                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4308                   goto release;
4309                 }
4310               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4311                 {
4312                   jumpIfTrue (ifx);
4313                   goto release;
4314                 }
4315               emitcode ("clr", "c");
4316             }
4317         }
4318       else
4319         {
4320           if (AOP_TYPE (right) == AOP_CRY)
4321             {
4322               // c = bit & bit;
4323               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4324               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4325             }
4326           else
4327             {
4328               // c = bit & val;
4329               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4330               // c = lsb
4331               emitcode ("rrc", "a");
4332               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4333             }
4334         }
4335       // bit = c
4336       // val = c
4337       if (size)
4338         outBitC (result);
4339       // if(bit & ...)
4340       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4341         genIfxJump (ifx, "c");
4342       goto release;
4343     }
4344
4345   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4346   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4347   if ((AOP_TYPE (right) == AOP_LIT) &&
4348       (AOP_TYPE (result) == AOP_CRY) &&
4349       (AOP_TYPE (left) != AOP_CRY))
4350     {
4351       int posbit = isLiteralBit (lit);
4352       /* left &  2^n */
4353       if (posbit)
4354         {
4355           posbit--;
4356           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4357           // bit = left & 2^n
4358           if (size)
4359             emitcode ("mov", "c,acc.%d", posbit & 0x07);
4360           // if(left &  2^n)
4361           else
4362             {
4363               if (ifx)
4364                 {
4365                   sprintf (buffer, "acc.%d", posbit & 0x07);
4366                   genIfxJump (ifx, buffer);
4367                 }
4368               goto release;
4369             }
4370         }
4371       else
4372         {
4373           symbol *tlbl = newiTempLabel (NULL);
4374           int sizel = AOP_SIZE (left);
4375           if (size)
4376             emitcode ("setb", "c");
4377           while (sizel--)
4378             {
4379               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4380                 {
4381                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4382                   // byte ==  2^n ?
4383                   if ((posbit = isLiteralBit (bytelit)) != 0)
4384                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4385                   else
4386                     {
4387                       if (bytelit != 0x0FFL)
4388                         emitcode ("anl", "a,%s",
4389                                   aopGet (AOP (right), offset, FALSE, TRUE));
4390                       emitcode ("jnz", "%05d$", tlbl->key + 100);
4391                     }
4392                 }
4393               offset++;
4394             }
4395           // bit = left & literal
4396           if (size)
4397             {
4398               emitcode ("clr", "c");
4399               emitcode ("", "%05d$:", tlbl->key + 100);
4400             }
4401           // if(left & literal)
4402           else
4403             {
4404               if (ifx)
4405                 jmpTrueOrFalse (ifx, tlbl);
4406               goto release;
4407             }
4408         }
4409       outBitC (result);
4410       goto release;
4411     }
4412
4413   /* if left is same as result */
4414   if (sameRegs (AOP (result), AOP (left)))
4415     {
4416       for (; size--; offset++)
4417         {
4418           if (AOP_TYPE (right) == AOP_LIT)
4419             {
4420               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4421                 continue;
4422               else if (bytelit == 0)
4423                 aopPut (AOP (result), zero, offset);
4424               else if (IS_AOP_PREG (result))
4425                 {
4426                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4427                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4428                   aopPut (AOP (result), "a", offset);
4429                 }
4430               else
4431                 emitcode ("anl", "%s,%s",
4432                           aopGet (AOP (left), offset, FALSE, TRUE),
4433                           aopGet (AOP (right), offset, FALSE, FALSE));
4434             }
4435           else
4436             {
4437               if (AOP_TYPE (left) == AOP_ACC)
4438                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4439               else
4440                 {
4441                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4442                   if (IS_AOP_PREG (result))
4443                     {
4444                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4445                       aopPut (AOP (result), "a", offset);
4446
4447                     }
4448                   else
4449                     emitcode ("anl", "%s,a",
4450                               aopGet (AOP (left), offset, FALSE, TRUE));
4451                 }
4452             }
4453         }
4454     }
4455   else
4456     {
4457       // left & result in different registers
4458       if (AOP_TYPE (result) == AOP_CRY)
4459         {
4460           // result = bit
4461           // if(size), result in bit
4462           // if(!size && ifx), conditional oper: if(left & right)
4463           symbol *tlbl = newiTempLabel (NULL);
4464           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4465           if (size)
4466             emitcode ("setb", "c");
4467           while (sizer--)
4468             {
4469               MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4470               emitcode ("anl", "a,%s",
4471                         aopGet (AOP (left), offset, FALSE, FALSE));
4472               emitcode ("jnz", "%05d$", tlbl->key + 100);
4473               offset++;
4474             }
4475           if (size)
4476             {
4477               CLRC;
4478               emitcode ("", "%05d$:", tlbl->key + 100);
4479               outBitC (result);
4480             }
4481           else if (ifx)
4482             jmpTrueOrFalse (ifx, tlbl);
4483         }
4484       else
4485         {
4486           for (; (size--); offset++)
4487             {
4488               // normal case
4489               // result = left & right
4490               if (AOP_TYPE (right) == AOP_LIT)
4491                 {
4492                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4493                     {
4494                       aopPut (AOP (result),
4495                               aopGet (AOP (left), offset, FALSE, FALSE),
4496                               offset);
4497                       continue;
4498                     }
4499                   else if (bytelit == 0)
4500                     {
4501                       aopPut (AOP (result), zero, offset);
4502                       continue;
4503                     }
4504                 }
4505               // faster than result <- left, anl result,right
4506               // and better if result is SFR
4507               if (AOP_TYPE (left) == AOP_ACC)
4508                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4509               else
4510                 {
4511                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4512                   emitcode ("anl", "a,%s",
4513                             aopGet (AOP (left), offset, FALSE, FALSE));
4514                 }
4515               aopPut (AOP (result), "a", offset);
4516             }
4517         }
4518     }
4519
4520 release:
4521   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4522   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4523   freeAsmop (result, NULL, ic, TRUE);
4524 }
4525
4526 /*-----------------------------------------------------------------*/
4527 /* genOr  - code for or                                            */
4528 /*-----------------------------------------------------------------*/
4529 static void
4530 genOr (iCode * ic, iCode * ifx)
4531 {
4532   operand *left, *right, *result;
4533   int size, offset = 0;
4534   unsigned long lit = 0L;
4535
4536   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4537   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4538   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4539
4540 #ifdef DEBUG_TYPE
4541   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4542             AOP_TYPE (result),
4543             AOP_TYPE (left), AOP_TYPE (right));
4544   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4545             AOP_SIZE (result),
4546             AOP_SIZE (left), AOP_SIZE (right));
4547 #endif
4548
4549   /* if left is a literal & right is not then exchange them */
4550   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4551       AOP_NEEDSACC (left))
4552     {
4553       operand *tmp = right;
4554       right = left;
4555       left = tmp;
4556     }
4557
4558   /* if result = right then exchange them */
4559   if (sameRegs (AOP (result), AOP (right)))
4560     {
4561       operand *tmp = right;
4562       right = left;
4563       left = tmp;
4564     }
4565
4566   /* if right is bit then exchange them */
4567   if (AOP_TYPE (right) == AOP_CRY &&
4568       AOP_TYPE (left) != AOP_CRY)
4569     {
4570       operand *tmp = right;
4571       right = left;
4572       left = tmp;
4573     }
4574   if (AOP_TYPE (right) == AOP_LIT)
4575     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4576
4577   size = AOP_SIZE (result);
4578
4579   // if(bit | yy)
4580   // xx = bit | yy;
4581   if (AOP_TYPE (left) == AOP_CRY)
4582     {
4583       if (AOP_TYPE (right) == AOP_LIT)
4584         {
4585           // c = bit & literal;
4586           if (lit)
4587             {
4588               // lit != 0 => result = 1
4589               if (AOP_TYPE (result) == AOP_CRY)
4590                 {
4591                   if (size)
4592                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4593                   else if (ifx)
4594                     continueIfTrue (ifx);
4595                   goto release;
4596                 }
4597               emitcode ("setb", "c");
4598             }
4599           else
4600             {
4601               // lit == 0 => result = left
4602               if (size && sameRegs (AOP (result), AOP (left)))
4603                 goto release;
4604               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4605             }
4606         }
4607       else
4608         {
4609           if (AOP_TYPE (right) == AOP_CRY)
4610             {
4611               // c = bit | bit;
4612               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4613               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4614             }
4615           else
4616             {
4617               // c = bit | val;
4618               symbol *tlbl = newiTempLabel (NULL);
4619               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4620                 emitcode ("setb", "c");
4621               emitcode ("jb", "%s,%05d$",
4622                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
4623               toBoolean (right);
4624               emitcode ("jnz", "%05d$", tlbl->key + 100);
4625               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4626                 {
4627                   jmpTrueOrFalse (ifx, tlbl);
4628                   goto release;
4629                 }
4630               else
4631                 {
4632                   CLRC;
4633                   emitcode ("", "%05d$:", tlbl->key + 100);
4634                 }
4635             }
4636         }
4637       // bit = c
4638       // val = c
4639       if (size)
4640         outBitC (result);
4641       // if(bit | ...)
4642       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4643         genIfxJump (ifx, "c");
4644       goto release;
4645     }
4646
4647   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4648   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4649   if ((AOP_TYPE (right) == AOP_LIT) &&
4650       (AOP_TYPE (result) == AOP_CRY) &&
4651       (AOP_TYPE (left) != AOP_CRY))
4652     {
4653       if (lit)
4654         {
4655           // result = 1
4656           if (size)
4657             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4658           else
4659             continueIfTrue (ifx);
4660           goto release;
4661         }
4662       else
4663         {
4664           // lit = 0, result = boolean(left)
4665           if (size)
4666             emitcode ("setb", "c");
4667           toBoolean (right);
4668           if (size)
4669             {
4670               symbol *tlbl = newiTempLabel (NULL);
4671               emitcode ("jnz", "%05d$", tlbl->key + 100);
4672               CLRC;
4673               emitcode ("", "%05d$:", tlbl->key + 100);
4674             }
4675           else
4676             {
4677               genIfxJump (ifx, "a");
4678               goto release;
4679             }
4680         }
4681       outBitC (result);
4682       goto release;
4683     }
4684
4685   /* if left is same as result */
4686   if (sameRegs (AOP (result), AOP (left)))
4687     {
4688       for (; size--; offset++)
4689         {
4690           if (AOP_TYPE (right) == AOP_LIT)
4691             {
4692               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4693                 continue;
4694               else if (IS_AOP_PREG (left))
4695                 {
4696                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4697                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4698                   aopPut (AOP (result), "a", offset);
4699                 }
4700               else
4701                 emitcode ("orl", "%s,%s",
4702                           aopGet (AOP (left), offset, FALSE, TRUE),
4703                           aopGet (AOP (right), offset, FALSE, FALSE));
4704             }
4705           else
4706             {
4707               if (AOP_TYPE (left) == AOP_ACC)
4708                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4709               else
4710                 {
4711                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4712                   if (IS_AOP_PREG (left))
4713                     {
4714                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4715                       aopPut (AOP (result), "a", offset);
4716                     }
4717                   else
4718                     emitcode ("orl", "%s,a",
4719                               aopGet (AOP (left), offset, FALSE, TRUE));
4720                 }
4721             }
4722         }
4723     }
4724   else
4725     {
4726       // left & result in different registers
4727       if (AOP_TYPE (result) == AOP_CRY)
4728         {
4729           // result = bit
4730           // if(size), result in bit
4731           // if(!size && ifx), conditional oper: if(left | right)
4732           symbol *tlbl = newiTempLabel (NULL);
4733           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4734           if (size)
4735             emitcode ("setb", "c");
4736           while (sizer--)
4737             {
4738               MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4739               emitcode ("orl", "a,%s",
4740                         aopGet (AOP (left), offset, FALSE, FALSE));
4741               emitcode ("jnz", "%05d$", tlbl->key + 100);
4742               offset++;
4743             }
4744           if (size)
4745             {
4746               CLRC;
4747               emitcode ("", "%05d$:", tlbl->key + 100);
4748               outBitC (result);
4749             }
4750           else if (ifx)
4751             jmpTrueOrFalse (ifx, tlbl);
4752         }
4753       else
4754         for (; (size--); offset++)
4755           {
4756             // normal case
4757             // result = left & right
4758             if (AOP_TYPE (right) == AOP_LIT)
4759               {
4760                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4761                   {
4762                     aopPut (AOP (result),
4763                             aopGet (AOP (left), offset, FALSE, FALSE),
4764                             offset);
4765                     continue;
4766                   }
4767               }
4768             // faster than result <- left, anl result,right
4769             // and better if result is SFR
4770             if (AOP_TYPE (left) == AOP_ACC)
4771               emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4772             else
4773               {
4774                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4775                 emitcode ("orl", "a,%s",
4776                           aopGet (AOP (left), offset, FALSE, FALSE));
4777               }
4778             aopPut (AOP (result), "a", offset);
4779           }
4780     }
4781
4782 release:
4783   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4784   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4785   freeAsmop (result, NULL, ic, TRUE);
4786 }
4787
4788 /*-----------------------------------------------------------------*/
4789 /* genXor - code for xclusive or                                   */
4790 /*-----------------------------------------------------------------*/
4791 static void
4792 genXor (iCode * ic, iCode * ifx)
4793 {
4794   operand *left, *right, *result;
4795   int size, offset = 0;
4796   unsigned long lit = 0L;
4797
4798   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4799   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4800   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4801
4802 #ifdef DEBUG_TYPE
4803   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4804             AOP_TYPE (result),
4805             AOP_TYPE (left), AOP_TYPE (right));
4806   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4807             AOP_SIZE (result),
4808             AOP_SIZE (left), AOP_SIZE (right));
4809 #endif
4810
4811   /* if left is a literal & right is not ||
4812      if left needs acc & right does not */
4813   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4814       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4815     {
4816       operand *tmp = right;
4817       right = left;
4818       left = tmp;
4819     }
4820
4821   /* if result = right then exchange them */
4822   if (sameRegs (AOP (result), AOP (right)))
4823     {
4824       operand *tmp = right;
4825       right = left;
4826       left = tmp;
4827     }
4828
4829   /* if right is bit then exchange them */
4830   if (AOP_TYPE (right) == AOP_CRY &&
4831       AOP_TYPE (left) != AOP_CRY)
4832     {
4833       operand *tmp = right;
4834       right = left;
4835       left = tmp;
4836     }
4837   if (AOP_TYPE (right) == AOP_LIT)
4838     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4839
4840   size = AOP_SIZE (result);
4841
4842   // if(bit ^ yy)
4843   // xx = bit ^ yy;
4844   if (AOP_TYPE (left) == AOP_CRY)
4845     {
4846       if (AOP_TYPE (right) == AOP_LIT)
4847         {
4848           // c = bit & literal;
4849           if (lit >> 1)
4850             {
4851               // lit>>1  != 0 => result = 1
4852               if (AOP_TYPE (result) == AOP_CRY)
4853                 {
4854                   if (size)
4855                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4856                   else if (ifx)
4857                     continueIfTrue (ifx);
4858                   goto release;
4859                 }
4860               emitcode ("setb", "c");
4861             }
4862           else
4863             {
4864               // lit == (0 or 1)
4865               if (lit == 0)
4866                 {
4867                   // lit == 0, result = left
4868                   if (size && sameRegs (AOP (result), AOP (left)))
4869                     goto release;
4870                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4871                 }
4872               else
4873                 {
4874                   // lit == 1, result = not(left)
4875                   if (size && sameRegs (AOP (result), AOP (left)))
4876                     {
4877                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
4878                       goto release;
4879                     }
4880                   else
4881                     {
4882                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4883                       emitcode ("cpl", "c");
4884                     }
4885                 }
4886             }
4887
4888         }
4889       else
4890         {
4891           // right != literal
4892           symbol *tlbl = newiTempLabel (NULL);
4893           if (AOP_TYPE (right) == AOP_CRY)
4894             {
4895               // c = bit ^ bit;
4896               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4897             }
4898           else
4899             {
4900               int sizer = AOP_SIZE (right);
4901               // c = bit ^ val
4902               // if val>>1 != 0, result = 1
4903               emitcode ("setb", "c");
4904               while (sizer)
4905                 {
4906                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
4907                   if (sizer == 1)
4908                     // test the msb of the lsb
4909                     emitcode ("anl", "a,#0xfe");
4910                   emitcode ("jnz", "%05d$", tlbl->key + 100);
4911                   sizer--;
4912                 }
4913               // val = (0,1)
4914               emitcode ("rrc", "a");
4915             }
4916           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
4917           emitcode ("cpl", "c");
4918           emitcode ("", "%05d$:", (tlbl->key + 100));
4919         }
4920       // bit = c
4921       // val = c
4922       if (size)
4923         outBitC (result);
4924       // if(bit | ...)
4925       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4926         genIfxJump (ifx, "c");
4927       goto release;
4928     }
4929
4930   if (sameRegs (AOP (result), AOP (left)))
4931     {
4932       /* if left is same as result */
4933       for (; size--; offset++)
4934         {
4935           if (AOP_TYPE (right) == AOP_LIT)
4936             {
4937               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4938                 continue;
4939               else if (IS_AOP_PREG (left))
4940                 {
4941                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4942                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4943                   aopPut (AOP (result), "a", offset);
4944                 }
4945               else
4946                 emitcode ("xrl", "%s,%s",
4947                           aopGet (AOP (left), offset, FALSE, TRUE),
4948                           aopGet (AOP (right), offset, FALSE, FALSE));
4949             }
4950           else
4951             {
4952               if (AOP_TYPE (left) == AOP_ACC)
4953                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4954               else
4955                 {
4956                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4957                   if (IS_AOP_PREG (left))
4958                     {
4959                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4960                       aopPut (AOP (result), "a", offset);
4961                     }
4962                   else
4963                     emitcode ("xrl", "%s,a",
4964                               aopGet (AOP (left), offset, FALSE, TRUE));
4965                 }
4966             }
4967         }
4968     }
4969   else
4970     {
4971       // left & result in different registers
4972       if (AOP_TYPE (result) == AOP_CRY)
4973         {
4974           // result = bit
4975           // if(size), result in bit
4976           // if(!size && ifx), conditional oper: if(left ^ right)
4977           symbol *tlbl = newiTempLabel (NULL);
4978           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4979           if (size)
4980             emitcode ("setb", "c");
4981           while (sizer--)
4982             {
4983               if ((AOP_TYPE (right) == AOP_LIT) &&
4984                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
4985                 {
4986                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4987                 }
4988               else
4989                 {
4990                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4991                   emitcode ("xrl", "a,%s",
4992                             aopGet (AOP (left), offset, FALSE, FALSE));
4993                 }
4994               emitcode ("jnz", "%05d$", tlbl->key + 100);
4995               offset++;
4996             }
4997           if (size)
4998             {
4999               CLRC;
5000               emitcode ("", "%05d$:", tlbl->key + 100);
5001               outBitC (result);
5002             }
5003           else if (ifx)
5004             jmpTrueOrFalse (ifx, tlbl);
5005         }
5006       else
5007         for (; (size--); offset++)
5008           {
5009             // normal case
5010             // result = left & right
5011             if (AOP_TYPE (right) == AOP_LIT)
5012               {
5013                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5014                   {
5015                     aopPut (AOP (result),
5016                             aopGet (AOP (left), offset, FALSE, FALSE),
5017                             offset);
5018                     continue;
5019                   }
5020               }
5021             // faster than result <- left, anl result,right
5022             // and better if result is SFR
5023             if (AOP_TYPE (left) == AOP_ACC)
5024               emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5025             else
5026               {
5027                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5028                 emitcode ("xrl", "a,%s",
5029                           aopGet (AOP (left), offset, FALSE, TRUE));
5030               }
5031             aopPut (AOP (result), "a", offset);
5032           }
5033     }
5034
5035 release:
5036   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5037   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5038   freeAsmop (result, NULL, ic, TRUE);
5039 }
5040
5041 /*-----------------------------------------------------------------*/
5042 /* genInline - write the inline code out                           */
5043 /*-----------------------------------------------------------------*/
5044 static void
5045 genInline (iCode * ic)
5046 {
5047   char buffer[MAX_INLINEASM];
5048   char *bp = buffer;
5049   char *bp1 = buffer;
5050
5051   _G.inLine += (!options.asmpeep);
5052   strcpy (buffer, IC_INLINE (ic));
5053
5054   /* emit each line as a code */
5055   while (*bp)
5056     {
5057       if (*bp == '\n')
5058         {
5059           *bp++ = '\0';
5060           emitcode (bp1, "");
5061           bp1 = bp;
5062         }
5063       else
5064         {
5065           if (*bp == ':')
5066             {
5067               bp++;
5068               *bp = '\0';
5069               bp++;
5070               emitcode (bp1, "");
5071               bp1 = bp;
5072             }
5073           else
5074             bp++;
5075         }
5076     }
5077   if (bp1 != bp)
5078     emitcode (bp1, "");
5079   /*     emitcode("",buffer); */
5080   _G.inLine -= (!options.asmpeep);
5081 }
5082
5083 /*-----------------------------------------------------------------*/
5084 /* genRRC - rotate right with carry                                */
5085 /*-----------------------------------------------------------------*/
5086 static void
5087 genRRC (iCode * ic)
5088 {
5089   operand *left, *result;
5090   int size, offset = 0;
5091   char *l;
5092
5093   /* rotate right with carry */
5094   left = IC_LEFT (ic);
5095   result = IC_RESULT (ic);
5096   aopOp (left, ic, FALSE);
5097   aopOp (result, ic, FALSE);
5098
5099   /* move it to the result */
5100   size = AOP_SIZE (result);
5101   offset = size - 1;
5102   CLRC;
5103   while (size--)
5104     {
5105       l = aopGet (AOP (left), offset, FALSE, FALSE);
5106       MOVA (l);
5107       emitcode ("rrc", "a");
5108       if (AOP_SIZE (result) > 1)
5109         aopPut (AOP (result), "a", offset--);
5110     }
5111   /* now we need to put the carry into the
5112      highest order byte of the result */
5113   if (AOP_SIZE (result) > 1)
5114     {
5115       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5116       MOVA (l);
5117     }
5118   emitcode ("mov", "acc.7,c");
5119   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5120   freeAsmop (left, NULL, ic, TRUE);
5121   freeAsmop (result, NULL, ic, TRUE);
5122 }
5123
5124 /*-----------------------------------------------------------------*/
5125 /* genRLC - generate code for rotate left with carry               */
5126 /*-----------------------------------------------------------------*/
5127 static void
5128 genRLC (iCode * ic)
5129 {
5130   operand *left, *result;
5131   int size, offset = 0;
5132   char *l;
5133
5134   /* rotate right with carry */
5135   left = IC_LEFT (ic);
5136   result = IC_RESULT (ic);
5137   aopOp (left, ic, FALSE);
5138   aopOp (result, ic, FALSE);
5139
5140   /* move it to the result */
5141   size = AOP_SIZE (result);
5142   offset = 0;
5143   if (size--)
5144     {
5145       l = aopGet (AOP (left), offset, FALSE, FALSE);
5146       MOVA (l);
5147       emitcode ("add", "a,acc");
5148       if (AOP_SIZE (result) > 1)
5149         aopPut (AOP (result), "a", offset++);
5150       while (size--)
5151         {
5152           l = aopGet (AOP (left), offset, FALSE, FALSE);
5153           MOVA (l);
5154           emitcode ("rlc", "a");
5155           if (AOP_SIZE (result) > 1)
5156             aopPut (AOP (result), "a", offset++);
5157         }
5158     }
5159   /* now we need to put the carry into the
5160      highest order byte of the result */
5161   if (AOP_SIZE (result) > 1)
5162     {
5163       l = aopGet (AOP (result), 0, FALSE, FALSE);
5164       MOVA (l);
5165     }
5166   emitcode ("mov", "acc.0,c");
5167   aopPut (AOP (result), "a", 0);
5168   freeAsmop (left, NULL, ic, TRUE);
5169   freeAsmop (result, NULL, ic, TRUE);
5170 }
5171
5172 /*-----------------------------------------------------------------*/
5173 /* genGetHbit - generates code get highest order bit               */
5174 /*-----------------------------------------------------------------*/
5175 static void
5176 genGetHbit (iCode * ic)
5177 {
5178   operand *left, *result;
5179   left = IC_LEFT (ic);
5180   result = IC_RESULT (ic);
5181   aopOp (left, ic, FALSE);
5182   aopOp (result, ic, FALSE);
5183
5184   /* get the highest order byte into a */
5185   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5186   if (AOP_TYPE (result) == AOP_CRY)
5187     {
5188       emitcode ("rlc", "a");
5189       outBitC (result);
5190     }
5191   else
5192     {
5193       emitcode ("rl", "a");
5194       emitcode ("anl", "a,#0x01");
5195       outAcc (result);
5196     }
5197
5198
5199   freeAsmop (left, NULL, ic, TRUE);
5200   freeAsmop (result, NULL, ic, TRUE);
5201 }
5202
5203 /*-----------------------------------------------------------------*/
5204 /* AccRol - rotate left accumulator by known count                 */
5205 /*-----------------------------------------------------------------*/
5206 static void
5207 AccRol (int shCount)
5208 {
5209   shCount &= 0x0007;            // shCount : 0..7
5210
5211   switch (shCount)
5212     {
5213     case 0:
5214       break;
5215     case 1:
5216       emitcode ("rl", "a");
5217       break;
5218     case 2:
5219       emitcode ("rl", "a");
5220       emitcode ("rl", "a");
5221       break;
5222     case 3:
5223       emitcode ("swap", "a");
5224       emitcode ("rr", "a");
5225       break;
5226     case 4:
5227       emitcode ("swap", "a");
5228       break;
5229     case 5:
5230       emitcode ("swap", "a");
5231       emitcode ("rl", "a");
5232       break;
5233     case 6:
5234       emitcode ("rr", "a");
5235       emitcode ("rr", "a");
5236       break;
5237     case 7:
5238       emitcode ("rr", "a");
5239       break;
5240     }
5241 }
5242
5243 /*-----------------------------------------------------------------*/
5244 /* AccLsh - left shift accumulator by known count                  */
5245 /*-----------------------------------------------------------------*/
5246 static void
5247 AccLsh (int shCount)
5248 {
5249   if (shCount != 0)
5250     {
5251       if (shCount == 1)
5252         emitcode ("add", "a,acc");
5253       else if (shCount == 2)
5254         {
5255           emitcode ("add", "a,acc");
5256           emitcode ("add", "a,acc");
5257         }
5258       else
5259         {
5260           /* rotate left accumulator */
5261           AccRol (shCount);
5262           /* and kill the lower order bits */
5263           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5264         }
5265     }
5266 }
5267
5268 /*-----------------------------------------------------------------*/
5269 /* AccRsh - right shift accumulator by known count                 */
5270 /*-----------------------------------------------------------------*/
5271 static void
5272 AccRsh (int shCount)
5273 {
5274   if (shCount != 0)
5275     {
5276       if (shCount == 1)
5277         {
5278           CLRC;
5279           emitcode ("rrc", "a");
5280         }
5281       else
5282         {
5283           /* rotate right accumulator */
5284           AccRol (8 - shCount);
5285           /* and kill the higher order bits */
5286           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5287         }
5288     }
5289 }
5290
5291 /*-----------------------------------------------------------------*/
5292 /* AccSRsh - signed right shift accumulator by known count                 */
5293 /*-----------------------------------------------------------------*/
5294 static void
5295 AccSRsh (int shCount)
5296 {
5297   symbol *tlbl;
5298   if (shCount != 0)
5299     {
5300       if (shCount == 1)
5301         {
5302           emitcode ("mov", "c,acc.7");
5303           emitcode ("rrc", "a");
5304         }
5305       else if (shCount == 2)
5306         {
5307           emitcode ("mov", "c,acc.7");
5308           emitcode ("rrc", "a");
5309           emitcode ("mov", "c,acc.7");
5310           emitcode ("rrc", "a");
5311         }
5312       else
5313         {
5314           tlbl = newiTempLabel (NULL);
5315           /* rotate right accumulator */
5316           AccRol (8 - shCount);
5317           /* and kill the higher order bits */
5318           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5319           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5320           emitcode ("orl", "a,#0x%02x",
5321                     (unsigned char) ~SRMask[shCount]);
5322           emitcode ("", "%05d$:", tlbl->key + 100);
5323         }
5324     }
5325 }
5326
5327 /*-----------------------------------------------------------------*/
5328 /* shiftR1Left2Result - shift right one byte from left to result   */
5329 /*-----------------------------------------------------------------*/
5330 static void
5331 shiftR1Left2Result (operand * left, int offl,
5332                     operand * result, int offr,
5333                     int shCount, int sign)
5334 {
5335   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5336   /* shift right accumulator */
5337   if (sign)
5338     AccSRsh (shCount);
5339   else
5340     AccRsh (shCount);
5341   aopPut (AOP (result), "a", offr);
5342 }
5343
5344 /*-----------------------------------------------------------------*/
5345 /* shiftL1Left2Result - shift left one byte from left to result    */
5346 /*-----------------------------------------------------------------*/
5347 static void
5348 shiftL1Left2Result (operand * left, int offl,
5349                     operand * result, int offr, int shCount)
5350 {
5351   char *l;
5352   l = aopGet (AOP (left), offl, FALSE, FALSE);
5353   MOVA (l);
5354   /* shift left accumulator */
5355   AccLsh (shCount);
5356   aopPut (AOP (result), "a", offr);
5357 }
5358
5359 /*-----------------------------------------------------------------*/
5360 /* movLeft2Result - move byte from left to result                  */
5361 /*-----------------------------------------------------------------*/
5362 static void
5363 movLeft2Result (operand * left, int offl,
5364                 operand * result, int offr, int sign)
5365 {
5366   char *l;
5367   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5368     {
5369       l = aopGet (AOP (left), offl, FALSE, FALSE);
5370
5371       if (*l == '@' && (IS_AOP_PREG (result)))
5372         {
5373           emitcode ("mov", "a,%s", l);
5374           aopPut (AOP (result), "a", offr);
5375         }
5376       else
5377         {
5378           if (!sign)
5379             aopPut (AOP (result), l, offr);
5380           else
5381             {
5382               /* MSB sign in acc.7 ! */
5383               if (getDataSize (left) == offl + 1)
5384                 {
5385                   emitcode ("mov", "a,%s", l);
5386                   aopPut (AOP (result), "a", offr);
5387                 }
5388             }
5389         }
5390     }
5391 }
5392
5393 /*-----------------------------------------------------------------*/
5394 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5395 /*-----------------------------------------------------------------*/
5396 static void
5397 AccAXRrl1 (char *x)
5398 {
5399   emitcode ("rrc", "a");
5400   emitcode ("xch", "a,%s", x);
5401   emitcode ("rrc", "a");
5402   emitcode ("xch", "a,%s", x);
5403 }
5404
5405 /*-----------------------------------------------------------------*/
5406 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5407 /*-----------------------------------------------------------------*/
5408 static void
5409 AccAXLrl1 (char *x)
5410 {
5411   emitcode ("xch", "a,%s", x);
5412   emitcode ("rlc", "a");
5413   emitcode ("xch", "a,%s", x);
5414   emitcode ("rlc", "a");
5415 }
5416
5417 /*-----------------------------------------------------------------*/
5418 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5419 /*-----------------------------------------------------------------*/
5420 static void
5421 AccAXLsh1 (char *x)
5422 {
5423   emitcode ("xch", "a,%s", x);
5424   emitcode ("add", "a,acc");
5425   emitcode ("xch", "a,%s", x);
5426   emitcode ("rlc", "a");
5427 }
5428
5429 /*-----------------------------------------------------------------*/
5430 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5431 /*-----------------------------------------------------------------*/
5432 static void
5433 AccAXLsh (char *x, int shCount)
5434 {
5435   switch (shCount)
5436     {
5437     case 0:
5438       break;
5439     case 1:
5440       AccAXLsh1 (x);
5441       break;
5442     case 2:
5443       AccAXLsh1 (x);
5444       AccAXLsh1 (x);
5445       break;
5446     case 3:
5447     case 4:
5448     case 5:                     // AAAAABBB:CCCCCDDD
5449
5450       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
5451
5452       emitcode ("anl", "a,#0x%02x",
5453                 SLMask[shCount]);       // BBB00000:CCCCCDDD
5454
5455       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
5456
5457       AccRol (shCount);         // DDDCCCCC:BBB00000
5458
5459       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
5460
5461       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
5462
5463       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
5464
5465       emitcode ("anl", "a,#0x%02x",
5466                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
5467
5468       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
5469
5470       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
5471
5472       break;
5473     case 6:                     // AAAAAABB:CCCCCCDD
5474       emitcode ("anl", "a,#0x%02x",
5475                 SRMask[shCount]);       // 000000BB:CCCCCCDD
5476       emitcode ("mov", "c,acc.0");      // c = B
5477       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
5478 #if 0 // REMOVE ME
5479       AccAXRrl1 (x);            // BCCCCCCD:D000000B
5480       AccAXRrl1 (x);            // BBCCCCCC:DD000000
5481 #else
5482       emitcode("rrc","a"); 
5483       emitcode("xch","a,%s", x); 
5484       emitcode("rrc","a"); 
5485       emitcode("mov","c,acc.0"); //<< get correct bit 
5486       emitcode("xch","a,%s", x); 
5487
5488       emitcode("rrc","a"); 
5489       emitcode("xch","a,%s", x); 
5490       emitcode("rrc","a"); 
5491       emitcode("xch","a,%s", x); 
5492 #endif
5493       break;
5494     case 7:                     // a:x <<= 7
5495
5496       emitcode ("anl", "a,#0x%02x",
5497                 SRMask[shCount]);       // 0000000B:CCCCCCCD
5498
5499       emitcode ("mov", "c,acc.0");      // c = B
5500
5501       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
5502
5503       AccAXRrl1 (x);            // BCCCCCCC:D0000000
5504
5505       break;
5506     default:
5507       break;
5508     }
5509 }
5510
5511 /*-----------------------------------------------------------------*/
5512 /* AccAXRsh - right shift a:x known count (0..7)                   */
5513 /*-----------------------------------------------------------------*/
5514 static void
5515 AccAXRsh (char *x, int shCount)
5516 {
5517   switch (shCount)
5518     {
5519     case 0:
5520       break;
5521     case 1:
5522       CLRC;
5523       AccAXRrl1 (x);            // 0->a:x
5524
5525       break;
5526     case 2:
5527       CLRC;
5528       AccAXRrl1 (x);            // 0->a:x
5529
5530       CLRC;
5531       AccAXRrl1 (x);            // 0->a:x
5532
5533       break;
5534     case 3:
5535     case 4:
5536     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5537
5538       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
5539
5540       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5541
5542       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5543
5544       emitcode ("anl", "a,#0x%02x",
5545                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5546
5547       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5548
5549       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5550
5551       emitcode ("anl", "a,#0x%02x",
5552                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5553
5554       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5555
5556       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5557
5558       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
5559
5560       break;
5561     case 6:                     // AABBBBBB:CCDDDDDD
5562
5563       emitcode ("mov", "c,acc.7");
5564       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5565
5566       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5567
5568       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5569
5570       emitcode ("anl", "a,#0x%02x",
5571                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5572
5573       break;
5574     case 7:                     // ABBBBBBB:CDDDDDDD
5575
5576       emitcode ("mov", "c,acc.7");      // c = A
5577
5578       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5579
5580       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5581
5582       emitcode ("anl", "a,#0x%02x",
5583                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5584
5585       break;
5586     default:
5587       break;
5588     }
5589 }
5590
5591 /*-----------------------------------------------------------------*/
5592 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5593 /*-----------------------------------------------------------------*/
5594 static void
5595 AccAXRshS (char *x, int shCount)
5596 {
5597   symbol *tlbl;
5598   switch (shCount)
5599     {
5600     case 0:
5601       break;
5602     case 1:
5603       emitcode ("mov", "c,acc.7");
5604       AccAXRrl1 (x);            // s->a:x
5605
5606       break;
5607     case 2:
5608       emitcode ("mov", "c,acc.7");
5609       AccAXRrl1 (x);            // s->a:x
5610
5611       emitcode ("mov", "c,acc.7");
5612       AccAXRrl1 (x);            // s->a:x
5613
5614       break;
5615     case 3:
5616     case 4:
5617     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5618
5619       tlbl = newiTempLabel (NULL);
5620       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
5621
5622       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5623
5624       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5625
5626       emitcode ("anl", "a,#0x%02x",
5627                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5628
5629       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5630
5631       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5632
5633       emitcode ("anl", "a,#0x%02x",
5634                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5635
5636       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5637
5638       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5639
5640       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
5641
5642       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5643       emitcode ("orl", "a,#0x%02x",
5644                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
5645
5646       emitcode ("", "%05d$:", tlbl->key + 100);
5647       break;                    // SSSSAAAA:BBBCCCCC
5648
5649     case 6:                     // AABBBBBB:CCDDDDDD
5650
5651       tlbl = newiTempLabel (NULL);
5652       emitcode ("mov", "c,acc.7");
5653       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5654
5655       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5656
5657       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5658
5659       emitcode ("anl", "a,#0x%02x",
5660                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5661
5662       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5663       emitcode ("orl", "a,#0x%02x",
5664                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
5665
5666       emitcode ("", "%05d$:", tlbl->key + 100);
5667       break;
5668     case 7:                     // ABBBBBBB:CDDDDDDD
5669
5670       tlbl = newiTempLabel (NULL);
5671       emitcode ("mov", "c,acc.7");      // c = A
5672
5673       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5674
5675       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5676
5677       emitcode ("anl", "a,#0x%02x",
5678                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5679
5680       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5681       emitcode ("orl", "a,#0x%02x",
5682                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
5683
5684       emitcode ("", "%05d$:", tlbl->key + 100);
5685       break;
5686     default:
5687       break;
5688     }
5689 }
5690
5691 /*-----------------------------------------------------------------*/
5692 /* shiftL2Left2Result - shift left two bytes from left to result   */
5693 /*-----------------------------------------------------------------*/
5694 static void
5695 shiftL2Left2Result (operand * left, int offl,
5696                     operand * result, int offr, int shCount)
5697 {
5698   if (sameRegs (AOP (result), AOP (left)) &&
5699       ((offl + MSB16) == offr))
5700     {
5701       /* don't crash result[offr] */
5702       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5703       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5704     }
5705   else
5706     {
5707       movLeft2Result (left, offl, result, offr, 0);
5708       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5709     }
5710   /* ax << shCount (x = lsb(result)) */
5711   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5712   aopPut (AOP (result), "a", offr + MSB16);
5713 }
5714
5715
5716 /*-----------------------------------------------------------------*/
5717 /* shiftR2Left2Result - shift right two bytes from left to result  */
5718 /*-----------------------------------------------------------------*/
5719 static void
5720 shiftR2Left2Result (operand * left, int offl,
5721                     operand * result, int offr,
5722                     int shCount, int sign)
5723 {
5724   if (sameRegs (AOP (result), AOP (left)) &&
5725       ((offl + MSB16) == offr))
5726     {
5727       /* don't crash result[offr] */
5728       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5729       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5730     }
5731   else
5732     {
5733       movLeft2Result (left, offl, result, offr, 0);
5734       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5735     }
5736   /* a:x >> shCount (x = lsb(result)) */
5737   if (sign)
5738     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5739   else
5740     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5741   if (getDataSize (result) > 1)
5742     aopPut (AOP (result), "a", offr + MSB16);
5743 }
5744
5745 /*-----------------------------------------------------------------*/
5746 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5747 /*-----------------------------------------------------------------*/
5748 static void
5749 shiftLLeftOrResult (operand * left, int offl,
5750                     operand * result, int offr, int shCount)
5751 {
5752   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5753   /* shift left accumulator */
5754   AccLsh (shCount);
5755   /* or with result */
5756   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5757   /* back to result */
5758   aopPut (AOP (result), "a", offr);
5759 }
5760
5761 /*-----------------------------------------------------------------*/
5762 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5763 /*-----------------------------------------------------------------*/
5764 static void
5765 shiftRLeftOrResult (operand * left, int offl,
5766                     operand * result, int offr, int shCount)
5767 {
5768   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5769   /* shift right accumulator */
5770   AccRsh (shCount);
5771   /* or with result */
5772   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5773   /* back to result */
5774   aopPut (AOP (result), "a", offr);
5775 }
5776
5777 /*-----------------------------------------------------------------*/
5778 /* genlshOne - left shift a one byte quantity by known count       */
5779 /*-----------------------------------------------------------------*/
5780 static void
5781 genlshOne (operand * result, operand * left, int shCount)
5782 {
5783   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5784 }
5785
5786 /*-----------------------------------------------------------------*/
5787 /* genlshTwo - left shift two bytes by known amount != 0           */
5788 /*-----------------------------------------------------------------*/
5789 static void
5790 genlshTwo (operand * result, operand * left, int shCount)
5791 {
5792   int size;
5793
5794   size = getDataSize (result);
5795
5796   /* if shCount >= 8 */
5797   if (shCount >= 8)
5798     {
5799       shCount -= 8;
5800
5801       if (size > 1)
5802         {
5803           if (shCount)
5804             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5805           else
5806             movLeft2Result (left, LSB, result, MSB16, 0);
5807         }
5808       aopPut (AOP (result), zero, LSB);
5809     }
5810
5811   /*  1 <= shCount <= 7 */
5812   else
5813     {
5814       if (size == 1)
5815         shiftL1Left2Result (left, LSB, result, LSB, shCount);
5816       else
5817         shiftL2Left2Result (left, LSB, result, LSB, shCount);
5818     }
5819 }
5820
5821 /*-----------------------------------------------------------------*/
5822 /* shiftLLong - shift left one long from left to result            */
5823 /* offl = LSB or MSB16                                             */
5824 /*-----------------------------------------------------------------*/
5825 static void
5826 shiftLLong (operand * left, operand * result, int offr)
5827 {
5828   char *l;
5829   int size = AOP_SIZE (result);
5830
5831   if (size >= LSB + offr)
5832     {
5833       l = aopGet (AOP (left), LSB, FALSE, FALSE);
5834       MOVA (l);
5835       emitcode ("add", "a,acc");
5836       if (sameRegs (AOP (left), AOP (result)) &&
5837           size >= MSB16 + offr && offr != LSB)
5838         emitcode ("xch", "a,%s",
5839                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5840       else
5841         aopPut (AOP (result), "a", LSB + offr);
5842     }
5843
5844   if (size >= MSB16 + offr)
5845     {
5846       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5847         {
5848           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5849           MOVA (l);
5850         }
5851       emitcode ("rlc", "a");
5852       if (sameRegs (AOP (left), AOP (result)) &&
5853           size >= MSB24 + offr && offr != LSB)
5854         emitcode ("xch", "a,%s",
5855                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5856       else
5857         aopPut (AOP (result), "a", MSB16 + offr);
5858     }
5859
5860   if (size >= MSB24 + offr)
5861     {
5862       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
5863         {
5864           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
5865           MOVA (l);
5866         }
5867       emitcode ("rlc", "a");
5868       if (sameRegs (AOP (left), AOP (result)) &&
5869           size >= MSB32 + offr && offr != LSB)
5870         emitcode ("xch", "a,%s",
5871                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
5872       else
5873         aopPut (AOP (result), "a", MSB24 + offr);
5874     }
5875
5876   if (size > MSB32 + offr)
5877     {
5878       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
5879         {
5880           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
5881           MOVA (l);
5882         }
5883       emitcode ("rlc", "a");
5884       aopPut (AOP (result), "a", MSB32 + offr);
5885     }
5886   if (offr != LSB)
5887     aopPut (AOP (result), zero, LSB);
5888 }
5889
5890 /*-----------------------------------------------------------------*/
5891 /* genlshFour - shift four byte by a known amount != 0             */
5892 /*-----------------------------------------------------------------*/
5893 static void
5894 genlshFour (operand * result, operand * left, int shCount)
5895 {
5896   int size;
5897
5898   size = AOP_SIZE (result);
5899
5900   /* if shifting more that 3 bytes */
5901   if (shCount >= 24)
5902     {
5903       shCount -= 24;
5904       if (shCount)
5905         /* lowest order of left goes to the highest
5906            order of the destination */
5907         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5908       else
5909         movLeft2Result (left, LSB, result, MSB32, 0);
5910       aopPut (AOP (result), zero, LSB);
5911       aopPut (AOP (result), zero, MSB16);
5912       aopPut (AOP (result), zero, MSB24);
5913       return;
5914     }
5915
5916   /* more than two bytes */
5917   else if (shCount >= 16)
5918     {
5919       /* lower order two bytes goes to higher order two bytes */
5920       shCount -= 16;
5921       /* if some more remaining */
5922       if (shCount)
5923         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5924       else
5925         {
5926           movLeft2Result (left, MSB16, result, MSB32, 0);
5927           movLeft2Result (left, LSB, result, MSB24, 0);
5928         }
5929       aopPut (AOP (result), zero, MSB16);
5930       aopPut (AOP (result), zero, LSB);
5931       return;
5932     }
5933
5934   /* if more than 1 byte */
5935   else if (shCount >= 8)
5936     {
5937       /* lower order three bytes goes to higher order  three bytes */
5938       shCount -= 8;
5939       if (size == 2)
5940         {
5941           if (shCount)
5942             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5943           else
5944             movLeft2Result (left, LSB, result, MSB16, 0);
5945         }
5946       else
5947         {                       /* size = 4 */
5948           if (shCount == 0)
5949             {
5950               movLeft2Result (left, MSB24, result, MSB32, 0);
5951               movLeft2Result (left, MSB16, result, MSB24, 0);
5952               movLeft2Result (left, LSB, result, MSB16, 0);
5953               aopPut (AOP (result), zero, LSB);
5954             }
5955           else if (shCount == 1)
5956             shiftLLong (left, result, MSB16);
5957           else
5958             {
5959               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5960               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5961               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5962               aopPut (AOP (result), zero, LSB);
5963             }
5964         }
5965     }
5966
5967   /* 1 <= shCount <= 7 */
5968   else if (shCount <= 2)
5969     {
5970       shiftLLong (left, result, LSB);
5971       if (shCount == 2)
5972         shiftLLong (result, result, LSB);
5973     }
5974   /* 3 <= shCount <= 7, optimize */
5975   else
5976     {
5977       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5978       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5979       shiftL2Left2Result (left, LSB, result, LSB, shCount);
5980     }
5981 }
5982
5983 /*-----------------------------------------------------------------*/
5984 /* genLeftShiftLiteral - left shifting by known count              */
5985 /*-----------------------------------------------------------------*/
5986 static void
5987 genLeftShiftLiteral (operand * left,
5988                      operand * right,
5989                      operand * result,
5990                      iCode * ic)
5991 {
5992   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5993   int size;
5994
5995   freeAsmop (right, NULL, ic, TRUE);
5996
5997   aopOp (left, ic, FALSE);
5998   aopOp (result, ic, FALSE);
5999
6000   size = getSize (operandType (result));
6001
6002 #if VIEW_SIZE
6003   emitcode ("; shift left ", "result %d, left %d", size,
6004             AOP_SIZE (left));
6005 #endif
6006
6007   /* I suppose that the left size >= result size */
6008   if (shCount == 0)
6009     {
6010       while (size--)
6011         {
6012           movLeft2Result (left, size, result, size, 0);
6013         }
6014     }
6015
6016   else if (shCount >= (size * 8))
6017     while (size--)
6018       aopPut (AOP (result), zero, size);
6019   else
6020     {
6021       switch (size)
6022         {
6023         case 1:
6024           genlshOne (result, left, shCount);
6025           break;
6026
6027         case 2:
6028         case 3:
6029           genlshTwo (result, left, shCount);
6030           break;
6031
6032         case 4:
6033           genlshFour (result, left, shCount);
6034           break;
6035         }
6036     }
6037   freeAsmop (left, NULL, ic, TRUE);
6038   freeAsmop (result, NULL, ic, TRUE);
6039 }
6040
6041 /*-----------------------------------------------------------------*/
6042 /* genLeftShift - generates code for left shifting                 */
6043 /*-----------------------------------------------------------------*/
6044 static void
6045 genLeftShift (iCode * ic)
6046 {
6047   operand *left, *right, *result;
6048   int size, offset;
6049   char *l;
6050   symbol *tlbl, *tlbl1;
6051
6052   right = IC_RIGHT (ic);
6053   left = IC_LEFT (ic);
6054   result = IC_RESULT (ic);
6055
6056   aopOp (right, ic, FALSE);
6057
6058   /* if the shift count is known then do it
6059      as efficiently as possible */
6060   if (AOP_TYPE (right) == AOP_LIT)
6061     {
6062       genLeftShiftLiteral (left, right, result, ic);
6063       return;
6064     }
6065
6066   /* shift count is unknown then we have to form
6067      a loop get the loop count in B : Note: we take
6068      only the lower order byte since shifting
6069      more that 32 bits make no sense anyway, ( the
6070      largest size of an object can be only 32 bits ) */
6071
6072   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6073   emitcode ("inc", "b");
6074   freeAsmop (right, NULL, ic, TRUE);
6075   aopOp (left, ic, FALSE);
6076   aopOp (result, ic, FALSE);
6077
6078   /* now move the left to the result if they are not the
6079      same */
6080   if (!sameRegs (AOP (left), AOP (result)) &&
6081       AOP_SIZE (result) > 1)
6082     {
6083
6084       size = AOP_SIZE (result);
6085       offset = 0;
6086       while (size--)
6087         {
6088           l = aopGet (AOP (left), offset, FALSE, TRUE);
6089           if (*l == '@' && (IS_AOP_PREG (result)))
6090             {
6091
6092               emitcode ("mov", "a,%s", l);
6093               aopPut (AOP (result), "a", offset);
6094             }
6095           else
6096             aopPut (AOP (result), l, offset);
6097           offset++;
6098         }
6099     }
6100
6101   tlbl = newiTempLabel (NULL);
6102   size = AOP_SIZE (result);
6103   offset = 0;
6104   tlbl1 = newiTempLabel (NULL);
6105
6106   /* if it is only one byte then */
6107   if (size == 1)
6108     {
6109       symbol *tlbl1 = newiTempLabel (NULL);
6110
6111       l = aopGet (AOP (left), 0, FALSE, FALSE);
6112       MOVA (l);
6113       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6114       emitcode ("", "%05d$:", tlbl->key + 100);
6115       emitcode ("add", "a,acc");
6116       emitcode ("", "%05d$:", tlbl1->key + 100);
6117       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6118       aopPut (AOP (result), "a", 0);
6119       goto release;
6120     }
6121
6122   reAdjustPreg (AOP (result));
6123
6124   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6125   emitcode ("", "%05d$:", tlbl->key + 100);
6126   l = aopGet (AOP (result), offset, FALSE, FALSE);
6127   MOVA (l);
6128   emitcode ("add", "a,acc");
6129   aopPut (AOP (result), "a", offset++);
6130   while (--size)
6131     {
6132       l = aopGet (AOP (result), offset, FALSE, FALSE);
6133       MOVA (l);
6134       emitcode ("rlc", "a");
6135       aopPut (AOP (result), "a", offset++);
6136     }
6137   reAdjustPreg (AOP (result));
6138
6139   emitcode ("", "%05d$:", tlbl1->key + 100);
6140   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6141 release:
6142   freeAsmop (left, NULL, ic, TRUE);
6143   freeAsmop (result, NULL, ic, TRUE);
6144 }
6145
6146 /*-----------------------------------------------------------------*/
6147 /* genrshOne - right shift a one byte quantity by known count      */
6148 /*-----------------------------------------------------------------*/
6149 static void
6150 genrshOne (operand * result, operand * left,
6151            int shCount, int sign)
6152 {
6153   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6154 }
6155
6156 /*-----------------------------------------------------------------*/
6157 /* genrshTwo - right shift two bytes by known amount != 0          */
6158 /*-----------------------------------------------------------------*/
6159 static void
6160 genrshTwo (operand * result, operand * left,
6161            int shCount, int sign)
6162 {
6163   /* if shCount >= 8 */
6164   if (shCount >= 8)
6165     {
6166       shCount -= 8;
6167       if (shCount)
6168         shiftR1Left2Result (left, MSB16, result, LSB,
6169                             shCount, sign);
6170       else
6171         movLeft2Result (left, MSB16, result, LSB, sign);
6172       addSign (result, MSB16, sign);
6173     }
6174
6175   /*  1 <= shCount <= 7 */
6176   else
6177     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6178 }
6179
6180 /*-----------------------------------------------------------------*/
6181 /* shiftRLong - shift right one long from left to result           */
6182 /* offl = LSB or MSB16                                             */
6183 /*-----------------------------------------------------------------*/
6184 static void
6185 shiftRLong (operand * left, int offl,
6186             operand * result, int sign)
6187 {
6188   if (!sign)
6189     emitcode ("clr", "c");
6190   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6191   if (sign)
6192     emitcode ("mov", "c,acc.7");
6193   emitcode ("rrc", "a");
6194   aopPut (AOP (result), "a", MSB32 - offl);
6195   if (offl == MSB16)
6196     /* add sign of "a" */
6197     addSign (result, MSB32, sign);
6198
6199   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6200   emitcode ("rrc", "a");
6201   aopPut (AOP (result), "a", MSB24 - offl);
6202
6203   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6204   emitcode ("rrc", "a");
6205   aopPut (AOP (result), "a", MSB16 - offl);
6206
6207   if (offl == LSB)
6208     {
6209       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6210       emitcode ("rrc", "a");
6211       aopPut (AOP (result), "a", LSB);
6212     }
6213 }
6214
6215 /*-----------------------------------------------------------------*/
6216 /* genrshFour - shift four byte by a known amount != 0             */
6217 /*-----------------------------------------------------------------*/
6218 static void
6219 genrshFour (operand * result, operand * left,
6220             int shCount, int sign)
6221 {
6222   /* if shifting more that 3 bytes */
6223   if (shCount >= 24)
6224     {
6225       shCount -= 24;
6226       if (shCount)
6227         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6228       else
6229         movLeft2Result (left, MSB32, result, LSB, sign);
6230       addSign (result, MSB16, sign);
6231     }
6232   else if (shCount >= 16)
6233     {
6234       shCount -= 16;
6235       if (shCount)
6236         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6237       else
6238         {
6239           movLeft2Result (left, MSB24, result, LSB, 0);
6240           movLeft2Result (left, MSB32, result, MSB16, sign);
6241         }
6242       addSign (result, MSB24, sign);
6243     }
6244   else if (shCount >= 8)
6245     {
6246       shCount -= 8;
6247       if (shCount == 1)
6248         shiftRLong (left, MSB16, result, sign);
6249       else if (shCount == 0)
6250         {
6251           movLeft2Result (left, MSB16, result, LSB, 0);
6252           movLeft2Result (left, MSB24, result, MSB16, 0);
6253           movLeft2Result (left, MSB32, result, MSB24, sign);
6254           addSign (result, MSB32, sign);
6255         }
6256       else
6257         {
6258           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6259           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6260           /* the last shift is signed */
6261           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6262           addSign (result, MSB32, sign);
6263         }
6264     }
6265   else
6266     {                           /* 1 <= shCount <= 7 */
6267       if (shCount <= 2)
6268         {
6269           shiftRLong (left, LSB, result, sign);
6270           if (shCount == 2)
6271             shiftRLong (result, LSB, result, sign);
6272         }
6273       else
6274         {
6275           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6276           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6277           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6278         }
6279     }
6280 }
6281
6282 /*-----------------------------------------------------------------*/
6283 /* genRightShiftLiteral - right shifting by known count            */
6284 /*-----------------------------------------------------------------*/
6285 static void
6286 genRightShiftLiteral (operand * left,
6287                       operand * right,
6288                       operand * result,
6289                       iCode * ic,
6290                       int sign)
6291 {
6292   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6293   int size;
6294
6295   freeAsmop (right, NULL, ic, TRUE);
6296
6297   aopOp (left, ic, FALSE);
6298   aopOp (result, ic, FALSE);
6299
6300 #if VIEW_SIZE
6301   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6302             AOP_SIZE (left));
6303 #endif
6304
6305   size = getDataSize (left);
6306   /* test the LEFT size !!! */
6307
6308   /* I suppose that the left size >= result size */
6309   if (shCount == 0)
6310     {
6311       size = getDataSize (result);
6312       while (size--)
6313         movLeft2Result (left, size, result, size, 0);
6314     }
6315
6316   else if (shCount >= (size * 8))
6317     {
6318       if (sign)
6319         /* get sign in acc.7 */
6320         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6321       addSign (result, LSB, sign);
6322     }
6323   else
6324     {
6325       switch (size)
6326         {
6327         case 1:
6328           genrshOne (result, left, shCount, sign);
6329           break;
6330
6331         case 2:
6332           genrshTwo (result, left, shCount, sign);
6333           break;
6334
6335         case 4:
6336           genrshFour (result, left, shCount, sign);
6337           break;
6338         default:
6339           break;
6340         }
6341
6342       freeAsmop (left, NULL, ic, TRUE);
6343       freeAsmop (result, NULL, ic, TRUE);
6344     }
6345 }
6346
6347 /*-----------------------------------------------------------------*/
6348 /* genSignedRightShift - right shift of signed number              */
6349 /*-----------------------------------------------------------------*/
6350 static void
6351 genSignedRightShift (iCode * ic)
6352 {
6353   operand *right, *left, *result;
6354   int size, offset;
6355   char *l;
6356   symbol *tlbl, *tlbl1;
6357
6358   /* we do it the hard way put the shift count in b
6359      and loop thru preserving the sign */
6360
6361   right = IC_RIGHT (ic);
6362   left = IC_LEFT (ic);
6363   result = IC_RESULT (ic);
6364
6365   aopOp (right, ic, FALSE);
6366
6367
6368   if (AOP_TYPE (right) == AOP_LIT)
6369     {
6370       genRightShiftLiteral (left, right, result, ic, 1);
6371       return;
6372     }
6373   /* shift count is unknown then we have to form
6374      a loop get the loop count in B : Note: we take
6375      only the lower order byte since shifting
6376      more that 32 bits make no sense anyway, ( the
6377      largest size of an object can be only 32 bits ) */
6378
6379   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6380   emitcode ("inc", "b");
6381   freeAsmop (right, NULL, ic, TRUE);
6382   aopOp (left, ic, FALSE);
6383   aopOp (result, ic, FALSE);
6384
6385   /* now move the left to the result if they are not the
6386      same */
6387   if (!sameRegs (AOP (left), AOP (result)) &&
6388       AOP_SIZE (result) > 1)
6389     {
6390
6391       size = AOP_SIZE (result);
6392       offset = 0;
6393       while (size--)
6394         {
6395           l = aopGet (AOP (left), offset, FALSE, TRUE);
6396           if (*l == '@' && IS_AOP_PREG (result))
6397             {
6398
6399               emitcode ("mov", "a,%s", l);
6400               aopPut (AOP (result), "a", offset);
6401             }
6402           else
6403             aopPut (AOP (result), l, offset);
6404           offset++;
6405         }
6406     }
6407
6408   /* mov the highest order bit to OVR */
6409   tlbl = newiTempLabel (NULL);
6410   tlbl1 = newiTempLabel (NULL);
6411
6412   size = AOP_SIZE (result);
6413   offset = size - 1;
6414   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6415   emitcode ("rlc", "a");
6416   emitcode ("mov", "ov,c");
6417   /* if it is only one byte then */
6418   if (size == 1)
6419     {
6420       l = aopGet (AOP (left), 0, FALSE, FALSE);
6421       MOVA (l);
6422       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6423       emitcode ("", "%05d$:", tlbl->key + 100);
6424       emitcode ("mov", "c,ov");
6425       emitcode ("rrc", "a");
6426       emitcode ("", "%05d$:", tlbl1->key + 100);
6427       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6428       aopPut (AOP (result), "a", 0);
6429       goto release;
6430     }
6431
6432   reAdjustPreg (AOP (result));
6433   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6434   emitcode ("", "%05d$:", tlbl->key + 100);
6435   emitcode ("mov", "c,ov");
6436   while (size--)
6437     {
6438       l = aopGet (AOP (result), offset, FALSE, FALSE);
6439       MOVA (l);
6440       emitcode ("rrc", "a");
6441       aopPut (AOP (result), "a", offset--);
6442     }
6443   reAdjustPreg (AOP (result));
6444   emitcode ("", "%05d$:", tlbl1->key + 100);
6445   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6446
6447 release:
6448   freeAsmop (left, NULL, ic, TRUE);
6449   freeAsmop (result, NULL, ic, TRUE);
6450 }
6451
6452 /*-----------------------------------------------------------------*/
6453 /* genRightShift - generate code for right shifting                */
6454 /*-----------------------------------------------------------------*/
6455 static void
6456 genRightShift (iCode * ic)
6457 {
6458   operand *right, *left, *result;
6459   sym_link *retype;
6460   int size, offset;
6461   char *l;
6462   symbol *tlbl, *tlbl1;
6463
6464   /* if signed then we do it the hard way preserve the
6465      sign bit moving it inwards */
6466   retype = getSpec (operandType (IC_RESULT (ic)));
6467
6468   if (!SPEC_USIGN (retype))
6469     {
6470       genSignedRightShift (ic);
6471       return;
6472     }
6473
6474   /* signed & unsigned types are treated the same : i.e. the
6475      signed is NOT propagated inwards : quoting from the
6476      ANSI - standard : "for E1 >> E2, is equivalent to division
6477      by 2**E2 if unsigned or if it has a non-negative value,
6478      otherwise the result is implementation defined ", MY definition
6479      is that the sign does not get propagated */
6480
6481   right = IC_RIGHT (ic);
6482   left = IC_LEFT (ic);
6483   result = IC_RESULT (ic);
6484
6485   aopOp (right, ic, FALSE);
6486
6487   /* if the shift count is known then do it
6488      as efficiently as possible */
6489   if (AOP_TYPE (right) == AOP_LIT)
6490     {
6491       genRightShiftLiteral (left, right, result, ic, 0);
6492       return;
6493     }
6494
6495   /* shift count is unknown then we have to form
6496      a loop get the loop count in B : Note: we take
6497      only the lower order byte since shifting
6498      more that 32 bits make no sense anyway, ( the
6499      largest size of an object can be only 32 bits ) */
6500
6501   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6502   emitcode ("inc", "b");
6503   freeAsmop (right, NULL, ic, TRUE);
6504   aopOp (left, ic, FALSE);
6505   aopOp (result, ic, FALSE);
6506
6507   /* now move the left to the result if they are not the
6508      same */
6509   if (!sameRegs (AOP (left), AOP (result)) &&
6510       AOP_SIZE (result) > 1)
6511     {
6512
6513       size = AOP_SIZE (result);
6514       offset = 0;
6515       while (size--)
6516         {
6517           l = aopGet (AOP (left), offset, FALSE, TRUE);
6518           if (*l == '@' && IS_AOP_PREG (result))
6519             {
6520
6521               emitcode ("mov", "a,%s", l);
6522               aopPut (AOP (result), "a", offset);
6523             }
6524           else
6525             aopPut (AOP (result), l, offset);
6526           offset++;
6527         }
6528     }
6529
6530   tlbl = newiTempLabel (NULL);
6531   tlbl1 = newiTempLabel (NULL);
6532   size = AOP_SIZE (result);
6533   offset = size - 1;
6534
6535   /* if it is only one byte then */
6536   if (size == 1)
6537     {
6538       l = aopGet (AOP (left), 0, FALSE, FALSE);
6539       MOVA (l);
6540       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6541       emitcode ("", "%05d$:", tlbl->key + 100);
6542       CLRC;
6543       emitcode ("rrc", "a");
6544       emitcode ("", "%05d$:", tlbl1->key + 100);
6545       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6546       aopPut (AOP (result), "a", 0);
6547       goto release;
6548     }
6549
6550   reAdjustPreg (AOP (result));
6551   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6552   emitcode ("", "%05d$:", tlbl->key + 100);
6553   CLRC;
6554   while (size--)
6555     {
6556       l = aopGet (AOP (result), offset, FALSE, FALSE);
6557       MOVA (l);
6558       emitcode ("rrc", "a");
6559       aopPut (AOP (result), "a", offset--);
6560     }
6561   reAdjustPreg (AOP (result));
6562
6563   emitcode ("", "%05d$:", tlbl1->key + 100);
6564   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6565
6566 release:
6567   freeAsmop (left, NULL, ic, TRUE);
6568   freeAsmop (result, NULL, ic, TRUE);
6569 }
6570
6571 /*-----------------------------------------------------------------*/
6572 /* genUnpackBits - generates code for unpacking bits               */
6573 /*-----------------------------------------------------------------*/
6574 static void
6575 genUnpackBits (operand * result, char *rname, int ptype)
6576 {
6577   int shCnt;
6578   int rlen = 0;
6579   sym_link *etype;
6580   int offset = 0;
6581   int rsize;
6582
6583   etype = getSpec (operandType (result));
6584   rsize = getSize (operandType (result));
6585   /* read the first byte  */
6586   switch (ptype)
6587     {
6588
6589     case POINTER:
6590     case IPOINTER:
6591       emitcode ("mov", "a,@%s", rname);
6592       break;
6593
6594     case PPOINTER:
6595       emitcode ("movx", "a,@%s", rname);
6596       break;
6597
6598     case FPOINTER:
6599       emitcode ("movx", "a,@dptr");
6600       break;
6601
6602     case CPOINTER:
6603       emitcode ("clr", "a");
6604       emitcode ("movc", "a,%s", "@a+dptr");
6605       break;
6606
6607     case GPOINTER:
6608       emitcode ("lcall", "__gptrget");
6609       break;
6610     }
6611
6612   rlen = SPEC_BLEN (etype);
6613
6614   /* if we have bitdisplacement then it fits   */
6615   /* into this byte completely or if length is */
6616   /* less than a byte                          */
6617   if ((shCnt = SPEC_BSTR (etype)) ||
6618       (SPEC_BLEN (etype) <= 8))
6619     {
6620
6621       /* shift right acc */
6622       AccRsh (shCnt);
6623
6624       emitcode ("anl", "a,#0x%02x",
6625                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6626       aopPut (AOP (result), "a", offset++);
6627       goto finish;
6628     }
6629
6630   /* bit field did not fit in a byte  */
6631   aopPut (AOP (result), "a", offset++);
6632
6633   while (1)
6634     {
6635
6636       switch (ptype)
6637         {
6638         case POINTER:
6639         case IPOINTER:
6640           emitcode ("inc", "%s", rname);
6641           emitcode ("mov", "a,@%s", rname);
6642           break;
6643
6644         case PPOINTER:
6645           emitcode ("inc", "%s", rname);
6646           emitcode ("movx", "a,@%s", rname);
6647           break;
6648
6649         case FPOINTER:
6650           emitcode ("inc", "dptr");
6651           emitcode ("movx", "a,@dptr");
6652           break;
6653
6654         case CPOINTER:
6655           emitcode ("clr", "a");
6656           emitcode ("inc", "dptr");
6657           emitcode ("movc", "a", "@a+dptr");
6658           break;
6659
6660         case GPOINTER:
6661           emitcode ("inc", "dptr");
6662           emitcode ("lcall", "__gptrget");
6663           break;
6664         }
6665
6666       rlen -= 8;
6667       /* if we are done */
6668       if (rlen < 8)
6669         break;
6670
6671       aopPut (AOP (result), "a", offset++);
6672
6673     }
6674
6675   if (rlen)
6676     {
6677       //  emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6678       AccLsh (8 - rlen);
6679       aopPut (AOP (result), "a", offset++);
6680     }
6681
6682 finish:
6683   if (offset < rsize)
6684     {
6685       rsize -= offset;
6686       while (rsize--)
6687         aopPut (AOP (result), zero, offset++);
6688     }
6689   return;
6690 }
6691
6692
6693 /*-----------------------------------------------------------------*/
6694 /* genDataPointerGet - generates code when ptr offset is known     */
6695 /*-----------------------------------------------------------------*/
6696 static void
6697 genDataPointerGet (operand * left,
6698                    operand * result,
6699                    iCode * ic)
6700 {
6701   char *l;
6702   char buffer[256];
6703   int size, offset = 0;
6704   aopOp (result, ic, TRUE);
6705
6706   /* get the string representation of the name */
6707   l = aopGet (AOP (left), 0, FALSE, TRUE);
6708   size = AOP_SIZE (result);
6709   while (size--)
6710     {
6711       if (offset)
6712         sprintf (buffer, "(%s + %d)", l + 1, offset);
6713       else
6714         sprintf (buffer, "%s", l + 1);
6715       aopPut (AOP (result), buffer, offset++);
6716     }
6717
6718   freeAsmop (left, NULL, ic, TRUE);
6719   freeAsmop (result, NULL, ic, TRUE);
6720 }
6721
6722 /*-----------------------------------------------------------------*/
6723 /* genNearPointerGet - emitcode for near pointer fetch             */
6724 /*-----------------------------------------------------------------*/
6725 static void
6726 genNearPointerGet (operand * left,
6727                    operand * result,
6728                    iCode * ic,
6729                    iCode * pi)
6730 {
6731   asmop *aop = NULL;
6732   regs *preg = NULL;
6733   char *rname;
6734   sym_link *rtype, *retype;
6735   sym_link *ltype = operandType (left);
6736   char buffer[80];
6737
6738   rtype = operandType (result);
6739   retype = getSpec (rtype);
6740
6741   aopOp (left, ic, FALSE);
6742
6743   /* if left is rematerialisable and
6744      result is not bit variable type and
6745      the left is pointer to data space i.e
6746      lower 128 bytes of space */
6747   if (AOP_TYPE (left) == AOP_IMMD &&
6748       !IS_BITVAR (retype) &&
6749       DCL_TYPE (ltype) == POINTER)
6750     {
6751       genDataPointerGet (left, result, ic);
6752       return;
6753     }
6754
6755   /* if the value is already in a pointer register
6756      then don't need anything more */
6757   if (!AOP_INPREG (AOP (left)))
6758     {
6759       /* otherwise get a free pointer register */
6760       aop = newAsmop (0);
6761       preg = getFreePtr (ic, &aop, FALSE);
6762       emitcode ("mov", "%s,%s",
6763                 preg->name,
6764                 aopGet (AOP (left), 0, FALSE, TRUE));
6765       rname = preg->name;
6766     }
6767   else
6768     rname = aopGet (AOP (left), 0, FALSE, FALSE);
6769
6770   aopOp (result, ic, FALSE);
6771
6772   /* if bitfield then unpack the bits */
6773   if (IS_BITVAR (retype))
6774     genUnpackBits (result, rname, POINTER);
6775   else
6776     {
6777       /* we have can just get the values */
6778       int size = AOP_SIZE (result);
6779       int offset = 0;
6780
6781       while (size--)
6782         {
6783           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6784             {
6785
6786               emitcode ("mov", "a,@%s", rname);
6787               aopPut (AOP (result), "a", offset);
6788             }
6789           else
6790             {
6791               sprintf (buffer, "@%s", rname);
6792               aopPut (AOP (result), buffer, offset);
6793             }
6794           offset++;
6795           if (size || pi)
6796             emitcode ("inc", "%s", rname);
6797         }
6798     }
6799
6800   /* now some housekeeping stuff */
6801   if (aop)       /* we had to allocate for this iCode */
6802     {
6803       if (pi) { /* post increment present */
6804         aopPut(AOP ( left ),rname,0);
6805       }
6806       freeAsmop (NULL, aop, ic, TRUE);
6807     }
6808   else
6809     {
6810       /* we did not allocate which means left
6811          already in a pointer register, then
6812          if size > 0 && this could be used again
6813          we have to point it back to where it
6814          belongs */
6815       if ((AOP_SIZE (result) > 1 &&
6816            !OP_SYMBOL (left)->remat &&
6817            (OP_SYMBOL (left)->liveTo > ic->seq ||
6818             ic->depth)) &&
6819           !pi)
6820         {
6821           int size = AOP_SIZE (result) - 1;
6822           while (size--)
6823             emitcode ("dec", "%s", rname);
6824         }
6825     }
6826
6827   /* done */
6828   freeAsmop (left, NULL, ic, TRUE);
6829   freeAsmop (result, NULL, ic, TRUE);
6830   if (pi) pi->generated = 1;
6831 }
6832
6833 /*-----------------------------------------------------------------*/
6834 /* genPagedPointerGet - emitcode for paged pointer fetch           */
6835 /*-----------------------------------------------------------------*/
6836 static void
6837 genPagedPointerGet (operand * left,
6838                     operand * result,
6839                     iCode * ic,
6840                     iCode *pi)
6841 {
6842   asmop *aop = NULL;
6843   regs *preg = NULL;
6844   char *rname;
6845   sym_link *rtype, *retype;
6846
6847   rtype = operandType (result);
6848   retype = getSpec (rtype);
6849
6850   aopOp (left, ic, FALSE);
6851
6852   /* if the value is already in a pointer register
6853      then don't need anything more */
6854   if (!AOP_INPREG (AOP (left)))
6855     {
6856       /* otherwise get a free pointer register */
6857       aop = newAsmop (0);
6858       preg = getFreePtr (ic, &aop, FALSE);
6859       emitcode ("mov", "%s,%s",
6860                 preg->name,
6861                 aopGet (AOP (left), 0, FALSE, TRUE));
6862       rname = preg->name;
6863     }
6864   else
6865     rname = aopGet (AOP (left), 0, FALSE, FALSE);
6866
6867   aopOp (result, ic, FALSE);
6868
6869   /* if bitfield then unpack the bits */
6870   if (IS_BITVAR (retype))
6871     genUnpackBits (result, rname, PPOINTER);
6872   else
6873     {
6874       /* we have can just get the values */
6875       int size = AOP_SIZE (result);
6876       int offset = 0;
6877
6878       while (size--)
6879         {
6880
6881           emitcode ("movx", "a,@%s", rname);
6882           aopPut (AOP (result), "a", offset);
6883
6884           offset++;
6885
6886           if (size || pi)
6887             emitcode ("inc", "%s", rname);
6888         }
6889     }
6890
6891   /* now some housekeeping stuff */
6892   if (aop) /* we had to allocate for this iCode */
6893     {
6894       if (pi) aopPut ( AOP (left), rname, 0);
6895       freeAsmop (NULL, aop, ic, TRUE);
6896     }
6897   else
6898     {
6899       /* we did not allocate which means left
6900          already in a pointer register, then
6901          if size > 0 && this could be used again
6902          we have to point it back to where it
6903          belongs */
6904       if ((AOP_SIZE (result) > 1 &&
6905            !OP_SYMBOL (left)->remat &&
6906            (OP_SYMBOL (left)->liveTo > ic->seq ||
6907             ic->depth)) &&
6908           !pi)
6909         {
6910           int size = AOP_SIZE (result) - 1;
6911           while (size--)
6912             emitcode ("dec", "%s", rname);
6913         }
6914     }
6915
6916   /* done */
6917   freeAsmop (left, NULL, ic, TRUE);
6918   freeAsmop (result, NULL, ic, TRUE);
6919   if (pi) pi->generated = 1;
6920
6921 }
6922
6923 /*-----------------------------------------------------------------*/
6924 /* genFarPointerGet - gget value from far space                    */
6925 /*-----------------------------------------------------------------*/
6926 static void
6927 genFarPointerGet (operand * left,
6928                   operand * result, iCode * ic, iCode * pi)
6929 {
6930   int size, offset;
6931   sym_link *retype = getSpec (operandType (result));
6932
6933   aopOp (left, ic, FALSE);
6934
6935   /* if the operand is already in dptr
6936      then we do nothing else we move the value to dptr */
6937   if (AOP_TYPE (left) != AOP_STR)
6938     {
6939       /* if this is remateriazable */
6940       if (AOP_TYPE (left) == AOP_IMMD)
6941         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6942       else
6943         {                       /* we need to get it byte by byte */
6944           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6945           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
6946         }
6947     }
6948   /* so dptr know contains the address */
6949   aopOp (result, ic, FALSE);
6950
6951   /* if bit then unpack */
6952   if (IS_BITVAR (retype))
6953     genUnpackBits (result, "dptr", FPOINTER);
6954   else
6955     {
6956       size = AOP_SIZE (result);
6957       offset = 0;
6958
6959       while (size--)
6960         {
6961           emitcode ("movx", "a,@dptr");
6962           aopPut (AOP (result), "a", offset++);
6963           if (size || pi)
6964             emitcode ("inc", "dptr");
6965         }
6966     }
6967   
6968   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
6969     aopPut ( AOP (left), "dpl", 0);
6970     aopPut ( AOP (left), "dph", 1);
6971     pi->generated = 1;
6972   }
6973   freeAsmop (left, NULL, ic, TRUE);
6974   freeAsmop (result, NULL, ic, TRUE);
6975 }
6976
6977 /*-----------------------------------------------------------------*/
6978 /* genCodePointerGet - gget value from code space                  */
6979 /*-----------------------------------------------------------------*/
6980 static void
6981 genCodePointerGet (operand * left,
6982                     operand * result, iCode * ic, iCode *pi)
6983 {
6984   int size, offset;
6985   sym_link *retype = getSpec (operandType (result));
6986
6987   aopOp (left, ic, FALSE);
6988
6989   /* if the operand is already in dptr
6990      then we do nothing else we move the value to dptr */
6991   if (AOP_TYPE (left) != AOP_STR)
6992     {
6993       /* if this is remateriazable */
6994       if (AOP_TYPE (left) == AOP_IMMD)
6995         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
6996       else
6997         {                       /* we need to get it byte by byte */
6998           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
6999           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7000         }
7001     }
7002   /* so dptr know contains the address */
7003   aopOp (result, ic, FALSE);
7004
7005   /* if bit then unpack */
7006   if (IS_BITVAR (retype))
7007     genUnpackBits (result, "dptr", CPOINTER);
7008   else
7009     {
7010       size = AOP_SIZE (result);
7011       offset = 0;
7012
7013       while (size--)
7014         {
7015           emitcode ("clr", "a");
7016           emitcode ("movc", "a,@a+dptr");
7017           aopPut (AOP (result), "a", offset++);
7018           if (size || pi)
7019             emitcode ("inc", "dptr");
7020         }
7021     }
7022
7023   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7024     aopPut ( AOP (left), "dpl", 0);
7025     aopPut ( AOP (left), "dph", 1);
7026     pi->generated = 1;
7027   }
7028   freeAsmop (left, NULL, ic, TRUE);
7029   freeAsmop (result, NULL, ic, TRUE);
7030 }
7031
7032 /*-----------------------------------------------------------------*/
7033 /* genGenPointerGet - gget value from generic pointer space        */
7034 /*-----------------------------------------------------------------*/
7035 static void
7036 genGenPointerGet (operand * left,
7037                   operand * result, iCode * ic, iCode *pi)
7038 {
7039   int size, offset;
7040   sym_link *retype = getSpec (operandType (result));
7041
7042   aopOp (left, ic, FALSE);
7043
7044   /* if the operand is already in dptr
7045      then we do nothing else we move the value to dptr */
7046   if (AOP_TYPE (left) != AOP_STR)
7047     {
7048       /* if this is remateriazable */
7049       if (AOP_TYPE (left) == AOP_IMMD)
7050         {
7051           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7052           emitcode ("mov", "b,#%d", pointerCode (retype));
7053         }
7054       else
7055         {                       /* we need to get it byte by byte */
7056           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7057           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7058           emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7059         }
7060     }
7061   /* so dptr know contains the address */
7062   aopOp (result, ic, FALSE);
7063
7064   /* if bit then unpack */
7065   if (IS_BITVAR (retype))
7066     genUnpackBits (result, "dptr", GPOINTER);
7067   else
7068     {
7069       size = AOP_SIZE (result);
7070       offset = 0;
7071
7072       while (size--)
7073         {
7074           emitcode ("lcall", "__gptrget");
7075           aopPut (AOP (result), "a", offset++);
7076           if (size || pi)
7077             emitcode ("inc", "dptr");
7078         }
7079     }
7080
7081   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7082     aopPut ( AOP (left), "dpl", 0);
7083     aopPut ( AOP (left), "dph", 1);
7084     pi->generated = 1;
7085   }
7086   freeAsmop (left, NULL, ic, TRUE);
7087   freeAsmop (result, NULL, ic, TRUE);
7088 }
7089
7090 /*-----------------------------------------------------------------*/
7091 /* genPointerGet - generate code for pointer get                   */
7092 /*-----------------------------------------------------------------*/
7093 static void
7094 genPointerGet (iCode * ic, iCode *pi)
7095 {
7096   operand *left, *result;
7097   sym_link *type, *etype;
7098   int p_type;
7099
7100   left = IC_LEFT (ic);
7101   result = IC_RESULT (ic);
7102
7103   /* depending on the type of pointer we need to
7104      move it to the correct pointer register */
7105   type = operandType (left);
7106   etype = getSpec (type);
7107   /* if left is of type of pointer then it is simple */
7108   if (IS_PTR (type) && !IS_FUNC (type->next))
7109     p_type = DCL_TYPE (type);
7110   else
7111     {
7112       /* we have to go by the storage class */
7113       p_type = PTR_TYPE (SPEC_OCLS (etype));
7114     }
7115
7116   /* now that we have the pointer type we assign
7117      the pointer values */
7118   switch (p_type)
7119     {
7120
7121     case POINTER:
7122     case IPOINTER:
7123       genNearPointerGet (left, result, ic, pi);
7124       break;
7125
7126     case PPOINTER:
7127       genPagedPointerGet (left, result, ic, pi);
7128       break;
7129
7130     case FPOINTER:
7131       genFarPointerGet (left, result, ic, pi);
7132       break;
7133
7134     case CPOINTER:
7135       genCodePointerGet (left, result, ic, pi);
7136       break;
7137
7138     case GPOINTER:
7139       genGenPointerGet (left, result, ic, pi);
7140       break;
7141     }
7142
7143 }
7144
7145 /*-----------------------------------------------------------------*/
7146 /* genPackBits - generates code for packed bit storage             */
7147 /*-----------------------------------------------------------------*/
7148 static void
7149 genPackBits (sym_link * etype,
7150              operand * right,
7151              char *rname, int p_type)
7152 {
7153   int shCount = 0;
7154   int offset = 0;
7155   int rLen = 0;
7156   int blen, bstr;
7157   char *l;
7158
7159   blen = SPEC_BLEN (etype);
7160   bstr = SPEC_BSTR (etype);
7161
7162   l = aopGet (AOP (right), offset++, FALSE, FALSE);
7163   MOVA (l);
7164
7165   /* if the bit lenth is less than or    */
7166   /* it exactly fits a byte then         */
7167   if (SPEC_BLEN (etype) <= 8)
7168     {
7169       shCount = SPEC_BSTR (etype);
7170
7171       /* shift left acc */
7172       AccLsh (shCount);
7173
7174       if (SPEC_BLEN (etype) < 8)
7175         {                       /* if smaller than a byte */
7176
7177
7178           switch (p_type)
7179             {
7180             case POINTER:
7181               emitcode ("mov", "b,a");
7182               emitcode ("mov", "a,@%s", rname);
7183               break;
7184
7185             case FPOINTER:
7186               emitcode ("mov", "b,a");
7187               emitcode ("movx", "a,@dptr");
7188               break;
7189
7190             case GPOINTER:
7191               emitcode ("push", "b");
7192               emitcode ("push", "acc");
7193               emitcode ("lcall", "__gptrget");
7194               emitcode ("pop", "b");
7195               break;
7196             }
7197
7198           emitcode ("anl", "a,#0x%02x", (unsigned char)
7199                     ((unsigned char) (0xFF << (blen + bstr)) |
7200                      (unsigned char) (0xFF >> (8 - bstr))));
7201           emitcode ("orl", "a,b");
7202           if (p_type == GPOINTER)
7203             emitcode ("pop", "b");
7204         }
7205     }
7206
7207   switch (p_type)
7208     {
7209     case POINTER:
7210       emitcode ("mov", "@%s,a", rname);
7211       break;
7212
7213     case FPOINTER:
7214       emitcode ("movx", "@dptr,a");
7215       break;
7216
7217     case GPOINTER:
7218       emitcode ("lcall", "__gptrput");
7219       break;
7220     }
7221
7222   /* if we r done */
7223   if (SPEC_BLEN (etype) <= 8)
7224     return;
7225
7226   emitcode ("inc", "%s", rname);
7227   rLen = SPEC_BLEN (etype);
7228
7229   /* now generate for lengths greater than one byte */
7230   while (1)
7231     {
7232
7233       l = aopGet (AOP (right), offset++, FALSE, TRUE);
7234
7235       rLen -= 8;
7236       if (rLen < 8)
7237         break;
7238
7239       switch (p_type)
7240         {
7241         case POINTER:
7242           if (*l == '@')
7243             {
7244               MOVA (l);
7245               emitcode ("mov", "@%s,a", rname);
7246             }
7247           else
7248             emitcode ("mov", "@%s,%s", rname, l);
7249           break;
7250
7251         case FPOINTER:
7252           MOVA (l);
7253           emitcode ("movx", "@dptr,a");
7254           break;
7255
7256         case GPOINTER:
7257           MOVA (l);
7258           emitcode ("lcall", "__gptrput");
7259           break;
7260         }
7261       emitcode ("inc", "%s", rname);
7262     }
7263
7264   MOVA (l);
7265
7266   /* last last was not complete */
7267   if (rLen)
7268     {
7269       /* save the byte & read byte */
7270       switch (p_type)
7271         {
7272         case POINTER:
7273           emitcode ("mov", "b,a");
7274           emitcode ("mov", "a,@%s", rname);
7275           break;
7276
7277         case FPOINTER:
7278           emitcode ("mov", "b,a");
7279           emitcode ("movx", "a,@dptr");
7280           break;
7281
7282         case GPOINTER:
7283           emitcode ("push", "b");
7284           emitcode ("push", "acc");
7285           emitcode ("lcall", "__gptrget");
7286           emitcode ("pop", "b");
7287           break;
7288         }
7289
7290       emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7291       emitcode ("orl", "a,b");
7292     }
7293
7294   if (p_type == GPOINTER)
7295     emitcode ("pop", "b");
7296
7297   switch (p_type)
7298     {
7299
7300     case POINTER:
7301       emitcode ("mov", "@%s,a", rname);
7302       break;
7303
7304     case FPOINTER:
7305       emitcode ("movx", "@dptr,a");
7306       break;
7307
7308     case GPOINTER:
7309       emitcode ("lcall", "__gptrput");
7310       break;
7311     }
7312 }
7313 /*-----------------------------------------------------------------*/
7314 /* genDataPointerSet - remat pointer to data space                 */
7315 /*-----------------------------------------------------------------*/
7316 static void
7317 genDataPointerSet (operand * right,
7318                    operand * result,
7319                    iCode * ic)
7320 {
7321   int size, offset = 0;
7322   char *l, buffer[256];
7323
7324   aopOp (right, ic, FALSE);
7325
7326   l = aopGet (AOP (result), 0, FALSE, TRUE);
7327   size = AOP_SIZE (right);
7328   while (size--)
7329     {
7330       if (offset)
7331         sprintf (buffer, "(%s + %d)", l + 1, offset);
7332       else
7333         sprintf (buffer, "%s", l + 1);
7334       emitcode ("mov", "%s,%s", buffer,
7335                 aopGet (AOP (right), offset++, FALSE, FALSE));
7336     }
7337
7338   freeAsmop (right, NULL, ic, TRUE);
7339   freeAsmop (result, NULL, ic, TRUE);
7340 }
7341
7342 /*-----------------------------------------------------------------*/
7343 /* genNearPointerSet - emitcode for near pointer put                */
7344 /*-----------------------------------------------------------------*/
7345 static void
7346 genNearPointerSet (operand * right,
7347                    operand * result,
7348                    iCode * ic,
7349                    iCode * pi)
7350 {
7351   asmop *aop = NULL;
7352   regs *preg = NULL;
7353   char *rname, *l;
7354   sym_link *retype, *letype;
7355   sym_link *ptype = operandType (result);
7356
7357   retype = getSpec (operandType (right));
7358   letype = getSpec (ptype);
7359   aopOp (result, ic, FALSE);
7360
7361   /* if the result is rematerializable &
7362      in data space & not a bit variable */
7363   if (AOP_TYPE (result) == AOP_IMMD &&
7364       DCL_TYPE (ptype) == POINTER &&
7365       !IS_BITVAR (retype) &&
7366       !IS_BITVAR (letype))
7367     {
7368       genDataPointerSet (right, result, ic);
7369       return;
7370     }
7371
7372   /* if the value is already in a pointer register
7373      then don't need anything more */
7374   if (!AOP_INPREG (AOP (result)))
7375     {
7376       /* otherwise get a free pointer register */
7377       aop = newAsmop (0);
7378       preg = getFreePtr (ic, &aop, FALSE);
7379       emitcode ("mov", "%s,%s",
7380                 preg->name,
7381                 aopGet (AOP (result), 0, FALSE, TRUE));
7382       rname = preg->name;
7383     }
7384   else
7385     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7386
7387   aopOp (right, ic, FALSE);
7388
7389   /* if bitfield then unpack the bits */
7390   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7391     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7392   else
7393     {
7394       /* we have can just get the values */
7395       int size = AOP_SIZE (right);
7396       int offset = 0;
7397
7398       while (size--)
7399         {
7400           l = aopGet (AOP (right), offset, FALSE, TRUE);
7401           if (*l == '@')
7402             {
7403               MOVA (l);
7404               emitcode ("mov", "@%s,a", rname);
7405             }
7406           else
7407             emitcode ("mov", "@%s,%s", rname, l);
7408           if (size || pi)
7409             emitcode ("inc", "%s", rname);
7410           offset++;
7411         }
7412     }
7413
7414   /* now some housekeeping stuff */
7415   if (aop) /* we had to allocate for this iCode */
7416     {
7417       if (pi) aopPut (AOP (result),rname,0);
7418       freeAsmop (NULL, aop, ic, TRUE);
7419     }
7420   else
7421     {
7422       /* we did not allocate which means left
7423          already in a pointer register, then
7424          if size > 0 && this could be used again
7425          we have to point it back to where it
7426          belongs */
7427       if ((AOP_SIZE (right) > 1 &&
7428            !OP_SYMBOL (result)->remat &&
7429            (OP_SYMBOL (result)->liveTo > ic->seq ||
7430             ic->depth)) &&
7431           !pi)
7432         {
7433           int size = AOP_SIZE (right) - 1;
7434           while (size--)
7435             emitcode ("dec", "%s", rname);
7436         }
7437     }
7438
7439   /* done */
7440   if (pi) pi->generated = 1;
7441   freeAsmop (result, NULL, ic, TRUE);
7442   freeAsmop (right, NULL, ic, TRUE);
7443 }
7444
7445 /*-----------------------------------------------------------------*/
7446 /* genPagedPointerSet - emitcode for Paged pointer put             */
7447 /*-----------------------------------------------------------------*/
7448 static void
7449 genPagedPointerSet (operand * right,
7450                     operand * result,
7451                     iCode * ic,
7452                     iCode * pi)
7453 {
7454   asmop *aop = NULL;
7455   regs *preg = NULL;
7456   char *rname, *l;
7457   sym_link *retype, *letype;
7458
7459   retype = getSpec (operandType (right));
7460   letype = getSpec (operandType (result));
7461
7462   aopOp (result, ic, FALSE);
7463
7464   /* if the value is already in a pointer register
7465      then don't need anything more */
7466   if (!AOP_INPREG (AOP (result)))
7467     {
7468       /* otherwise get a free pointer register */
7469       aop = newAsmop (0);
7470       preg = getFreePtr (ic, &aop, FALSE);
7471       emitcode ("mov", "%s,%s",
7472                 preg->name,
7473                 aopGet (AOP (result), 0, FALSE, TRUE));
7474       rname = preg->name;
7475     }
7476   else
7477     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7478
7479   aopOp (right, ic, FALSE);
7480
7481   /* if bitfield then unpack the bits */
7482   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7483     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7484   else
7485     {
7486       /* we have can just get the values */
7487       int size = AOP_SIZE (right);
7488       int offset = 0;
7489
7490       while (size--)
7491         {
7492           l = aopGet (AOP (right), offset, FALSE, TRUE);
7493
7494           MOVA (l);
7495           emitcode ("movx", "@%s,a", rname);
7496
7497           if (size || pi)
7498             emitcode ("inc", "%s", rname);
7499
7500           offset++;
7501         }
7502     }
7503
7504   /* now some housekeeping stuff */
7505   if (aop) /* we had to allocate for this iCode */
7506     {
7507       if (pi) aopPut (AOP (result),rname,0);
7508       freeAsmop (NULL, aop, ic, TRUE);
7509     }
7510   else
7511     {
7512       /* we did not allocate which means left
7513          already in a pointer register, then
7514          if size > 0 && this could be used again
7515          we have to point it back to where it
7516          belongs */
7517       if (AOP_SIZE (right) > 1 &&
7518           !OP_SYMBOL (result)->remat &&
7519           (OP_SYMBOL (result)->liveTo > ic->seq ||
7520            ic->depth))
7521         {
7522           int size = AOP_SIZE (right) - 1;
7523           while (size--)
7524             emitcode ("dec", "%s", rname);
7525         }
7526     }
7527
7528   /* done */
7529   if (pi) pi->generated = 1;
7530   freeAsmop (result, NULL, ic, TRUE);
7531   freeAsmop (right, NULL, ic, TRUE);
7532
7533
7534 }
7535
7536 /*-----------------------------------------------------------------*/
7537 /* genFarPointerSet - set value from far space                     */
7538 /*-----------------------------------------------------------------*/
7539 static void
7540 genFarPointerSet (operand * right,
7541                   operand * result, iCode * ic, iCode * pi)
7542 {
7543   int size, offset;
7544   sym_link *retype = getSpec (operandType (right));
7545   sym_link *letype = getSpec (operandType (result));
7546   aopOp (result, ic, FALSE);
7547
7548   /* if the operand is already in dptr
7549      then we do nothing else we move the value to dptr */
7550   if (AOP_TYPE (result) != AOP_STR)
7551     {
7552       /* if this is remateriazable */
7553       if (AOP_TYPE (result) == AOP_IMMD)
7554         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7555       else
7556         {                       /* we need to get it byte by byte */
7557           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7558           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7559         }
7560     }
7561   /* so dptr know contains the address */
7562   aopOp (right, ic, FALSE);
7563
7564   /* if bit then unpack */
7565   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7566     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7567   else
7568     {
7569       size = AOP_SIZE (right);
7570       offset = 0;
7571
7572       while (size--)
7573         {
7574           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7575           MOVA (l);
7576           emitcode ("movx", "@dptr,a");
7577           if (size || pi)
7578             emitcode ("inc", "dptr");
7579         }
7580     }
7581   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7582     aopPut (AOP(result),"dpl",0);
7583     aopPut (AOP(result),"dph",1);
7584     pi->generated=1;
7585   }
7586   freeAsmop (result, NULL, ic, TRUE);
7587   freeAsmop (right, NULL, ic, TRUE);
7588 }
7589
7590 /*-----------------------------------------------------------------*/
7591 /* genGenPointerSet - set value from generic pointer space         */
7592 /*-----------------------------------------------------------------*/
7593 static void
7594 genGenPointerSet (operand * right,
7595                   operand * result, iCode * ic, iCode * pi)
7596 {
7597   int size, offset;
7598   sym_link *retype = getSpec (operandType (right));
7599   sym_link *letype = getSpec (operandType (result));
7600
7601   aopOp (result, ic, FALSE);
7602
7603   /* if the operand is already in dptr
7604      then we do nothing else we move the value to dptr */
7605   if (AOP_TYPE (result) != AOP_STR)
7606     {
7607       /* if this is remateriazable */
7608       if (AOP_TYPE (result) == AOP_IMMD)
7609         {
7610           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7611           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7612         }
7613       else
7614         {                       /* we need to get it byte by byte */
7615           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7616           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7617           emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7618         }
7619     }
7620   /* so dptr know contains the address */
7621   aopOp (right, ic, FALSE);
7622
7623   /* if bit then unpack */
7624   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7625     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7626   else
7627     {
7628       size = AOP_SIZE (right);
7629       offset = 0;
7630
7631       while (size--)
7632         {
7633           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7634           MOVA (l);
7635           emitcode ("lcall", "__gptrput");
7636           if (size || pi)
7637             emitcode ("inc", "dptr");
7638         }
7639     }
7640
7641   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7642     aopPut (AOP(result),"dpl",0);
7643     aopPut (AOP(result),"dph",1);
7644     pi->generated=1;
7645   }
7646   freeAsmop (result, NULL, ic, TRUE);
7647   freeAsmop (right, NULL, ic, TRUE);
7648 }
7649
7650 /*-----------------------------------------------------------------*/
7651 /* genPointerSet - stores the value into a pointer location        */
7652 /*-----------------------------------------------------------------*/
7653 static void
7654 genPointerSet (iCode * ic, iCode *pi)
7655 {
7656   operand *right, *result;
7657   sym_link *type, *etype;
7658   int p_type;
7659
7660   right = IC_RIGHT (ic);
7661   result = IC_RESULT (ic);
7662
7663   /* depending on the type of pointer we need to
7664      move it to the correct pointer register */
7665   type = operandType (result);
7666   etype = getSpec (type);
7667   /* if left is of type of pointer then it is simple */
7668   if (IS_PTR (type) && !IS_FUNC (type->next))
7669     {
7670       p_type = DCL_TYPE (type);
7671     }
7672   else
7673     {
7674       /* we have to go by the storage class */
7675       p_type = PTR_TYPE (SPEC_OCLS (etype));
7676     }
7677
7678   /* now that we have the pointer type we assign
7679      the pointer values */
7680   switch (p_type)
7681     {
7682
7683     case POINTER:
7684     case IPOINTER:
7685       genNearPointerSet (right, result, ic, pi);
7686       break;
7687
7688     case PPOINTER:
7689       genPagedPointerSet (right, result, ic, pi);
7690       break;
7691
7692     case FPOINTER:
7693       genFarPointerSet (right, result, ic, pi);
7694       break;
7695
7696     case GPOINTER:
7697       genGenPointerSet (right, result, ic, pi);
7698       break;
7699     }
7700
7701 }
7702
7703 /*-----------------------------------------------------------------*/
7704 /* genIfx - generate code for Ifx statement                        */
7705 /*-----------------------------------------------------------------*/
7706 static void
7707 genIfx (iCode * ic, iCode * popIc)
7708 {
7709   operand *cond = IC_COND (ic);
7710   int isbit = 0;
7711
7712   aopOp (cond, ic, FALSE);
7713
7714   /* get the value into acc */
7715   if (AOP_TYPE (cond) != AOP_CRY)
7716     toBoolean (cond);
7717   else
7718     isbit = 1;
7719   /* the result is now in the accumulator */
7720   freeAsmop (cond, NULL, ic, TRUE);
7721
7722   /* if there was something to be popped then do it */
7723   if (popIc)
7724     genIpop (popIc);
7725
7726   /* if the condition is  a bit variable */
7727   if (isbit && IS_ITEMP (cond) &&
7728       SPIL_LOC (cond))
7729     genIfxJump (ic, SPIL_LOC (cond)->rname);
7730   else if (isbit && !IS_ITEMP (cond))
7731     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7732   else
7733     genIfxJump (ic, "a");
7734
7735   ic->generated = 1;
7736 }
7737
7738 /*-----------------------------------------------------------------*/
7739 /* genAddrOf - generates code for address of                       */
7740 /*-----------------------------------------------------------------*/
7741 static void
7742 genAddrOf (iCode * ic)
7743 {
7744   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7745   int size, offset;
7746
7747   aopOp (IC_RESULT (ic), ic, FALSE);
7748
7749   /* if the operand is on the stack then we
7750      need to get the stack offset of this
7751      variable */
7752   if (sym->onStack)
7753     {
7754       /* if it has an offset then we need to compute
7755          it */
7756       if (sym->stack)
7757         {
7758           emitcode ("mov", "a,_bp");
7759           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7760           aopPut (AOP (IC_RESULT (ic)), "a", 0);
7761         }
7762       else
7763         {
7764           /* we can just move _bp */
7765           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7766         }
7767       /* fill the result with zero */
7768       size = AOP_SIZE (IC_RESULT (ic)) - 1;
7769
7770       offset = 1;
7771       while (size--)
7772         {
7773           aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7774         }
7775
7776       goto release;
7777     }
7778
7779   /* object not on stack then we need the name */
7780   size = AOP_SIZE (IC_RESULT (ic));
7781   offset = 0;
7782
7783   while (size--)
7784     {
7785       char s[SDCC_NAME_MAX];
7786       if (offset)
7787         sprintf (s, "#(%s >> %d)",
7788                  sym->rname,
7789                  offset * 8);
7790       else
7791         sprintf (s, "#%s", sym->rname);
7792       aopPut (AOP (IC_RESULT (ic)), s, offset++);
7793     }
7794
7795 release:
7796   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7797
7798 }
7799
7800 /*-----------------------------------------------------------------*/
7801 /* genFarFarAssign - assignment when both are in far space         */
7802 /*-----------------------------------------------------------------*/
7803 static void
7804 genFarFarAssign (operand * result, operand * right, iCode * ic)
7805 {
7806   int size = AOP_SIZE (right);
7807   int offset = 0;
7808   char *l;
7809   /* first push the right side on to the stack */
7810   while (size--)
7811     {
7812       l = aopGet (AOP (right), offset++, FALSE, FALSE);
7813       MOVA (l);
7814       emitcode ("push", "acc");
7815     }
7816
7817   freeAsmop (right, NULL, ic, FALSE);
7818   /* now assign DPTR to result */
7819   aopOp (result, ic, FALSE);
7820   size = AOP_SIZE (result);
7821   while (size--)
7822     {
7823       emitcode ("pop", "acc");
7824       aopPut (AOP (result), "a", --offset);
7825     }
7826   freeAsmop (result, NULL, ic, FALSE);
7827
7828 }
7829
7830 /*-----------------------------------------------------------------*/
7831 /* genAssign - generate code for assignment                        */
7832 /*-----------------------------------------------------------------*/
7833 static void
7834 genAssign (iCode * ic)
7835 {
7836   operand *result, *right;
7837   int size, offset;
7838   unsigned long lit = 0L;
7839
7840   result = IC_RESULT (ic);
7841   right = IC_RIGHT (ic);
7842
7843   /* if they are the same */
7844   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7845     return;
7846
7847   aopOp (right, ic, FALSE);
7848
7849   /* special case both in far space */
7850   if ((AOP_TYPE (right) == AOP_DPTR ||
7851        AOP_TYPE (right) == AOP_DPTR2) &&
7852       IS_TRUE_SYMOP (result) &&
7853       isOperandInFarSpace (result))
7854     {
7855
7856       genFarFarAssign (result, right, ic);
7857       return;
7858     }
7859
7860   aopOp (result, ic, TRUE);
7861
7862   /* if they are the same registers */
7863   if (sameRegs (AOP (right), AOP (result)))
7864     goto release;
7865
7866   /* if the result is a bit */
7867   if (AOP_TYPE (result) == AOP_CRY)
7868     {
7869
7870       /* if the right size is a literal then
7871          we know what the value is */
7872       if (AOP_TYPE (right) == AOP_LIT)
7873         {
7874           if (((int) operandLitValue (right)))
7875             aopPut (AOP (result), one, 0);
7876           else
7877             aopPut (AOP (result), zero, 0);
7878           goto release;
7879         }
7880
7881       /* the right is also a bit variable */
7882       if (AOP_TYPE (right) == AOP_CRY)
7883         {
7884           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7885           aopPut (AOP (result), "c", 0);
7886           goto release;
7887         }
7888
7889       /* we need to or */
7890       toBoolean (right);
7891       aopPut (AOP (result), "a", 0);
7892       goto release;
7893     }
7894
7895   /* bit variables done */
7896   /* general case */
7897   size = AOP_SIZE (result);
7898   offset = 0;
7899   if (AOP_TYPE (right) == AOP_LIT)
7900     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7901   if ((size > 1) &&
7902       (AOP_TYPE (result) != AOP_REG) &&
7903       (AOP_TYPE (right) == AOP_LIT) &&
7904       !IS_FLOAT (operandType (right)) &&
7905       (lit < 256L))
7906     {
7907       emitcode ("clr", "a");
7908       while (size--)
7909         {
7910           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
7911             aopPut (AOP (result), "a", size);
7912           else
7913             aopPut (AOP (result),
7914                     aopGet (AOP (right), size, FALSE, FALSE),
7915                     size);
7916         }
7917     }
7918   else
7919     {
7920       while (size--)
7921         {
7922           aopPut (AOP (result),
7923                   aopGet (AOP (right), offset, FALSE, FALSE),
7924                   offset);
7925           offset++;
7926         }
7927     }
7928
7929 release:
7930   freeAsmop (right, NULL, ic, TRUE);
7931   freeAsmop (result, NULL, ic, TRUE);
7932 }
7933
7934 /*-----------------------------------------------------------------*/
7935 /* genJumpTab - genrates code for jump table                       */
7936 /*-----------------------------------------------------------------*/
7937 static void
7938 genJumpTab (iCode * ic)
7939 {
7940   symbol *jtab;
7941   char *l;
7942
7943   aopOp (IC_JTCOND (ic), ic, FALSE);
7944   /* get the condition into accumulator */
7945   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
7946   MOVA (l);
7947   /* multiply by three */
7948   emitcode ("add", "a,acc");
7949   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
7950   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7951
7952   jtab = newiTempLabel (NULL);
7953   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
7954   emitcode ("jmp", "@a+dptr");
7955   emitcode ("", "%05d$:", jtab->key + 100);
7956   /* now generate the jump labels */
7957   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7958        jtab = setNextItem (IC_JTLABELS (ic)))
7959     emitcode ("ljmp", "%05d$", jtab->key + 100);
7960
7961 }
7962
7963 /*-----------------------------------------------------------------*/
7964 /* genCast - gen code for casting                                  */
7965 /*-----------------------------------------------------------------*/
7966 static void
7967 genCast (iCode * ic)
7968 {
7969   operand *result = IC_RESULT (ic);
7970   sym_link *ctype = operandType (IC_LEFT (ic));
7971   sym_link *rtype = operandType (IC_RIGHT (ic));
7972   operand *right = IC_RIGHT (ic);
7973   int size, offset;
7974
7975   /* if they are equivalent then do nothing */
7976   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7977     return;
7978
7979   aopOp (right, ic, FALSE);
7980   aopOp (result, ic, FALSE);
7981
7982   /* if the result is a bit */
7983   if (AOP_TYPE (result) == AOP_CRY)
7984     {
7985       /* if the right size is a literal then
7986          we know what the value is */
7987       if (AOP_TYPE (right) == AOP_LIT)
7988         {
7989           if (((int) operandLitValue (right)))
7990             aopPut (AOP (result), one, 0);
7991           else
7992             aopPut (AOP (result), zero, 0);
7993
7994           goto release;
7995         }
7996
7997       /* the right is also a bit variable */
7998       if (AOP_TYPE (right) == AOP_CRY)
7999         {
8000           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8001           aopPut (AOP (result), "c", 0);
8002           goto release;
8003         }
8004
8005       /* we need to or */
8006       toBoolean (right);
8007       aopPut (AOP (result), "a", 0);
8008       goto release;
8009     }
8010
8011   /* if they are the same size : or less */
8012   if (AOP_SIZE (result) <= AOP_SIZE (right))
8013     {
8014
8015       /* if they are in the same place */
8016       if (sameRegs (AOP (right), AOP (result)))
8017         goto release;
8018
8019       /* if they in different places then copy */
8020       size = AOP_SIZE (result);
8021       offset = 0;
8022       while (size--)
8023         {
8024           aopPut (AOP (result),
8025                   aopGet (AOP (right), offset, FALSE, FALSE),
8026                   offset);
8027           offset++;
8028         }
8029       goto release;
8030     }
8031
8032
8033   /* if the result is of type pointer */
8034   if (IS_PTR (ctype))
8035     {
8036
8037       int p_type;
8038       sym_link *type = operandType (right);
8039       sym_link *etype = getSpec (type);
8040
8041       /* pointer to generic pointer */
8042       if (IS_GENPTR (ctype))
8043         {
8044           char *l = zero;
8045
8046           if (IS_PTR (type))
8047             p_type = DCL_TYPE (type);
8048           else
8049             {
8050               /* we have to go by the storage class */
8051               p_type = PTR_TYPE (SPEC_OCLS (etype));
8052             }
8053
8054           /* the first two bytes are known */
8055           size = GPTRSIZE - 1;
8056           offset = 0;
8057           while (size--)
8058             {
8059               aopPut (AOP (result),
8060                       aopGet (AOP (right), offset, FALSE, FALSE),
8061                       offset);
8062               offset++;
8063             }
8064           /* the last byte depending on type */
8065           switch (p_type)
8066             {
8067             case IPOINTER:
8068             case POINTER:
8069               l = zero;
8070               break;
8071             case FPOINTER:
8072               l = one;
8073               break;
8074             case CPOINTER:
8075               l = "#0x02";
8076               break;
8077             case PPOINTER:
8078               l = "#0x03";
8079               break;
8080
8081             default:
8082               /* this should never happen */
8083               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8084                       "got unknown pointer type");
8085               exit (1);
8086             }
8087           aopPut (AOP (result), l, GPTRSIZE - 1);
8088           goto release;
8089         }
8090
8091       /* just copy the pointers */
8092       size = AOP_SIZE (result);
8093       offset = 0;
8094       while (size--)
8095         {
8096           aopPut (AOP (result),
8097                   aopGet (AOP (right), offset, FALSE, FALSE),
8098                   offset);
8099           offset++;
8100         }
8101       goto release;
8102     }
8103
8104   /* so we now know that the size of destination is greater
8105      than the size of the source */
8106   /* we move to result for the size of source */
8107   size = AOP_SIZE (right);
8108   offset = 0;
8109   while (size--)
8110     {
8111       aopPut (AOP (result),
8112               aopGet (AOP (right), offset, FALSE, FALSE),
8113               offset);
8114       offset++;
8115     }
8116
8117   /* now depending on the sign of the source && destination */
8118   size = AOP_SIZE (result) - AOP_SIZE (right);
8119   /* if unsigned or not an integral type */
8120   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8121     {
8122       while (size--)
8123         aopPut (AOP (result), zero, offset++);
8124     }
8125   else
8126     {
8127       /* we need to extend the sign :{ */
8128       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8129                         FALSE, FALSE);
8130       MOVA (l);
8131       emitcode ("rlc", "a");
8132       emitcode ("subb", "a,acc");
8133       while (size--)
8134         aopPut (AOP (result), "a", offset++);
8135     }
8136
8137   /* we are done hurray !!!! */
8138
8139 release:
8140   freeAsmop (right, NULL, ic, TRUE);
8141   freeAsmop (result, NULL, ic, TRUE);
8142
8143 }
8144
8145 /*-----------------------------------------------------------------*/
8146 /* genDjnz - generate decrement & jump if not zero instrucion      */
8147 /*-----------------------------------------------------------------*/
8148 static int
8149 genDjnz (iCode * ic, iCode * ifx)
8150 {
8151   symbol *lbl, *lbl1;
8152   if (!ifx)
8153     return 0;
8154
8155   /* if the if condition has a false label
8156      then we cannot save */
8157   if (IC_FALSE (ifx))
8158     return 0;
8159
8160   /* if the minus is not of the form
8161      a = a - 1 */
8162   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8163       !IS_OP_LITERAL (IC_RIGHT (ic)))
8164     return 0;
8165
8166   if (operandLitValue (IC_RIGHT (ic)) != 1)
8167     return 0;
8168
8169   /* if the size of this greater than one then no
8170      saving */
8171   if (getSize (operandType (IC_RESULT (ic))) > 1)
8172     return 0;
8173
8174   /* otherwise we can save BIG */
8175   lbl = newiTempLabel (NULL);
8176   lbl1 = newiTempLabel (NULL);
8177
8178   aopOp (IC_RESULT (ic), ic, FALSE);
8179
8180   if (IS_AOP_PREG (IC_RESULT (ic)))
8181     {
8182       emitcode ("dec", "%s",
8183                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8184       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8185       emitcode ("jnz", "%05d$", lbl->key + 100);
8186     }
8187   else
8188     {
8189       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8190                 lbl->key + 100);
8191     }
8192   emitcode ("sjmp", "%05d$", lbl1->key + 100);
8193   emitcode ("", "%05d$:", lbl->key + 100);
8194   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8195   emitcode ("", "%05d$:", lbl1->key + 100);
8196
8197   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8198   ifx->generated = 1;
8199   return 1;
8200 }
8201
8202 /*-----------------------------------------------------------------*/
8203 /* genReceive - generate code for a receive iCode                  */
8204 /*-----------------------------------------------------------------*/
8205 static void
8206 genReceive (iCode * ic)
8207 {
8208   if (isOperandInFarSpace (IC_RESULT (ic)) &&
8209       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8210        IS_TRUE_SYMOP (IC_RESULT (ic))))
8211     {
8212
8213       int size = getSize (operandType (IC_RESULT (ic)));
8214       int offset = fReturnSizeMCS51 - size;
8215       while (size--)
8216         {
8217           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8218                                 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8219           offset++;
8220         }
8221       aopOp (IC_RESULT (ic), ic, FALSE);
8222       size = AOP_SIZE (IC_RESULT (ic));
8223       offset = 0;
8224       while (size--)
8225         {
8226           emitcode ("pop", "acc");
8227           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8228         }
8229
8230     }
8231   else
8232     {
8233       _G.accInUse++;
8234       aopOp (IC_RESULT (ic), ic, FALSE);
8235       _G.accInUse--;
8236       assignResultValue (IC_RESULT (ic));
8237     }
8238
8239   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8240 }
8241
8242 /*-----------------------------------------------------------------*/
8243 /* gen51Code - generate code for 8051 based controllers            */
8244 /*-----------------------------------------------------------------*/
8245 void
8246 gen51Code (iCode * lic)
8247 {
8248   iCode *ic;
8249   int cln = 0;
8250
8251   lineHead = lineCurr = NULL;
8252
8253   /* print the allocation information */
8254   if (allocInfo)
8255     printAllocInfo (currFunc, codeOutFile);
8256   /* if debug information required */
8257 /*     if (options.debug && currFunc) { */
8258   if (currFunc)
8259     {
8260       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8261       _G.debugLine = 1;
8262       if (IS_STATIC (currFunc->etype))
8263         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8264       else
8265         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8266       _G.debugLine = 0;
8267     }
8268   /* stack pointer name */
8269   if (options.useXstack)
8270     spname = "_spx";
8271   else
8272     spname = "sp";
8273
8274
8275   for (ic = lic; ic; ic = ic->next)
8276     {
8277
8278       if (cln != ic->lineno)
8279         {
8280           if (options.debug)
8281             {
8282               _G.debugLine = 1;
8283               emitcode ("", "C$%s$%d$%d$%d ==.",
8284                         FileBaseName (ic->filename), ic->lineno,
8285                         ic->level, ic->block);
8286               _G.debugLine = 0;
8287             }
8288           emitcode (";", "%s %d", ic->filename, ic->lineno);
8289           cln = ic->lineno;
8290         }
8291       /* if the result is marked as
8292          spilt and rematerializable or code for
8293          this has already been generated then
8294          do nothing */
8295       if (resultRemat (ic) || ic->generated)
8296         continue;
8297
8298       /* depending on the operation */
8299       switch (ic->op)
8300         {
8301         case '!':
8302           genNot (ic);
8303           break;
8304
8305         case '~':
8306           genCpl (ic);
8307           break;
8308
8309         case UNARYMINUS:
8310           genUminus (ic);
8311           break;
8312
8313         case IPUSH:
8314           genIpush (ic);
8315           break;
8316
8317         case IPOP:
8318           /* IPOP happens only when trying to restore a
8319              spilt live range, if there is an ifx statement
8320              following this pop then the if statement might
8321              be using some of the registers being popped which
8322              would destory the contents of the register so
8323              we need to check for this condition and handle it */
8324           if (ic->next &&
8325               ic->next->op == IFX &&
8326               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8327             genIfx (ic->next, ic);
8328           else
8329             genIpop (ic);
8330           break;
8331
8332         case CALL:
8333           genCall (ic);
8334           break;
8335
8336         case PCALL:
8337           genPcall (ic);
8338           break;
8339
8340         case FUNCTION:
8341           genFunction (ic);
8342           break;
8343
8344         case ENDFUNCTION:
8345           genEndFunction (ic);
8346           break;
8347
8348         case RETURN:
8349           genRet (ic);
8350           break;
8351
8352         case LABEL:
8353           genLabel (ic);
8354           break;
8355
8356         case GOTO:
8357           genGoto (ic);
8358           break;
8359
8360         case '+':
8361           genPlus (ic);
8362           break;
8363
8364         case '-':
8365           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8366             genMinus (ic);
8367           break;
8368
8369         case '*':
8370           genMult (ic);
8371           break;
8372
8373         case '/':
8374           genDiv (ic);
8375           break;
8376
8377         case '%':
8378           genMod (ic);
8379           break;
8380
8381         case '>':
8382           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8383           break;
8384
8385         case '<':
8386           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8387           break;
8388
8389         case LE_OP:
8390         case GE_OP:
8391         case NE_OP:
8392
8393           /* note these two are xlated by algebraic equivalence
8394              during parsing SDCC.y */
8395           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8396                   "got '>=' or '<=' shouldn't have come here");
8397           break;
8398
8399         case EQ_OP:
8400           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8401           break;
8402
8403         case AND_OP:
8404           genAndOp (ic);
8405           break;
8406
8407         case OR_OP:
8408           genOrOp (ic);
8409           break;
8410
8411         case '^':
8412           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8413           break;
8414
8415         case '|':
8416           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8417           break;
8418
8419         case BITWISEAND:
8420           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8421           break;
8422
8423         case INLINEASM:
8424           genInline (ic);
8425           break;
8426
8427         case RRC:
8428           genRRC (ic);
8429           break;
8430
8431         case RLC:
8432           genRLC (ic);
8433           break;
8434
8435         case GETHBIT:
8436           genGetHbit (ic);
8437           break;
8438
8439         case LEFT_OP:
8440           genLeftShift (ic);
8441           break;
8442
8443         case RIGHT_OP:
8444           genRightShift (ic);
8445           break;
8446
8447         case GET_VALUE_AT_ADDRESS:
8448           genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8449           break;
8450
8451         case '=':
8452           if (POINTER_SET (ic))
8453             genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8454           else
8455             genAssign (ic);
8456           break;
8457
8458         case IFX:
8459           genIfx (ic, NULL);
8460           break;
8461
8462         case ADDRESS_OF:
8463           genAddrOf (ic);
8464           break;
8465
8466         case JUMPTABLE:
8467           genJumpTab (ic);
8468           break;
8469
8470         case CAST:
8471           genCast (ic);
8472           break;
8473
8474         case RECEIVE:
8475           genReceive (ic);
8476           break;
8477
8478         case SEND:
8479           addSet (&_G.sendSet, ic);
8480           break;
8481
8482         default:
8483           ic = ic;
8484         }
8485     }
8486
8487
8488   /* now we are ready to call the
8489      peep hole optimizer */
8490   if (!options.nopeep)
8491     peepHole (&lineHead);
8492
8493   /* now do the actual printing */
8494   printLine (lineHead, codeOutFile);
8495   return;
8496 }