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