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