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