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