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