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