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