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