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