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