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