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