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