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