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