* src/ds390/peeph.def: fix #123; add 14 rules by Fiorenzo D. Ramaglia <fd.ramaglia...
[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       return FALSE;
789     case AOP_DPTR:
790       return TRUE;
791     case AOP_IMMD:
792       return FALSE;
793     case AOP_DIR:
794       return FALSE;
795     case AOP_REG:
796       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
797       return FALSE;
798     case AOP_CRY:
799       return TRUE;
800     case AOP_ACC:
801       return TRUE;
802     case AOP_LIT:
803       return FALSE;
804     case AOP_STR:
805       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
806         return TRUE;
807       return FALSE;
808     default:
809       /* Error case --- will have been caught already */
810       wassert(0);
811       return FALSE;
812     }
813 }
814
815
816 /*-----------------------------------------------------------------*/
817 /* aopGet - for fetching value of the aop                          */
818 /*-----------------------------------------------------------------*/
819 static char *
820 aopGet (asmop * aop, int offset, bool bit16, bool dname)
821 {
822   char *s = buffer;
823   char *rs;
824
825   /* offset is greater than
826      size then zero */
827   if (offset > (aop->size - 1) &&
828       aop->type != AOP_LIT)
829     return zero;
830
831   /* depending on type */
832   switch (aop->type)
833     {
834
835     case AOP_R0:
836     case AOP_R1:
837       /* if we need to increment it */
838       while (offset > aop->coff)
839         {
840           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
841           aop->coff++;
842         }
843
844       while (offset < aop->coff)
845         {
846           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
847           aop->coff--;
848         }
849
850       aop->coff = offset;
851       if (aop->paged)
852         {
853           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
854           return (dname ? "acc" : "a");
855         }
856       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
857       rs = Safe_calloc (1, strlen (s) + 1);
858       strcpy (rs, s);
859       return rs;
860
861     case AOP_DPTR:
862       while (offset > aop->coff)
863         {
864           emitcode ("inc", "dptr");
865           aop->coff++;
866         }
867
868       while (offset < aop->coff)
869         {
870           emitcode ("lcall", "__decdptr");
871           aop->coff--;
872         }
873
874       aop->coff = offset;
875       if (aop->code)
876         {
877           emitcode ("clr", "a");
878           emitcode ("movc", "a,@a+dptr");
879         }
880       else
881         {
882           emitcode ("movx", "a,@dptr");
883         }
884       return (dname ? "acc" : "a");
885
886
887     case AOP_IMMD:
888       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
889               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
890       } else if (bit16)
891         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
892       else if (offset)
893         sprintf (s, "#(%s >> %d)",
894                  aop->aopu.aop_immd.aop_immd1,
895                  offset * 8);
896       else
897         sprintf (s, "#%s",
898                  aop->aopu.aop_immd.aop_immd1);
899       rs = Safe_calloc (1, strlen (s) + 1);
900       strcpy (rs, s);
901       return rs;
902
903     case AOP_DIR:
904       if (offset)
905         sprintf (s, "(%s + %d)",
906                  aop->aopu.aop_dir,
907                  offset);
908       else
909         sprintf (s, "%s", aop->aopu.aop_dir);
910       rs = Safe_calloc (1, strlen (s) + 1);
911       strcpy (rs, s);
912       return rs;
913
914     case AOP_REG:
915       if (dname)
916         return aop->aopu.aop_reg[offset]->dname;
917       else
918         return aop->aopu.aop_reg[offset]->name;
919
920     case AOP_CRY:
921       emitcode ("clr", "a");
922       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
923       emitcode ("rlc", "a");
924       return (dname ? "acc" : "a");
925
926     case AOP_ACC:
927       if (!offset && dname)
928         return "acc";
929       return aop->aopu.aop_str[offset];
930
931     case AOP_LIT:
932       return aopLiteral (aop->aopu.aop_lit, offset);
933
934     case AOP_STR:
935       aop->coff = offset;
936       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
937           dname)
938         return "acc";
939
940       return aop->aopu.aop_str[offset];
941
942     }
943
944   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
945           "aopget got unsupported aop->type");
946   exit (1);
947 }
948 /*-----------------------------------------------------------------*/
949 /* aopPut - puts a string for a aop                                */
950 /*-----------------------------------------------------------------*/
951 static void
952 aopPut (asmop * aop, char *s, int offset)
953 {
954   char *d = buffer;
955
956   if (aop->size && offset > (aop->size - 1))
957     {
958       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
959               "aopPut got offset > aop->size");
960       exit (1);
961     }
962
963   /* will assign value to value */
964   /* depending on where it is ofcourse */
965   switch (aop->type)
966     {
967     case AOP_DIR:
968       if (offset)
969         sprintf (d, "(%s + %d)",
970                  aop->aopu.aop_dir, offset);
971       else
972         sprintf (d, "%s", aop->aopu.aop_dir);
973
974       if (strcmp (d, s))
975         emitcode ("mov", "%s,%s", d, s);
976
977       break;
978
979     case AOP_REG:
980       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
981           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
982         {
983           if (*s == '@' ||
984               strcmp (s, "r0") == 0 ||
985               strcmp (s, "r1") == 0 ||
986               strcmp (s, "r2") == 0 ||
987               strcmp (s, "r3") == 0 ||
988               strcmp (s, "r4") == 0 ||
989               strcmp (s, "r5") == 0 ||
990               strcmp (s, "r6") == 0 ||
991               strcmp (s, "r7") == 0)
992             emitcode ("mov", "%s,%s",
993                       aop->aopu.aop_reg[offset]->dname, s);
994           else
995             emitcode ("mov", "%s,%s",
996                       aop->aopu.aop_reg[offset]->name, s);
997         }
998       break;
999
1000     case AOP_DPTR:
1001       if (aop->code)
1002         {
1003           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1004                   "aopPut writting to code space");
1005           exit (1);
1006         }
1007
1008       while (offset > aop->coff)
1009         {
1010           aop->coff++;
1011           emitcode ("inc", "dptr");
1012         }
1013
1014       while (offset < aop->coff)
1015         {
1016           aop->coff--;
1017           emitcode ("lcall", "__decdptr");
1018         }
1019
1020       aop->coff = offset;
1021
1022       /* if not in accumulater */
1023       MOVA (s);
1024
1025       emitcode ("movx", "@dptr,a");
1026       break;
1027
1028     case AOP_R0:
1029     case AOP_R1:
1030       while (offset > aop->coff)
1031         {
1032           aop->coff++;
1033           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1034         }
1035       while (offset < aop->coff)
1036         {
1037           aop->coff--;
1038           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1039         }
1040       aop->coff = offset;
1041
1042       if (aop->paged)
1043         {
1044           MOVA (s);
1045           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1046
1047         }
1048       else if (*s == '@')
1049         {
1050           MOVA (s);
1051           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1052         }
1053       else if (strcmp (s, "r0") == 0 ||
1054                strcmp (s, "r1") == 0 ||
1055                strcmp (s, "r2") == 0 ||
1056                strcmp (s, "r3") == 0 ||
1057                strcmp (s, "r4") == 0 ||
1058                strcmp (s, "r5") == 0 ||
1059                strcmp (s, "r6") == 0 ||
1060                strcmp (s, "r7") == 0)
1061         {
1062           char buffer[10];
1063           sprintf (buffer, "a%s", s);
1064           emitcode ("mov", "@%s,%s",
1065                     aop->aopu.aop_ptr->name, buffer);
1066         }
1067       else
1068         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1069
1070       break;
1071
1072     case AOP_STK:
1073       if (strcmp (s, "a") == 0)
1074         emitcode ("push", "acc");
1075       else
1076         if (*s=='@') {
1077           MOVA(s);
1078           emitcode ("push", "acc");
1079         } else {
1080           emitcode ("push", s);
1081         }
1082
1083       break;
1084
1085     case AOP_CRY:
1086       /* if bit variable */
1087       if (!aop->aopu.aop_dir)
1088         {
1089           emitcode ("clr", "a");
1090           emitcode ("rlc", "a");
1091         }
1092       else
1093         {
1094           if (s == zero)
1095             emitcode ("clr", "%s", aop->aopu.aop_dir);
1096           else if (s == one)
1097             emitcode ("setb", "%s", aop->aopu.aop_dir);
1098           else if (!strcmp (s, "c"))
1099             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1100           else
1101             {
1102               if (strcmp (s, "a"))
1103                 {
1104                   MOVA (s);
1105                 }
1106               {
1107                 /* set C, if a >= 1 */
1108                 emitcode ("add", "a,#0xff");
1109                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1110               }
1111             }
1112         }
1113       break;
1114
1115     case AOP_STR:
1116       aop->coff = offset;
1117       if (strcmp (aop->aopu.aop_str[offset], s))
1118         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1119       break;
1120
1121     case AOP_ACC:
1122       aop->coff = offset;
1123       if (!offset && (strcmp (s, "acc") == 0))
1124         break;
1125
1126       if (strcmp (aop->aopu.aop_str[offset], s))
1127         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1128       break;
1129
1130     default:
1131       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1132               "aopPut got unsupported aop->type");
1133       exit (1);
1134     }
1135
1136 }
1137
1138
1139 #if 0
1140 /*-----------------------------------------------------------------*/
1141 /* pointToEnd :- points to the last byte of the operand            */
1142 /*-----------------------------------------------------------------*/
1143 static void
1144 pointToEnd (asmop * aop)
1145 {
1146   int count;
1147   if (!aop)
1148     return;
1149
1150   aop->coff = count = (aop->size - 1);
1151   switch (aop->type)
1152     {
1153     case AOP_R0:
1154     case AOP_R1:
1155       while (count--)
1156         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1157       break;
1158     case AOP_DPTR:
1159       while (count--)
1160         emitcode ("inc", "dptr");
1161       break;
1162     }
1163
1164 }
1165 #endif
1166
1167 /*-----------------------------------------------------------------*/
1168 /* reAdjustPreg - points a register back to where it should        */
1169 /*-----------------------------------------------------------------*/
1170 static void
1171 reAdjustPreg (asmop * aop)
1172 {
1173   if ((aop->coff==0) || aop->size <= 1)
1174     return;
1175
1176   switch (aop->type)
1177     {
1178     case AOP_R0:
1179     case AOP_R1:
1180       while (aop->coff--)
1181         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1182       break;
1183     case AOP_DPTR:
1184       while (aop->coff--)
1185         {
1186           emitcode ("lcall", "__decdptr");
1187         }
1188       break;
1189     }
1190   aop->coff = 0;
1191 }
1192
1193 #define AOP(op) op->aop
1194 #define AOP_TYPE(op) AOP(op)->type
1195 #define AOP_SIZE(op) AOP(op)->size
1196 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1197                        AOP_TYPE(x) == AOP_R0))
1198
1199 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1200                         AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1201
1202 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1203                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1204                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1205
1206 /*-----------------------------------------------------------------*/
1207 /* genNotFloat - generates not for float operations              */
1208 /*-----------------------------------------------------------------*/
1209 static void
1210 genNotFloat (operand * op, operand * res)
1211 {
1212   int size, offset;
1213   char *l;
1214   symbol *tlbl;
1215
1216   D(emitcode (";", "genNotFloat"));
1217
1218   /* we will put 127 in the first byte of
1219      the result */
1220   aopPut (AOP (res), "#127", 0);
1221   size = AOP_SIZE (op) - 1;
1222   offset = 1;
1223
1224   l = aopGet (op->aop, offset++, FALSE, FALSE);
1225   MOVA (l);
1226
1227   while (size--)
1228     {
1229       emitcode ("orl", "a,%s",
1230                 aopGet (op->aop,
1231                         offset++, FALSE, FALSE));
1232     }
1233
1234   tlbl = newiTempLabel (NULL);
1235   aopPut (res->aop, one, 1);
1236   emitcode ("jz", "%05d$", (tlbl->key + 100));
1237   aopPut (res->aop, zero, 1);
1238   emitcode ("", "%05d$:", (tlbl->key + 100));
1239
1240   size = res->aop->size - 2;
1241   offset = 2;
1242   /* put zeros in the rest */
1243   while (size--)
1244     aopPut (res->aop, zero, offset++);
1245 }
1246
1247 /*-----------------------------------------------------------------*/
1248 /* opIsGptr: returns non-zero if the passed operand is       */
1249 /* a generic pointer type.             */
1250 /*-----------------------------------------------------------------*/
1251 static int
1252 opIsGptr (operand * op)
1253 {
1254   sym_link *type = operandType (op);
1255
1256   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1257     {
1258       return 1;
1259     }
1260   return 0;
1261 }
1262
1263 /*-----------------------------------------------------------------*/
1264 /* getDataSize - get the operand data size                         */
1265 /*-----------------------------------------------------------------*/
1266 static int
1267 getDataSize (operand * op)
1268 {
1269   int size;
1270   size = AOP_SIZE (op);
1271   if (size == GPTRSIZE)
1272     {
1273       sym_link *type = operandType (op);
1274       if (IS_GENPTR (type))
1275         {
1276           /* generic pointer; arithmetic operations
1277            * should ignore the high byte (pointer type).
1278            */
1279           size--;
1280         }
1281     }
1282   return size;
1283 }
1284
1285 /*-----------------------------------------------------------------*/
1286 /* outAcc - output Acc                                             */
1287 /*-----------------------------------------------------------------*/
1288 static void
1289 outAcc (operand * result)
1290 {
1291   int size, offset;
1292   size = getDataSize (result);
1293   if (size)
1294     {
1295       aopPut (AOP (result), "a", 0);
1296       size--;
1297       offset = 1;
1298       /* unsigned or positive */
1299       while (size--)
1300         {
1301           aopPut (AOP (result), zero, offset++);
1302         }
1303     }
1304 }
1305
1306 /*-----------------------------------------------------------------*/
1307 /* outBitC - output a bit C                                        */
1308 /*-----------------------------------------------------------------*/
1309 static void
1310 outBitC (operand * result)
1311 {
1312   /* if the result is bit */
1313   if (AOP_TYPE (result) == AOP_CRY)
1314     aopPut (AOP (result), "c", 0);
1315   else
1316     {
1317       emitcode ("clr", "a");
1318       emitcode ("rlc", "a");
1319       outAcc (result);
1320     }
1321 }
1322
1323 /*-----------------------------------------------------------------*/
1324 /* toBoolean - emit code for orl a,operator(sizeop)                */
1325 /*-----------------------------------------------------------------*/
1326 static void
1327 toBoolean (operand * oper)
1328 {
1329   int size = AOP_SIZE (oper) - 1;
1330   int offset = 1;
1331   MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1332   while (size--)
1333     emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1334 }
1335
1336
1337 /*-----------------------------------------------------------------*/
1338 /* genNot - generate code for ! operation                          */
1339 /*-----------------------------------------------------------------*/
1340 static void
1341 genNot (iCode * ic)
1342 {
1343   symbol *tlbl;
1344   sym_link *optype = operandType (IC_LEFT (ic));
1345
1346   D(emitcode (";", "genNot"));
1347
1348   /* assign asmOps to operand & result */
1349   aopOp (IC_LEFT (ic), ic, FALSE);
1350   aopOp (IC_RESULT (ic), ic, TRUE);
1351
1352   /* if in bit space then a special case */
1353   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1354     {
1355       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1356       emitcode ("cpl", "c");
1357       outBitC (IC_RESULT (ic));
1358       goto release;
1359     }
1360
1361   /* if type float then do float */
1362   if (IS_FLOAT (optype))
1363     {
1364       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1365       goto release;
1366     }
1367
1368   toBoolean (IC_LEFT (ic));
1369
1370   tlbl = newiTempLabel (NULL);
1371   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1372   emitcode ("", "%05d$:", tlbl->key + 100);
1373   outBitC (IC_RESULT (ic));
1374
1375 release:
1376   /* release the aops */
1377   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1378   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1379 }
1380
1381
1382 /*-----------------------------------------------------------------*/
1383 /* genCpl - generate code for complement                           */
1384 /*-----------------------------------------------------------------*/
1385 static void
1386 genCpl (iCode * ic)
1387 {
1388   int offset = 0;
1389   int size;
1390   symbol *tlbl;
1391
1392   D(emitcode (";", "genCpl"));
1393
1394   /* assign asmOps to operand & result */
1395   aopOp (IC_LEFT (ic), ic, FALSE);
1396   aopOp (IC_RESULT (ic), ic, TRUE);
1397
1398   /* special case if in bit space */
1399   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1400     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1401       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1402       emitcode ("cpl", "c");
1403       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1404       goto release;
1405     }
1406     tlbl=newiTempLabel(NULL);
1407     emitcode ("cjne", "%s,#0x01,%05d$", 
1408               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1409     emitcode ("", "%05d$:", tlbl->key+100);
1410     outBitC (IC_RESULT(ic));
1411     goto release;
1412   }
1413
1414   size = AOP_SIZE (IC_RESULT (ic));
1415   while (size--)
1416     {
1417       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1418       MOVA (l);
1419       emitcode ("cpl", "a");
1420       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1421     }
1422
1423
1424 release:
1425   /* release the aops */
1426   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1427   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1428 }
1429
1430 /*-----------------------------------------------------------------*/
1431 /* genUminusFloat - unary minus for floating points                */
1432 /*-----------------------------------------------------------------*/
1433 static void
1434 genUminusFloat (operand * op, operand * result)
1435 {
1436   int size, offset = 0;
1437   char *l;
1438
1439   D(emitcode (";", "genUminusFloat"));
1440
1441   /* for this we just need to flip the
1442      first it then copy the rest in place */
1443   size = AOP_SIZE (op) - 1;
1444   l = aopGet (AOP (op), 3, FALSE, FALSE);
1445
1446   MOVA (l);
1447
1448   emitcode ("cpl", "acc.7");
1449   aopPut (AOP (result), "a", 3);
1450
1451   while (size--)
1452     {
1453       aopPut (AOP (result),
1454               aopGet (AOP (op), offset, FALSE, FALSE),
1455               offset);
1456       offset++;
1457     }
1458 }
1459
1460 /*-----------------------------------------------------------------*/
1461 /* genUminus - unary minus code generation                         */
1462 /*-----------------------------------------------------------------*/
1463 static void
1464 genUminus (iCode * ic)
1465 {
1466   int offset, size;
1467   sym_link *optype, *rtype;
1468
1469
1470   D(emitcode (";", "genUminus"));
1471
1472   /* assign asmops */
1473   aopOp (IC_LEFT (ic), ic, FALSE);
1474   aopOp (IC_RESULT (ic), ic, TRUE);
1475
1476   /* if both in bit space then special
1477      case */
1478   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1479       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1480     {
1481
1482       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1483       emitcode ("cpl", "c");
1484       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1485       goto release;
1486     }
1487
1488   optype = operandType (IC_LEFT (ic));
1489   rtype = operandType (IC_RESULT (ic));
1490
1491   /* if float then do float stuff */
1492   if (IS_FLOAT (optype))
1493     {
1494       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1495       goto release;
1496     }
1497
1498   /* otherwise subtract from zero */
1499   size = AOP_SIZE (IC_LEFT (ic));
1500   offset = 0;
1501   //CLRC ;
1502   while (size--)
1503     {
1504       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1505       if (!strcmp (l, "a"))
1506         {
1507           if (offset == 0)
1508             SETC;
1509           emitcode ("cpl", "a");
1510           emitcode ("addc", "a,#0");
1511         }
1512       else
1513         {
1514           if (offset == 0)
1515             CLRC;
1516           emitcode ("clr", "a");
1517           emitcode ("subb", "a,%s", l);
1518         }
1519       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1520     }
1521
1522   /* if any remaining bytes in the result */
1523   /* we just need to propagate the sign   */
1524   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1525     {
1526       emitcode ("rlc", "a");
1527       emitcode ("subb", "a,acc");
1528       while (size--)
1529         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1530     }
1531
1532 release:
1533   /* release the aops */
1534   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1535   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1536 }
1537
1538 /*-----------------------------------------------------------------*/
1539 /* saveRegisters - will look for a call and save the registers     */
1540 /*-----------------------------------------------------------------*/
1541 static void
1542 saveRegisters (iCode * lic)
1543 {
1544   int i;
1545   iCode *ic;
1546   bitVect *rsave;
1547
1548   /* look for call */
1549   for (ic = lic; ic; ic = ic->next)
1550     if (ic->op == CALL || ic->op == PCALL)
1551       break;
1552
1553   if (!ic)
1554     {
1555       fprintf (stderr, "found parameter push with no function call\n");
1556       return;
1557     }
1558
1559   /* if the registers have been saved already or don't need to be then
1560      do nothing */
1561   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1562       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1563     return;
1564
1565   /* safe the registers in use at this time but skip the
1566      ones for the result */
1567   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1568                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1569
1570   ic->regsSaved = 1;
1571   if (options.useXstack)
1572     {
1573       if (bitVectBitValue (rsave, R0_IDX))
1574         emitcode ("mov", "b,r0");
1575       emitcode ("mov", "r0,%s", spname);
1576       for (i = 0; i < mcs51_nRegs; i++)
1577         {
1578           if (bitVectBitValue (rsave, i))
1579             {
1580               if (i == R0_IDX)
1581                 emitcode ("mov", "a,b");
1582               else
1583                 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1584               emitcode ("movx", "@r0,a");
1585               emitcode ("inc", "r0");
1586             }
1587         }
1588       emitcode ("mov", "%s,r0", spname);
1589       if (bitVectBitValue (rsave, R0_IDX))
1590         emitcode ("mov", "r0,b");
1591     }
1592   else
1593     for (i = 0; i < mcs51_nRegs; i++)
1594       {
1595         if (bitVectBitValue (rsave, i))
1596           emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1597       }
1598 }
1599
1600 /*-----------------------------------------------------------------*/
1601 /* unsaveRegisters - pop the pushed registers                      */
1602 /*-----------------------------------------------------------------*/
1603 static void
1604 unsaveRegisters (iCode * ic)
1605 {
1606   int i;
1607   bitVect *rsave;
1608
1609   /* restore the registers in use at this time but skip the
1610      ones for the result */
1611   rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1612                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1613
1614   if (options.useXstack)
1615     {
1616       emitcode ("mov", "r0,%s", spname);
1617       for (i = mcs51_nRegs; i >= 0; i--)
1618         {
1619           if (bitVectBitValue (rsave, i))
1620             {
1621               emitcode ("dec", "r0");
1622               emitcode ("movx", "a,@r0");
1623               if (i == R0_IDX)
1624                 emitcode ("mov", "b,a");
1625               else
1626                 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1627             }
1628
1629         }
1630       emitcode ("mov", "%s,r0", spname);
1631       if (bitVectBitValue (rsave, R0_IDX))
1632         emitcode ("mov", "r0,b");
1633     }
1634   else
1635     for (i = mcs51_nRegs; i >= 0; i--)
1636       {
1637         if (bitVectBitValue (rsave, i))
1638           emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1639       }
1640
1641 }
1642
1643
1644 /*-----------------------------------------------------------------*/
1645 /* pushSide -                */
1646 /*-----------------------------------------------------------------*/
1647 static void
1648 pushSide (operand * oper, int size)
1649 {
1650   int offset = 0;
1651   while (size--)
1652     {
1653       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1654       if (AOP_TYPE (oper) != AOP_REG &&
1655           AOP_TYPE (oper) != AOP_DIR &&
1656           strcmp (l, "a"))
1657         {
1658           emitcode ("mov", "a,%s", l);
1659           emitcode ("push", "acc");
1660         }
1661       else
1662         emitcode ("push", "%s", l);
1663     }
1664 }
1665
1666 /*-----------------------------------------------------------------*/
1667 /* assignResultValue -               */
1668 /*-----------------------------------------------------------------*/
1669 static void
1670 assignResultValue (operand * oper)
1671 {
1672   int offset = 0;
1673   int size = AOP_SIZE (oper);
1674   while (size--)
1675     {
1676       aopPut (AOP (oper), fReturn[offset], offset);
1677       offset++;
1678     }
1679 }
1680
1681
1682 /*-----------------------------------------------------------------*/
1683 /* genXpush - pushes onto the external stack                       */
1684 /*-----------------------------------------------------------------*/
1685 static void
1686 genXpush (iCode * ic)
1687 {
1688   asmop *aop = newAsmop (0);
1689   regs *r;
1690   int size, offset = 0;
1691
1692   D(emitcode (";", "genXpush"));
1693
1694   aopOp (IC_LEFT (ic), ic, FALSE);
1695   r = getFreePtr (ic, &aop, FALSE);
1696
1697
1698   emitcode ("mov", "%s,_spx", r->name);
1699
1700   size = AOP_SIZE (IC_LEFT (ic));
1701   while (size--)
1702     {
1703
1704       char *l = aopGet (AOP (IC_LEFT (ic)),
1705                         offset++, FALSE, FALSE);
1706       MOVA (l);
1707       emitcode ("movx", "@%s,a", r->name);
1708       emitcode ("inc", "%s", r->name);
1709
1710     }
1711
1712
1713   emitcode ("mov", "_spx,%s", r->name);
1714
1715   freeAsmop (NULL, aop, ic, TRUE);
1716   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* genIpush - genrate code for pushing this gets a little complex  */
1721 /*-----------------------------------------------------------------*/
1722 static void
1723 genIpush (iCode * ic)
1724 {
1725   int size, offset = 0;
1726   char *l;
1727
1728   D(emitcode (";", "genIpush"));
1729
1730   /* if this is not a parm push : ie. it is spill push
1731      and spill push is always done on the local stack */
1732   if (!ic->parmPush)
1733     {
1734
1735       /* and the item is spilt then do nothing */
1736       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1737         return;
1738
1739       aopOp (IC_LEFT (ic), ic, FALSE);
1740       size = AOP_SIZE (IC_LEFT (ic));
1741       /* push it on the stack */
1742       while (size--)
1743         {
1744           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1745           if (*l == '#')
1746             {
1747               MOVA (l);
1748               l = "acc";
1749             }
1750           emitcode ("push", "%s", l);
1751         }
1752       return;
1753     }
1754
1755   /* this is a paramter push: in this case we call
1756      the routine to find the call and save those
1757      registers that need to be saved */
1758   saveRegisters (ic);
1759
1760   /* if use external stack then call the external
1761      stack pushing routine */
1762   if (options.useXstack)
1763     {
1764       genXpush (ic);
1765       return;
1766     }
1767
1768   /* then do the push */
1769   aopOp (IC_LEFT (ic), ic, FALSE);
1770
1771
1772   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1773   size = AOP_SIZE (IC_LEFT (ic));
1774
1775   while (size--)
1776     {
1777       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1778       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1779           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1780           strcmp (l, "a"))
1781         {
1782           emitcode ("mov", "a,%s", l);
1783           emitcode ("push", "acc");
1784         }
1785       else
1786         emitcode ("push", "%s", l);
1787     }
1788
1789   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1790 }
1791
1792 /*-----------------------------------------------------------------*/
1793 /* genIpop - recover the registers: can happen only for spilling   */
1794 /*-----------------------------------------------------------------*/
1795 static void
1796 genIpop (iCode * ic)
1797 {
1798   int size, offset;
1799
1800   D(emitcode (";", "genIpop"));
1801
1802   /* if the temp was not pushed then */
1803   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1804     return;
1805
1806   aopOp (IC_LEFT (ic), ic, FALSE);
1807   size = AOP_SIZE (IC_LEFT (ic));
1808   offset = (size - 1);
1809   while (size--)
1810     emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1811                                    FALSE, TRUE));
1812
1813   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* unsaveRBank - restores the resgister bank from stack            */
1818 /*-----------------------------------------------------------------*/
1819 static void
1820 unsaveRBank (int bank, iCode * ic, bool popPsw)
1821 {
1822   int i;
1823   asmop *aop = NULL;
1824   regs *r = NULL;
1825
1826   if (options.useXstack)
1827   {
1828       if (!ic)
1829       {
1830           /* Assume r0 is available for use. */
1831           r = mcs51_regWithIdx (R0_IDX);;          
1832       } 
1833       else
1834       {
1835           aop = newAsmop (0);
1836           r = getFreePtr (ic, &aop, FALSE);
1837       }
1838       emitcode ("mov", "%s,_spx", r->name);      
1839   }
1840   
1841   if (popPsw)
1842     {
1843       if (options.useXstack)
1844       {
1845           emitcode ("movx", "a,@%s", r->name);
1846           emitcode ("mov", "psw,a");
1847           emitcode ("dec", "%s", r->name);
1848         }
1849       else
1850       {
1851         emitcode ("pop", "psw");
1852       }
1853     }
1854
1855   for (i = (mcs51_nRegs - 1); i >= 0; i--)
1856     {
1857       if (options.useXstack)
1858         {
1859           emitcode ("movx", "a,@%s", r->name);
1860           emitcode ("mov", "(%s+%d),a",
1861                     regs8051[i].base, 8 * bank + regs8051[i].offset);
1862           emitcode ("dec", "%s", r->name);
1863
1864         }
1865       else
1866         emitcode ("pop", "(%s+%d)",
1867                   regs8051[i].base, 8 * bank + regs8051[i].offset);
1868     }
1869
1870   if (options.useXstack)
1871     {
1872       emitcode ("mov", "_spx,%s", r->name);
1873     }
1874     
1875   if (aop)
1876   {
1877       freeAsmop (NULL, aop, ic, TRUE);  
1878   }    
1879 }
1880
1881 /*-----------------------------------------------------------------*/
1882 /* saveRBank - saves an entire register bank on the stack          */
1883 /*-----------------------------------------------------------------*/
1884 static void
1885 saveRBank (int bank, iCode * ic, bool pushPsw)
1886 {
1887   int i;
1888   asmop *aop = NULL;
1889   regs *r = NULL;
1890
1891   if (options.useXstack)
1892     {
1893       if (!ic)
1894       {
1895           /* Assume r0 is available for use. */
1896           r = mcs51_regWithIdx (R0_IDX);;
1897       }
1898       else
1899       {
1900           aop = newAsmop (0);
1901           r = getFreePtr (ic, &aop, FALSE);
1902       }
1903       emitcode ("mov", "%s,_spx", r->name);
1904     }
1905
1906   for (i = 0; i < mcs51_nRegs; i++)
1907     {
1908       if (options.useXstack)
1909         {
1910           emitcode ("inc", "%s", r->name);
1911           emitcode ("mov", "a,(%s+%d)",
1912                     regs8051[i].base, 8 * bank + regs8051[i].offset);
1913           emitcode ("movx", "@%s,a", r->name);
1914         }
1915       else
1916         emitcode ("push", "(%s+%d)",
1917                   regs8051[i].base, 8 * bank + regs8051[i].offset);
1918     }
1919
1920   if (pushPsw)
1921     {
1922       if (options.useXstack)
1923         {
1924           emitcode ("mov", "a,psw");
1925           emitcode ("movx", "@%s,a", r->name);
1926           emitcode ("inc", "%s", r->name);
1927           emitcode ("mov", "_spx,%s", r->name);
1928
1929         }
1930       else
1931       {
1932         emitcode ("push", "psw");
1933       }
1934
1935       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1936     }
1937
1938     if (aop)
1939     {
1940         freeAsmop (NULL, aop, ic, TRUE);
1941     }
1942
1943   if (ic)
1944   {  
1945       ic->bankSaved = 1;
1946   }
1947 }
1948
1949 /*-----------------------------------------------------------------*/
1950 /* genSend - gen code for SEND                                     */
1951 /*-----------------------------------------------------------------*/
1952 static void genSend(set *sendSet)
1953 {
1954     iCode *sic;
1955     int rb1_count = 0 ;
1956
1957     for (sic = setFirstItem (_G.sendSet); sic;
1958          sic = setNextItem (_G.sendSet)) {
1959           int size, offset = 0;
1960           aopOp (IC_LEFT (sic), sic, FALSE);
1961           size = AOP_SIZE (IC_LEFT (sic));
1962
1963           if (sic->argreg == 1) {
1964               while (size--) {
1965                   char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1966                                     FALSE, FALSE);
1967                   if (strcmp (l, fReturn[offset]))
1968                       emitcode ("mov", "%s,%s", fReturn[offset], l);
1969                   offset++;
1970               }
1971               rb1_count = 0;
1972           } else {
1973               while (size--) {
1974                   emitcode ("mov","b1_%d,%s",rb1_count++,
1975                             aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1976               }
1977           }       
1978           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1979     }
1980 }
1981
1982 /*-----------------------------------------------------------------*/
1983 /* genCall - generates a call statement                            */
1984 /*-----------------------------------------------------------------*/
1985 static void
1986 genCall (iCode * ic)
1987 {
1988   sym_link *dtype;
1989 //  bool restoreBank = FALSE;
1990   bool swapBanks = FALSE;
1991
1992   D(emitcode(";", "genCall"));
1993
1994   dtype = operandType (IC_LEFT (ic));
1995   /* if send set is not empty the assign */
1996   if (_G.sendSet)
1997     {
1998         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1999             genSend(reverseSet(_G.sendSet));
2000         } else {
2001             genSend(_G.sendSet);
2002         }
2003
2004       _G.sendSet = NULL;
2005     }
2006
2007   /* if we are calling a not _naked function that is not using
2008      the same register bank then we need to save the
2009      destination registers on the stack */
2010   dtype = operandType (IC_LEFT (ic));
2011   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2012       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2013        !IFFUNC_ISISR (dtype))
2014   {
2015       swapBanks = TRUE;  
2016   } 
2017     
2018   /* if caller saves & we have not saved then */
2019   if (!ic->regsSaved)
2020       saveRegisters (ic);
2021
2022   if (swapBanks)
2023   {
2024         emitcode ("mov", "psw,#0x%02x", 
2025            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2026   }
2027
2028   /* make the call */
2029   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2030                             OP_SYMBOL (IC_LEFT (ic))->rname :
2031                             OP_SYMBOL (IC_LEFT (ic))->name));
2032
2033   if (swapBanks)
2034   {
2035        emitcode ("mov", "psw,#0x%02x", 
2036           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2037   }
2038
2039   /* if we need assign a result value */
2040   if ((IS_ITEMP (IC_RESULT (ic)) &&
2041        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2042         OP_SYMBOL (IC_RESULT (ic))->accuse || 
2043         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2044       IS_TRUE_SYMOP (IC_RESULT (ic)))
2045     {
2046
2047       _G.accInUse++;
2048       aopOp (IC_RESULT (ic), ic, FALSE);
2049       _G.accInUse--;
2050
2051       assignResultValue (IC_RESULT (ic));
2052
2053       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2054     }
2055
2056   /* adjust the stack for parameters if
2057      required */
2058   if (ic->parmBytes)
2059     {
2060       int i;
2061       if (ic->parmBytes > 3)
2062         {
2063           emitcode ("mov", "a,%s", spname);
2064           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2065           emitcode ("mov", "%s,a", spname);
2066         }
2067       else
2068         for (i = 0; i < ic->parmBytes; i++)
2069           emitcode ("dec", "%s", spname);
2070     }
2071
2072   /* if we hade saved some registers then unsave them */
2073   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2074     unsaveRegisters (ic);
2075
2076 //  /* if register bank was saved then pop them */
2077 //  if (restoreBank)
2078 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2079 }
2080
2081 /*-----------------------------------------------------------------*/
2082 /* -10l - generates a call by pointer statement                */
2083 /*-----------------------------------------------------------------*/
2084 static void
2085 genPcall (iCode * ic)
2086 {
2087   sym_link *dtype;
2088   symbol *rlbl = newiTempLabel (NULL);
2089 //  bool restoreBank=FALSE;
2090   bool swapBanks = FALSE;
2091
2092   D(emitcode(";", "genPCall"));
2093
2094   /* if caller saves & we have not saved then */
2095   if (!ic->regsSaved)
2096     saveRegisters (ic);
2097
2098   /* if we are calling a not _naked function that is not using
2099      the same register bank then we need to save the
2100      destination registers on the stack */
2101   dtype = operandType (IC_LEFT (ic))->next;
2102   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2103       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2104       !IFFUNC_ISISR (dtype))
2105   {
2106 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2107 //    restoreBank=TRUE;
2108       swapBanks = TRUE;
2109       // need caution message to user here
2110   }
2111
2112   /* push the return address on to the stack */
2113   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2114   emitcode ("push", "acc");
2115   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2116   emitcode ("push", "acc");
2117
2118   /* now push the calling address */
2119   aopOp (IC_LEFT (ic), ic, FALSE);
2120
2121   pushSide (IC_LEFT (ic), FPTRSIZE);
2122
2123   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2124
2125   /* if send set is not empty the assign */
2126   if (_G.sendSet)
2127     {
2128         genSend(reverseSet(_G.sendSet));
2129         _G.sendSet = NULL;
2130     }
2131
2132   if (swapBanks)
2133   {
2134         emitcode ("mov", "psw,#0x%02x", 
2135            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2136   }
2137
2138   /* make the call */
2139   emitcode ("ret", "");
2140   emitcode ("", "%05d$:", (rlbl->key + 100));
2141
2142
2143   if (swapBanks)
2144   {
2145        emitcode ("mov", "psw,#0x%02x", 
2146           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2147   }
2148
2149   /* if we need assign a result value */
2150   if ((IS_ITEMP (IC_RESULT (ic)) &&
2151        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2152         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2153       IS_TRUE_SYMOP (IC_RESULT (ic)))
2154     {
2155
2156       _G.accInUse++;
2157       aopOp (IC_RESULT (ic), ic, FALSE);
2158       _G.accInUse--;
2159
2160       assignResultValue (IC_RESULT (ic));
2161
2162       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2163     }
2164
2165   /* adjust the stack for parameters if
2166      required */
2167   if (ic->parmBytes)
2168     {
2169       int i;
2170       if (ic->parmBytes > 3)
2171         {
2172           emitcode ("mov", "a,%s", spname);
2173           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2174           emitcode ("mov", "%s,a", spname);
2175         }
2176       else
2177         for (i = 0; i < ic->parmBytes; i++)
2178           emitcode ("dec", "%s", spname);
2179
2180     }
2181
2182 //  /* if register bank was saved then unsave them */
2183 //  if (restoreBank)
2184 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2185
2186   /* if we hade saved some registers then
2187      unsave them */
2188   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2189     unsaveRegisters (ic);
2190 }
2191
2192 /*-----------------------------------------------------------------*/
2193 /* resultRemat - result  is rematerializable                       */
2194 /*-----------------------------------------------------------------*/
2195 static int
2196 resultRemat (iCode * ic)
2197 {
2198   if (SKIP_IC (ic) || ic->op == IFX)
2199     return 0;
2200
2201   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2202     {
2203       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2204       if (sym->remat && !POINTER_SET (ic))
2205         return 1;
2206     }
2207
2208   return 0;
2209 }
2210
2211 #if defined(__BORLANDC__) || defined(_MSC_VER)
2212 #define STRCASECMP stricmp
2213 #else
2214 #define STRCASECMP strcasecmp
2215 #endif
2216
2217 /*-----------------------------------------------------------------*/
2218 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2219 /*-----------------------------------------------------------------*/
2220 static bool
2221 inExcludeList (char *s)
2222 {
2223   int i = 0;
2224
2225   if (options.excludeRegs[i] &&
2226       STRCASECMP (options.excludeRegs[i], "none") == 0)
2227     return FALSE;
2228
2229   for (i = 0; options.excludeRegs[i]; i++)
2230     {
2231       if (options.excludeRegs[i] &&
2232           STRCASECMP (s, options.excludeRegs[i]) == 0)
2233         return TRUE;
2234     }
2235   return FALSE;
2236 }
2237
2238 /*-----------------------------------------------------------------*/
2239 /* genFunction - generated code for function entry                 */
2240 /*-----------------------------------------------------------------*/
2241 static void
2242 genFunction (iCode * ic)
2243 {
2244   symbol *sym;
2245   sym_link *ftype;
2246   bool   switchedPSW = FALSE;
2247   int calleesaves_saved_register = -1;
2248
2249   _G.nRegsSaved = 0;
2250   /* create the function header */
2251   emitcode (";", "-----------------------------------------");
2252   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2253   emitcode (";", "-----------------------------------------");
2254
2255   emitcode ("", "%s:", sym->rname);
2256   ftype = operandType (IC_LEFT (ic));
2257
2258   if (IFFUNC_ISNAKED(ftype))
2259   {
2260       emitcode(";", "naked function: no prologue.");
2261       return;
2262   }
2263
2264   /* if critical function then turn interrupts off */
2265   if (IFFUNC_ISCRITICAL (ftype))
2266     emitcode ("clr", "ea");
2267
2268   /* here we need to generate the equates for the
2269      register bank if required */
2270   if (FUNC_REGBANK (ftype) != rbank)
2271     {
2272       int i;
2273
2274       rbank = FUNC_REGBANK (ftype);
2275       for (i = 0; i < mcs51_nRegs; i++)
2276         {
2277           if (strcmp (regs8051[i].base, "0") == 0)
2278             emitcode ("", "%s = 0x%02x",
2279                       regs8051[i].dname,
2280                       8 * rbank + regs8051[i].offset);
2281           else
2282             emitcode ("", "%s = %s + 0x%02x",
2283                       regs8051[i].dname,
2284                       regs8051[i].base,
2285                       8 * rbank + regs8051[i].offset);
2286         }
2287     }
2288
2289   /* if this is an interrupt service routine then
2290      save acc, b, dpl, dph  */
2291   if (IFFUNC_ISISR (sym->type))
2292     {
2293
2294       if (!inExcludeList ("acc"))
2295         emitcode ("push", "acc");
2296       if (!inExcludeList ("b"))
2297         emitcode ("push", "b");
2298       if (!inExcludeList ("dpl"))
2299         emitcode ("push", "dpl");
2300       if (!inExcludeList ("dph"))
2301         emitcode ("push", "dph");
2302       /* if this isr has no bank i.e. is going to
2303          run with bank 0 , then we need to save more
2304          registers :-) */
2305       if (!FUNC_REGBANK (sym->type))
2306         {
2307
2308           /* if this function does not call any other
2309              function then we can be economical and
2310              save only those registers that are used */
2311           if (!IFFUNC_HASFCALL(sym->type))
2312             {
2313               int i;
2314
2315               /* if any registers used */
2316               if (sym->regsUsed)
2317                 {
2318                   /* save the registers used */
2319                   for (i = 0; i < sym->regsUsed->size; i++)
2320                     {
2321                       if (bitVectBitValue (sym->regsUsed, i) ||
2322                           (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2323                         emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2324                     }
2325                 }
2326
2327             }
2328           else
2329             {
2330                 
2331               /* this function has  a function call cannot
2332                  determines register usage so we will have to push the
2333                  entire bank */
2334                 saveRBank (0, ic, FALSE);
2335                 if (options.parms_in_bank1) {
2336                     int i;
2337                     for (i=0; i < 8 ; i++ ) {
2338                         emitcode ("push","%s",rb1regs[i]);
2339                     }
2340                 }
2341             }
2342         }
2343         else
2344         {
2345             /* This ISR uses a non-zero bank.
2346              *
2347              * We assume that the bank is available for our
2348              * exclusive use.
2349              *
2350              * However, if this ISR calls a function which uses some
2351              * other bank, we must save that bank entirely.
2352              */
2353             unsigned long banksToSave = 0;
2354             
2355             if (IFFUNC_HASFCALL(sym->type))
2356             {
2357
2358 #define MAX_REGISTER_BANKS 4
2359
2360                 iCode *i;
2361                 int ix;
2362
2363                 for (i = ic; i; i = i->next)
2364                 {
2365                     if (i->op == ENDFUNCTION)
2366                     {
2367                         /* we got to the end OK. */
2368                         break;
2369                     }
2370                     
2371                     if (i->op == CALL)
2372                     {
2373                         sym_link *dtype;
2374                         
2375                         dtype = operandType (IC_LEFT(i));
2376                         if (dtype
2377                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2378                         {
2379                              /* Mark this bank for saving. */
2380                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2381                              {
2382                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2383                              }
2384                              else
2385                              {
2386                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2387                              }
2388                              
2389                              /* And note that we don't need to do it in 
2390                               * genCall.
2391                               */
2392                              i->bankSaved = 1;
2393                         }
2394                     }
2395                     if (i->op == PCALL)
2396                     {
2397                         /* This is a mess; we have no idea what
2398                          * register bank the called function might
2399                          * use.
2400                          *
2401                          * The only thing I can think of to do is
2402                          * throw a warning and hope.
2403                          */
2404                         werror(W_FUNCPTR_IN_USING_ISR);   
2405                     }
2406                 }
2407
2408                 if (banksToSave && options.useXstack)
2409                 {
2410                     /* Since we aren't passing it an ic, 
2411                      * saveRBank will assume r0 is available to abuse.
2412                      *
2413                      * So switch to our (trashable) bank now, so
2414                      * the caller's R0 isn't trashed.
2415                      */
2416                     emitcode ("push", "psw");
2417                     emitcode ("mov", "psw,#0x%02x", 
2418                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2419                     switchedPSW = TRUE;
2420                 }
2421                 
2422                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2423                 {
2424                      if (banksToSave & (1 << ix))
2425                      {
2426                          saveRBank(ix, NULL, FALSE);
2427                      }
2428                 }
2429             }
2430             // jwk: this needs a closer look
2431             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2432         }
2433     }
2434   else
2435     {
2436       /* if callee-save to be used for this function
2437          then save the registers being used in this function */
2438       if (IFFUNC_CALLEESAVES(sym->type))
2439         {
2440           int i;
2441
2442           /* if any registers used */
2443           if (sym->regsUsed)
2444             {
2445               /* save the registers used */
2446               for (i = 0; i < sym->regsUsed->size; i++)
2447                 {
2448                   if (bitVectBitValue (sym->regsUsed, i) ||
2449                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2450                     {
2451                       /* remember one saved register for later usage */
2452                       if (calleesaves_saved_register < 0)
2453                         calleesaves_saved_register = i;
2454                       emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2455                       _G.nRegsSaved++;
2456                     }
2457                 }
2458             }
2459         }
2460     }
2461
2462   /* set the register bank to the desired value */
2463   if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2464    && !switchedPSW)
2465     {
2466       emitcode ("push", "psw");
2467       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2468     }
2469
2470   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2471     {
2472
2473       if (options.useXstack)
2474         {
2475           emitcode ("mov", "r0,%s", spname);
2476           emitcode ("mov", "a,_bp");
2477           emitcode ("movx", "@r0,a");
2478           emitcode ("inc", "%s", spname);
2479         }
2480       else
2481         {
2482           /* set up the stack */
2483           emitcode ("push", "_bp");     /* save the callers stack  */
2484         }
2485       emitcode ("mov", "_bp,%s", spname);
2486     }
2487
2488   /* adjust the stack for the function */
2489   if (sym->stack)
2490     {
2491
2492       int i = sym->stack;
2493       if (i > 256)
2494         werror (W_STACK_OVERFLOW, sym->name);
2495
2496       if (i > 3 && sym->recvSize < 4)
2497         {
2498
2499           emitcode ("mov", "a,sp");
2500           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2501           emitcode ("mov", "sp,a");
2502
2503         }
2504       else if (i > 5)
2505         {
2506           if (IFFUNC_CALLEESAVES(sym->type))
2507             {
2508               /* if it's a callee-saves function we need a saved register */
2509               if (calleesaves_saved_register >= 0)
2510                 {
2511                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2512                   emitcode ("mov", "a,sp");
2513                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2514                   emitcode ("mov", "sp,a");
2515                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2516                 }
2517               else
2518                 /* do it the hard way */
2519                 while (i--)
2520                   emitcode ("inc", "sp");
2521             }
2522           else
2523             {
2524               /* not callee-saves, we can clobber r0 */
2525               emitcode ("mov", "r0,a");
2526               emitcode ("mov", "a,sp");
2527               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2528               emitcode ("mov", "sp,a");
2529               emitcode ("mov", "a,r0");
2530             }
2531         }
2532       else
2533         while (i--)
2534           emitcode ("inc", "sp");
2535     }
2536
2537   if (sym->xstack)
2538     {
2539
2540       emitcode ("mov", "a,_spx");
2541       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2542       emitcode ("mov", "_spx,a");
2543     }
2544
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* genEndFunction - generates epilogue for functions               */
2549 /*-----------------------------------------------------------------*/
2550 static void
2551 genEndFunction (iCode * ic)
2552 {
2553   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2554
2555   if (IFFUNC_ISNAKED(sym->type))
2556   {
2557       emitcode(";", "naked function: no epilogue.");
2558       return;
2559   }
2560
2561   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2562     {
2563       emitcode ("mov", "%s,_bp", spname);
2564     }
2565
2566   /* if use external stack but some variables were
2567      added to the local stack then decrement the
2568      local stack */
2569   if (options.useXstack && sym->stack)
2570     {
2571       emitcode ("mov", "a,sp");
2572       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2573       emitcode ("mov", "sp,a");
2574     }
2575
2576
2577   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2578     {
2579       if (options.useXstack)
2580         {
2581           emitcode ("mov", "r0,%s", spname);
2582           emitcode ("movx", "a,@r0");
2583           emitcode ("mov", "_bp,a");
2584           emitcode ("dec", "%s", spname);
2585         }
2586       else
2587         {
2588           emitcode ("pop", "_bp");
2589         }
2590     }
2591
2592   /* restore the register bank  */
2593   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2594   {
2595     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2596      || !options.useXstack)
2597     {
2598         /* Special case of ISR using non-zero bank with useXstack
2599          * is handled below.
2600          */
2601         emitcode ("pop", "psw");
2602     }
2603   }
2604
2605   if (IFFUNC_ISISR (sym->type))
2606     {
2607
2608       /* now we need to restore the registers */
2609       /* if this isr has no bank i.e. is going to
2610          run with bank 0 , then we need to save more
2611          registers :-) */
2612       if (!FUNC_REGBANK (sym->type))
2613         {
2614           /* if this function does not call any other
2615              function then we can be economical and
2616              save only those registers that are used */
2617           if (!IFFUNC_HASFCALL(sym->type))
2618             {
2619               int i;
2620
2621               /* if any registers used */
2622               if (sym->regsUsed)
2623                 {
2624                   /* save the registers used */
2625                   for (i = sym->regsUsed->size; i >= 0; i--)
2626                     {
2627                       if (bitVectBitValue (sym->regsUsed, i) ||
2628                           (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2629                         emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2630                     }
2631                 }
2632
2633             }
2634           else
2635             {
2636               if (options.parms_in_bank1) {
2637                   int i;
2638                   for (i = 7 ; i >= 0 ; i-- ) {               
2639                       emitcode ("pop","%s",rb1regs[i]);
2640                   }
2641               }
2642               /* this function has  a function call cannot
2643                  determines register usage so we will have to pop the
2644                  entire bank */
2645               unsaveRBank (0, ic, FALSE);
2646             }
2647         }
2648         else
2649         {
2650             /* This ISR uses a non-zero bank.
2651              *
2652              * Restore any register banks saved by genFunction
2653              * in reverse order.
2654              */
2655           // jwk: this needs a closer look
2656             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2657             int ix;
2658           
2659             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2660             {
2661                 if (savedBanks & (1 << ix))
2662                 {
2663                     unsaveRBank(ix, NULL, FALSE);
2664                 }
2665             }
2666             
2667             if (options.useXstack)
2668             {
2669                 /* Restore bank AFTER calling unsaveRBank,
2670                  * since it can trash r0.
2671                  */
2672                 emitcode ("pop", "psw");
2673             }
2674         }
2675
2676       if (!inExcludeList ("dph"))
2677         emitcode ("pop", "dph");
2678       if (!inExcludeList ("dpl"))
2679         emitcode ("pop", "dpl");
2680       if (!inExcludeList ("b"))
2681         emitcode ("pop", "b");
2682       if (!inExcludeList ("acc"))
2683         emitcode ("pop", "acc");
2684
2685       if (IFFUNC_ISCRITICAL (sym->type))
2686         emitcode ("setb", "ea");
2687
2688       /* if debug then send end of function */
2689       if (options.debug && currFunc)
2690         {
2691           _G.debugLine = 1;
2692           emitcode ("", "C$%s$%d$%d$%d ==.",
2693                     FileBaseName (ic->filename), currFunc->lastLine,
2694                     ic->level, ic->block);
2695           if (IS_STATIC (currFunc->etype))
2696             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2697           else
2698             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2699           _G.debugLine = 0;
2700         }
2701
2702       emitcode ("reti", "");
2703     }
2704   else
2705     {
2706       if (IFFUNC_ISCRITICAL (sym->type))
2707         emitcode ("setb", "ea");
2708
2709       if (IFFUNC_CALLEESAVES(sym->type))
2710         {
2711           int i;
2712
2713           /* if any registers used */
2714           if (sym->regsUsed)
2715             {
2716               /* save the registers used */
2717               for (i = sym->regsUsed->size; i >= 0; i--)
2718                 {
2719                   if (bitVectBitValue (sym->regsUsed, i) ||
2720                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2721                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2722                 }
2723             }
2724
2725         }
2726
2727       /* if debug then send end of function */
2728       if (options.debug && currFunc)
2729         {
2730           _G.debugLine = 1;
2731           emitcode ("", "C$%s$%d$%d$%d ==.",
2732                     FileBaseName (ic->filename), currFunc->lastLine,
2733                     ic->level, ic->block);
2734           if (IS_STATIC (currFunc->etype))
2735             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2736           else
2737             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2738           _G.debugLine = 0;
2739         }
2740
2741       emitcode ("ret", "");
2742     }
2743
2744 }
2745
2746 /*-----------------------------------------------------------------*/
2747 /* genRet - generate code for return statement                     */
2748 /*-----------------------------------------------------------------*/
2749 static void
2750 genRet (iCode * ic)
2751 {
2752   int size, offset = 0, pushed = 0;
2753
2754   D(emitcode (";", "genRet"));
2755
2756   /* if we have no return value then
2757      just generate the "ret" */
2758   if (!IC_LEFT (ic))
2759     goto jumpret;
2760
2761   /* we have something to return then
2762      move the return value into place */
2763   aopOp (IC_LEFT (ic), ic, FALSE);
2764   size = AOP_SIZE (IC_LEFT (ic));
2765
2766   while (size--)
2767     {
2768       char *l;
2769       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2770         {
2771           /* #NOCHANGE */
2772           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2773                       FALSE, TRUE);
2774           emitcode ("push", "%s", l);
2775           pushed++;
2776         }
2777       else
2778         {
2779           l = aopGet (AOP (IC_LEFT (ic)), offset,
2780                       FALSE, FALSE);
2781           if (strcmp (fReturn[offset], l))
2782             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2783         }
2784     }
2785
2786   if (pushed)
2787     {
2788       while (pushed)
2789         {
2790           pushed--;
2791           if (strcmp (fReturn[pushed], "a"))
2792             emitcode ("pop", fReturn[pushed]);
2793           else
2794             emitcode ("pop", "acc");
2795         }
2796     }
2797   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2798
2799 jumpret:
2800   /* generate a jump to the return label
2801      if the next is not the return statement */
2802   if (!(ic->next && ic->next->op == LABEL &&
2803         IC_LABEL (ic->next) == returnLabel))
2804
2805     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2806
2807 }
2808
2809 /*-----------------------------------------------------------------*/
2810 /* genLabel - generates a label                                    */
2811 /*-----------------------------------------------------------------*/
2812 static void
2813 genLabel (iCode * ic)
2814 {
2815   /* special case never generate */
2816   if (IC_LABEL (ic) == entryLabel)
2817     return;
2818
2819   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2820 }
2821
2822 /*-----------------------------------------------------------------*/
2823 /* genGoto - generates a ljmp                                      */
2824 /*-----------------------------------------------------------------*/
2825 static void
2826 genGoto (iCode * ic)
2827 {
2828   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2829 }
2830
2831 /*-----------------------------------------------------------------*/
2832 /* findLabelBackwards: walks back through the iCode chain looking  */
2833 /* for the given label. Returns number of iCode instructions     */
2834 /* between that label and given ic.          */
2835 /* Returns zero if label not found.          */
2836 /*-----------------------------------------------------------------*/
2837 static int
2838 findLabelBackwards (iCode * ic, int key)
2839 {
2840   int count = 0;
2841
2842   while (ic->prev)
2843     {
2844       ic = ic->prev;
2845       count++;
2846
2847       /* If we have any pushes or pops, we cannot predict the distance.
2848          I don't like this at all, this should be dealt with in the 
2849          back-end */
2850       if (ic->op == IPUSH || ic->op == IPOP) {
2851         return 0;
2852       }
2853
2854       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2855         {
2856           return count;
2857         }
2858     }
2859
2860   return 0;
2861 }
2862
2863 /*-----------------------------------------------------------------*/
2864 /* genPlusIncr :- does addition with increment if possible         */
2865 /*-----------------------------------------------------------------*/
2866 static bool
2867 genPlusIncr (iCode * ic)
2868 {
2869   unsigned int icount;
2870   unsigned int size = getDataSize (IC_RESULT (ic));
2871
2872   /* will try to generate an increment */
2873   /* if the right side is not a literal
2874      we cannot */
2875   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2876     return FALSE;
2877
2878   /* if the literal value of the right hand side
2879      is greater than 4 then it is not worth it */
2880   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2881     return FALSE;
2882
2883   D(emitcode (";", "genPlusIncr"));
2884
2885   /* if increment 16 bits in register */
2886   if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2887       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && 
2888       (size > 1) &&
2889       (icount == 1))
2890     {
2891       symbol *tlbl;
2892       int emitTlbl;
2893       int labelRange;
2894
2895       /* If the next instruction is a goto and the goto target
2896        * is < 10 instructions previous to this, we can generate
2897        * jumps straight to that target.
2898        */
2899       if (ic->next && ic->next->op == GOTO
2900           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2901           && labelRange <= 10)
2902         {
2903           emitcode (";", "tail increment optimized");
2904           tlbl = IC_LABEL (ic->next);
2905           emitTlbl = 0;
2906         }
2907       else
2908         {
2909           tlbl = newiTempLabel (NULL);
2910           emitTlbl = 1;
2911         }
2912       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2913       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2914           IS_AOP_PREG (IC_RESULT (ic)))
2915         emitcode ("cjne", "%s,#0x00,%05d$",
2916                   aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2917                   tlbl->key + 100);
2918       else
2919         {
2920           emitcode ("clr", "a");
2921           emitcode ("cjne", "a,%s,%05d$",
2922                     aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2923                     tlbl->key + 100);
2924         }
2925
2926       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2927       if (size > 2)
2928         {
2929           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2930               IS_AOP_PREG (IC_RESULT (ic)))
2931             emitcode ("cjne", "%s,#0x00,%05d$",
2932                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2933                       tlbl->key + 100);
2934           else
2935             emitcode ("cjne", "a,%s,%05d$",
2936                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2937                       tlbl->key + 100);
2938
2939           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2940         }
2941       if (size > 3)
2942         {
2943           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2944               IS_AOP_PREG (IC_RESULT (ic)))
2945             emitcode ("cjne", "%s,#0x00,%05d$",
2946                       aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2947                       tlbl->key + 100);
2948           else
2949             {
2950               emitcode ("cjne", "a,%s,%05d$",
2951                         aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2952                         tlbl->key + 100);
2953             }
2954           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2955         }
2956
2957       if (emitTlbl)
2958         {
2959           emitcode ("", "%05d$:", tlbl->key + 100);
2960         }
2961       return TRUE;
2962     }
2963
2964   /* if the sizes are greater than 1 then we cannot */
2965   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2966       AOP_SIZE (IC_LEFT (ic)) > 1)
2967     return FALSE;
2968
2969   /* we can if the aops of the left & result match or
2970      if they are in registers and the registers are the
2971      same */
2972   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2973     {
2974
2975       if (icount > 3)
2976         {
2977           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2978           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2979           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2980         }
2981       else
2982         {
2983
2984           while (icount--)
2985             emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2986         }
2987
2988       return TRUE;
2989     }
2990
2991   return FALSE;
2992 }
2993
2994 /*-----------------------------------------------------------------*/
2995 /* outBitAcc - output a bit in acc                                 */
2996 /*-----------------------------------------------------------------*/
2997 static void
2998 outBitAcc (operand * result)
2999 {
3000   symbol *tlbl = newiTempLabel (NULL);
3001   /* if the result is a bit */
3002   if (AOP_TYPE (result) == AOP_CRY)
3003     {
3004       aopPut (AOP (result), "a", 0);
3005     }
3006   else
3007     {
3008       emitcode ("jz", "%05d$", tlbl->key + 100);
3009       emitcode ("mov", "a,%s", one);
3010       emitcode ("", "%05d$:", tlbl->key + 100);
3011       outAcc (result);
3012     }
3013 }
3014
3015 /*-----------------------------------------------------------------*/
3016 /* genPlusBits - generates code for addition of two bits           */
3017 /*-----------------------------------------------------------------*/
3018 static void
3019 genPlusBits (iCode * ic)
3020 {
3021   D(emitcode (";", "genPlusBits"));
3022
3023   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3024     {
3025       symbol *lbl = newiTempLabel (NULL);
3026       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3027       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3028       emitcode ("cpl", "c");
3029       emitcode ("", "%05d$:", (lbl->key + 100));
3030       outBitC (IC_RESULT (ic));
3031     }
3032   else
3033     {
3034       emitcode ("clr", "a");
3035       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3036       emitcode ("rlc", "a");
3037       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3038       emitcode ("addc", "a,#0x00");
3039       outAcc (IC_RESULT (ic));
3040     }
3041 }
3042
3043 #if 0
3044 /* This is the original version of this code.
3045
3046  * This is being kept around for reference,
3047  * because I am not entirely sure I got it right...
3048  */
3049 static void
3050 adjustArithmeticResult (iCode * ic)
3051 {
3052   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3053       AOP_SIZE (IC_LEFT (ic)) == 3 &&
3054       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3055     aopPut (AOP (IC_RESULT (ic)),
3056             aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3057             2);
3058
3059   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3060       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3061       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3062     aopPut (AOP (IC_RESULT (ic)),
3063             aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3064             2);
3065
3066   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3067       AOP_SIZE (IC_LEFT (ic)) < 3 &&
3068       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3069       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3070       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3071     {
3072       char buffer[5];
3073       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3074       aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3075     }
3076 }
3077 #else
3078 /* This is the pure and virtuous version of this code.
3079  * I'm pretty certain it's right, but not enough to toss the old
3080  * code just yet...
3081  */
3082 static void
3083 adjustArithmeticResult (iCode * ic)
3084 {
3085   if (opIsGptr (IC_RESULT (ic)) &&
3086       opIsGptr (IC_LEFT (ic)) &&
3087       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3088     {
3089       aopPut (AOP (IC_RESULT (ic)),
3090               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3091               GPTRSIZE - 1);
3092     }
3093
3094   if (opIsGptr (IC_RESULT (ic)) &&
3095       opIsGptr (IC_RIGHT (ic)) &&
3096       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3097     {
3098       aopPut (AOP (IC_RESULT (ic)),
3099               aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3100               GPTRSIZE - 1);
3101     }
3102
3103   if (opIsGptr (IC_RESULT (ic)) &&
3104       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3105       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3106       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3107       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3108     {
3109       char buffer[5];
3110       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3111       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3112     }
3113 }
3114 #endif
3115
3116 /*-----------------------------------------------------------------*/
3117 /* genPlus - generates code for addition                           */
3118 /*-----------------------------------------------------------------*/
3119 static void
3120 genPlus (iCode * ic)
3121 {
3122   int size, offset = 0;
3123   char *add;
3124   asmop *leftOp, *rightOp;
3125
3126   /* special cases :- */
3127
3128   D(emitcode (";", "genPlus"));
3129
3130   aopOp (IC_LEFT (ic), ic, FALSE);
3131   aopOp (IC_RIGHT (ic), ic, FALSE);
3132   aopOp (IC_RESULT (ic), ic, TRUE);
3133
3134   /* if literal, literal on the right or
3135      if left requires ACC or right is already
3136      in ACC */
3137   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3138       (AOP_NEEDSACC (IC_LEFT (ic))) ||
3139       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3140     {
3141       operand *t = IC_RIGHT (ic);
3142       IC_RIGHT (ic) = IC_LEFT (ic);
3143       IC_LEFT (ic) = t;
3144     }
3145
3146   /* if both left & right are in bit
3147      space */
3148   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3149       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3150     {
3151       genPlusBits (ic);
3152       goto release;
3153     }
3154
3155   /* if left in bit space & right literal */
3156   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3157       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3158     {
3159       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3160       /* if result in bit space */
3161       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3162         {
3163           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3164             emitcode ("cpl", "c");
3165           outBitC (IC_RESULT (ic));
3166         }
3167       else
3168         {
3169           size = getDataSize (IC_RESULT (ic));
3170           while (size--)
3171             {
3172               MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3173               emitcode ("addc", "a,#00");
3174               aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3175             }
3176         }
3177       goto release;
3178     }
3179
3180   /* if I can do an increment instead
3181      of add then GOOD for ME */
3182   if (genPlusIncr (ic) == TRUE)
3183     goto release;
3184
3185   size = getDataSize (IC_RESULT (ic));
3186
3187   leftOp = AOP(IC_LEFT(ic));
3188   rightOp = AOP(IC_RIGHT(ic));
3189   add = "add";
3190
3191   while (size--)
3192     {
3193       if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3194         {
3195           emitcode("mov", "b,a");
3196           MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
3197           emitcode("xch", "a,b");
3198           MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3199           emitcode (add, "a,b");
3200         }
3201       else if (aopGetUsesAcc (leftOp, offset))
3202         {
3203           MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3204           emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3205         }
3206       else
3207         {
3208           MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3209           emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3210         }
3211       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3212       add = "addc";  /* further adds must propagate carry */
3213     }
3214
3215   adjustArithmeticResult (ic);
3216
3217 release:
3218   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3219   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3220   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /* genMinusDec :- does subtraction with deccrement if possible     */
3225 /*-----------------------------------------------------------------*/
3226 static bool
3227 genMinusDec (iCode * ic)
3228 {
3229   unsigned int icount;
3230   unsigned int size = getDataSize (IC_RESULT (ic));
3231
3232   /* will try to generate an increment */
3233   /* if the right side is not a literal
3234      we cannot */
3235   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3236     return FALSE;
3237
3238   /* if the literal value of the right hand side
3239      is greater than 4 then it is not worth it */
3240   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3241     return FALSE;
3242
3243   D(emitcode (";", "genMinusDec"));
3244
3245   /* if decrement 16 bits in register */
3246   if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3247       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3248       (size > 1) &&
3249       (icount == 1))
3250     {
3251       symbol *tlbl;
3252       int emitTlbl;
3253       int labelRange;
3254
3255       /* If the next instruction is a goto and the goto target
3256        * is <= 10 instructions previous to this, we can generate
3257        * jumps straight to that target.
3258        */
3259       if (ic->next && ic->next->op == GOTO
3260           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3261           && labelRange <= 10)
3262         {
3263           emitcode (";", "tail decrement optimized");
3264           tlbl = IC_LABEL (ic->next);
3265           emitTlbl = 0;
3266         }
3267       else
3268         {
3269           tlbl = newiTempLabel (NULL);
3270           emitTlbl = 1;
3271         }
3272
3273       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3274       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3275           IS_AOP_PREG (IC_RESULT (ic)))
3276         emitcode ("cjne", "%s,#0xff,%05d$"
3277                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3278                   ,tlbl->key + 100);
3279       else
3280         {
3281           emitcode ("mov", "a,#0xff");
3282           emitcode ("cjne", "a,%s,%05d$"
3283                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3284                     ,tlbl->key + 100);
3285         }
3286       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3287       if (size > 2)
3288         {
3289           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3290               IS_AOP_PREG (IC_RESULT (ic)))
3291             emitcode ("cjne", "%s,#0xff,%05d$"
3292                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3293                       ,tlbl->key + 100);
3294           else
3295             {
3296               emitcode ("cjne", "a,%s,%05d$"
3297                         ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3298                         ,tlbl->key + 100);
3299             }
3300           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3301         }
3302       if (size > 3)
3303         {
3304           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3305               IS_AOP_PREG (IC_RESULT (ic)))
3306             emitcode ("cjne", "%s,#0xff,%05d$"
3307                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3308                       ,tlbl->key + 100);
3309           else
3310             {
3311               emitcode ("cjne", "a,%s,%05d$"
3312                         ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3313                         ,tlbl->key + 100);
3314             }
3315           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3316         }
3317       if (emitTlbl)
3318         {
3319           emitcode ("", "%05d$:", tlbl->key + 100);
3320         }
3321       return TRUE;
3322     }
3323
3324   /* if the sizes are greater than 1 then we cannot */
3325   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3326       AOP_SIZE (IC_LEFT (ic)) > 1)
3327     return FALSE;
3328
3329   /* we can if the aops of the left & result match or
3330      if they are in registers and the registers are the
3331      same */
3332   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3333     {
3334
3335       while (icount--)
3336         emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3337
3338       return TRUE;
3339     }
3340
3341   return FALSE;
3342 }
3343
3344 /*-----------------------------------------------------------------*/
3345 /* addSign - complete with sign                                    */
3346 /*-----------------------------------------------------------------*/
3347 static void
3348 addSign (operand * result, int offset, int sign)
3349 {
3350   int size = (getDataSize (result) - offset);
3351   if (size > 0)
3352     {
3353       if (sign)
3354         {
3355           emitcode ("rlc", "a");
3356           emitcode ("subb", "a,acc");
3357           while (size--)
3358             aopPut (AOP (result), "a", offset++);
3359         }
3360       else
3361         while (size--)
3362           aopPut (AOP (result), zero, offset++);
3363     }
3364 }
3365
3366 /*-----------------------------------------------------------------*/
3367 /* genMinusBits - generates code for subtraction  of two bits      */
3368 /*-----------------------------------------------------------------*/
3369 static void
3370 genMinusBits (iCode * ic)
3371 {
3372   symbol *lbl = newiTempLabel (NULL);
3373
3374   D(emitcode (";", "genMinusBits"));
3375
3376   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3377     {
3378       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3379       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3380       emitcode ("cpl", "c");
3381       emitcode ("", "%05d$:", (lbl->key + 100));
3382       outBitC (IC_RESULT (ic));
3383     }
3384   else
3385     {
3386       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3387       emitcode ("subb", "a,acc");
3388       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3389       emitcode ("inc", "a");
3390       emitcode ("", "%05d$:", (lbl->key + 100));
3391       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3392       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3393     }
3394 }
3395
3396 /*-----------------------------------------------------------------*/
3397 /* genMinus - generates code for subtraction                       */
3398 /*-----------------------------------------------------------------*/
3399 static void
3400 genMinus (iCode * ic)
3401 {
3402   int size, offset = 0;
3403
3404   D(emitcode (";", "genMinus"));
3405
3406   aopOp (IC_LEFT (ic), ic, FALSE);
3407   aopOp (IC_RIGHT (ic), ic, FALSE);
3408   aopOp (IC_RESULT (ic), ic, TRUE);
3409
3410   /* special cases :- */
3411   /* if both left & right are in bit space */
3412   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3413       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3414     {
3415       genMinusBits (ic);
3416       goto release;
3417     }
3418
3419   /* if I can do an decrement instead
3420      of subtract then GOOD for ME */
3421   if (genMinusDec (ic) == TRUE)
3422     goto release;
3423
3424   size = getDataSize (IC_RESULT (ic));
3425
3426   /* if literal, add a,#-lit, else normal subb */
3427   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3428     {
3429       unsigned long lit = 0L;
3430
3431       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3432       lit = -(long) lit;
3433
3434       while (size--)
3435         {
3436           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3437           /* first add without previous c */
3438           if (!offset) {
3439             if (!size && lit==-1) {
3440               emitcode ("dec", "a");
3441             } else {
3442               emitcode ("add", "a,#0x%02x", 
3443                         (unsigned int) (lit & 0x0FFL));
3444             }
3445           } else {
3446             emitcode ("addc", "a,#0x%02x",
3447                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3448           }
3449           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3450         }
3451     }
3452   else
3453     {
3454       asmop *leftOp, *rightOp;
3455
3456       leftOp = AOP(IC_LEFT(ic));
3457       rightOp = AOP(IC_RIGHT(ic));
3458
3459       while (size--)
3460         {
3461           if (aopGetUsesAcc(rightOp, offset)) {
3462             wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3463             MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3464             if (offset > 0) {
3465               emitcode( "cpl", "c");
3466             } else {
3467               emitcode( "setb", "c");
3468             }
3469             emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3470             emitcode("cpl", "a");
3471           } else {
3472             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3473             if (offset == 0)
3474               CLRC;
3475             emitcode ("subb", "a,%s",
3476                       aopGet(rightOp, offset, FALSE, TRUE));
3477           }
3478
3479           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
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 = 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 = 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 }