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