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