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