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