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