src/mcs51/gen.c (genCpl): fixed bug http://sf.net/mailarchive/message.php?msg_id...
[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       emitcode ("mov", "c,ea");
2608       emitcode ("push", "psw"); /* save old ea via c in psw */
2609       emitcode ("clr", "ea");
2610     }
2611 }
2612
2613 /*-----------------------------------------------------------------*/
2614 /* genEndFunction - generates epilogue for functions               */
2615 /*-----------------------------------------------------------------*/
2616 static void
2617 genEndFunction (iCode * ic)
2618 {
2619   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2620
2621   if (IFFUNC_ISNAKED(sym->type))
2622   {
2623       emitcode(";", "naked function: no epilogue.");
2624       return;
2625   }
2626       
2627   if (IFFUNC_ISCRITICAL (sym->type))
2628     {
2629       emitcode ("pop", "psw"); /* restore ea via c in psw */
2630       emitcode ("mov", "ea,c");
2631     }
2632
2633   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2634     {
2635       emitcode ("mov", "%s,_bp", spname);
2636     }
2637
2638   /* if use external stack but some variables were
2639      added to the local stack then decrement the
2640      local stack */
2641   if (options.useXstack && sym->stack)
2642     {
2643       emitcode ("mov", "a,sp");
2644       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2645       emitcode ("mov", "sp,a");
2646     }
2647
2648
2649   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2650     {
2651       if (options.useXstack)
2652         {
2653           emitcode ("mov", "r0,%s", spname);
2654           emitcode ("movx", "a,@r0");
2655           emitcode ("mov", "_bp,a");
2656           emitcode ("dec", "%s", spname);
2657         }
2658       else
2659         {
2660           emitcode ("pop", "_bp");
2661         }
2662     }
2663
2664   /* restore the register bank  */
2665   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2666   {
2667     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2668      || !options.useXstack)
2669     {
2670         /* Special case of ISR using non-zero bank with useXstack
2671          * is handled below.
2672          */
2673         emitcode ("pop", "psw");
2674     }
2675   }
2676
2677   if (IFFUNC_ISISR (sym->type))
2678     {
2679
2680       /* now we need to restore the registers */
2681       /* if this isr has no bank i.e. is going to
2682          run with bank 0 , then we need to save more
2683          registers :-) */
2684       if (!FUNC_REGBANK (sym->type))
2685         {
2686           /* if this function does not call any other
2687              function then we can be economical and
2688              save only those registers that are used */
2689           if (!IFFUNC_HASFCALL(sym->type))
2690             {
2691               int i;
2692
2693               /* if any registers used */
2694               if (sym->regsUsed)
2695                 {
2696                   /* save the registers used */
2697                   for (i = sym->regsUsed->size; i >= 0; i--)
2698                     {
2699                       if (bitVectBitValue (sym->regsUsed, i) ||
2700                           (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2701                         emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2702                     }
2703                 }
2704
2705             }
2706           else
2707             {
2708               if (options.parms_in_bank1) {
2709                   int i;
2710                   for (i = 7 ; i >= 0 ; i-- ) {               
2711                       emitcode ("pop","%s",rb1regs[i]);
2712                   }
2713               }
2714               /* this function has  a function call cannot
2715                  determines register usage so we will have to pop the
2716                  entire bank */
2717               unsaveRBank (0, ic, FALSE);
2718             }
2719         }
2720         else
2721         {
2722             /* This ISR uses a non-zero bank.
2723              *
2724              * Restore any register banks saved by genFunction
2725              * in reverse order.
2726              */
2727             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2728             int ix;
2729           
2730             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2731             {
2732                 if (savedBanks & (1 << ix))
2733                 {
2734                     unsaveRBank(ix, NULL, FALSE);
2735                 }
2736             }
2737             
2738             if (options.useXstack)
2739             {
2740                 /* Restore bank AFTER calling unsaveRBank,
2741                  * since it can trash r0.
2742                  */
2743                 emitcode ("pop", "psw");
2744             }
2745         }
2746
2747       if (!inExcludeList ("dph"))
2748         emitcode ("pop", "dph");
2749       if (!inExcludeList ("dpl"))
2750         emitcode ("pop", "dpl");
2751       if (!inExcludeList ("b"))
2752         emitcode ("pop", "b");
2753       if (!inExcludeList ("acc"))
2754         emitcode ("pop", "acc");
2755
2756       /* if debug then send end of function */
2757       if (options.debug && currFunc)
2758         {
2759           _G.debugLine = 1;
2760           emitcode ("", "C$%s$%d$%d$%d ==.",
2761                     FileBaseName (ic->filename), currFunc->lastLine,
2762                     ic->level, ic->block);
2763           if (IS_STATIC (currFunc->etype))
2764             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2765           else
2766             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2767           _G.debugLine = 0;
2768         }
2769
2770       emitcode ("reti", "");
2771     }
2772   else
2773     {
2774       if (IFFUNC_CALLEESAVES(sym->type))
2775         {
2776           int i;
2777
2778           /* if any registers used */
2779           if (sym->regsUsed)
2780             {
2781               /* save the registers used */
2782               for (i = sym->regsUsed->size; i >= 0; i--)
2783                 {
2784                   if (bitVectBitValue (sym->regsUsed, i) ||
2785                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2786                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2787                 }
2788             }
2789
2790         }
2791
2792       /* if debug then send end of function */
2793       if (options.debug && currFunc)
2794         {
2795           _G.debugLine = 1;
2796           emitcode ("", "C$%s$%d$%d$%d ==.",
2797                     FileBaseName (ic->filename), currFunc->lastLine,
2798                     ic->level, ic->block);
2799           if (IS_STATIC (currFunc->etype))
2800             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2801           else
2802             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2803           _G.debugLine = 0;
2804         }
2805
2806       emitcode ("ret", "");
2807     }
2808
2809 }
2810
2811 /*-----------------------------------------------------------------*/
2812 /* genRet - generate code for return statement                     */
2813 /*-----------------------------------------------------------------*/
2814 static void
2815 genRet (iCode * ic)
2816 {
2817   int size, offset = 0, pushed = 0;
2818
2819   D(emitcode (";     genRet",""));
2820
2821   /* if we have no return value then
2822      just generate the "ret" */
2823   if (!IC_LEFT (ic))
2824     goto jumpret;
2825
2826   /* we have something to return then
2827      move the return value into place */
2828   aopOp (IC_LEFT (ic), ic, FALSE);
2829   size = AOP_SIZE (IC_LEFT (ic));
2830
2831   while (size--)
2832     {
2833       char *l;
2834       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2835         {
2836           /* #NOCHANGE */
2837           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2838                       FALSE, TRUE);
2839           emitcode ("push", "%s", l);
2840           pushed++;
2841         }
2842       else
2843         {
2844           l = aopGet (AOP (IC_LEFT (ic)), offset,
2845                       FALSE, FALSE);
2846           if (strcmp (fReturn[offset], l))
2847             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2848         }
2849     }
2850
2851   if (pushed)
2852     {
2853       while (pushed)
2854         {
2855           pushed--;
2856           if (strcmp (fReturn[pushed], "a"))
2857             emitcode ("pop", fReturn[pushed]);
2858           else
2859             emitcode ("pop", "acc");
2860         }
2861     }
2862   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2863
2864 jumpret:
2865   /* generate a jump to the return label
2866      if the next is not the return statement */
2867   if (!(ic->next && ic->next->op == LABEL &&
2868         IC_LABEL (ic->next) == returnLabel))
2869
2870     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2871
2872 }
2873
2874 /*-----------------------------------------------------------------*/
2875 /* genLabel - generates a label                                    */
2876 /*-----------------------------------------------------------------*/
2877 static void
2878 genLabel (iCode * ic)
2879 {
2880   /* special case never generate */
2881   if (IC_LABEL (ic) == entryLabel)
2882     return;
2883
2884   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2885 }
2886
2887 /*-----------------------------------------------------------------*/
2888 /* genGoto - generates a ljmp                                      */
2889 /*-----------------------------------------------------------------*/
2890 static void
2891 genGoto (iCode * ic)
2892 {
2893   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2894 }
2895
2896 /*-----------------------------------------------------------------*/
2897 /* findLabelBackwards: walks back through the iCode chain looking  */
2898 /* for the given label. Returns number of iCode instructions     */
2899 /* between that label and given ic.          */
2900 /* Returns zero if label not found.          */
2901 /*-----------------------------------------------------------------*/
2902 static int
2903 findLabelBackwards (iCode * ic, int key)
2904 {
2905   int count = 0;
2906
2907   while (ic->prev)
2908     {
2909       ic = ic->prev;
2910       count++;
2911
2912       /* If we have any pushes or pops, we cannot predict the distance.
2913          I don't like this at all, this should be dealt with in the 
2914          back-end */
2915       if (ic->op == IPUSH || ic->op == IPOP) {
2916         return 0;
2917       }
2918
2919       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2920         {
2921           return count;
2922         }
2923     }
2924
2925   return 0;
2926 }
2927
2928 /*-----------------------------------------------------------------*/
2929 /* genPlusIncr :- does addition with increment if possible         */
2930 /*-----------------------------------------------------------------*/
2931 static bool
2932 genPlusIncr (iCode * ic)
2933 {
2934   unsigned int icount;
2935   unsigned int size = getDataSize (IC_RESULT (ic));
2936
2937   /* will try to generate an increment */
2938   /* if the right side is not a literal
2939      we cannot */
2940   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2941     return FALSE;
2942
2943   /* if the literal value of the right hand side
2944      is greater than 4 then it is not worth it */
2945   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2946     return FALSE;
2947
2948   D(emitcode (";     genPlusIncr",""));
2949
2950   /* if increment >=16 bits in register or direct space */
2951   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2952       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && 
2953       (size > 1) &&
2954       (icount == 1))
2955     {
2956       symbol *tlbl;
2957       int emitTlbl;
2958       int labelRange;
2959
2960       /* If the next instruction is a goto and the goto target
2961        * is < 10 instructions previous to this, we can generate
2962        * jumps straight to that target.
2963        */
2964       if (ic->next && ic->next->op == GOTO
2965           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2966           && labelRange <= 10)
2967         {
2968           emitcode (";", "tail increment optimized");
2969           tlbl = IC_LABEL (ic->next);
2970           emitTlbl = 0;
2971         }
2972       else
2973         {
2974           tlbl = newiTempLabel (NULL);
2975           emitTlbl = 1;
2976         }
2977       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2978       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2979           IS_AOP_PREG (IC_RESULT (ic)))
2980         emitcode ("cjne", "%s,#0x00,%05d$",
2981                   aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2982                   tlbl->key + 100);
2983       else
2984         {
2985           emitcode ("clr", "a");
2986           emitcode ("cjne", "a,%s,%05d$",
2987                     aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2988                     tlbl->key + 100);
2989         }
2990
2991       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2992       if (size > 2)
2993         {
2994           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2995               IS_AOP_PREG (IC_RESULT (ic)))
2996             emitcode ("cjne", "%s,#0x00,%05d$",
2997                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2998                       tlbl->key + 100);
2999           else
3000             emitcode ("cjne", "a,%s,%05d$",
3001                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3002                       tlbl->key + 100);
3003
3004           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3005         }
3006       if (size > 3)
3007         {
3008           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3009               IS_AOP_PREG (IC_RESULT (ic)))
3010             emitcode ("cjne", "%s,#0x00,%05d$",
3011                       aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3012                       tlbl->key + 100);
3013           else
3014             {
3015               emitcode ("cjne", "a,%s,%05d$",
3016                         aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3017                         tlbl->key + 100);
3018             }
3019           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3020         }
3021
3022       if (emitTlbl)
3023         {
3024           emitcode ("", "%05d$:", tlbl->key + 100);
3025         }
3026       return TRUE;
3027     }
3028
3029   /* if the sizes are greater than 1 then we cannot */
3030   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3031       AOP_SIZE (IC_LEFT (ic)) > 1)
3032     return FALSE;
3033
3034   /* we can if the aops of the left & result match or
3035      if they are in registers and the registers are the
3036      same */
3037   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3038     {
3039
3040       if (icount > 3)
3041         {
3042           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3043           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3044           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3045         }
3046       else
3047         {
3048
3049           while (icount--)
3050             emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3051         }
3052
3053       return TRUE;
3054     }
3055
3056   return FALSE;
3057 }
3058
3059 /*-----------------------------------------------------------------*/
3060 /* outBitAcc - output a bit in acc                                 */
3061 /*-----------------------------------------------------------------*/
3062 static void
3063 outBitAcc (operand * result)
3064 {
3065   symbol *tlbl = newiTempLabel (NULL);
3066   /* if the result is a bit */
3067   if (AOP_TYPE (result) == AOP_CRY)
3068     {
3069       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3070     }
3071   else
3072     {
3073       emitcode ("jz", "%05d$", tlbl->key + 100);
3074       emitcode ("mov", "a,%s", one);
3075       emitcode ("", "%05d$:", tlbl->key + 100);
3076       outAcc (result);
3077     }
3078 }
3079
3080 /*-----------------------------------------------------------------*/
3081 /* genPlusBits - generates code for addition of two bits           */
3082 /*-----------------------------------------------------------------*/
3083 static void
3084 genPlusBits (iCode * ic)
3085 {
3086   D(emitcode (";     genPlusBits",""));
3087
3088   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3089     {
3090       symbol *lbl = newiTempLabel (NULL);
3091       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3092       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3093       emitcode ("cpl", "c");
3094       emitcode ("", "%05d$:", (lbl->key + 100));
3095       outBitC (IC_RESULT (ic));
3096     }
3097   else
3098     {
3099       emitcode ("clr", "a");
3100       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3101       emitcode ("rlc", "a");
3102       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3103       emitcode ("addc", "a,#0x00");
3104       outAcc (IC_RESULT (ic));
3105     }
3106 }
3107
3108 #if 0
3109 /* This is the original version of this code.
3110
3111  * This is being kept around for reference,
3112  * because I am not entirely sure I got it right...
3113  */
3114 static void
3115 adjustArithmeticResult (iCode * ic)
3116 {
3117   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3118       AOP_SIZE (IC_LEFT (ic)) == 3 &&
3119       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3120     aopPut (AOP (IC_RESULT (ic)),
3121             aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3122             2,
3123             isOperandVolatile (IC_RESULT (ic), FALSE));
3124
3125   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3126       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3127       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3128     aopPut (AOP (IC_RESULT (ic)),
3129             aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3130             2,
3131             isOperandVolatile (IC_RESULT (ic), FALSE));
3132
3133   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3134       AOP_SIZE (IC_LEFT (ic)) < 3 &&
3135       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3136       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3137       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3138     {
3139       char buffer[5];
3140       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3141       aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3142     }
3143 }
3144 #else
3145 /* This is the pure and virtuous version of this code.
3146  * I'm pretty certain it's right, but not enough to toss the old
3147  * code just yet...
3148  */
3149 static void
3150 adjustArithmeticResult (iCode * ic)
3151 {
3152   if (opIsGptr (IC_RESULT (ic)) &&
3153       opIsGptr (IC_LEFT (ic)) &&
3154       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3155     {
3156       aopPut (AOP (IC_RESULT (ic)),
3157               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3158               GPTRSIZE - 1,
3159               isOperandVolatile (IC_RESULT (ic), FALSE));
3160     }
3161
3162   if (opIsGptr (IC_RESULT (ic)) &&
3163       opIsGptr (IC_RIGHT (ic)) &&
3164       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3165     {
3166       aopPut (AOP (IC_RESULT (ic)),
3167               aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3168               GPTRSIZE - 1,
3169               isOperandVolatile (IC_RESULT (ic), FALSE));
3170     }
3171
3172   if (opIsGptr (IC_RESULT (ic)) &&
3173       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3174       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3175       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3176       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3177     {
3178       char buffer[5];
3179       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3180       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3181     }
3182 }
3183 #endif
3184
3185 /*-----------------------------------------------------------------*/
3186 /* genPlus - generates code for addition                           */
3187 /*-----------------------------------------------------------------*/
3188 static void
3189 genPlus (iCode * ic)
3190 {
3191   int size, offset = 0;
3192   char *add;
3193   asmop *leftOp, *rightOp;
3194
3195   /* special cases :- */
3196
3197   D(emitcode (";     genPlus",""));
3198
3199   aopOp (IC_LEFT (ic), ic, FALSE);
3200   aopOp (IC_RIGHT (ic), ic, FALSE);
3201   aopOp (IC_RESULT (ic), ic, TRUE);
3202
3203   /* if literal, literal on the right or
3204      if left requires ACC or right is already
3205      in ACC */
3206   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3207       (AOP_NEEDSACC (IC_LEFT (ic))) ||
3208       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3209     {
3210       operand *t = IC_RIGHT (ic);
3211       IC_RIGHT (ic) = IC_LEFT (ic);
3212       IC_LEFT (ic) = t;
3213     }
3214
3215   /* if both left & right are in bit
3216      space */
3217   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3218       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3219     {
3220       genPlusBits (ic);
3221       goto release;
3222     }
3223
3224   /* if left in bit space & right literal */
3225   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3226       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3227     {
3228       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3229       /* if result in bit space */
3230       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3231         {
3232           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3233             emitcode ("cpl", "c");
3234           outBitC (IC_RESULT (ic));
3235         }
3236       else
3237         {
3238           size = getDataSize (IC_RESULT (ic));
3239           while (size--)
3240             {
3241               MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3242               emitcode ("addc", "a,#00");
3243               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3244             }
3245         }
3246       goto release;
3247     }
3248
3249   /* if I can do an increment instead
3250      of add then GOOD for ME */
3251   if (genPlusIncr (ic) == TRUE)
3252     goto release;
3253
3254   size = getDataSize (IC_RESULT (ic));
3255
3256   leftOp = AOP(IC_LEFT(ic));
3257   rightOp = AOP(IC_RIGHT(ic));
3258   add = "add";
3259
3260   while (size--)
3261     {
3262       if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3263         {
3264           emitcode("mov", "b,a");
3265           MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
3266           emitcode("xch", "a,b");
3267           MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3268           emitcode (add, "a,b");
3269         }
3270       else if (aopGetUsesAcc (leftOp, offset))
3271         {
3272           MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3273           emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3274         }
3275       else
3276         {
3277           MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3278           emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3279         }
3280       aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3281       add = "addc";  /* further adds must propagate carry */
3282     }
3283
3284   adjustArithmeticResult (ic);
3285
3286 release:
3287   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3288   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3289   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3290 }
3291
3292 /*-----------------------------------------------------------------*/
3293 /* genMinusDec :- does subtraction with deccrement if possible     */
3294 /*-----------------------------------------------------------------*/
3295 static bool
3296 genMinusDec (iCode * ic)
3297 {
3298   unsigned int icount;
3299   unsigned int size = getDataSize (IC_RESULT (ic));
3300
3301   /* will try to generate an increment */
3302   /* if the right side is not a literal
3303      we cannot */
3304   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3305     return FALSE;
3306
3307   /* if the literal value of the right hand side
3308      is greater than 4 then it is not worth it */
3309   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3310     return FALSE;
3311
3312   D(emitcode (";     genMinusDec",""));
3313
3314   /* if decrement >=16 bits in register or direct space */
3315   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3316       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3317       (size > 1) &&
3318       (icount == 1))
3319     {
3320       symbol *tlbl;
3321       int emitTlbl;
3322       int labelRange;
3323
3324       /* If the next instruction is a goto and the goto target
3325        * is <= 10 instructions previous to this, we can generate
3326        * jumps straight to that target.
3327        */
3328       if (ic->next && ic->next->op == GOTO
3329           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3330           && labelRange <= 10)
3331         {
3332           emitcode (";", "tail decrement optimized");
3333           tlbl = IC_LABEL (ic->next);
3334           emitTlbl = 0;
3335         }
3336       else
3337         {
3338           tlbl = newiTempLabel (NULL);
3339           emitTlbl = 1;
3340         }
3341
3342       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3343       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3344           IS_AOP_PREG (IC_RESULT (ic)))
3345         emitcode ("cjne", "%s,#0xff,%05d$"
3346                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3347                   ,tlbl->key + 100);
3348       else
3349         {
3350           emitcode ("mov", "a,#0xff");
3351           emitcode ("cjne", "a,%s,%05d$"
3352                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3353                     ,tlbl->key + 100);
3354         }
3355       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3356       if (size > 2)
3357         {
3358           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3359               IS_AOP_PREG (IC_RESULT (ic)))
3360             emitcode ("cjne", "%s,#0xff,%05d$"
3361                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3362                       ,tlbl->key + 100);
3363           else
3364             {
3365               emitcode ("cjne", "a,%s,%05d$"
3366                         ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3367                         ,tlbl->key + 100);
3368             }
3369           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3370         }
3371       if (size > 3)
3372         {
3373           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3374               IS_AOP_PREG (IC_RESULT (ic)))
3375             emitcode ("cjne", "%s,#0xff,%05d$"
3376                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3377                       ,tlbl->key + 100);
3378           else
3379             {
3380               emitcode ("cjne", "a,%s,%05d$"
3381                         ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3382                         ,tlbl->key + 100);
3383             }
3384           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3385         }
3386       if (emitTlbl)
3387         {
3388           emitcode ("", "%05d$:", tlbl->key + 100);
3389         }
3390       return TRUE;
3391     }
3392
3393   /* if the sizes are greater than 1 then we cannot */
3394   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3395       AOP_SIZE (IC_LEFT (ic)) > 1)
3396     return FALSE;
3397
3398   /* we can if the aops of the left & result match or
3399      if they are in registers and the registers are the
3400      same */
3401   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3402     {
3403
3404       while (icount--)
3405         emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3406
3407       return TRUE;
3408     }
3409
3410   return FALSE;
3411 }
3412
3413 /*-----------------------------------------------------------------*/
3414 /* addSign - complete with sign                                    */
3415 /*-----------------------------------------------------------------*/
3416 static void
3417 addSign (operand * result, int offset, int sign)
3418 {
3419   int size = (getDataSize (result) - offset);
3420   if (size > 0)
3421     {
3422       if (sign)
3423         {
3424           emitcode ("rlc", "a");
3425           emitcode ("subb", "a,acc");
3426           while (size--)
3427             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3428         }
3429       else
3430         while (size--)
3431           aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3432     }
3433 }
3434
3435 /*-----------------------------------------------------------------*/
3436 /* genMinusBits - generates code for subtraction  of two bits      */
3437 /*-----------------------------------------------------------------*/
3438 static void
3439 genMinusBits (iCode * ic)
3440 {
3441   symbol *lbl = newiTempLabel (NULL);
3442
3443   D(emitcode (";     genMinusBits",""));
3444
3445   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3446     {
3447       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3448       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3449       emitcode ("cpl", "c");
3450       emitcode ("", "%05d$:", (lbl->key + 100));
3451       outBitC (IC_RESULT (ic));
3452     }
3453   else
3454     {
3455       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3456       emitcode ("subb", "a,acc");
3457       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3458       emitcode ("inc", "a");
3459       emitcode ("", "%05d$:", (lbl->key + 100));
3460       aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3461       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3462     }
3463 }
3464
3465 /*-----------------------------------------------------------------*/
3466 /* genMinus - generates code for subtraction                       */
3467 /*-----------------------------------------------------------------*/
3468 static void
3469 genMinus (iCode * ic)
3470 {
3471   int size, offset = 0;
3472
3473   D(emitcode (";     genMinus",""));
3474
3475   aopOp (IC_LEFT (ic), ic, FALSE);
3476   aopOp (IC_RIGHT (ic), ic, FALSE);
3477   aopOp (IC_RESULT (ic), ic, TRUE);
3478
3479   /* special cases :- */
3480   /* if both left & right are in bit space */
3481   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3482       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3483     {
3484       genMinusBits (ic);
3485       goto release;
3486     }
3487
3488   /* if I can do an decrement instead
3489      of subtract then GOOD for ME */
3490   if (genMinusDec (ic) == TRUE)
3491     goto release;
3492
3493   size = getDataSize (IC_RESULT (ic));
3494
3495   /* if literal, add a,#-lit, else normal subb */
3496   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3497     {
3498       unsigned long lit = 0L;
3499
3500       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3501       lit = -(long) lit;
3502
3503       while (size--)
3504         {
3505           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3506           /* first add without previous c */
3507           if (!offset) {
3508             if (!size && lit== (unsigned long) -1) {
3509               emitcode ("dec", "a");
3510             } else {
3511               emitcode ("add", "a,#0x%02x",
3512                         (unsigned int) (lit & 0x0FFL));
3513             }
3514           } else {
3515             emitcode ("addc", "a,#0x%02x",
3516                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3517           }
3518           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3519         }
3520     }
3521   else
3522     {
3523       asmop *leftOp, *rightOp;
3524
3525       leftOp = AOP(IC_LEFT(ic));
3526       rightOp = AOP(IC_RIGHT(ic));
3527
3528       while (size--)
3529         {
3530           if (aopGetUsesAcc(rightOp, offset)) {
3531             wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3532             MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3533             if (offset == 0) {
3534               emitcode( "setb", "c");
3535             }
3536             emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3537             emitcode("cpl", "a");
3538           } else {
3539             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3540             if (offset == 0)
3541               CLRC;
3542             emitcode ("subb", "a,%s",
3543                       aopGet(rightOp, offset, FALSE, TRUE));
3544           }
3545
3546           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3547         }
3548     }
3549   
3550   
3551   adjustArithmeticResult (ic);
3552
3553 release:
3554   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3555   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3556   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3557 }
3558
3559
3560 /*-----------------------------------------------------------------*/
3561 /* genMultbits :- multiplication of bits                           */
3562 /*-----------------------------------------------------------------*/
3563 static void
3564 genMultbits (operand * left,
3565              operand * right,
3566              operand * result)
3567 {
3568   D(emitcode (";     genMultbits",""));
3569
3570   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3571   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3572   outBitC (result);
3573 }
3574
3575
3576 /*-----------------------------------------------------------------*/
3577 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3578 /*-----------------------------------------------------------------*/
3579 static void
3580 genMultOneByte (operand * left,
3581                 operand * right,
3582                 operand * result)
3583 {
3584   sym_link *opetype = operandType (result);
3585   symbol *lbl;
3586   int size=AOP_SIZE(result);
3587
3588   D(emitcode (";     genMultOneByte",""));
3589
3590   if (size<1 || size>2) {
3591     // this should never happen
3592       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3593                AOP_SIZE(result), __FILE__, lineno);
3594       exit (1);
3595   }
3596
3597   /* (if two literals: the value is computed before) */
3598   /* if one literal, literal on the right */
3599   if (AOP_TYPE (left) == AOP_LIT)
3600     {
3601       operand *t = right;
3602       right = left;
3603       left = t;
3604       //emitcode (";", "swapped left and right");
3605     }
3606
3607   if (SPEC_USIGN(opetype)
3608       // ignore the sign of left and right, what else can we do?
3609       || (SPEC_USIGN(operandType(left)) &&
3610           SPEC_USIGN(operandType(right)))) {
3611     // just an unsigned 8*8=8/16 multiply
3612     //emitcode (";","unsigned");
3613     // TODO: check for accumulator clash between left & right aops?
3614     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3615     MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3616     emitcode ("mul", "ab");
3617     aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3618     if (size==2) {
3619       aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3620     }
3621     return;
3622   }
3623
3624   // we have to do a signed multiply
3625
3626   //emitcode (";", "signed");
3627   emitcode ("clr", "F0"); // reset sign flag
3628   MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3629
3630   lbl=newiTempLabel(NULL);
3631   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3632   // left side is negative, 8-bit two's complement, this fails for -128
3633   emitcode ("setb", "F0"); // set sign flag
3634   emitcode ("cpl", "a");
3635   emitcode ("inc", "a");
3636
3637   emitcode ("", "%05d$:", lbl->key+100);
3638
3639   /* if literal */
3640   if (AOP_TYPE(right)==AOP_LIT) {
3641     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3642     /* AND literal negative */
3643     if (val < 0) {
3644       emitcode ("cpl", "F0"); // complement sign flag
3645       emitcode ("mov", "b,#0x%02x", -val);
3646     } else {
3647       emitcode ("mov", "b,#0x%02x", val);
3648     }
3649   } else {
3650     lbl=newiTempLabel(NULL);
3651     emitcode ("mov", "b,a");
3652     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3653     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3654     // right side is negative, 8-bit two's complement
3655     emitcode ("cpl", "F0"); // complement sign flag
3656     emitcode ("cpl", "a");
3657     emitcode ("inc", "a");
3658     emitcode ("", "%05d$:", lbl->key+100);
3659   }
3660   emitcode ("mul", "ab");
3661
3662   lbl=newiTempLabel(NULL);
3663   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3664   // only ONE op was negative, we have to do a 8/16-bit two's complement
3665   emitcode ("cpl", "a"); // lsb
3666   if (size==1) {
3667     emitcode ("inc", "a");
3668   } else {
3669     emitcode ("add", "a,#1");
3670     emitcode ("xch", "a,b");
3671     emitcode ("cpl", "a"); // msb
3672     emitcode ("addc", "a,#0");
3673     emitcode ("xch", "a,b");
3674   }
3675
3676   emitcode ("", "%05d$:", lbl->key+100);
3677   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3678   if (size==2) {
3679     aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3680   }
3681 }
3682
3683 /*-----------------------------------------------------------------*/
3684 /* genMult - generates code for multiplication                     */
3685 /*-----------------------------------------------------------------*/
3686 static void
3687 genMult (iCode * ic)
3688 {
3689   operand *left = IC_LEFT (ic);
3690   operand *right = IC_RIGHT (ic);
3691   operand *result = IC_RESULT (ic);
3692
3693   D(emitcode (";     genMult",""));
3694
3695   /* assign the amsops */
3696   aopOp (left, ic, FALSE);
3697   aopOp (right, ic, FALSE);
3698   aopOp (result, ic, TRUE);
3699
3700   /* special cases first */
3701   /* both are bits */
3702   if (AOP_TYPE (left) == AOP_CRY &&
3703       AOP_TYPE (right) == AOP_CRY)
3704     {
3705       genMultbits (left, right, result);
3706       goto release;
3707     }
3708
3709   /* if both are of size == 1 */
3710 #if 0 // one of them can be a sloc shared with the result
3711     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3712 #else
3713   if (getSize(operandType(left)) == 1 &&
3714       getSize(operandType(right)) == 1)
3715 #endif
3716     {
3717       genMultOneByte (left, right, result);
3718       goto release;
3719     }
3720
3721   /* should have been converted to function call */
3722     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3723              getSize(OP_SYMBOL(right)->type));
3724   assert (0);
3725
3726 release:
3727   freeAsmop (result, NULL, ic, TRUE);
3728   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3729   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3730 }
3731
3732 /*-----------------------------------------------------------------*/
3733 /* genDivbits :- division of bits                                  */
3734 /*-----------------------------------------------------------------*/
3735 static void
3736 genDivbits (operand * left,
3737             operand * right,
3738             operand * result)
3739 {
3740
3741   char *l;
3742
3743   D(emitcode (";     genDivbits",""));
3744
3745   /* the result must be bit */
3746   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3747   l = aopGet (AOP (left), 0, FALSE, FALSE);
3748
3749   MOVA (l);
3750
3751   emitcode ("div", "ab");
3752   emitcode ("rrc", "a");
3753   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3754 }
3755
3756 /*-----------------------------------------------------------------*/
3757 /* genDivOneByte : 8 bit division                                  */
3758 /*-----------------------------------------------------------------*/
3759 static void
3760 genDivOneByte (operand * left,
3761                operand * right,
3762                operand * result)
3763 {
3764   sym_link *opetype = operandType (result);
3765   char *l;
3766   symbol *lbl;
3767   int size, offset;
3768
3769   D(emitcode (";     genDivOneByte",""));
3770
3771   size = AOP_SIZE (result) - 1;
3772   offset = 1;
3773   /* signed or unsigned */
3774   if (SPEC_USIGN (opetype))
3775     {
3776       /* unsigned is easy */
3777       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3778       l = aopGet (AOP (left), 0, FALSE, FALSE);
3779       MOVA (l);
3780       emitcode ("div", "ab");
3781       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3782       while (size--)
3783         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3784       return;
3785     }
3786
3787   /* signed is a little bit more difficult */
3788
3789   /* save the signs of the operands */
3790   l = aopGet (AOP (left), 0, FALSE, FALSE);
3791   MOVA (l);
3792   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3793   emitcode ("push", "acc");     /* save it on the stack */
3794
3795   /* now sign adjust for both left & right */
3796   l = aopGet (AOP (right), 0, FALSE, FALSE);
3797   MOVA (l);
3798   lbl = newiTempLabel (NULL);
3799   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3800   emitcode ("cpl", "a");
3801   emitcode ("inc", "a");
3802   emitcode ("", "%05d$:", (lbl->key + 100));
3803   emitcode ("mov", "b,a");
3804
3805   /* sign adjust left side */
3806   l = aopGet (AOP (left), 0, FALSE, FALSE);
3807   MOVA (l);
3808
3809   lbl = newiTempLabel (NULL);
3810   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3811   emitcode ("cpl", "a");
3812   emitcode ("inc", "a");
3813   emitcode ("", "%05d$:", (lbl->key + 100));
3814
3815   /* now the division */
3816   emitcode ("div", "ab");
3817   /* we are interested in the lower order
3818      only */
3819   emitcode ("mov", "b,a");
3820   lbl = newiTempLabel (NULL);
3821   emitcode ("pop", "acc");
3822   /* if there was an over flow we don't
3823      adjust the sign of the result */
3824   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3825   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3826   CLRC;
3827   emitcode ("clr", "a");
3828   emitcode ("subb", "a,b");
3829   emitcode ("mov", "b,a");
3830   emitcode ("", "%05d$:", (lbl->key + 100));
3831
3832   /* now we are done */
3833   aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3834   if (size > 0)
3835     {
3836       emitcode ("mov", "c,b.7");
3837       emitcode ("subb", "a,acc");
3838     }
3839   while (size--)
3840     aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3841
3842 }
3843
3844 /*-----------------------------------------------------------------*/
3845 /* genDiv - generates code for division                            */
3846 /*-----------------------------------------------------------------*/
3847 static void
3848 genDiv (iCode * ic)
3849 {
3850   operand *left = IC_LEFT (ic);
3851   operand *right = IC_RIGHT (ic);
3852   operand *result = IC_RESULT (ic);
3853
3854   D(emitcode (";     genDiv",""));
3855
3856   /* assign the amsops */
3857   aopOp (left, ic, FALSE);
3858   aopOp (right, ic, FALSE);
3859   aopOp (result, ic, TRUE);
3860
3861   /* special cases first */
3862   /* both are bits */
3863   if (AOP_TYPE (left) == AOP_CRY &&
3864       AOP_TYPE (right) == AOP_CRY)
3865     {
3866       genDivbits (left, right, result);
3867       goto release;
3868     }
3869
3870   /* if both are of size == 1 */
3871   if (AOP_SIZE (left) == 1 &&
3872       AOP_SIZE (right) == 1)
3873     {
3874       genDivOneByte (left, right, result);
3875       goto release;
3876     }
3877
3878   /* should have been converted to function call */
3879   assert (0);
3880 release:
3881   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3882   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3883   freeAsmop (result, NULL, ic, TRUE);
3884 }
3885
3886 /*-----------------------------------------------------------------*/
3887 /* genModbits :- modulus of bits                                   */
3888 /*-----------------------------------------------------------------*/
3889 static void
3890 genModbits (operand * left,
3891             operand * right,
3892             operand * result)
3893 {
3894
3895   char *l;
3896
3897   D(emitcode (";     genModbits",""));
3898
3899   /* the result must be bit */
3900   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3901   l = aopGet (AOP (left), 0, FALSE, FALSE);
3902
3903   MOVA (l);
3904
3905   emitcode ("div", "ab");
3906   emitcode ("mov", "a,b");
3907   emitcode ("rrc", "a");
3908   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3909 }
3910
3911 /*-----------------------------------------------------------------*/
3912 /* genModOneByte : 8 bit modulus                                   */
3913 /*-----------------------------------------------------------------*/
3914 static void
3915 genModOneByte (operand * left,
3916                operand * right,
3917                operand * result)
3918 {
3919   sym_link *opetype = operandType (result);
3920   char *l;
3921   symbol *lbl;
3922
3923   D(emitcode (";     genModOneByte",""));
3924
3925   /* signed or unsigned */
3926   if (SPEC_USIGN (opetype))
3927     {
3928       /* unsigned is easy */
3929       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3930       l = aopGet (AOP (left), 0, FALSE, FALSE);
3931       MOVA (l);
3932       emitcode ("div", "ab");
3933       aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3934       return;
3935     }
3936
3937   /* signed is a little bit more difficult */
3938
3939   /* save the signs of the operands */
3940   l = aopGet (AOP (left), 0, FALSE, FALSE);
3941   MOVA (l);
3942
3943   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3944   emitcode ("push", "acc");     /* save it on the stack */
3945
3946   /* now sign adjust for both left & right */
3947   l = aopGet (AOP (right), 0, FALSE, FALSE);
3948   MOVA (l);
3949
3950   lbl = newiTempLabel (NULL);
3951   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3952   emitcode ("cpl", "a");
3953   emitcode ("inc", "a");
3954   emitcode ("", "%05d$:", (lbl->key + 100));
3955   emitcode ("mov", "b,a");
3956
3957   /* sign adjust left side */
3958   l = aopGet (AOP (left), 0, FALSE, FALSE);
3959   MOVA (l);
3960
3961   lbl = newiTempLabel (NULL);
3962   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3963   emitcode ("cpl", "a");
3964   emitcode ("inc", "a");
3965   emitcode ("", "%05d$:", (lbl->key + 100));
3966
3967   /* now the multiplication */
3968   emitcode ("div", "ab");
3969   /* we are interested in the lower order
3970      only */
3971   lbl = newiTempLabel (NULL);
3972   emitcode ("pop", "acc");
3973   /* if there was an over flow we don't
3974      adjust the sign of the result */
3975   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3976   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3977   CLRC;
3978   emitcode ("clr", "a");
3979   emitcode ("subb", "a,b");
3980   emitcode ("mov", "b,a");
3981   emitcode ("", "%05d$:", (lbl->key + 100));
3982
3983   /* now we are done */
3984   aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3985
3986 }
3987
3988 /*-----------------------------------------------------------------*/
3989 /* genMod - generates code for division                            */
3990 /*-----------------------------------------------------------------*/
3991 static void
3992 genMod (iCode * ic)
3993 {
3994   operand *left = IC_LEFT (ic);
3995   operand *right = IC_RIGHT (ic);
3996   operand *result = IC_RESULT (ic);
3997
3998   D(emitcode (";     genMod",""));
3999
4000   /* assign the amsops */
4001   aopOp (left, ic, FALSE);
4002   aopOp (right, ic, FALSE);
4003   aopOp (result, ic, TRUE);
4004
4005   /* special cases first */
4006   /* both are bits */
4007   if (AOP_TYPE (left) == AOP_CRY &&
4008       AOP_TYPE (right) == AOP_CRY)
4009     {
4010       genModbits (left, right, result);
4011       goto release;
4012     }
4013
4014   /* if both are of size == 1 */
4015   if (AOP_SIZE (left) == 1 &&
4016       AOP_SIZE (right) == 1)
4017     {
4018       genModOneByte (left, right, result);
4019       goto release;
4020     }
4021
4022   /* should have been converted to function call */
4023   assert (0);
4024
4025 release:
4026   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4027   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4028   freeAsmop (result, NULL, ic, TRUE);
4029 }
4030
4031 /*-----------------------------------------------------------------*/
4032 /* genIfxJump :- will create a jump depending on the ifx           */
4033 /*-----------------------------------------------------------------*/
4034 static void
4035 genIfxJump (iCode * ic, char *jval)
4036 {
4037   symbol *jlbl;
4038   symbol *tlbl = newiTempLabel (NULL);
4039   char *inst;
4040
4041   D(emitcode (";     genIfxJump",""));
4042
4043   /* if true label then we jump if condition
4044      supplied is true */
4045   if (IC_TRUE (ic))
4046     {
4047       jlbl = IC_TRUE (ic);
4048       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4049                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4050     }
4051   else
4052     {
4053       /* false label is present */
4054       jlbl = IC_FALSE (ic);
4055       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4056                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4057     }
4058   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4059     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4060   else
4061     emitcode (inst, "%05d$", tlbl->key + 100);
4062   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4063   emitcode ("", "%05d$:", tlbl->key + 100);
4064
4065   /* mark the icode as generated */
4066   ic->generated = 1;
4067 }
4068
4069 /*-----------------------------------------------------------------*/
4070 /* genCmp :- greater or less than comparison                       */
4071 /*-----------------------------------------------------------------*/
4072 static void
4073 genCmp (operand * left, operand * right,
4074         operand * result, iCode * ifx, int sign, iCode *ic)
4075 {
4076   int size, offset = 0;
4077   unsigned long lit = 0L;
4078   bool rightInB;
4079
4080   D(emitcode (";     genCmp",""));
4081
4082   /* if left & right are bit variables */
4083   if (AOP_TYPE (left) == AOP_CRY &&
4084       AOP_TYPE (right) == AOP_CRY)
4085     {
4086       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4087       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4088     }
4089   else
4090     {
4091       /* subtract right from left if at the
4092          end the carry flag is set then we know that
4093          left is greater than right */
4094       size = max (AOP_SIZE (left), AOP_SIZE (right));
4095
4096       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4097       if ((size == 1) && !sign &&
4098           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4099         {
4100           symbol *lbl = newiTempLabel (NULL);
4101           emitcode ("cjne", "%s,%s,%05d$",
4102                     aopGet (AOP (left), offset, FALSE, FALSE),
4103                     aopGet (AOP (right), offset, FALSE, FALSE),
4104                     lbl->key + 100);
4105           emitcode ("", "%05d$:", lbl->key + 100);
4106         }
4107       else
4108         {
4109           if (AOP_TYPE (right) == AOP_LIT)
4110             {
4111               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4112               /* optimize if(x < 0) or if(x >= 0) */
4113               if (lit == 0L)
4114                 {
4115                   if (!sign)
4116                     {
4117                       CLRC;
4118                     }
4119                   else
4120                     {
4121                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4122                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4123                         {
4124                           genIfxJump (ifx, "acc.7");
4125                           return;
4126                         }
4127                       else
4128                         emitcode ("rlc", "a");
4129                     }
4130                   goto release;
4131                 }
4132             }
4133           CLRC;
4134           while (size--)
4135             {
4136               rightInB = aopGetUsesAcc(AOP (right), offset);
4137               if (rightInB)
4138                 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4139               MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4140               if (sign && size == 0)
4141                 {
4142                   emitcode ("xrl", "a,#0x80");
4143                   if (AOP_TYPE (right) == AOP_LIT)
4144                     {
4145                       unsigned long lit = (unsigned long)
4146                       floatFromVal (AOP (right)->aopu.aop_lit);
4147                       emitcode ("subb", "a,#0x%02x",
4148                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4149                     }
4150                   else
4151                     {
4152                       if (!rightInB)
4153                         emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4154                       emitcode ("xrl", "b,#0x80");
4155                       emitcode ("subb", "a,b");
4156                     }
4157                 }
4158               else
4159                 {
4160                   if (rightInB)
4161                     emitcode ("subb", "a,b");
4162                   else
4163                     emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4164                 }
4165               offset++;
4166             }
4167         }
4168     }
4169
4170 release:
4171   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4172   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4173   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4174     {
4175       outBitC (result);
4176     }
4177   else
4178     {
4179       /* if the result is used in the next
4180          ifx conditional branch then generate
4181          code a little differently */
4182       if (ifx)
4183         genIfxJump (ifx, "c");
4184       else
4185         outBitC (result);
4186       /* leave the result in acc */
4187     }
4188 }
4189
4190 /*-----------------------------------------------------------------*/
4191 /* genCmpGt :- greater than comparison                             */
4192 /*-----------------------------------------------------------------*/
4193 static void
4194 genCmpGt (iCode * ic, iCode * ifx)
4195 {
4196   operand *left, *right, *result;
4197   sym_link *letype, *retype;
4198   int sign;
4199
4200   D(emitcode (";     genCmpGt",""));
4201
4202   left = IC_LEFT (ic);
4203   right = IC_RIGHT (ic);
4204   result = IC_RESULT (ic);
4205
4206   letype = getSpec (operandType (left));
4207   retype = getSpec (operandType (right));
4208   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4209   /* assign the amsops */
4210   aopOp (left, ic, FALSE);
4211   aopOp (right, ic, FALSE);
4212   aopOp (result, ic, TRUE);
4213
4214   genCmp (right, left, result, ifx, sign,ic);
4215
4216   freeAsmop (result, NULL, ic, TRUE);
4217 }
4218
4219 /*-----------------------------------------------------------------*/
4220 /* genCmpLt - less than comparisons                                */
4221 /*-----------------------------------------------------------------*/
4222 static void
4223 genCmpLt (iCode * ic, iCode * ifx)
4224 {
4225   operand *left, *right, *result;
4226   sym_link *letype, *retype;
4227   int sign;
4228
4229   D(emitcode (";     genCmpLt",""));
4230
4231   left = IC_LEFT (ic);
4232   right = IC_RIGHT (ic);
4233   result = IC_RESULT (ic);
4234
4235   letype = getSpec (operandType (left));
4236   retype = getSpec (operandType (right));
4237   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4238
4239   /* assign the amsops */
4240   aopOp (left, ic, FALSE);
4241   aopOp (right, ic, FALSE);
4242   aopOp (result, ic, TRUE);
4243
4244   genCmp (left, right, result, ifx, sign,ic);
4245
4246   freeAsmop (result, NULL, ic, TRUE);
4247 }
4248
4249 /*-----------------------------------------------------------------*/
4250 /* gencjneshort - compare and jump if not equal                    */
4251 /*-----------------------------------------------------------------*/
4252 static void
4253 gencjneshort (operand * left, operand * right, symbol * lbl)
4254 {
4255   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4256   int offset = 0;
4257   unsigned long lit = 0L;
4258
4259   /* if the left side is a literal or
4260      if the right is in a pointer register and left
4261      is not */
4262   if ((AOP_TYPE (left) == AOP_LIT) ||
4263       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4264     {
4265       operand *t = right;
4266       right = left;
4267       left = t;
4268     }
4269   if (AOP_TYPE (right) == AOP_LIT)
4270     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4271
4272   /* if the right side is a literal then anything goes */
4273   if (AOP_TYPE (right) == AOP_LIT &&
4274       AOP_TYPE (left) != AOP_DIR  &&
4275       AOP_TYPE (left) != AOP_IMMD)
4276     {
4277       while (size--)
4278         {
4279           emitcode ("cjne", "%s,%s,%05d$",
4280                     aopGet (AOP (left), offset, FALSE, FALSE),
4281                     aopGet (AOP (right), offset, FALSE, FALSE),
4282                     lbl->key + 100);
4283           offset++;
4284         }
4285     }
4286
4287   /* if the right side is in a register or in direct space or
4288      if the left is a pointer register & right is not */
4289   else if (AOP_TYPE (right) == AOP_REG ||
4290            AOP_TYPE (right) == AOP_DIR ||
4291            AOP_TYPE (right) == AOP_LIT ||
4292            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4293            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4294     {
4295       while (size--)
4296         {
4297           MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4298           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4299               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4300             emitcode ("jnz", "%05d$", lbl->key + 100);
4301           else
4302             emitcode ("cjne", "a,%s,%05d$",
4303                       aopGet (AOP (right), offset, FALSE, TRUE),
4304                       lbl->key + 100);
4305           offset++;
4306         }
4307     }
4308   else
4309     {
4310       /* right is a pointer reg need both a & b */
4311       while (size--)
4312         {
4313           char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4314           if (strcmp (l, "b"))
4315             emitcode ("mov", "b,%s", l);
4316           MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4317           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4318           offset++;
4319         }
4320     }
4321 }
4322
4323 /*-----------------------------------------------------------------*/
4324 /* gencjne - compare and jump if not equal                         */
4325 /*-----------------------------------------------------------------*/
4326 static void
4327 gencjne (operand * left, operand * right, symbol * lbl)
4328 {
4329   symbol *tlbl = newiTempLabel (NULL);
4330
4331   gencjneshort (left, right, lbl);
4332
4333   emitcode ("mov", "a,%s", one);
4334   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4335   emitcode ("", "%05d$:", lbl->key + 100);
4336   emitcode ("clr", "a");
4337   emitcode ("", "%05d$:", tlbl->key + 100);
4338 }
4339
4340 /*-----------------------------------------------------------------*/
4341 /* genCmpEq - generates code for equal to                          */
4342 /*-----------------------------------------------------------------*/
4343 static void
4344 genCmpEq (iCode * ic, iCode * ifx)
4345 {
4346   operand *left, *right, *result;
4347
4348   D(emitcode (";     genCmpEq",""));
4349
4350   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4351   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4352   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4353
4354   /* if literal, literal on the right or
4355      if the right is in a pointer register and left
4356      is not */
4357   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4358       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4359     {
4360       operand *t = IC_RIGHT (ic);
4361       IC_RIGHT (ic) = IC_LEFT (ic);
4362       IC_LEFT (ic) = t;
4363     }
4364
4365   if (ifx && !AOP_SIZE (result))
4366     {
4367       symbol *tlbl;
4368       /* if they are both bit variables */
4369       if (AOP_TYPE (left) == AOP_CRY &&
4370           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4371         {
4372           if (AOP_TYPE (right) == AOP_LIT)
4373             {
4374               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4375               if (lit == 0L)
4376                 {
4377                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4378                   emitcode ("cpl", "c");
4379                 }
4380               else if (lit == 1L)
4381                 {
4382                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4383                 }
4384               else
4385                 {
4386                   emitcode ("clr", "c");
4387                 }
4388               /* AOP_TYPE(right) == AOP_CRY */
4389             }
4390           else
4391             {
4392               symbol *lbl = newiTempLabel (NULL);
4393               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4394               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4395               emitcode ("cpl", "c");
4396               emitcode ("", "%05d$:", (lbl->key + 100));
4397             }
4398           /* if true label then we jump if condition
4399              supplied is true */
4400           tlbl = newiTempLabel (NULL);
4401           if (IC_TRUE (ifx))
4402             {
4403               emitcode ("jnc", "%05d$", tlbl->key + 100);
4404               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4405             }
4406           else
4407             {
4408               emitcode ("jc", "%05d$", tlbl->key + 100);
4409               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4410             }
4411           emitcode ("", "%05d$:", tlbl->key + 100);
4412         }
4413       else
4414         {
4415           tlbl = newiTempLabel (NULL);
4416           gencjneshort (left, right, tlbl);
4417           if (IC_TRUE (ifx))
4418             {
4419               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4420               emitcode ("", "%05d$:", tlbl->key + 100);
4421             }
4422           else
4423             {
4424               symbol *lbl = newiTempLabel (NULL);
4425               emitcode ("sjmp", "%05d$", lbl->key + 100);
4426               emitcode ("", "%05d$:", tlbl->key + 100);
4427               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4428               emitcode ("", "%05d$:", lbl->key + 100);
4429             }
4430         }
4431       /* mark the icode as generated */
4432       ifx->generated = 1;
4433       goto release;
4434     }
4435
4436   /* if they are both bit variables */
4437   if (AOP_TYPE (left) == AOP_CRY &&
4438       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4439     {
4440       if (AOP_TYPE (right) == AOP_LIT)
4441         {
4442           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4443           if (lit == 0L)
4444             {
4445               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4446               emitcode ("cpl", "c");
4447             }
4448           else if (lit == 1L)
4449             {
4450               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4451             }
4452           else
4453             {
4454               emitcode ("clr", "c");
4455             }
4456           /* AOP_TYPE(right) == AOP_CRY */
4457         }
4458       else
4459         {
4460           symbol *lbl = newiTempLabel (NULL);
4461           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4462           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4463           emitcode ("cpl", "c");
4464           emitcode ("", "%05d$:", (lbl->key + 100));
4465         }
4466       /* c = 1 if egal */
4467       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4468         {
4469           outBitC (result);
4470           goto release;
4471         }
4472       if (ifx)
4473         {
4474           genIfxJump (ifx, "c");
4475           goto release;
4476         }
4477       /* if the result is used in an arithmetic operation
4478          then put the result in place */
4479       outBitC (result);
4480     }
4481   else
4482     {
4483       gencjne (left, right, newiTempLabel (NULL));
4484       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4485         {
4486           aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4487           goto release;
4488         }
4489       if (ifx)
4490         {
4491           genIfxJump (ifx, "a");
4492           goto release;
4493         }
4494       /* if the result is used in an arithmetic operation
4495          then put the result in place */
4496       if (AOP_TYPE (result) != AOP_CRY)
4497         outAcc (result);
4498       /* leave the result in acc */
4499     }
4500
4501 release:
4502   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4503   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4504   freeAsmop (result, NULL, ic, TRUE);
4505 }
4506
4507 /*-----------------------------------------------------------------*/
4508 /* ifxForOp - returns the icode containing the ifx for operand     */
4509 /*-----------------------------------------------------------------*/
4510 static iCode *
4511 ifxForOp (operand * op, iCode * ic)
4512 {
4513   /* if true symbol then needs to be assigned */
4514   if (IS_TRUE_SYMOP (op))
4515     return NULL;
4516
4517   /* if this has register type condition and
4518      the next instruction is ifx with the same operand
4519      and live to of the operand is upto the ifx only then */
4520   if (ic->next &&
4521       ic->next->op == IFX &&
4522       IC_COND (ic->next)->key == op->key &&
4523       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4524     return ic->next;
4525
4526   return NULL;
4527 }
4528
4529 /*-----------------------------------------------------------------*/
4530 /* hasInc - operand is incremented before any other use            */
4531 /*-----------------------------------------------------------------*/
4532 static iCode *
4533 hasInc (operand *op, iCode *ic,int osize)
4534 {
4535   sym_link *type = operandType(op);
4536   sym_link *retype = getSpec (type);
4537   iCode *lic = ic->next;
4538   int isize ;
4539   
4540   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4541   if (!IS_SYMOP(op)) return NULL;
4542
4543   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4544   if (IS_AGGREGATE(type->next)) return NULL;
4545   if (osize != (isize = getSize(type->next))) return NULL;
4546
4547   while (lic) {
4548     /* if operand of the form op = op + <sizeof *op> */
4549     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4550         isOperandEqual(IC_RESULT(lic),op) && 
4551         isOperandLiteral(IC_RIGHT(lic)) &&
4552         operandLitValue(IC_RIGHT(lic)) == isize) {
4553       return lic;
4554     }
4555     /* if the operand used or deffed */
4556     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4557       return NULL;
4558     }
4559     /* if GOTO or IFX */
4560     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4561     lic = lic->next;
4562   }
4563   return NULL;
4564 }
4565
4566 /*-----------------------------------------------------------------*/
4567 /* genAndOp - for && operation                                     */
4568 /*-----------------------------------------------------------------*/
4569 static void
4570 genAndOp (iCode * ic)
4571 {
4572   operand *left, *right, *result;
4573   symbol *tlbl;
4574
4575   D(emitcode (";     genAndOp",""));
4576
4577   /* note here that && operations that are in an
4578      if statement are taken away by backPatchLabels
4579      only those used in arthmetic operations remain */
4580   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4581   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4582   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4583
4584   /* if both are bit variables */
4585   if (AOP_TYPE (left) == AOP_CRY &&
4586       AOP_TYPE (right) == AOP_CRY)
4587     {
4588       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4589       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4590       outBitC (result);
4591     }
4592   else
4593     {
4594       tlbl = newiTempLabel (NULL);
4595       toBoolean (left);
4596       emitcode ("jz", "%05d$", tlbl->key + 100);
4597       toBoolean (right);
4598       emitcode ("", "%05d$:", tlbl->key + 100);
4599       outBitAcc (result);
4600     }
4601
4602   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604   freeAsmop (result, NULL, ic, TRUE);
4605 }
4606
4607
4608 /*-----------------------------------------------------------------*/
4609 /* genOrOp - for || operation                                      */
4610 /*-----------------------------------------------------------------*/
4611 static void
4612 genOrOp (iCode * ic)
4613 {
4614   operand *left, *right, *result;
4615   symbol *tlbl;
4616
4617   D(emitcode (";     genOrOp",""));
4618
4619   /* note here that || operations that are in an
4620      if statement are taken away by backPatchLabels
4621      only those used in arthmetic operations remain */
4622   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4623   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4624   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4625
4626   /* if both are bit variables */
4627   if (AOP_TYPE (left) == AOP_CRY &&
4628       AOP_TYPE (right) == AOP_CRY)
4629     {
4630       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4631       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4632       outBitC (result);
4633     }
4634   else
4635     {
4636       tlbl = newiTempLabel (NULL);
4637       toBoolean (left);
4638       emitcode ("jnz", "%05d$", tlbl->key + 100);
4639       toBoolean (right);
4640       emitcode ("", "%05d$:", tlbl->key + 100);
4641       outBitAcc (result);
4642     }
4643
4644   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4645   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4646   freeAsmop (result, NULL, ic, TRUE);
4647 }
4648
4649 /*-----------------------------------------------------------------*/
4650 /* isLiteralBit - test if lit == 2^n                               */
4651 /*-----------------------------------------------------------------*/
4652 static int
4653 isLiteralBit (unsigned long lit)
4654 {
4655   unsigned long pw[32] =
4656   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4657    0x100L, 0x200L, 0x400L, 0x800L,
4658    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4659    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4660    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4661    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4662    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4663   int idx;
4664
4665   for (idx = 0; idx < 32; idx++)
4666     if (lit == pw[idx])
4667       return idx + 1;
4668   return 0;
4669 }
4670
4671 /*-----------------------------------------------------------------*/
4672 /* continueIfTrue -                                                */
4673 /*-----------------------------------------------------------------*/
4674 static void
4675 continueIfTrue (iCode * ic)
4676 {
4677   if (IC_TRUE (ic))
4678     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4679   ic->generated = 1;
4680 }
4681
4682 /*-----------------------------------------------------------------*/
4683 /* jmpIfTrue -                                                     */
4684 /*-----------------------------------------------------------------*/
4685 static void
4686 jumpIfTrue (iCode * ic)
4687 {
4688   if (!IC_TRUE (ic))
4689     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4690   ic->generated = 1;
4691 }
4692
4693 /*-----------------------------------------------------------------*/
4694 /* jmpTrueOrFalse -                                                */
4695 /*-----------------------------------------------------------------*/
4696 static void
4697 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4698 {
4699   // ugly but optimized by peephole
4700   if (IC_TRUE (ic))
4701     {
4702       symbol *nlbl = newiTempLabel (NULL);
4703       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4704       emitcode ("", "%05d$:", tlbl->key + 100);
4705       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4706       emitcode ("", "%05d$:", nlbl->key + 100);
4707     }
4708   else
4709     {
4710       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4711       emitcode ("", "%05d$:", tlbl->key + 100);
4712     }
4713   ic->generated = 1;
4714 }
4715
4716 /*-----------------------------------------------------------------*/
4717 /* genAnd  - code for and                                          */
4718 /*-----------------------------------------------------------------*/
4719 static void
4720 genAnd (iCode * ic, iCode * ifx)
4721 {
4722   operand *left, *right, *result;
4723   int size, offset = 0;
4724   unsigned long lit = 0L;
4725   int bytelit = 0;
4726   char buffer[10];
4727
4728   D(emitcode (";     genAnd",""));
4729
4730   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4731   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4732   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4733
4734 #ifdef DEBUG_TYPE
4735   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4736             AOP_TYPE (result),
4737             AOP_TYPE (left), AOP_TYPE (right));
4738   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4739             AOP_SIZE (result),
4740             AOP_SIZE (left), AOP_SIZE (right));
4741 #endif
4742
4743   /* if left is a literal & right is not then exchange them */
4744   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4745       AOP_NEEDSACC (left))
4746     {
4747       operand *tmp = right;
4748       right = left;
4749       left = tmp;
4750     }
4751
4752   /* if result = right then exchange them */
4753   if (sameRegs (AOP (result), AOP (right)))
4754     {
4755       operand *tmp = right;
4756       right = left;
4757       left = tmp;
4758     }
4759
4760   /* if right is bit then exchange them */
4761   if (AOP_TYPE (right) == AOP_CRY &&
4762       AOP_TYPE (left) != AOP_CRY)
4763     {
4764       operand *tmp = right;
4765       right = left;
4766       left = tmp;
4767     }
4768   if (AOP_TYPE (right) == AOP_LIT)
4769     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4770
4771   size = AOP_SIZE (result);
4772
4773   // if(bit & yy)
4774   // result = bit & yy;
4775   if (AOP_TYPE (left) == AOP_CRY)
4776     {
4777       // c = bit & literal;
4778       if (AOP_TYPE (right) == AOP_LIT)
4779         {
4780           if (lit & 1)
4781             {
4782               if (size && sameRegs (AOP (result), AOP (left)))
4783                 // no change
4784                 goto release;
4785               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4786             }
4787           else
4788             {
4789               // bit(result) = 0;
4790               if (size && (AOP_TYPE (result) == AOP_CRY))
4791                 {
4792                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4793                   goto release;
4794                 }
4795               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4796                 {
4797                   jumpIfTrue (ifx);
4798                   goto release;
4799                 }
4800               emitcode ("clr", "c");
4801             }
4802         }
4803       else
4804         {
4805           if (AOP_TYPE (right) == AOP_CRY)
4806             {
4807               // c = bit & bit;
4808               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4809               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4810             }
4811           else
4812             {
4813               // c = bit & val;
4814               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4815               // c = lsb
4816               emitcode ("rrc", "a");
4817               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4818             }
4819         }
4820       // bit = c
4821       // val = c
4822       if (size)
4823         outBitC (result);
4824       // if(bit & ...)
4825       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4826         genIfxJump (ifx, "c");
4827       goto release;
4828     }
4829
4830   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4831   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4832   if ((AOP_TYPE (right) == AOP_LIT) &&
4833       (AOP_TYPE (result) == AOP_CRY) &&
4834       (AOP_TYPE (left) != AOP_CRY))
4835     {
4836       int posbit = isLiteralBit (lit);
4837       /* left &  2^n */
4838       if (posbit)
4839         {
4840           posbit--;
4841           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4842           // bit = left & 2^n
4843           if (size)
4844             emitcode ("mov", "c,acc.%d", posbit & 0x07);
4845           // if(left &  2^n)
4846           else
4847             {
4848               if (ifx)
4849                 {
4850                   sprintf (buffer, "acc.%d", posbit & 0x07);
4851                   genIfxJump (ifx, buffer);
4852                 }
4853               goto release;
4854             }
4855         }
4856       else
4857         {
4858           symbol *tlbl = newiTempLabel (NULL);
4859           int sizel = AOP_SIZE (left);
4860           if (size)
4861             emitcode ("setb", "c");
4862           while (sizel--)
4863             {
4864               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4865                 {
4866                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4867                   // byte ==  2^n ?
4868                   if ((posbit = isLiteralBit (bytelit)) != 0)
4869                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4870                   else
4871                     {
4872                       if (bytelit != 0x0FFL)
4873                         emitcode ("anl", "a,%s",
4874                                   aopGet (AOP (right), offset, FALSE, TRUE));
4875                       emitcode ("jnz", "%05d$", tlbl->key + 100);
4876                     }
4877                 }
4878               offset++;
4879             }
4880           // bit = left & literal
4881           if (size)
4882             {
4883               emitcode ("clr", "c");
4884               emitcode ("", "%05d$:", tlbl->key + 100);
4885             }
4886           // if(left & literal)
4887           else
4888             {
4889               if (ifx)
4890                 jmpTrueOrFalse (ifx, tlbl);
4891               goto release;
4892             }
4893         }
4894       outBitC (result);
4895       goto release;
4896     }
4897
4898   /* if left is same as result */
4899   if (sameRegs (AOP (result), AOP (left)))
4900     {
4901       for (; size--; offset++)
4902         {
4903           if (AOP_TYPE (right) == AOP_LIT)
4904             {
4905               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4906                 continue;
4907               else if (bytelit == 0)
4908                 {
4909                   aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4910                 }
4911               else if (IS_AOP_PREG (result))
4912                 {
4913                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4914                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4915                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4916                 }
4917               else
4918                 emitcode ("anl", "%s,%s",
4919                           aopGet (AOP (left), offset, FALSE, TRUE),
4920                           aopGet (AOP (right), offset, FALSE, FALSE));
4921             }
4922           else
4923             {
4924               if (AOP_TYPE (left) == AOP_ACC)
4925                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4926               else
4927                 {
4928                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4929                   if (IS_AOP_PREG (result))
4930                     {
4931                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4932                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4933
4934                     }
4935                   else
4936                     emitcode ("anl", "%s,a",
4937                               aopGet (AOP (left), offset, FALSE, TRUE));
4938                 }
4939             }
4940         }
4941     }
4942   else
4943     {
4944       // left & result in different registers
4945       if (AOP_TYPE (result) == AOP_CRY)
4946         {
4947           // result = bit
4948           // if(size), result in bit
4949           // if(!size && ifx), conditional oper: if(left & right)
4950           symbol *tlbl = newiTempLabel (NULL);
4951           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4952           if (size)
4953             emitcode ("setb", "c");
4954           while (sizer--)
4955             {
4956               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4957                 emitcode ("anl", "a,%s",
4958                           aopGet (AOP (right), offset, FALSE, FALSE));
4959               } else {
4960                 if (AOP_TYPE(left)==AOP_ACC) {
4961                   emitcode("mov", "b,a");
4962                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4963                   emitcode("anl", "a,b");
4964                 }else {
4965                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4966                   emitcode ("anl", "a,%s",
4967                             aopGet (AOP (left), offset, FALSE, FALSE));
4968                 }
4969               }
4970               emitcode ("jnz", "%05d$", tlbl->key + 100);
4971               offset++;
4972             }
4973           if (size)
4974             {
4975               CLRC;
4976               emitcode ("", "%05d$:", tlbl->key + 100);
4977               outBitC (result);
4978             }
4979           else if (ifx)
4980             jmpTrueOrFalse (ifx, tlbl);
4981         }
4982       else
4983         {
4984           for (; (size--); offset++)
4985             {
4986               // normal case
4987               // result = left & right
4988               if (AOP_TYPE (right) == AOP_LIT)
4989                 {
4990                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4991                     {
4992                       aopPut (AOP (result),
4993                               aopGet (AOP (left), offset, FALSE, FALSE),
4994                               offset,
4995                               isOperandVolatile (result, FALSE));
4996                       continue;
4997                     }
4998                   else if (bytelit == 0)
4999                     {
5000                       /* dummy read of volatile operand */
5001                       if (isOperandVolatile (left, FALSE))
5002                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5003                       aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5004                       continue;
5005                     }
5006                 }
5007               // faster than result <- left, anl result,right
5008               // and better if result is SFR
5009               if (AOP_TYPE (left) == AOP_ACC)
5010                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5011               else
5012                 {
5013                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5014                   emitcode ("anl", "a,%s",
5015                             aopGet (AOP (left), offset, FALSE, FALSE));
5016                 }
5017               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5018             }
5019         }
5020     }
5021
5022 release:
5023   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5024   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5025   freeAsmop (result, NULL, ic, TRUE);
5026 }
5027
5028 /*-----------------------------------------------------------------*/
5029 /* genOr  - code for or                                            */
5030 /*-----------------------------------------------------------------*/
5031 static void
5032 genOr (iCode * ic, iCode * ifx)
5033 {
5034   operand *left, *right, *result;
5035   int size, offset = 0;
5036   unsigned long lit = 0L;
5037
5038   D(emitcode (";     genOr",""));
5039
5040   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5041   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5042   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5043
5044 #ifdef DEBUG_TYPE
5045   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5046             AOP_TYPE (result),
5047             AOP_TYPE (left), AOP_TYPE (right));
5048   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5049             AOP_SIZE (result),
5050             AOP_SIZE (left), AOP_SIZE (right));
5051 #endif
5052
5053   /* if left is a literal & right is not then exchange them */
5054   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5055       AOP_NEEDSACC (left))
5056     {
5057       operand *tmp = right;
5058       right = left;
5059       left = tmp;
5060     }
5061
5062   /* if result = right then exchange them */
5063   if (sameRegs (AOP (result), AOP (right)))
5064     {
5065       operand *tmp = right;
5066       right = left;
5067       left = tmp;
5068     }
5069
5070   /* if right is bit then exchange them */
5071   if (AOP_TYPE (right) == AOP_CRY &&
5072       AOP_TYPE (left) != AOP_CRY)
5073     {
5074       operand *tmp = right;
5075       right = left;
5076       left = tmp;
5077     }
5078   if (AOP_TYPE (right) == AOP_LIT)
5079     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5080
5081   size = AOP_SIZE (result);
5082
5083   // if(bit | yy)
5084   // xx = bit | yy;
5085   if (AOP_TYPE (left) == AOP_CRY)
5086     {
5087       if (AOP_TYPE (right) == AOP_LIT)
5088         {
5089           // c = bit | literal;
5090           if (lit)
5091             {
5092               // lit != 0 => result = 1
5093               if (AOP_TYPE (result) == AOP_CRY)
5094                 {
5095                   if (size)
5096                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5097                   else if (ifx)
5098                     continueIfTrue (ifx);
5099                   goto release;
5100                 }
5101               emitcode ("setb", "c");
5102             }
5103           else
5104             {
5105               // lit == 0 => result = left
5106               if (size && sameRegs (AOP (result), AOP (left)))
5107                 goto release;
5108               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5109             }
5110         }
5111       else
5112         {
5113           if (AOP_TYPE (right) == AOP_CRY)
5114             {
5115               // c = bit | bit;
5116               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5117               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5118             }
5119           else
5120             {
5121               // c = bit | val;
5122               symbol *tlbl = newiTempLabel (NULL);
5123               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5124                 emitcode ("setb", "c");
5125               emitcode ("jb", "%s,%05d$",
5126                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5127               toBoolean (right);
5128               emitcode ("jnz", "%05d$", tlbl->key + 100);
5129               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5130                 {
5131                   jmpTrueOrFalse (ifx, tlbl);
5132                   goto release;
5133                 }
5134               else
5135                 {
5136                   CLRC;
5137                   emitcode ("", "%05d$:", tlbl->key + 100);
5138                 }
5139             }
5140         }
5141       // bit = c
5142       // val = c
5143       if (size)
5144         outBitC (result);
5145       // if(bit | ...)
5146       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5147         genIfxJump (ifx, "c");
5148       goto release;
5149     }
5150
5151   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5152   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5153   if ((AOP_TYPE (right) == AOP_LIT) &&
5154       (AOP_TYPE (result) == AOP_CRY) &&
5155       (AOP_TYPE (left) != AOP_CRY))
5156     {
5157       if (lit)
5158         {
5159           // result = 1
5160           if (size)
5161             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5162           else
5163             continueIfTrue (ifx);
5164           goto release;
5165         }
5166       else
5167         {
5168           // lit = 0, result = boolean(left)
5169           if (size)
5170             emitcode ("setb", "c");
5171           toBoolean (right);
5172           if (size)
5173             {
5174               symbol *tlbl = newiTempLabel (NULL);
5175               emitcode ("jnz", "%05d$", tlbl->key + 100);
5176               CLRC;
5177               emitcode ("", "%05d$:", tlbl->key + 100);
5178             }
5179           else
5180             {
5181               genIfxJump (ifx, "a");
5182               goto release;
5183             }
5184         }
5185       outBitC (result);
5186       goto release;
5187     }
5188
5189   /* if left is same as result */
5190   if (sameRegs (AOP (result), AOP (left)))
5191     {
5192       for (; size--; offset++)
5193         {
5194           if (AOP_TYPE (right) == AOP_LIT)
5195             {
5196               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5197                 {
5198                   /* dummy read of volatile operand */
5199                   if (isOperandVolatile (left, FALSE))
5200                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5201                   else
5202                     continue;
5203                 }
5204               else if (IS_AOP_PREG (left))
5205                 {
5206                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5207                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5208                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5209                 }
5210               else
5211                 emitcode ("orl", "%s,%s",
5212                           aopGet (AOP (left), offset, FALSE, TRUE),
5213                           aopGet (AOP (right), offset, FALSE, FALSE));
5214             }
5215           else
5216             {
5217               if (AOP_TYPE (left) == AOP_ACC)
5218                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5219               else
5220                 {
5221                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5222                   if (IS_AOP_PREG (left))
5223                     {
5224                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5225                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5226                     }
5227                   else
5228                     emitcode ("orl", "%s,a",
5229                               aopGet (AOP (left), offset, FALSE, TRUE));
5230                 }
5231             }
5232         }
5233     }
5234   else
5235     {
5236       // left & result in different registers
5237       if (AOP_TYPE (result) == AOP_CRY)
5238         {
5239           // result = bit
5240           // if(size), result in bit
5241           // if(!size && ifx), conditional oper: if(left | right)
5242           symbol *tlbl = newiTempLabel (NULL);
5243           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5244           if (size)
5245             emitcode ("setb", "c");
5246           while (sizer--)
5247             {
5248               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5249                 emitcode ("orl", "a,%s",
5250                           aopGet (AOP (right), offset, FALSE, FALSE));
5251               } else {
5252                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5253                 emitcode ("orl", "a,%s",
5254                           aopGet (AOP (left), offset, FALSE, FALSE));
5255               }
5256               emitcode ("jnz", "%05d$", tlbl->key + 100);
5257               offset++;
5258             }
5259           if (size)
5260             {
5261               CLRC;
5262               emitcode ("", "%05d$:", tlbl->key + 100);
5263               outBitC (result);
5264             }
5265           else if (ifx)
5266             jmpTrueOrFalse (ifx, tlbl);
5267         }
5268       else
5269         for (; (size--); offset++)
5270           {
5271             // normal case
5272             // result = left & right
5273             if (AOP_TYPE (right) == AOP_LIT)
5274               {
5275                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5276                   {
5277                     aopPut (AOP (result),
5278                             aopGet (AOP (left), offset, FALSE, FALSE),
5279                             offset,
5280                             isOperandVolatile (result, FALSE));
5281                     continue;
5282                   }
5283               }
5284             // faster than result <- left, anl result,right
5285             // and better if result is SFR
5286             if (AOP_TYPE (left) == AOP_ACC)
5287               emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5288             else
5289               {
5290                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5291                 emitcode ("orl", "a,%s",
5292                           aopGet (AOP (left), offset, FALSE, FALSE));
5293               }
5294             aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5295           }
5296     }
5297
5298 release:
5299   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5300   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5301   freeAsmop (result, NULL, ic, TRUE);
5302 }
5303
5304 /*-----------------------------------------------------------------*/
5305 /* genXor - code for xclusive or                                   */
5306 /*-----------------------------------------------------------------*/
5307 static void
5308 genXor (iCode * ic, iCode * ifx)
5309 {
5310   operand *left, *right, *result;
5311   int size, offset = 0;
5312   unsigned long lit = 0L;
5313
5314   D(emitcode (";     genXor",""));
5315
5316   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5317   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5318   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5319
5320 #ifdef DEBUG_TYPE
5321   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5322             AOP_TYPE (result),
5323             AOP_TYPE (left), AOP_TYPE (right));
5324   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5325             AOP_SIZE (result),
5326             AOP_SIZE (left), AOP_SIZE (right));
5327 #endif
5328
5329   /* if left is a literal & right is not ||
5330      if left needs acc & right does not */
5331   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5332       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5333     {
5334       operand *tmp = right;
5335       right = left;
5336       left = tmp;
5337     }
5338
5339   /* if result = right then exchange them */
5340   if (sameRegs (AOP (result), AOP (right)))
5341     {
5342       operand *tmp = right;
5343       right = left;
5344       left = tmp;
5345     }
5346
5347   /* if right is bit then exchange them */
5348   if (AOP_TYPE (right) == AOP_CRY &&
5349       AOP_TYPE (left) != AOP_CRY)
5350     {
5351       operand *tmp = right;
5352       right = left;
5353       left = tmp;
5354     }
5355   if (AOP_TYPE (right) == AOP_LIT)
5356     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5357
5358   size = AOP_SIZE (result);
5359
5360   // if(bit ^ yy)
5361   // xx = bit ^ yy;
5362   if (AOP_TYPE (left) == AOP_CRY)
5363     {
5364       if (AOP_TYPE (right) == AOP_LIT)
5365         {
5366           // c = bit & literal;
5367           if (lit >> 1)
5368             {
5369               // lit>>1  != 0 => result = 1
5370               if (AOP_TYPE (result) == AOP_CRY)
5371                 {
5372                   if (size)
5373                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5374                   else if (ifx)
5375                     continueIfTrue (ifx);
5376                   goto release;
5377                 }
5378               emitcode ("setb", "c");
5379             }
5380           else
5381             {
5382               // lit == (0 or 1)
5383               if (lit == 0)
5384                 {
5385                   // lit == 0, result = left
5386                   if (size && sameRegs (AOP (result), AOP (left)))
5387                     goto release;
5388                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5389                 }
5390               else
5391                 {
5392                   // lit == 1, result = not(left)
5393                   if (size && sameRegs (AOP (result), AOP (left)))
5394                     {
5395                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5396                       goto release;
5397                     }
5398                   else
5399                     {
5400                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5401                       emitcode ("cpl", "c");
5402                     }
5403                 }
5404             }
5405
5406         }
5407       else
5408         {
5409           // right != literal
5410           symbol *tlbl = newiTempLabel (NULL);
5411           if (AOP_TYPE (right) == AOP_CRY)
5412             {
5413               // c = bit ^ bit;
5414               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5415             }
5416           else
5417             {
5418               int sizer = AOP_SIZE (right);
5419               // c = bit ^ val
5420               // if val>>1 != 0, result = 1
5421               emitcode ("setb", "c");
5422               while (sizer)
5423                 {
5424                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5425                   if (sizer == 1)
5426                     // test the msb of the lsb
5427                     emitcode ("anl", "a,#0xfe");
5428                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5429                   sizer--;
5430                 }
5431               // val = (0,1)
5432               emitcode ("rrc", "a");
5433             }
5434           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5435           emitcode ("cpl", "c");
5436           emitcode ("", "%05d$:", (tlbl->key + 100));
5437         }
5438       // bit = c
5439       // val = c
5440       if (size)
5441         outBitC (result);
5442       // if(bit | ...)
5443       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5444         genIfxJump (ifx, "c");
5445       goto release;
5446     }
5447
5448   if (sameRegs (AOP (result), AOP (left)))
5449     {
5450       /* if left is same as result */
5451       for (; size--; offset++)
5452         {
5453           if (AOP_TYPE (right) == AOP_LIT)
5454             {
5455               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5456                 continue;
5457               else if (IS_AOP_PREG (left))
5458                 {
5459                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5460                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5461                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5462                 }
5463               else
5464                 emitcode ("xrl", "%s,%s",
5465                           aopGet (AOP (left), offset, FALSE, TRUE),
5466                           aopGet (AOP (right), offset, FALSE, FALSE));
5467             }
5468           else
5469             {
5470               if (AOP_TYPE (left) == AOP_ACC)
5471                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5472               else
5473                 {
5474                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5475                   if (IS_AOP_PREG (left))
5476                     {
5477                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5478                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5479                     }
5480                   else
5481                     emitcode ("xrl", "%s,a",
5482                               aopGet (AOP (left), offset, FALSE, TRUE));
5483                 }
5484             }
5485         }
5486     }
5487   else
5488     {
5489       // left & result in different registers
5490       if (AOP_TYPE (result) == AOP_CRY)
5491         {
5492           // result = bit
5493           // if(size), result in bit
5494           // if(!size && ifx), conditional oper: if(left ^ right)
5495           symbol *tlbl = newiTempLabel (NULL);
5496           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5497           if (size)
5498             emitcode ("setb", "c");
5499           while (sizer--)
5500             {
5501               if ((AOP_TYPE (right) == AOP_LIT) &&
5502                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5503                 {
5504                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5505                 }
5506               else
5507                 {
5508                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5509                     emitcode ("xrl", "a,%s",
5510                               aopGet (AOP (right), offset, FALSE, FALSE));
5511                   } else {
5512                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5513                     emitcode ("xrl", "a,%s",
5514                               aopGet (AOP (left), offset, FALSE, FALSE));
5515                   }
5516                 }
5517               emitcode ("jnz", "%05d$", tlbl->key + 100);
5518               offset++;
5519             }
5520           if (size)
5521             {
5522               CLRC;
5523               emitcode ("", "%05d$:", tlbl->key + 100);
5524               outBitC (result);
5525             }
5526           else if (ifx)
5527             jmpTrueOrFalse (ifx, tlbl);
5528         }
5529       else
5530         for (; (size--); offset++)
5531           {
5532             // normal case
5533             // result = left & right
5534             if (AOP_TYPE (right) == AOP_LIT)
5535               {
5536                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5537                   {
5538                     aopPut (AOP (result),
5539                             aopGet (AOP (left), offset, FALSE, FALSE),
5540                             offset,
5541                             isOperandVolatile (result, FALSE));
5542                     continue;
5543                   }
5544               }
5545             // faster than result <- left, anl result,right
5546             // and better if result is SFR
5547             if (AOP_TYPE (left) == AOP_ACC)
5548               emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5549             else
5550               {
5551                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5552                 emitcode ("xrl", "a,%s",
5553                           aopGet (AOP (left), offset, FALSE, TRUE));
5554               }
5555             aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5556           }
5557     }
5558
5559 release:
5560   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5561   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5562   freeAsmop (result, NULL, ic, TRUE);
5563 }
5564
5565 /*-----------------------------------------------------------------*/
5566 /* genInline - write the inline code out                           */
5567 /*-----------------------------------------------------------------*/
5568 static void
5569 genInline (iCode * ic)
5570 {
5571   char *buffer, *bp, *bp1;
5572
5573   D(emitcode (";     genInline",""));
5574
5575   _G.inLine += (!options.asmpeep);
5576
5577   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5578   strcpy (buffer, IC_INLINE (ic));
5579
5580   /* emit each line as a code */
5581   while (*bp)
5582     {
5583       if (*bp == '\n')
5584         {
5585           *bp++ = '\0';
5586           emitcode (bp1, "");
5587           bp1 = bp;
5588         }
5589       else
5590         {
5591           if (*bp == ':')
5592             {
5593               bp++;
5594               *bp = '\0';
5595               bp++;
5596               emitcode (bp1, "");
5597               bp1 = bp;
5598             }
5599           else
5600             bp++;
5601         }
5602     }
5603   if (bp1 != bp)
5604     emitcode (bp1, "");
5605   /*     emitcode("",buffer); */
5606   _G.inLine -= (!options.asmpeep);
5607 }
5608
5609 /*-----------------------------------------------------------------*/
5610 /* genRRC - rotate right with carry                                */
5611 /*-----------------------------------------------------------------*/
5612 static void
5613 genRRC (iCode * ic)
5614 {
5615   operand *left, *result;
5616   int size, offset = 0;
5617   char *l;
5618
5619   D(emitcode (";     genRRC",""));
5620
5621   /* rotate right with carry */
5622   left = IC_LEFT (ic);
5623   result = IC_RESULT (ic);
5624   aopOp (left, ic, FALSE);
5625   aopOp (result, ic, FALSE);
5626
5627   /* move it to the result */
5628   size = AOP_SIZE (result);
5629   offset = size - 1;
5630   if (size == 1) { /* special case for 1 byte */
5631       l = aopGet (AOP (left), offset, FALSE, FALSE);
5632       MOVA (l);
5633       emitcode ("rr", "a");
5634       goto release;
5635   }
5636   CLRC;
5637   while (size--)
5638     {
5639       l = aopGet (AOP (left), offset, FALSE, FALSE);
5640       MOVA (l);
5641       emitcode ("rrc", "a");
5642       if (AOP_SIZE (result) > 1)
5643         aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5644     }
5645   /* now we need to put the carry into the
5646      highest order byte of the result */
5647   if (AOP_SIZE (result) > 1)
5648     {
5649       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5650       MOVA (l);
5651     }
5652   emitcode ("mov", "acc.7,c");
5653  release:
5654   aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5655   freeAsmop (left, NULL, ic, TRUE);
5656   freeAsmop (result, NULL, ic, TRUE);
5657 }
5658
5659 /*-----------------------------------------------------------------*/
5660 /* genRLC - generate code for rotate left with carry               */
5661 /*-----------------------------------------------------------------*/
5662 static void
5663 genRLC (iCode * ic)
5664 {
5665   operand *left, *result;
5666   int size, offset = 0;
5667   char *l;
5668
5669   D(emitcode (";     genRLC",""));
5670
5671   /* rotate right with carry */
5672   left = IC_LEFT (ic);
5673   result = IC_RESULT (ic);
5674   aopOp (left, ic, FALSE);
5675   aopOp (result, ic, FALSE);
5676
5677   /* move it to the result */
5678   size = AOP_SIZE (result);
5679   offset = 0;
5680   if (size--)
5681     {
5682       l = aopGet (AOP (left), offset, FALSE, FALSE);
5683       MOVA (l);
5684       if (size == 0) { /* special case for 1 byte */
5685               emitcode("rl","a");
5686               goto release;
5687       }
5688       emitcode ("add", "a,acc");
5689       if (AOP_SIZE (result) > 1)
5690         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5691       while (size--)
5692         {
5693           l = aopGet (AOP (left), offset, FALSE, FALSE);
5694           MOVA (l);
5695           emitcode ("rlc", "a");
5696           if (AOP_SIZE (result) > 1)
5697             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5698         }
5699     }
5700   /* now we need to put the carry into the
5701      highest order byte of the result */
5702   if (AOP_SIZE (result) > 1)
5703     {
5704       l = aopGet (AOP (result), 0, FALSE, FALSE);
5705       MOVA (l);
5706     }
5707   emitcode ("mov", "acc.0,c");
5708  release:
5709   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5710   freeAsmop (left, NULL, ic, TRUE);
5711   freeAsmop (result, NULL, ic, TRUE);
5712 }
5713
5714 /*-----------------------------------------------------------------*/
5715 /* genGetHbit - generates code get highest order bit               */
5716 /*-----------------------------------------------------------------*/
5717 static void
5718 genGetHbit (iCode * ic)
5719 {
5720   operand *left, *result;
5721
5722   D(emitcode (";     genGetHbit",""));
5723
5724   left = IC_LEFT (ic);
5725   result = IC_RESULT (ic);
5726   aopOp (left, ic, FALSE);
5727   aopOp (result, ic, FALSE);
5728
5729   /* get the highest order byte into a */
5730   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5731   if (AOP_TYPE (result) == AOP_CRY)
5732     {
5733       emitcode ("rlc", "a");
5734       outBitC (result);
5735     }
5736   else
5737     {
5738       emitcode ("rl", "a");
5739       emitcode ("anl", "a,#0x01");
5740       outAcc (result);
5741     }
5742
5743
5744   freeAsmop (left, NULL, ic, TRUE);
5745   freeAsmop (result, NULL, ic, TRUE);
5746 }
5747
5748 /*-----------------------------------------------------------------*/
5749 /* AccRol - rotate left accumulator by known count                 */
5750 /*-----------------------------------------------------------------*/
5751 static void
5752 AccRol (int shCount)
5753 {
5754   shCount &= 0x0007;            // shCount : 0..7
5755
5756   switch (shCount)
5757     {
5758     case 0:
5759       break;
5760     case 1:
5761       emitcode ("rl", "a");
5762       break;
5763     case 2:
5764       emitcode ("rl", "a");
5765       emitcode ("rl", "a");
5766       break;
5767     case 3:
5768       emitcode ("swap", "a");
5769       emitcode ("rr", "a");
5770       break;
5771     case 4:
5772       emitcode ("swap", "a");
5773       break;
5774     case 5:
5775       emitcode ("swap", "a");
5776       emitcode ("rl", "a");
5777       break;
5778     case 6:
5779       emitcode ("rr", "a");
5780       emitcode ("rr", "a");
5781       break;
5782     case 7:
5783       emitcode ("rr", "a");
5784       break;
5785     }
5786 }
5787
5788 /*-----------------------------------------------------------------*/
5789 /* AccLsh - left shift accumulator by known count                  */
5790 /*-----------------------------------------------------------------*/
5791 static void
5792 AccLsh (int shCount)
5793 {
5794   if (shCount != 0)
5795     {
5796       if (shCount == 1)
5797         emitcode ("add", "a,acc");
5798       else if (shCount == 2)
5799         {
5800           emitcode ("add", "a,acc");
5801           emitcode ("add", "a,acc");
5802         }
5803       else
5804         {
5805           /* rotate left accumulator */
5806           AccRol (shCount);
5807           /* and kill the lower order bits */
5808           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5809         }
5810     }
5811 }
5812
5813 /*-----------------------------------------------------------------*/
5814 /* AccRsh - right shift accumulator by known count                 */
5815 /*-----------------------------------------------------------------*/
5816 static void
5817 AccRsh (int shCount)
5818 {
5819   if (shCount != 0)
5820     {
5821       if (shCount == 1)
5822         {
5823           CLRC;
5824           emitcode ("rrc", "a");
5825         }
5826       else
5827         {
5828           /* rotate right accumulator */
5829           AccRol (8 - shCount);
5830           /* and kill the higher order bits */
5831           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5832         }
5833     }
5834 }
5835
5836 /*-----------------------------------------------------------------*/
5837 /* AccSRsh - signed right shift accumulator by known count                 */
5838 /*-----------------------------------------------------------------*/
5839 static void
5840 AccSRsh (int shCount)
5841 {
5842   symbol *tlbl;
5843   if (shCount != 0)
5844     {
5845       if (shCount == 1)
5846         {
5847           emitcode ("mov", "c,acc.7");
5848           emitcode ("rrc", "a");
5849         }
5850       else if (shCount == 2)
5851         {
5852           emitcode ("mov", "c,acc.7");
5853           emitcode ("rrc", "a");
5854           emitcode ("mov", "c,acc.7");
5855           emitcode ("rrc", "a");
5856         }
5857       else
5858         {
5859           tlbl = newiTempLabel (NULL);
5860           /* rotate right accumulator */
5861           AccRol (8 - shCount);
5862           /* and kill the higher order bits */
5863           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5864           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5865           emitcode ("orl", "a,#0x%02x",
5866                     (unsigned char) ~SRMask[shCount]);
5867           emitcode ("", "%05d$:", tlbl->key + 100);
5868         }
5869     }
5870 }
5871
5872 /*-----------------------------------------------------------------*/
5873 /* shiftR1Left2Result - shift right one byte from left to result   */
5874 /*-----------------------------------------------------------------*/
5875 static void
5876 shiftR1Left2Result (operand * left, int offl,
5877                     operand * result, int offr,
5878                     int shCount, int sign)
5879 {
5880   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5881   /* shift right accumulator */
5882   if (sign)
5883     AccSRsh (shCount);
5884   else
5885     AccRsh (shCount);
5886   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5887 }
5888
5889 /*-----------------------------------------------------------------*/
5890 /* shiftL1Left2Result - shift left one byte from left to result    */
5891 /*-----------------------------------------------------------------*/
5892 static void
5893 shiftL1Left2Result (operand * left, int offl,
5894                     operand * result, int offr, int shCount)
5895 {
5896   char *l;
5897   l = aopGet (AOP (left), offl, FALSE, FALSE);
5898   MOVA (l);
5899   /* shift left accumulator */
5900   AccLsh (shCount);
5901   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5902 }
5903
5904 /*-----------------------------------------------------------------*/
5905 /* movLeft2Result - move byte from left to result                  */
5906 /*-----------------------------------------------------------------*/
5907 static void
5908 movLeft2Result (operand * left, int offl,
5909                 operand * result, int offr, int sign)
5910 {
5911   char *l;
5912   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5913     {
5914       l = aopGet (AOP (left), offl, FALSE, FALSE);
5915
5916       if (*l == '@' && (IS_AOP_PREG (result)))
5917         {
5918           emitcode ("mov", "a,%s", l);
5919           aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5920         }
5921       else
5922         {
5923           if (!sign)
5924             aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5925           else
5926             {
5927               /* MSB sign in acc.7 ! */
5928               if (getDataSize (left) == offl + 1)
5929                 {
5930                   emitcode ("mov", "a,%s", l);
5931                   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5932                 }
5933             }
5934         }
5935     }
5936 }
5937
5938 /*-----------------------------------------------------------------*/
5939 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5940 /*-----------------------------------------------------------------*/
5941 static void
5942 AccAXRrl1 (char *x)
5943 {
5944   emitcode ("rrc", "a");
5945   emitcode ("xch", "a,%s", x);
5946   emitcode ("rrc", "a");
5947   emitcode ("xch", "a,%s", x);
5948 }
5949
5950 /*-----------------------------------------------------------------*/
5951 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5952 /*-----------------------------------------------------------------*/
5953 static void
5954 AccAXLrl1 (char *x)
5955 {
5956   emitcode ("xch", "a,%s", x);
5957   emitcode ("rlc", "a");
5958   emitcode ("xch", "a,%s", x);
5959   emitcode ("rlc", "a");
5960 }
5961
5962 /*-----------------------------------------------------------------*/
5963 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5964 /*-----------------------------------------------------------------*/
5965 static void
5966 AccAXLsh1 (char *x)
5967 {
5968   emitcode ("xch", "a,%s", x);
5969   emitcode ("add", "a,acc");
5970   emitcode ("xch", "a,%s", x);
5971   emitcode ("rlc", "a");
5972 }
5973
5974 /*-----------------------------------------------------------------*/
5975 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5976 /*-----------------------------------------------------------------*/
5977 static void
5978 AccAXLsh (char *x, int shCount)
5979 {
5980   switch (shCount)
5981     {
5982     case 0:
5983       break;
5984     case 1:
5985       AccAXLsh1 (x);
5986       break;
5987     case 2:
5988       AccAXLsh1 (x);
5989       AccAXLsh1 (x);
5990       break;
5991     case 3:
5992     case 4:
5993     case 5:                     // AAAAABBB:CCCCCDDD
5994
5995       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
5996
5997       emitcode ("anl", "a,#0x%02x",
5998                 SLMask[shCount]);       // BBB00000:CCCCCDDD
5999
6000       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6001
6002       AccRol (shCount);         // DDDCCCCC:BBB00000
6003
6004       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6005
6006       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6007
6008       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6009
6010       emitcode ("anl", "a,#0x%02x",
6011                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6012
6013       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6014
6015       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6016
6017       break;
6018     case 6:                     // AAAAAABB:CCCCCCDD
6019       emitcode ("anl", "a,#0x%02x",
6020                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6021       emitcode ("mov", "c,acc.0");      // c = B
6022       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6023 #if 0 // REMOVE ME
6024       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6025       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6026 #else
6027       emitcode("rrc","a"); 
6028       emitcode("xch","a,%s", x); 
6029       emitcode("rrc","a"); 
6030       emitcode("mov","c,acc.0"); //<< get correct bit 
6031       emitcode("xch","a,%s", x); 
6032
6033       emitcode("rrc","a"); 
6034       emitcode("xch","a,%s", x); 
6035       emitcode("rrc","a"); 
6036       emitcode("xch","a,%s", x); 
6037 #endif
6038       break;
6039     case 7:                     // a:x <<= 7
6040
6041       emitcode ("anl", "a,#0x%02x",
6042                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6043
6044       emitcode ("mov", "c,acc.0");      // c = B
6045
6046       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6047
6048       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6049
6050       break;
6051     default:
6052       break;
6053     }
6054 }
6055
6056 /*-----------------------------------------------------------------*/
6057 /* AccAXRsh - right shift a:x known count (0..7)                   */
6058 /*-----------------------------------------------------------------*/
6059 static void
6060 AccAXRsh (char *x, int shCount)
6061 {
6062   switch (shCount)
6063     {
6064     case 0:
6065       break;
6066     case 1:
6067       CLRC;
6068       AccAXRrl1 (x);            // 0->a:x
6069
6070       break;
6071     case 2:
6072       CLRC;
6073       AccAXRrl1 (x);            // 0->a:x
6074
6075       CLRC;
6076       AccAXRrl1 (x);            // 0->a:x
6077
6078       break;
6079     case 3:
6080     case 4:
6081     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6082
6083       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6084
6085       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6086
6087       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6088
6089       emitcode ("anl", "a,#0x%02x",
6090                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6091
6092       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6093
6094       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6095
6096       emitcode ("anl", "a,#0x%02x",
6097                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6098
6099       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6100
6101       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6102
6103       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6104
6105       break;
6106     case 6:                     // AABBBBBB:CCDDDDDD
6107
6108       emitcode ("mov", "c,acc.7");
6109       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6110
6111       emitcode ("mov", "c,acc.7");
6112       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6113
6114       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6115
6116       emitcode ("anl", "a,#0x%02x",
6117                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6118
6119       break;
6120     case 7:                     // ABBBBBBB:CDDDDDDD
6121
6122       emitcode ("mov", "c,acc.7");      // c = A
6123
6124       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6125
6126       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6127
6128       emitcode ("anl", "a,#0x%02x",
6129                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6130
6131       break;
6132     default:
6133       break;
6134     }
6135 }
6136
6137 /*-----------------------------------------------------------------*/
6138 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6139 /*-----------------------------------------------------------------*/
6140 static void
6141 AccAXRshS (char *x, int shCount)
6142 {
6143   symbol *tlbl;
6144   switch (shCount)
6145     {
6146     case 0:
6147       break;
6148     case 1:
6149       emitcode ("mov", "c,acc.7");
6150       AccAXRrl1 (x);            // s->a:x
6151
6152       break;
6153     case 2:
6154       emitcode ("mov", "c,acc.7");
6155       AccAXRrl1 (x);            // s->a:x
6156
6157       emitcode ("mov", "c,acc.7");
6158       AccAXRrl1 (x);            // s->a:x
6159
6160       break;
6161     case 3:
6162     case 4:
6163     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6164
6165       tlbl = newiTempLabel (NULL);
6166       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6167
6168       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6169
6170       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6171
6172       emitcode ("anl", "a,#0x%02x",
6173                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6174
6175       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6176
6177       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6178
6179       emitcode ("anl", "a,#0x%02x",
6180                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6181
6182       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6183
6184       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6185
6186       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6187
6188       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6189       emitcode ("orl", "a,#0x%02x",
6190                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6191
6192       emitcode ("", "%05d$:", tlbl->key + 100);
6193       break;                    // SSSSAAAA:BBBCCCCC
6194
6195     case 6:                     // AABBBBBB:CCDDDDDD
6196
6197       tlbl = newiTempLabel (NULL);
6198       emitcode ("mov", "c,acc.7");
6199       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6200
6201       emitcode ("mov", "c,acc.7");
6202       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6203
6204       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6205
6206       emitcode ("anl", "a,#0x%02x",
6207                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6208
6209       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6210       emitcode ("orl", "a,#0x%02x",
6211                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6212
6213       emitcode ("", "%05d$:", tlbl->key + 100);
6214       break;
6215     case 7:                     // ABBBBBBB:CDDDDDDD
6216
6217       tlbl = newiTempLabel (NULL);
6218       emitcode ("mov", "c,acc.7");      // c = A
6219
6220       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6221
6222       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6223
6224       emitcode ("anl", "a,#0x%02x",
6225                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6226
6227       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6228       emitcode ("orl", "a,#0x%02x",
6229                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6230
6231       emitcode ("", "%05d$:", tlbl->key + 100);
6232       break;
6233     default:
6234       break;
6235     }
6236 }
6237
6238 /*-----------------------------------------------------------------*/
6239 /* shiftL2Left2Result - shift left two bytes from left to result   */
6240 /*-----------------------------------------------------------------*/
6241 static void
6242 shiftL2Left2Result (operand * left, int offl,
6243                     operand * result, int offr, int shCount)
6244 {
6245   if (sameRegs (AOP (result), AOP (left)) &&
6246       ((offl + MSB16) == offr))
6247     {
6248       /* don't crash result[offr] */
6249       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6250       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6251     }
6252   else
6253     {
6254       movLeft2Result (left, offl, result, offr, 0);
6255       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6256     }
6257   /* ax << shCount (x = lsb(result)) */
6258   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6259   aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6260 }
6261
6262
6263 /*-----------------------------------------------------------------*/
6264 /* shiftR2Left2Result - shift right two bytes from left to result  */
6265 /*-----------------------------------------------------------------*/
6266 static void
6267 shiftR2Left2Result (operand * left, int offl,
6268                     operand * result, int offr,
6269                     int shCount, int sign)
6270 {
6271   if (sameRegs (AOP (result), AOP (left)) &&
6272       ((offl + MSB16) == offr))
6273     {
6274       /* don't crash result[offr] */
6275       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6276       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6277     }
6278   else
6279     {
6280       movLeft2Result (left, offl, result, offr, 0);
6281       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6282     }
6283   /* a:x >> shCount (x = lsb(result)) */
6284   if (sign)
6285     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6286   else
6287     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6288   if (getDataSize (result) > 1)
6289     aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6290 }
6291
6292 /*-----------------------------------------------------------------*/
6293 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6294 /*-----------------------------------------------------------------*/
6295 static void
6296 shiftLLeftOrResult (operand * left, int offl,
6297                     operand * result, int offr, int shCount)
6298 {
6299   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6300   /* shift left accumulator */
6301   AccLsh (shCount);
6302   /* or with result */
6303   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6304   /* back to result */
6305   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6306 }
6307
6308 /*-----------------------------------------------------------------*/
6309 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6310 /*-----------------------------------------------------------------*/
6311 static void
6312 shiftRLeftOrResult (operand * left, int offl,
6313                     operand * result, int offr, int shCount)
6314 {
6315   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6316   /* shift right accumulator */
6317   AccRsh (shCount);
6318   /* or with result */
6319   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6320   /* back to result */
6321   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6322 }
6323
6324 /*-----------------------------------------------------------------*/
6325 /* genlshOne - left shift a one byte quantity by known count       */
6326 /*-----------------------------------------------------------------*/
6327 static void
6328 genlshOne (operand * result, operand * left, int shCount)
6329 {
6330   D(emitcode (";     genlshOne",""));
6331
6332   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6333 }
6334
6335 /*-----------------------------------------------------------------*/
6336 /* genlshTwo - left shift two bytes by known amount != 0           */
6337 /*-----------------------------------------------------------------*/
6338 static void
6339 genlshTwo (operand * result, operand * left, int shCount)
6340 {
6341   int size;
6342
6343   D(emitcode (";     genlshTwo",""));
6344
6345   size = getDataSize (result);
6346
6347   /* if shCount >= 8 */
6348   if (shCount >= 8)
6349     {
6350       shCount -= 8;
6351
6352       if (size > 1)
6353         {
6354           if (shCount)
6355             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6356           else
6357             movLeft2Result (left, LSB, result, MSB16, 0);
6358         }
6359       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6360     }
6361
6362   /*  1 <= shCount <= 7 */
6363   else
6364     {
6365       if (size == 1)
6366         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6367       else
6368         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6369     }
6370 }
6371
6372 /*-----------------------------------------------------------------*/
6373 /* shiftLLong - shift left one long from left to result            */
6374 /* offl = LSB or MSB16                                             */
6375 /*-----------------------------------------------------------------*/
6376 static void
6377 shiftLLong (operand * left, operand * result, int offr)
6378 {
6379   char *l;
6380   int size = AOP_SIZE (result);
6381
6382   if (size >= LSB + offr)
6383     {
6384       l = aopGet (AOP (left), LSB, FALSE, FALSE);
6385       MOVA (l);
6386       emitcode ("add", "a,acc");
6387       if (sameRegs (AOP (left), AOP (result)) &&
6388           size >= MSB16 + offr && offr != LSB)
6389         emitcode ("xch", "a,%s",
6390                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6391       else
6392         aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6393     }
6394
6395   if (size >= MSB16 + offr)
6396     {
6397       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6398         {
6399           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6400           MOVA (l);
6401         }
6402       emitcode ("rlc", "a");
6403       if (sameRegs (AOP (left), AOP (result)) &&
6404           size >= MSB24 + offr && offr != LSB)
6405         emitcode ("xch", "a,%s",
6406                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6407       else
6408         aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6409     }
6410
6411   if (size >= MSB24 + offr)
6412     {
6413       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6414         {
6415           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6416           MOVA (l);
6417         }
6418       emitcode ("rlc", "a");
6419       if (sameRegs (AOP (left), AOP (result)) &&
6420           size >= MSB32 + offr && offr != LSB)
6421         emitcode ("xch", "a,%s",
6422                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6423       else
6424         aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6425     }
6426
6427   if (size > MSB32 + offr)
6428     {
6429       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6430         {
6431           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6432           MOVA (l);
6433         }
6434       emitcode ("rlc", "a");
6435       aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6436     }
6437   if (offr != LSB)
6438     aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6439 }
6440
6441 /*-----------------------------------------------------------------*/
6442 /* genlshFour - shift four byte by a known amount != 0             */
6443 /*-----------------------------------------------------------------*/
6444 static void
6445 genlshFour (operand * result, operand * left, int shCount)
6446 {
6447   int size;
6448
6449   D(emitcode (";     genlshFour",""));
6450
6451   size = AOP_SIZE (result);
6452
6453   /* if shifting more that 3 bytes */
6454   if (shCount >= 24)
6455     {
6456       shCount -= 24;
6457       if (shCount)
6458         /* lowest order of left goes to the highest
6459            order of the destination */
6460         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6461       else
6462         movLeft2Result (left, LSB, result, MSB32, 0);
6463       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6464       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6465       aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6466       return;
6467     }
6468
6469   /* more than two bytes */
6470   else if (shCount >= 16)
6471     {
6472       /* lower order two bytes goes to higher order two bytes */
6473       shCount -= 16;
6474       /* if some more remaining */
6475       if (shCount)
6476         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6477       else
6478         {
6479           movLeft2Result (left, MSB16, result, MSB32, 0);
6480           movLeft2Result (left, LSB, result, MSB24, 0);
6481         }
6482       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6483       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6484       return;
6485     }
6486
6487   /* if more than 1 byte */
6488   else if (shCount >= 8)
6489     {
6490       /* lower order three bytes goes to higher order  three bytes */
6491       shCount -= 8;
6492       if (size == 2)
6493         {
6494           if (shCount)
6495             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6496           else
6497             movLeft2Result (left, LSB, result, MSB16, 0);
6498         }
6499       else
6500         {                       /* size = 4 */
6501           if (shCount == 0)
6502             {
6503               movLeft2Result (left, MSB24, result, MSB32, 0);
6504               movLeft2Result (left, MSB16, result, MSB24, 0);
6505               movLeft2Result (left, LSB, result, MSB16, 0);
6506               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6507             }
6508           else if (shCount == 1)
6509             shiftLLong (left, result, MSB16);
6510           else
6511             {
6512               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6513               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6514               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6515               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6516             }
6517         }
6518     }
6519
6520   /* 1 <= shCount <= 7 */
6521   else if (shCount <= 2)
6522     {
6523       shiftLLong (left, result, LSB);
6524       if (shCount == 2)
6525         shiftLLong (result, result, LSB);
6526     }
6527   /* 3 <= shCount <= 7, optimize */
6528   else
6529     {
6530       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6531       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6532       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6533     }
6534 }
6535
6536 /*-----------------------------------------------------------------*/
6537 /* genLeftShiftLiteral - left shifting by known count              */
6538 /*-----------------------------------------------------------------*/
6539 static void
6540 genLeftShiftLiteral (operand * left,
6541                      operand * right,
6542                      operand * result,
6543                      iCode * ic)
6544 {
6545   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6546   int size;
6547
6548   D(emitcode (";     genLeftShiftLiteral",""));
6549
6550   freeAsmop (right, NULL, ic, TRUE);
6551
6552   aopOp (left, ic, FALSE);
6553   aopOp (result, ic, FALSE);
6554
6555   size = getSize (operandType (result));
6556
6557 #if VIEW_SIZE
6558   emitcode ("; shift left ", "result %d, left %d", size,
6559             AOP_SIZE (left));
6560 #endif
6561
6562   /* I suppose that the left size >= result size */
6563   if (shCount == 0)
6564     {
6565       while (size--)
6566         {
6567           movLeft2Result (left, size, result, size, 0);
6568         }
6569     }
6570
6571   else if (shCount >= (size * 8))
6572     while (size--)
6573       aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6574   else
6575     {
6576       switch (size)
6577         {
6578         case 1:
6579           genlshOne (result, left, shCount);
6580           break;
6581
6582         case 2:
6583           genlshTwo (result, left, shCount);
6584           break;
6585
6586         case 4:
6587           genlshFour (result, left, shCount);
6588           break;
6589         default:
6590           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6591                   "*** ack! mystery literal shift!\n");
6592           break;
6593         }
6594     }
6595   freeAsmop (left, NULL, ic, TRUE);
6596   freeAsmop (result, NULL, ic, TRUE);
6597 }
6598
6599 /*-----------------------------------------------------------------*/
6600 /* genLeftShift - generates code for left shifting                 */
6601 /*-----------------------------------------------------------------*/
6602 static void
6603 genLeftShift (iCode * ic)
6604 {
6605   operand *left, *right, *result;
6606   int size, offset;
6607   char *l;
6608   symbol *tlbl, *tlbl1;
6609
6610   D(emitcode (";     genLeftShift",""));
6611
6612   right = IC_RIGHT (ic);
6613   left = IC_LEFT (ic);
6614   result = IC_RESULT (ic);
6615
6616   aopOp (right, ic, FALSE);
6617
6618   /* if the shift count is known then do it
6619      as efficiently as possible */
6620   if (AOP_TYPE (right) == AOP_LIT)
6621     {
6622       genLeftShiftLiteral (left, right, result, ic);
6623       return;
6624     }
6625
6626   /* shift count is unknown then we have to form
6627      a loop get the loop count in B : Note: we take
6628      only the lower order byte since shifting
6629      more that 32 bits make no sense anyway, ( the
6630      largest size of an object can be only 32 bits ) */
6631
6632   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6633   emitcode ("inc", "b");
6634   freeAsmop (right, NULL, ic, TRUE);
6635   aopOp (left, ic, FALSE);
6636   aopOp (result, ic, FALSE);
6637
6638   /* now move the left to the result if they are not the
6639      same */
6640   if (!sameRegs (AOP (left), AOP (result)) &&
6641       AOP_SIZE (result) > 1)
6642     {
6643
6644       size = AOP_SIZE (result);
6645       offset = 0;
6646       while (size--)
6647         {
6648           l = aopGet (AOP (left), offset, FALSE, TRUE);
6649           if (*l == '@' && (IS_AOP_PREG (result)))
6650             {
6651
6652               emitcode ("mov", "a,%s", l);
6653               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6654             }
6655           else
6656             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6657           offset++;
6658         }
6659     }
6660
6661   tlbl = newiTempLabel (NULL);
6662   size = AOP_SIZE (result);
6663   offset = 0;
6664   tlbl1 = newiTempLabel (NULL);
6665
6666   /* if it is only one byte then */
6667   if (size == 1)
6668     {
6669       symbol *tlbl1 = newiTempLabel (NULL);
6670
6671       l = aopGet (AOP (left), 0, FALSE, FALSE);
6672       MOVA (l);
6673       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6674       emitcode ("", "%05d$:", tlbl->key + 100);
6675       emitcode ("add", "a,acc");
6676       emitcode ("", "%05d$:", tlbl1->key + 100);
6677       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6678       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6679       goto release;
6680     }
6681
6682   reAdjustPreg (AOP (result));
6683
6684   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6685   emitcode ("", "%05d$:", tlbl->key + 100);
6686   l = aopGet (AOP (result), offset, FALSE, FALSE);
6687   MOVA (l);
6688   emitcode ("add", "a,acc");
6689   aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6690   while (--size)
6691     {
6692       l = aopGet (AOP (result), offset, FALSE, FALSE);
6693       MOVA (l);
6694       emitcode ("rlc", "a");
6695       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6696     }
6697   reAdjustPreg (AOP (result));
6698
6699   emitcode ("", "%05d$:", tlbl1->key + 100);
6700   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6701 release:
6702   freeAsmop (left, NULL, ic, TRUE);
6703   freeAsmop (result, NULL, ic, TRUE);
6704 }
6705
6706 /*-----------------------------------------------------------------*/
6707 /* genrshOne - right shift a one byte quantity by known count      */
6708 /*-----------------------------------------------------------------*/
6709 static void
6710 genrshOne (operand * result, operand * left,
6711            int shCount, int sign)
6712 {
6713   D(emitcode (";     genrshOne",""));
6714
6715   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6716 }
6717
6718 /*-----------------------------------------------------------------*/
6719 /* genrshTwo - right shift two bytes by known amount != 0          */
6720 /*-----------------------------------------------------------------*/
6721 static void
6722 genrshTwo (operand * result, operand * left,
6723            int shCount, int sign)
6724 {
6725   D(emitcode (";     genrshTwo",""));
6726
6727   /* if shCount >= 8 */
6728   if (shCount >= 8)
6729     {
6730       shCount -= 8;
6731       if (shCount)
6732         shiftR1Left2Result (left, MSB16, result, LSB,
6733                             shCount, sign);
6734       else
6735         movLeft2Result (left, MSB16, result, LSB, sign);
6736       addSign (result, MSB16, sign);
6737     }
6738
6739   /*  1 <= shCount <= 7 */
6740   else
6741     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6742 }
6743
6744 /*-----------------------------------------------------------------*/
6745 /* shiftRLong - shift right one long from left to result           */
6746 /* offl = LSB or MSB16                                             */
6747 /*-----------------------------------------------------------------*/
6748 static void
6749 shiftRLong (operand * left, int offl,
6750             operand * result, int sign)
6751 {
6752   int isSameRegs=sameRegs(AOP(left),AOP(result));
6753
6754   if (isSameRegs && offl>1) {
6755     // we are in big trouble, but this shouldn't happen
6756     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6757   }
6758
6759   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6760   
6761   if (offl==MSB16) {
6762     // shift is > 8
6763     if (sign) {
6764       emitcode ("rlc", "a");
6765       emitcode ("subb", "a,acc");
6766       if (isSameRegs)
6767         emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6768       else {
6769         aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6770         MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6771       }
6772     } else {
6773       aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6774     }
6775   }
6776
6777   if (!sign) {
6778     emitcode ("clr", "c");
6779   } else {
6780     emitcode ("mov", "c,acc.7");
6781   }
6782
6783   emitcode ("rrc", "a");
6784
6785   if (isSameRegs && offl==MSB16) {
6786     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6787   } else {
6788     aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6789     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6790   }
6791
6792   emitcode ("rrc", "a");
6793   if (isSameRegs && offl==1) {
6794     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6795   } else {
6796     aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6797     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6798   }
6799   emitcode ("rrc", "a");
6800   aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6801
6802   if (offl == LSB)
6803     {
6804       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6805       emitcode ("rrc", "a");
6806       aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6807     }
6808 }
6809
6810 /*-----------------------------------------------------------------*/
6811 /* genrshFour - shift four byte by a known amount != 0             */
6812 /*-----------------------------------------------------------------*/
6813 static void
6814 genrshFour (operand * result, operand * left,
6815             int shCount, int sign)
6816 {
6817   D(emitcode (";     genrshFour",""));
6818
6819   /* if shifting more that 3 bytes */
6820   if (shCount >= 24)
6821     {
6822       shCount -= 24;
6823       if (shCount)
6824         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6825       else
6826         movLeft2Result (left, MSB32, result, LSB, sign);
6827       addSign (result, MSB16, sign);
6828     }
6829   else if (shCount >= 16)
6830     {
6831       shCount -= 16;
6832       if (shCount)
6833         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6834       else
6835         {
6836           movLeft2Result (left, MSB24, result, LSB, 0);
6837           movLeft2Result (left, MSB32, result, MSB16, sign);
6838         }
6839       addSign (result, MSB24, sign);
6840     }
6841   else if (shCount >= 8)
6842     {
6843       shCount -= 8;
6844       if (shCount == 1)
6845         shiftRLong (left, MSB16, result, sign);
6846       else if (shCount == 0)
6847         {
6848           movLeft2Result (left, MSB16, result, LSB, 0);
6849           movLeft2Result (left, MSB24, result, MSB16, 0);
6850           movLeft2Result (left, MSB32, result, MSB24, sign);
6851           addSign (result, MSB32, sign);
6852         }
6853       else
6854         {
6855           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6856           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6857           /* the last shift is signed */
6858           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6859           addSign (result, MSB32, sign);
6860         }
6861     }
6862   else
6863     {                           /* 1 <= shCount <= 7 */
6864       if (shCount <= 2)
6865         {
6866           shiftRLong (left, LSB, result, sign);
6867           if (shCount == 2)
6868             shiftRLong (result, LSB, result, sign);
6869         }
6870       else
6871         {
6872           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6873           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6874           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6875         }
6876     }
6877 }
6878
6879 /*-----------------------------------------------------------------*/
6880 /* genRightShiftLiteral - right shifting by known count            */
6881 /*-----------------------------------------------------------------*/
6882 static void
6883 genRightShiftLiteral (operand * left,
6884                       operand * right,
6885                       operand * result,
6886                       iCode * ic,
6887                       int sign)
6888 {
6889   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6890   int size;
6891
6892   D(emitcode (";     genRightShiftLiteral",""));
6893
6894   freeAsmop (right, NULL, ic, TRUE);
6895
6896   aopOp (left, ic, FALSE);
6897   aopOp (result, ic, FALSE);
6898
6899 #if VIEW_SIZE
6900   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6901             AOP_SIZE (left));
6902 #endif
6903
6904   size = getDataSize (left);
6905   /* test the LEFT size !!! */
6906
6907   /* I suppose that the left size >= result size */
6908   if (shCount == 0)
6909     {
6910       size = getDataSize (result);
6911       while (size--)
6912         movLeft2Result (left, size, result, size, 0);
6913     }
6914
6915   else if (shCount >= (size * 8))
6916     {
6917       if (sign) {
6918         /* get sign in acc.7 */
6919         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6920       }
6921       addSign (result, LSB, sign);
6922     }
6923   else
6924     {
6925       switch (size)
6926         {
6927         case 1:
6928           genrshOne (result, left, shCount, sign);
6929           break;
6930
6931         case 2:
6932           genrshTwo (result, left, shCount, sign);
6933           break;
6934
6935         case 4:
6936           genrshFour (result, left, shCount, sign);
6937           break;
6938         default:
6939           break;
6940         }
6941     }
6942   freeAsmop (left, NULL, ic, TRUE);
6943   freeAsmop (result, NULL, ic, TRUE);
6944 }
6945
6946 /*-----------------------------------------------------------------*/
6947 /* genSignedRightShift - right shift of signed number              */
6948 /*-----------------------------------------------------------------*/
6949 static void
6950 genSignedRightShift (iCode * ic)
6951 {
6952   operand *right, *left, *result;
6953   int size, offset;
6954   char *l;
6955   symbol *tlbl, *tlbl1;
6956
6957   D(emitcode (";     genSignedRightShift",""));
6958
6959   /* we do it the hard way put the shift count in b
6960      and loop thru preserving the sign */
6961
6962   right = IC_RIGHT (ic);
6963   left = IC_LEFT (ic);
6964   result = IC_RESULT (ic);
6965
6966   aopOp (right, ic, FALSE);
6967
6968
6969   if (AOP_TYPE (right) == AOP_LIT)
6970     {
6971       genRightShiftLiteral (left, right, result, ic, 1);
6972       return;
6973     }
6974   /* shift count is unknown then we have to form
6975      a loop get the loop count in B : Note: we take
6976      only the lower order byte since shifting
6977      more that 32 bits make no sense anyway, ( the
6978      largest size of an object can be only 32 bits ) */
6979
6980   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6981   emitcode ("inc", "b");
6982   freeAsmop (right, NULL, ic, TRUE);
6983   aopOp (left, ic, FALSE);
6984   aopOp (result, ic, FALSE);
6985
6986   /* now move the left to the result if they are not the
6987      same */
6988   if (!sameRegs (AOP (left), AOP (result)) &&
6989       AOP_SIZE (result) > 1)
6990     {
6991
6992       size = AOP_SIZE (result);
6993       offset = 0;
6994       while (size--)
6995         {
6996           l = aopGet (AOP (left), offset, FALSE, TRUE);
6997           if (*l == '@' && IS_AOP_PREG (result))
6998             {
6999
7000               emitcode ("mov", "a,%s", l);
7001               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7002             }
7003           else
7004             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7005           offset++;
7006         }
7007     }
7008
7009   /* mov the highest order bit to OVR */
7010   tlbl = newiTempLabel (NULL);
7011   tlbl1 = newiTempLabel (NULL);
7012
7013   size = AOP_SIZE (result);
7014   offset = size - 1;
7015   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7016   emitcode ("rlc", "a");
7017   emitcode ("mov", "ov,c");
7018   /* if it is only one byte then */
7019   if (size == 1)
7020     {
7021       l = aopGet (AOP (left), 0, FALSE, FALSE);
7022       MOVA (l);
7023       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7024       emitcode ("", "%05d$:", tlbl->key + 100);
7025       emitcode ("mov", "c,ov");
7026       emitcode ("rrc", "a");
7027       emitcode ("", "%05d$:", tlbl1->key + 100);
7028       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7029       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7030       goto release;
7031     }
7032
7033   reAdjustPreg (AOP (result));
7034   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7035   emitcode ("", "%05d$:", tlbl->key + 100);
7036   emitcode ("mov", "c,ov");
7037   while (size--)
7038     {
7039       l = aopGet (AOP (result), offset, FALSE, FALSE);
7040       MOVA (l);
7041       emitcode ("rrc", "a");
7042       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7043     }
7044   reAdjustPreg (AOP (result));
7045   emitcode ("", "%05d$:", tlbl1->key + 100);
7046   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7047
7048 release:
7049   freeAsmop (left, NULL, ic, TRUE);
7050   freeAsmop (result, NULL, ic, TRUE);
7051 }
7052
7053 /*-----------------------------------------------------------------*/
7054 /* genRightShift - generate code for right shifting                */
7055 /*-----------------------------------------------------------------*/
7056 static void
7057 genRightShift (iCode * ic)
7058 {
7059   operand *right, *left, *result;
7060   sym_link *retype;
7061   int size, offset;
7062   char *l;
7063   symbol *tlbl, *tlbl1;
7064
7065   D(emitcode (";     genRightShift",""));
7066
7067   /* if signed then we do it the hard way preserve the
7068      sign bit moving it inwards */
7069   retype = getSpec (operandType (IC_RESULT (ic)));
7070
7071   if (!SPEC_USIGN (retype))
7072     {
7073       genSignedRightShift (ic);
7074       return;
7075     }
7076
7077   /* signed & unsigned types are treated the same : i.e. the
7078      signed is NOT propagated inwards : quoting from the
7079      ANSI - standard : "for E1 >> E2, is equivalent to division
7080      by 2**E2 if unsigned or if it has a non-negative value,
7081      otherwise the result is implementation defined ", MY definition
7082      is that the sign does not get propagated */
7083
7084   right = IC_RIGHT (ic);
7085   left = IC_LEFT (ic);
7086   result = IC_RESULT (ic);
7087
7088   aopOp (right, ic, FALSE);
7089
7090   /* if the shift count is known then do it
7091      as efficiently as possible */
7092   if (AOP_TYPE (right) == AOP_LIT)
7093     {
7094       genRightShiftLiteral (left, right, result, ic, 0);
7095       return;
7096     }
7097
7098   /* shift count is unknown then we have to form
7099      a loop get the loop count in B : Note: we take
7100      only the lower order byte since shifting
7101      more that 32 bits make no sense anyway, ( the
7102      largest size of an object can be only 32 bits ) */
7103
7104   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7105   emitcode ("inc", "b");
7106   freeAsmop (right, NULL, ic, TRUE);
7107   aopOp (left, ic, FALSE);
7108   aopOp (result, ic, FALSE);
7109
7110   /* now move the left to the result if they are not the
7111      same */
7112   if (!sameRegs (AOP (left), AOP (result)) &&
7113       AOP_SIZE (result) > 1)
7114     {
7115
7116       size = AOP_SIZE (result);
7117       offset = 0;
7118       while (size--)
7119         {
7120           l = aopGet (AOP (left), offset, FALSE, TRUE);
7121           if (*l == '@' && IS_AOP_PREG (result))
7122             {
7123
7124               emitcode ("mov", "a,%s", l);
7125               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7126             }
7127           else
7128             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7129           offset++;
7130         }
7131     }
7132
7133   tlbl = newiTempLabel (NULL);
7134   tlbl1 = newiTempLabel (NULL);
7135   size = AOP_SIZE (result);
7136   offset = size - 1;
7137
7138   /* if it is only one byte then */
7139   if (size == 1)
7140     {
7141       l = aopGet (AOP (left), 0, FALSE, FALSE);
7142       MOVA (l);
7143       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7144       emitcode ("", "%05d$:", tlbl->key + 100);
7145       CLRC;
7146       emitcode ("rrc", "a");
7147       emitcode ("", "%05d$:", tlbl1->key + 100);
7148       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7149       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7150       goto release;
7151     }
7152
7153   reAdjustPreg (AOP (result));
7154   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7155   emitcode ("", "%05d$:", tlbl->key + 100);
7156   CLRC;
7157   while (size--)
7158     {
7159       l = aopGet (AOP (result), offset, FALSE, FALSE);
7160       MOVA (l);
7161       emitcode ("rrc", "a");
7162       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7163     }
7164   reAdjustPreg (AOP (result));
7165
7166   emitcode ("", "%05d$:", tlbl1->key + 100);
7167   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7168
7169 release:
7170   freeAsmop (left, NULL, ic, TRUE);
7171   freeAsmop (result, NULL, ic, TRUE);
7172 }
7173
7174 /*-----------------------------------------------------------------*/
7175 /* emitPtrByteGet - emits code to get a byte into A through a      */
7176 /*                  pointer register (R0, R1, or DPTR). The        */
7177 /*                  original value of A can be preserved in B.     */
7178 /*-----------------------------------------------------------------*/
7179 static void
7180 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7181 {
7182   switch (p_type)
7183     {
7184     case IPOINTER:
7185     case POINTER:
7186       if (preserveAinB)
7187         emitcode ("mov", "b,a");
7188       emitcode ("mov", "a,@%s", rname);
7189       break;
7190
7191     case PPOINTER:
7192       if (preserveAinB)
7193         emitcode ("mov", "b,a");
7194       emitcode ("movx", "a,@%s", rname);
7195       break;
7196       
7197     case FPOINTER:
7198       if (preserveAinB)
7199         emitcode ("mov", "b,a");
7200       emitcode ("movx", "a,@dptr");
7201       break;
7202
7203     case CPOINTER:
7204       if (preserveAinB)
7205         emitcode ("mov", "b,a");
7206       emitcode ("clr", "a");
7207       emitcode ("movc", "a,@a+dptr");
7208       break;
7209
7210     case GPOINTER:
7211       if (preserveAinB)
7212         {
7213           emitcode ("push", "b");
7214           emitcode ("push", "acc");
7215         }
7216       emitcode ("lcall", "__gptrget");
7217       if (preserveAinB)
7218         emitcode ("pop", "b");
7219       break;
7220     }
7221 }
7222
7223 /*-----------------------------------------------------------------*/
7224 /* emitPtrByteSet - emits code to set a byte from src through a    */
7225 /*                  pointer register (R0, R1, or DPTR).            */
7226 /*-----------------------------------------------------------------*/
7227 static void
7228 emitPtrByteSet (char *rname, int p_type, char *src)
7229 {
7230   switch (p_type)
7231     {
7232     case IPOINTER:
7233     case POINTER:
7234       if (*src=='@')
7235         {
7236           MOVA (src);
7237           emitcode ("mov", "@%s,a", rname);
7238         }
7239       else
7240         emitcode ("mov", "@%s,%s", rname, src);
7241       break;
7242
7243     case PPOINTER:
7244       MOVA (src);
7245       emitcode ("movx", "@%s,a", rname);
7246       break;
7247       
7248     case FPOINTER:
7249       MOVA (src);
7250       emitcode ("movx", "@dptr,a");
7251       break;
7252
7253     case GPOINTER:
7254       MOVA (src);
7255       emitcode ("lcall", "__gptrput");
7256       break;
7257     }
7258 }
7259
7260 /*-----------------------------------------------------------------*/
7261 /* genUnpackBits - generates code for unpacking bits               */
7262 /*-----------------------------------------------------------------*/
7263 static void
7264 genUnpackBits (operand * result, char *rname, int ptype)
7265 {
7266   int offset = 0;       /* result byte offset */
7267   int rsize;            /* result size */
7268   int rlen = 0;         /* remaining bitfield length */
7269   sym_link *etype;      /* bitfield type information */
7270   int blen;             /* bitfield length */
7271   int bstr;             /* bitfield starting bit within byte */
7272
7273   D(emitcode (";     genUnpackBits",""));
7274
7275   etype = getSpec (operandType (result));
7276   rsize = getSize (operandType (result));
7277   blen = SPEC_BLEN (etype);
7278   bstr = SPEC_BSTR (etype);
7279
7280   /* If the bitfield length is less than a byte */
7281   if (blen < 8)
7282     {
7283       emitPtrByteGet (rname, ptype, FALSE);
7284       AccRsh (bstr);
7285       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7286       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7287       goto finish;
7288     }
7289
7290   /* Bit field did not fit in a byte. Copy all
7291      but the partial byte at the end.  */
7292   for (rlen=blen;rlen>=8;rlen-=8)
7293     {
7294       emitPtrByteGet (rname, ptype, FALSE);
7295       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7296       if (rlen>8)
7297         emitcode ("inc", "%s", rname);
7298     }
7299
7300   /* Handle the partial byte at the end */
7301   if (rlen)
7302     {
7303       emitPtrByteGet (rname, ptype, FALSE);
7304       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7305       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7306     }
7307
7308 finish:
7309   if (offset < rsize)
7310     {
7311       rsize -= offset;
7312       while (rsize--)
7313         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7314     }
7315 }
7316
7317
7318 /*-----------------------------------------------------------------*/
7319 /* genDataPointerGet - generates code when ptr offset is known     */
7320 /*-----------------------------------------------------------------*/
7321 static void
7322 genDataPointerGet (operand * left,
7323                    operand * result,
7324                    iCode * ic)
7325 {
7326   char *l;
7327   char buffer[256];
7328   int size, offset = 0;
7329
7330   D(emitcode (";     genDataPointerGet",""));
7331
7332   aopOp (result, ic, TRUE);
7333
7334   /* get the string representation of the name */
7335   l = aopGet (AOP (left), 0, FALSE, TRUE);
7336   size = AOP_SIZE (result);
7337   while (size--)
7338     {
7339       if (offset)
7340         sprintf (buffer, "(%s + %d)", l + 1, offset);
7341       else
7342         sprintf (buffer, "%s", l + 1);
7343       aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7344     }
7345
7346   freeAsmop (left, NULL, ic, TRUE);
7347   freeAsmop (result, NULL, ic, TRUE);
7348 }
7349
7350 /*-----------------------------------------------------------------*/
7351 /* genNearPointerGet - emitcode for near pointer fetch             */
7352 /*-----------------------------------------------------------------*/
7353 static void
7354 genNearPointerGet (operand * left,
7355                    operand * result,
7356                    iCode * ic,
7357                    iCode * pi)
7358 {
7359   asmop *aop = NULL;
7360   regs *preg = NULL;
7361   char *rname;
7362   sym_link *rtype, *retype;
7363   sym_link *ltype = operandType (left);
7364   char buffer[80];
7365
7366   D(emitcode (";     genNearPointerGet",""));
7367
7368   rtype = operandType (result);
7369   retype = getSpec (rtype);
7370
7371   aopOp (left, ic, FALSE);
7372
7373   /* if left is rematerialisable and
7374      result is not bit variable type and
7375      the left is pointer to data space i.e
7376      lower 128 bytes of space */
7377   if (AOP_TYPE (left) == AOP_IMMD &&
7378       !IS_BITVAR (retype) &&
7379       DCL_TYPE (ltype) == POINTER)
7380     {
7381       genDataPointerGet (left, result, ic);
7382       return;
7383     }
7384
7385  /* if the value is already in a pointer register
7386      then don't need anything more */
7387   if (!AOP_INPREG (AOP (left)))
7388     {
7389       if (IS_AOP_PREG (left))
7390         {
7391           // Aha, it is a pointer, just in disguise.
7392           rname = aopGet (AOP (left), 0, FALSE, FALSE);
7393           if (*rname != '@')
7394             {
7395               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7396                       __FILE__, __LINE__);
7397             }
7398           else
7399             {
7400               // Expected case.
7401               emitcode ("mov", "a%s,%s", rname + 1, rname);
7402               rname++;  // skip the '@'.
7403             }
7404         }
7405       else
7406         {
7407           /* otherwise get a free pointer register */
7408           aop = newAsmop (0);
7409           preg = getFreePtr (ic, &aop, FALSE);
7410           emitcode ("mov", "%s,%s",
7411                     preg->name,
7412                     aopGet (AOP (left), 0, FALSE, TRUE));
7413           rname = preg->name;
7414         }
7415     }
7416   else
7417     rname = aopGet (AOP (left), 0, FALSE, FALSE);
7418
7419   //aopOp (result, ic, FALSE);
7420   aopOp (result, ic, result?TRUE:FALSE);
7421
7422   /* if bitfield then unpack the bits */
7423   if (IS_BITVAR (retype))
7424     genUnpackBits (result, rname, POINTER);
7425   else
7426     {
7427       /* we have can just get the values */
7428       int size = AOP_SIZE (result);
7429       int offset = 0;
7430
7431       while (size--)
7432         {
7433           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7434             {
7435
7436               emitcode ("mov", "a,@%s", rname);
7437               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7438             }
7439           else
7440             {
7441               sprintf (buffer, "@%s", rname);
7442               aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7443             }
7444           offset++;
7445           if (size || pi)
7446             emitcode ("inc", "%s", rname);
7447         }
7448     }
7449
7450   /* now some housekeeping stuff */
7451   if (aop)       /* we had to allocate for this iCode */
7452     {
7453       if (pi) { /* post increment present */
7454         aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7455       }
7456       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7457     }
7458   else
7459     {
7460       /* we did not allocate which means left
7461          already in a pointer register, then
7462          if size > 0 && this could be used again
7463          we have to point it back to where it
7464          belongs */
7465       if ((AOP_SIZE (result) > 1 &&
7466            !OP_SYMBOL (left)->remat &&
7467            (OP_SYMBOL (left)->liveTo > ic->seq ||
7468             ic->depth)) &&
7469           !pi)
7470         {
7471           int size = AOP_SIZE (result) - 1;
7472           while (size--)
7473             emitcode ("dec", "%s", rname);
7474         }
7475     }
7476
7477   /* done */
7478   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7479   freeAsmop (left, NULL, ic, TRUE);
7480   if (pi) pi->generated = 1;
7481 }
7482
7483 /*-----------------------------------------------------------------*/
7484 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7485 /*-----------------------------------------------------------------*/
7486 static void
7487 genPagedPointerGet (operand * left,
7488                     operand * result,
7489                     iCode * ic,
7490                     iCode *pi)
7491 {
7492   asmop *aop = NULL;
7493   regs *preg = NULL;
7494   char *rname;
7495   sym_link *rtype, *retype;
7496
7497   D(emitcode (";     genPagedPointerGet",""));
7498
7499   rtype = operandType (result);
7500   retype = getSpec (rtype);
7501
7502   aopOp (left, ic, FALSE);
7503
7504   /* if the value is already in a pointer register
7505      then don't need anything more */
7506   if (!AOP_INPREG (AOP (left)))
7507     {
7508       /* otherwise get a free pointer register */
7509       aop = newAsmop (0);
7510       preg = getFreePtr (ic, &aop, FALSE);
7511       emitcode ("mov", "%s,%s",
7512                 preg->name,
7513                 aopGet (AOP (left), 0, FALSE, TRUE));
7514       rname = preg->name;
7515     }
7516   else
7517     rname = aopGet (AOP (left), 0, FALSE, FALSE);
7518
7519   aopOp (result, ic, FALSE);
7520
7521   /* if bitfield then unpack the bits */
7522   if (IS_BITVAR (retype))
7523     genUnpackBits (result, rname, PPOINTER);
7524   else
7525     {
7526       /* we have can just get the values */
7527       int size = AOP_SIZE (result);
7528       int offset = 0;
7529
7530       while (size--)
7531         {
7532
7533           emitcode ("movx", "a,@%s", rname);
7534           aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7535
7536           offset++;
7537
7538           if (size || pi)
7539             emitcode ("inc", "%s", rname);
7540         }
7541     }
7542
7543   /* now some housekeeping stuff */
7544   if (aop) /* we had to allocate for this iCode */
7545     {
7546       if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7547       freeAsmop (NULL, aop, ic, TRUE);
7548     }
7549   else
7550     {
7551       /* we did not allocate which means left
7552          already in a pointer register, then
7553          if size > 0 && this could be used again
7554          we have to point it back to where it
7555          belongs */
7556       if ((AOP_SIZE (result) > 1 &&
7557            !OP_SYMBOL (left)->remat &&
7558            (OP_SYMBOL (left)->liveTo > ic->seq ||
7559             ic->depth)) &&
7560           !pi)
7561         {
7562           int size = AOP_SIZE (result) - 1;
7563           while (size--)
7564             emitcode ("dec", "%s", rname);
7565         }
7566     }
7567
7568   /* done */
7569   freeAsmop (left, NULL, ic, TRUE);
7570   freeAsmop (result, NULL, ic, TRUE);
7571   if (pi) pi->generated = 1;
7572
7573 }
7574
7575 /*--------------------------------------------------------------------*/
7576 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7577 /*--------------------------------------------------------------------*/
7578 static void
7579 loadDptrFromOperand (operand *op, bool loadBToo)
7580 {
7581   if (AOP_TYPE (op) != AOP_STR)
7582     {
7583       /* if this is remateriazable */
7584       if (AOP_TYPE (op) == AOP_IMMD)
7585         {
7586           emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7587           if (loadBToo)
7588             {
7589               if (AOP(op)->aopu.aop_immd.from_cast_remat) 
7590                 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7591               else
7592                 {
7593                   wassertl(FALSE, "need pointerCode");
7594                   emitcode ("", "; mov b,???");
7595                   /* genPointerGet and genPointerSet originally did different
7596                   ** things for this case. Both seem wrong.
7597                   ** from genPointerGet:
7598                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
7599                   ** from genPointerSet:
7600                   **  emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7601                   */
7602                 }
7603             }
7604         }
7605       else if (AOP_TYPE (op) == AOP_DPTR)
7606         {
7607           if (loadBToo)
7608             {
7609               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7610               emitcode ("push", "acc");
7611               MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7612               emitcode ("push", "acc");
7613               emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7614               emitcode ("pop", "dph");
7615               emitcode ("pop", "dpl");
7616             }
7617           else
7618             {
7619               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7620               emitcode ("push", "acc");
7621               emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7622               emitcode ("pop", "dpl");
7623             }
7624         }
7625       else
7626         {                       /* we need to get it byte by byte */
7627           emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7628           emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7629           if (loadBToo)
7630             emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7631         }
7632     }
7633 }
7634
7635 /*-----------------------------------------------------------------*/
7636 /* genFarPointerGet - gget value from far space                    */
7637 /*-----------------------------------------------------------------*/
7638 static void
7639 genFarPointerGet (operand * left,
7640                   operand * result, iCode * ic, iCode * pi)
7641 {
7642   int size, offset;
7643   sym_link *retype = getSpec (operandType (result));
7644
7645   D(emitcode (";     genFarPointerGet",""));
7646
7647   aopOp (left, ic, FALSE);
7648   loadDptrFromOperand (left, FALSE);
7649   
7650   /* so dptr now contains the address */
7651   aopOp (result, ic, FALSE);
7652
7653   /* if bit then unpack */
7654   if (IS_BITVAR (retype))
7655     genUnpackBits (result, "dptr", FPOINTER);
7656   else
7657     {
7658       size = AOP_SIZE (result);
7659       offset = 0;
7660
7661       while (size--)
7662         {
7663           emitcode ("movx", "a,@dptr");
7664           aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7665           if (size || pi)
7666             emitcode ("inc", "dptr");
7667         }
7668     }
7669   
7670   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7671     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7672     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7673     pi->generated = 1;
7674   }
7675   freeAsmop (left, NULL, ic, TRUE);
7676   freeAsmop (result, NULL, ic, TRUE);
7677 }
7678
7679 /*-----------------------------------------------------------------*/
7680 /* genCodePointerGet - gget value from code space                  */
7681 /*-----------------------------------------------------------------*/
7682 static void
7683 genCodePointerGet (operand * left,
7684                     operand * result, iCode * ic, iCode *pi)
7685 {
7686   int size, offset;
7687   sym_link *retype = getSpec (operandType (result));
7688
7689   D(emitcode (";     genCodePointerGet",""));
7690
7691   aopOp (left, ic, FALSE);
7692   loadDptrFromOperand (left, FALSE);
7693   
7694   /* so dptr now contains the address */
7695   aopOp (result, ic, FALSE);
7696
7697   /* if bit then unpack */
7698   if (IS_BITVAR (retype))
7699     genUnpackBits (result, "dptr", CPOINTER);
7700   else
7701     {
7702       size = AOP_SIZE (result);
7703       offset = 0;
7704
7705       while (size--)
7706         {
7707           if (pi)
7708             {
7709               emitcode ("clr", "a");
7710               emitcode ("movc", "a,@a+dptr");
7711               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7712               emitcode ("inc", "dptr");
7713             }
7714           else
7715             { 
7716               emitcode ("mov", "a,#0x%02x", offset);
7717               emitcode ("movc", "a,@a+dptr");
7718               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7719             }
7720         }
7721     }
7722
7723   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7724     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7725     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7726     pi->generated = 1;
7727   }
7728   freeAsmop (left, NULL, ic, TRUE);
7729   freeAsmop (result, NULL, ic, TRUE);
7730 }
7731
7732 /*-----------------------------------------------------------------*/
7733 /* genGenPointerGet - gget value from generic pointer space        */
7734 /*-----------------------------------------------------------------*/
7735 static void
7736 genGenPointerGet (operand * left,
7737                   operand * result, iCode * ic, iCode *pi)
7738 {
7739   int size, offset;
7740   sym_link *retype = getSpec (operandType (result));
7741
7742   D(emitcode (";     genGenPointerGet",""));
7743
7744   aopOp (left, ic, FALSE);
7745   loadDptrFromOperand (left, TRUE);
7746   
7747   /* so dptr know contains the address */
7748   aopOp (result, ic, FALSE);
7749
7750   /* if bit then unpack */
7751   if (IS_BITVAR (retype))
7752     genUnpackBits (result, "dptr", GPOINTER);
7753   else
7754     {
7755       size = AOP_SIZE (result);
7756       offset = 0;
7757
7758       while (size--)
7759         {
7760           emitcode ("lcall", "__gptrget");
7761           aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7762           if (size || pi)
7763             emitcode ("inc", "dptr");
7764         }
7765     }
7766
7767   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7768     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7769     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7770     pi->generated = 1;
7771   }
7772   freeAsmop (left, NULL, ic, TRUE);
7773   freeAsmop (result, NULL, ic, TRUE);
7774 }
7775
7776 /*-----------------------------------------------------------------*/
7777 /* genPointerGet - generate code for pointer get                   */
7778 /*-----------------------------------------------------------------*/
7779 static void
7780 genPointerGet (iCode * ic, iCode *pi)
7781 {
7782   operand *left, *result;
7783   sym_link *type, *etype;
7784   int p_type;
7785
7786   D(emitcode (";     genPointerGet",""));
7787
7788   left = IC_LEFT (ic);
7789   result = IC_RESULT (ic);
7790
7791   /* depending on the type of pointer we need to
7792      move it to the correct pointer register */
7793   type = operandType (left);
7794   etype = getSpec (type);
7795   /* if left is of type of pointer then it is simple */
7796   if (IS_PTR (type) && !IS_FUNC (type->next))
7797     p_type = DCL_TYPE (type);
7798   else
7799     {
7800       /* we have to go by the storage class */
7801       p_type = PTR_TYPE (SPEC_OCLS (etype));
7802     }
7803
7804   /* special case when cast remat */
7805   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7806       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7807           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7808           type = operandType (left);
7809           p_type = DCL_TYPE (type);
7810   }
7811   /* now that we have the pointer type we assign
7812      the pointer values */
7813   switch (p_type)
7814     {
7815
7816     case POINTER:
7817     case IPOINTER:
7818       genNearPointerGet (left, result, ic, pi);
7819       break;
7820
7821     case PPOINTER:
7822       genPagedPointerGet (left, result, ic, pi);
7823       break;
7824
7825     case FPOINTER:
7826       genFarPointerGet (left, result, ic, pi);
7827       break;
7828
7829     case CPOINTER:
7830       genCodePointerGet (left, result, ic, pi);
7831       break;
7832
7833     case GPOINTER:
7834       genGenPointerGet (left, result, ic, pi);
7835       break;
7836     }
7837
7838 }
7839
7840
7841
7842 /*-----------------------------------------------------------------*/
7843 /* genPackBits - generates code for packed bit storage             */
7844 /*-----------------------------------------------------------------*/
7845 static void
7846 genPackBits (sym_link * etype,
7847              operand * right,
7848              char *rname, int p_type)
7849 {
7850   int offset = 0;       /* source byte offset */
7851   int rlen = 0;         /* remaining bitfield length */
7852   int blen;             /* bitfield length */
7853   int bstr;             /* bitfield starting bit within byte */
7854   int litval;           /* source literal value (if AOP_LIT) */
7855   unsigned char mask;   /* bitmask within current byte */
7856
7857   D(emitcode (";     genPackBits",""));
7858
7859   blen = SPEC_BLEN (etype);
7860   bstr = SPEC_BSTR (etype);
7861
7862   /* If the bitfield length is less than a byte */
7863   if (blen < 8)
7864     {
7865       mask = ((unsigned char) (0xFF << (blen + bstr)) |
7866               (unsigned char) (0xFF >> (8 - bstr)));
7867
7868       if (AOP_TYPE (right) == AOP_LIT)
7869         {
7870           /* Case with a bitfield length <8 and literal source
7871           */
7872           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7873           litval <<= bstr;
7874           litval &= (~mask) & 0xff;
7875           emitPtrByteGet (rname, p_type, FALSE);
7876           if ((mask|litval)!=0xff)
7877             emitcode ("anl","a,#0x%02x", mask);
7878           if (litval)
7879             emitcode ("orl","a,#0x%02x", litval);
7880         }
7881       else
7882         {
7883           if ((blen==1) && (p_type!=GPOINTER))
7884             {
7885               /* Case with a bitfield length == 1 and no generic pointer
7886               */
7887               if (AOP_TYPE (right) == AOP_CRY)
7888                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7889               else
7890                 {
7891                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7892                   emitcode ("rrc","a");
7893                 }
7894               emitPtrByteGet (rname, p_type, FALSE);
7895               emitcode ("mov","acc.%d,c",bstr);
7896             }
7897           else
7898             {
7899               /* Case with a bitfield length < 8 and arbitrary source
7900               */
7901               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7902               /* shift and mask source value */
7903               AccLsh (bstr);
7904               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7905
7906               /* transfer A to B and get next byte */
7907               emitPtrByteGet (rname, p_type, TRUE);
7908
7909               emitcode ("anl", "a,#0x%02x", mask);
7910               emitcode ("orl", "a,b");
7911               if (p_type == GPOINTER)
7912                 emitcode ("pop", "b");
7913            }
7914         }
7915
7916       emitPtrByteSet (rname, p_type, "a");
7917       return;
7918     }
7919
7920   /* Bit length is greater than 7 bits. In this case, copy  */
7921   /* all except the partial byte at the end                 */
7922   for (rlen=blen;rlen>=8;rlen-=8)
7923     {
7924       emitPtrByteSet (rname, p_type, 
7925                       aopGet (AOP (right), offset++, FALSE, TRUE) );
7926       if (rlen>8)
7927         emitcode ("inc", "%s", rname);
7928     }
7929
7930   /* If there was a partial byte at the end */
7931   if (rlen)
7932     {
7933       mask = (((unsigned char) -1 << rlen) & 0xff);
7934       
7935       if (AOP_TYPE (right) == AOP_LIT)
7936         {
7937           /* Case with partial byte and literal source
7938           */
7939           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7940           litval >>= (blen-rlen);
7941           litval &= (~mask) & 0xff;
7942           emitPtrByteGet (rname, p_type, FALSE);
7943           if ((mask|litval)!=0xff)
7944             emitcode ("anl","a,#0x%02x", mask);
7945           if (litval)
7946             emitcode ("orl","a,#0x%02x", litval);
7947         }
7948       else
7949         {
7950           /* Case with partial byte and arbitrary source
7951           */
7952           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7953           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7954
7955           /* transfer A to B and get next byte */
7956           emitPtrByteGet (rname, p_type, TRUE);
7957
7958           emitcode ("anl", "a,#0x%02x", mask);
7959           emitcode ("orl", "a,b");
7960           if (p_type == GPOINTER)
7961             emitcode ("pop", "b");
7962         }
7963       emitPtrByteSet (rname, p_type, "a");
7964     }
7965
7966 }
7967
7968
7969 /*-----------------------------------------------------------------*/
7970 /* genDataPointerSet - remat pointer to data space                 */
7971 /*-----------------------------------------------------------------*/
7972 static void
7973 genDataPointerSet (operand * right,
7974                    operand * result,
7975                    iCode * ic)
7976 {
7977   int size, offset = 0;
7978   char *l, buffer[256];
7979
7980   D(emitcode (";     genDataPointerSet",""));
7981
7982   aopOp (right, ic, FALSE);
7983
7984   l = aopGet (AOP (result), 0, FALSE, TRUE);
7985   size = AOP_SIZE (right);
7986   while (size--)
7987     {
7988       if (offset)
7989         sprintf (buffer, "(%s + %d)", l + 1, offset);
7990       else
7991         sprintf (buffer, "%s", l + 1);
7992       emitcode ("mov", "%s,%s", buffer,
7993                 aopGet (AOP (right), offset++, FALSE, FALSE));
7994     }
7995
7996   freeAsmop (right, NULL, ic, TRUE);
7997   freeAsmop (result, NULL, ic, TRUE);
7998 }
7999
8000 /*-----------------------------------------------------------------*/
8001 /* genNearPointerSet - emitcode for near pointer put                */
8002 /*-----------------------------------------------------------------*/
8003 static void
8004 genNearPointerSet (operand * right,
8005                    operand * result,
8006                    iCode * ic,
8007                    iCode * pi)
8008 {
8009   asmop *aop = NULL;
8010   regs *preg = NULL;
8011   char *rname, *l;
8012   sym_link *retype, *letype;
8013   sym_link *ptype = operandType (result);
8014
8015   D(emitcode (";     genNearPointerSet",""));
8016
8017   retype = getSpec (operandType (right));
8018   letype = getSpec (ptype);
8019   aopOp (result, ic, FALSE);
8020
8021   /* if the result is rematerializable &
8022      in data space & not a bit variable */
8023   if (AOP_TYPE (result) == AOP_IMMD &&
8024       DCL_TYPE (ptype) == POINTER &&
8025       !IS_BITVAR (retype) &&
8026       !IS_BITVAR (letype))
8027     {
8028       genDataPointerSet (right, result, ic);
8029       return;
8030     }
8031
8032   /* if the value is already in a pointer register
8033      then don't need anything more */
8034   if (!AOP_INPREG (AOP (result)))
8035     {
8036         if (
8037             //AOP_TYPE (result) == AOP_STK
8038             IS_AOP_PREG(result)
8039             )
8040         {
8041             // Aha, it is a pointer, just in disguise.
8042             rname = aopGet (AOP (result), 0, FALSE, FALSE);
8043             if (*rname != '@')
8044             {
8045                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8046                         __FILE__, __LINE__);
8047             }
8048             else
8049             {
8050                 // Expected case.
8051                 emitcode ("mov", "a%s,%s", rname + 1, rname);
8052                 rname++;  // skip the '@'.
8053             }
8054         }
8055         else
8056         {
8057             /* otherwise get a free pointer register */
8058             aop = newAsmop (0);
8059             preg = getFreePtr (ic, &aop, FALSE);
8060             emitcode ("mov", "%s,%s",
8061                       preg->name,
8062                       aopGet (AOP (result), 0, FALSE, TRUE));
8063             rname = preg->name;
8064         }
8065     }
8066     else
8067     {
8068         rname = aopGet (AOP (result), 0, FALSE, FALSE);
8069     }
8070
8071   aopOp (right, ic, FALSE);
8072
8073   /* if bitfield then unpack the bits */
8074   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8075     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8076   else
8077     {
8078       /* we have can just get the values */
8079       int size = AOP_SIZE (right);
8080       int offset = 0;
8081
8082       while (size--)
8083         {
8084           l = aopGet (AOP (right), offset, FALSE, TRUE);
8085           if (*l == '@')
8086             {
8087               MOVA (l);
8088               emitcode ("mov", "@%s,a", rname);
8089             }
8090           else
8091             emitcode ("mov", "@%s,%s", rname, l);
8092           if (size || pi)
8093             emitcode ("inc", "%s", rname);
8094           offset++;
8095         }
8096     }
8097
8098   /* now some housekeeping stuff */
8099   if (aop) /* we had to allocate for this iCode */
8100     {
8101       if (pi)
8102         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8103       freeAsmop (NULL, aop, ic, TRUE);
8104     }
8105   else
8106     {
8107       /* we did not allocate which means left
8108          already in a pointer register, then
8109          if size > 0 && this could be used again
8110          we have to point it back to where it
8111          belongs */
8112       if ((AOP_SIZE (right) > 1 &&
8113            !OP_SYMBOL (result)->remat &&
8114            (OP_SYMBOL (result)->liveTo > ic->seq ||
8115             ic->depth)) &&
8116           !pi)
8117         {
8118           int size = AOP_SIZE (right) - 1;
8119           while (size--)
8120             emitcode ("dec", "%s", rname);
8121         }
8122     }
8123
8124   /* done */
8125   if (pi) pi->generated = 1;
8126   freeAsmop (result, NULL, ic, TRUE);
8127   freeAsmop (right, NULL, ic, TRUE);
8128 }
8129
8130 /*-----------------------------------------------------------------*/
8131 /* genPagedPointerSet - emitcode for Paged pointer put             */
8132 /*-----------------------------------------------------------------*/
8133 static void
8134 genPagedPointerSet (operand * right,
8135                     operand * result,
8136                     iCode * ic,
8137                     iCode * pi)
8138 {
8139   asmop *aop = NULL;
8140   regs *preg = NULL;
8141   char *rname, *l;
8142   sym_link *retype, *letype;
8143
8144   D(emitcode (";     genPagedPointerSet",""));
8145
8146   retype = getSpec (operandType (right));
8147   letype = getSpec (operandType (result));
8148
8149   aopOp (result, ic, FALSE);
8150
8151   /* if the value is already in a pointer register
8152      then don't need anything more */
8153   if (!AOP_INPREG (AOP (result)))
8154     {
8155       /* otherwise get a free pointer register */
8156       aop = newAsmop (0);
8157       preg = getFreePtr (ic, &aop, FALSE);
8158       emitcode ("mov", "%s,%s",
8159                 preg->name,
8160                 aopGet (AOP (result), 0, FALSE, TRUE));
8161       rname = preg->name;
8162     }
8163   else
8164     rname = aopGet (AOP (result), 0, FALSE, FALSE);
8165
8166   aopOp (right, ic, FALSE);
8167
8168   /* if bitfield then unpack the bits */
8169   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8170     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8171   else
8172     {
8173       /* we have can just get the values */
8174       int size = AOP_SIZE (right);
8175       int offset = 0;
8176
8177       while (size--)
8178         {
8179           l = aopGet (AOP (right), offset, FALSE, TRUE);
8180
8181           MOVA (l);
8182           emitcode ("movx", "@%s,a", rname);
8183
8184           if (size || pi)
8185             emitcode ("inc", "%s", rname);
8186
8187           offset++;
8188         }
8189     }
8190
8191   /* now some housekeeping stuff */
8192   if (aop) /* we had to allocate for this iCode */
8193     {
8194       if (pi)
8195         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8196       freeAsmop (NULL, aop, ic, TRUE);
8197     }
8198   else
8199     {
8200       /* we did not allocate which means left
8201          already in a pointer register, then
8202          if size > 0 && this could be used again
8203          we have to point it back to where it
8204          belongs */
8205       if (AOP_SIZE (right) > 1 &&
8206           !OP_SYMBOL (result)->remat &&
8207           (OP_SYMBOL (result)->liveTo > ic->seq ||
8208            ic->depth))
8209         {
8210           int size = AOP_SIZE (right) - 1;
8211           while (size--)
8212             emitcode ("dec", "%s", rname);
8213         }
8214     }
8215
8216   /* done */
8217   if (pi) pi->generated = 1;
8218   freeAsmop (result, NULL, ic, TRUE);
8219   freeAsmop (right, NULL, ic, TRUE);
8220
8221
8222 }
8223
8224 /*-----------------------------------------------------------------*/
8225 /* genFarPointerSet - set value from far space                     */
8226 /*-----------------------------------------------------------------*/
8227 static void
8228 genFarPointerSet (operand * right,
8229                   operand * result, iCode * ic, iCode * pi)
8230 {
8231   int size, offset;
8232   sym_link *retype = getSpec (operandType (right));
8233   sym_link *letype = getSpec (operandType (result));
8234
8235   D(emitcode (";     genFarPointerSet",""));
8236
8237   aopOp (result, ic, FALSE);
8238   loadDptrFromOperand (result, FALSE);
8239   
8240   /* so dptr know contains the address */
8241   aopOp (right, ic, FALSE);
8242
8243   /* if bit then unpack */
8244   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8245     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8246   else
8247     {
8248       size = AOP_SIZE (right);
8249       offset = 0;
8250
8251       while (size--)
8252         {
8253           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8254           MOVA (l);
8255           emitcode ("movx", "@dptr,a");
8256           if (size || pi)
8257             emitcode ("inc", "dptr");
8258         }
8259     }
8260   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8261     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8262     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8263     pi->generated=1;
8264   }
8265   freeAsmop (result, NULL, ic, TRUE);
8266   freeAsmop (right, NULL, ic, TRUE);
8267 }
8268
8269 /*-----------------------------------------------------------------*/
8270 /* genGenPointerSet - set value from generic pointer space         */
8271 /*-----------------------------------------------------------------*/
8272 static void
8273 genGenPointerSet (operand * right,
8274                   operand * result, iCode * ic, iCode * pi)
8275 {
8276   int size, offset;
8277   sym_link *retype = getSpec (operandType (right));
8278   sym_link *letype = getSpec (operandType (result));
8279
8280   D(emitcode (";     genGenPointerSet",""));
8281
8282   aopOp (result, ic, FALSE);
8283   loadDptrFromOperand (result, TRUE);
8284   
8285   /* so dptr know contains the address */
8286   aopOp (right, ic, FALSE);
8287
8288   /* if bit then unpack */
8289   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8290     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8291   else
8292     {
8293       size = AOP_SIZE (right);
8294       offset = 0;
8295
8296       while (size--)
8297         {
8298           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8299           MOVA (l);
8300           emitcode ("lcall", "__gptrput");
8301           if (size || pi)
8302             emitcode ("inc", "dptr");
8303         }
8304     }
8305
8306   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8307     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8308     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8309     pi->generated=1;
8310   }
8311   freeAsmop (result, NULL, ic, TRUE);
8312   freeAsmop (right, NULL, ic, TRUE);
8313 }
8314
8315 /*-----------------------------------------------------------------*/
8316 /* genPointerSet - stores the value into a pointer location        */
8317 /*-----------------------------------------------------------------*/
8318 static void
8319 genPointerSet (iCode * ic, iCode *pi)
8320 {
8321   operand *right, *result;
8322   sym_link *type, *etype;
8323   int p_type;
8324
8325   D(emitcode (";     genPointerSet",""));
8326
8327   right = IC_RIGHT (ic);
8328   result = IC_RESULT (ic);
8329
8330   /* depending on the type of pointer we need to
8331      move it to the correct pointer register */
8332   type = operandType (result);
8333   etype = getSpec (type);
8334   /* if left is of type of pointer then it is simple */
8335   if (IS_PTR (type) && !IS_FUNC (type->next))
8336     {
8337       p_type = DCL_TYPE (type);
8338     }
8339   else
8340     {
8341       /* we have to go by the storage class */
8342       p_type = PTR_TYPE (SPEC_OCLS (etype));
8343     }
8344
8345   /* special case when cast remat */
8346   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8347       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8348           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8349           type = operandType (result);
8350           p_type = DCL_TYPE (type);
8351   }
8352   /* now that we have the pointer type we assign
8353      the pointer values */
8354   switch (p_type)
8355     {
8356
8357     case POINTER:
8358     case IPOINTER:
8359       genNearPointerSet (right, result, ic, pi);
8360       break;
8361
8362     case PPOINTER:
8363       genPagedPointerSet (right, result, ic, pi);
8364       break;
8365
8366     case FPOINTER:
8367       genFarPointerSet (right, result, ic, pi);
8368       break;
8369
8370     case GPOINTER:
8371       genGenPointerSet (right, result, ic, pi);
8372       break;
8373
8374     default:
8375       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
8376               "genPointerSet: illegal pointer type");
8377     }
8378
8379 }
8380
8381 /*-----------------------------------------------------------------*/
8382 /* genIfx - generate code for Ifx statement                        */
8383 /*-----------------------------------------------------------------*/
8384 static void
8385 genIfx (iCode * ic, iCode * popIc)
8386 {
8387   operand *cond = IC_COND (ic);
8388   int isbit = 0;
8389
8390   D(emitcode (";     genIfx",""));
8391
8392   aopOp (cond, ic, FALSE);
8393
8394   /* get the value into acc */
8395   if (AOP_TYPE (cond) != AOP_CRY)
8396     toBoolean (cond);
8397   else
8398     isbit = 1;
8399   /* the result is now in the accumulator */
8400   freeAsmop (cond, NULL, ic, TRUE);
8401
8402   /* if there was something to be popped then do it */
8403   if (popIc)
8404     genIpop (popIc);
8405
8406   /* if the condition is  a bit variable */
8407   if (isbit && IS_ITEMP (cond) &&
8408       SPIL_LOC (cond))
8409     genIfxJump (ic, SPIL_LOC (cond)->rname);
8410   else if (isbit && !IS_ITEMP (cond))
8411     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8412   else
8413     genIfxJump (ic, "a");
8414
8415   ic->generated = 1;
8416 }
8417
8418 /*-----------------------------------------------------------------*/
8419 /* genAddrOf - generates code for address of                       */
8420 /*-----------------------------------------------------------------*/
8421 static void
8422 genAddrOf (iCode * ic)
8423 {
8424   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8425   int size, offset;
8426
8427   D(emitcode (";     genAddrOf",""));
8428
8429   aopOp (IC_RESULT (ic), ic, FALSE);
8430
8431   /* if the operand is on the stack then we
8432      need to get the stack offset of this
8433      variable */
8434   if (sym->onStack)
8435     {
8436       /* if it has an offset then we need to compute
8437          it */
8438       if (sym->stack)
8439         {
8440           emitcode ("mov", "a,_bp");
8441           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8442                                          ((char) (sym->stack - _G.nRegsSaved)) :
8443                                          ((char) sym->stack)) & 0xff);
8444           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8445         }
8446       else
8447         {
8448           /* we can just move _bp */
8449           aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8450         }
8451       /* fill the result with zero */
8452       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8453
8454       offset = 1;
8455       while (size--)
8456         {
8457           aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8458         }
8459
8460       goto release;
8461     }
8462
8463   /* object not on stack then we need the name */
8464   size = AOP_SIZE (IC_RESULT (ic));
8465   offset = 0;
8466
8467   while (size--)
8468     {
8469       char s[SDCC_NAME_MAX];
8470       if (offset)
8471         sprintf (s, "#(%s >> %d)",
8472                  sym->rname,
8473                  offset * 8);
8474       else
8475         sprintf (s, "#%s", sym->rname);
8476       aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8477     }
8478
8479 release:
8480   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8481
8482 }
8483
8484 /*-----------------------------------------------------------------*/
8485 /* genFarFarAssign - assignment when both are in far space         */
8486 /*-----------------------------------------------------------------*/
8487 static void
8488 genFarFarAssign (operand * result, operand * right, iCode * ic)
8489 {
8490   int size = AOP_SIZE (right);
8491   int offset = 0;
8492   char *l;
8493
8494   D(emitcode (";     genFarFarAssign",""));
8495
8496   /* first push the right side on to the stack */
8497   while (size--)
8498     {
8499       l = aopGet (AOP (right), offset++, FALSE, FALSE);
8500       MOVA (l);
8501       emitcode ("push", "acc");
8502     }
8503
8504   freeAsmop (right, NULL, ic, FALSE);
8505   /* now assign DPTR to result */
8506   aopOp (result, ic, FALSE);
8507   size = AOP_SIZE (result);
8508   while (size--)
8509     {
8510       emitcode ("pop", "acc");
8511       aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8512     }
8513   freeAsmop (result, NULL, ic, FALSE);
8514
8515 }
8516
8517 /*-----------------------------------------------------------------*/
8518 /* genAssign - generate code for assignment                        */
8519 /*-----------------------------------------------------------------*/
8520 static void
8521 genAssign (iCode * ic)
8522 {
8523   operand *result, *right;
8524   int size, offset;
8525   unsigned long lit = 0L;
8526
8527   D(emitcode(";     genAssign",""));
8528
8529   result = IC_RESULT (ic);
8530   right = IC_RIGHT (ic);
8531
8532   /* if they are the same */
8533   if (operandsEqu (result, right) &&
8534       !isOperandVolatile (result, FALSE) &&
8535       !isOperandVolatile (right, FALSE))
8536     return;
8537
8538   aopOp (right, ic, FALSE);
8539
8540   /* special case both in far space */
8541   if (AOP_TYPE (right) == AOP_DPTR &&
8542       IS_TRUE_SYMOP (result) &&
8543       isOperandInFarSpace (result))
8544     {
8545
8546       genFarFarAssign (result, right, ic);
8547       return;
8548     }
8549
8550   aopOp (result, ic, TRUE);
8551
8552   /* if they are the same registers */
8553   if (sameRegs (AOP (right), AOP (result)) &&
8554       !isOperandVolatile (result, FALSE) &&
8555       !isOperandVolatile (right, FALSE))
8556     goto release;
8557
8558   /* if the result is a bit */
8559   if (AOP_TYPE (result) == AOP_CRY)
8560     {
8561
8562       /* if the right size is a literal then
8563          we know what the value is */
8564       if (AOP_TYPE (right) == AOP_LIT)
8565         {
8566           if (((int) operandLitValue (right)))
8567             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8568           else
8569             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8570           goto release;
8571         }
8572
8573       /* the right is also a bit variable */
8574       if (AOP_TYPE (right) == AOP_CRY)
8575         {
8576           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8577           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8578           goto release;
8579         }
8580
8581       /* we need to or */
8582       toBoolean (right);
8583       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8584       goto release;
8585     }
8586
8587   /* bit variables done */
8588   /* general case */
8589   size = AOP_SIZE (result);
8590   offset = 0;
8591   if (AOP_TYPE (right) == AOP_LIT)
8592     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8593   if ((size > 1) &&
8594       (AOP_TYPE (result) != AOP_REG) &&
8595       (AOP_TYPE (right) == AOP_LIT) &&
8596       !IS_FLOAT (operandType (right)) &&
8597       (lit < 256L))
8598     {
8599       emitcode ("clr", "a");
8600       while (size--)
8601         {
8602           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8603             aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8604           else
8605             aopPut (AOP (result),
8606                     aopGet (AOP (right), size, FALSE, FALSE),
8607                     size,
8608                     isOperandVolatile (result, FALSE));
8609         }
8610     }
8611   else
8612     {
8613       while (size--)
8614         {
8615           aopPut (AOP (result),
8616                   aopGet (AOP (right), offset, FALSE, FALSE),
8617                   offset,
8618                   isOperandVolatile (result, FALSE));
8619           offset++;
8620         }
8621     }
8622
8623 release:
8624   freeAsmop (right, NULL, ic, TRUE);
8625   freeAsmop (result, NULL, ic, TRUE);
8626 }
8627
8628 /*-----------------------------------------------------------------*/
8629 /* genJumpTab - genrates code for jump table                       */
8630 /*-----------------------------------------------------------------*/
8631 static void
8632 genJumpTab (iCode * ic)
8633 {
8634   symbol *jtab;
8635   char *l;
8636
8637   D(emitcode (";     genJumpTab",""));
8638
8639   aopOp (IC_JTCOND (ic), ic, FALSE);
8640   /* get the condition into accumulator */
8641   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8642   MOVA (l);
8643   /* multiply by three */
8644   emitcode ("add", "a,acc");
8645   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8646   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8647
8648   jtab = newiTempLabel (NULL);
8649   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8650   emitcode ("jmp", "@a+dptr");
8651   emitcode ("", "%05d$:", jtab->key + 100);
8652   /* now generate the jump labels */
8653   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8654        jtab = setNextItem (IC_JTLABELS (ic)))
8655     emitcode ("ljmp", "%05d$", jtab->key + 100);
8656
8657 }
8658
8659 /*-----------------------------------------------------------------*/
8660 /* genCast - gen code for casting                                  */
8661 /*-----------------------------------------------------------------*/
8662 static void
8663 genCast (iCode * ic)
8664 {
8665   operand *result = IC_RESULT (ic);
8666   sym_link *ctype = operandType (IC_LEFT (ic));
8667   sym_link *rtype = operandType (IC_RIGHT (ic));
8668   operand *right = IC_RIGHT (ic);
8669   int size, offset;
8670
8671   D(emitcode(";     genCast",""));
8672
8673   /* if they are equivalent then do nothing */
8674   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8675     return;
8676
8677   aopOp (right, ic, FALSE);
8678   aopOp (result, ic, FALSE);
8679
8680   /* if the result is a bit (and not a bitfield) */
8681   // if (AOP_TYPE (result) == AOP_CRY)
8682   if (IS_BITVAR (OP_SYMBOL (result)->type)
8683       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8684     {
8685       /* if the right size is a literal then
8686          we know what the value is */
8687       if (AOP_TYPE (right) == AOP_LIT)
8688         {
8689           if (((int) operandLitValue (right)))
8690             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8691           else
8692             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8693
8694           goto release;
8695         }
8696
8697       /* the right is also a bit variable */
8698       if (AOP_TYPE (right) == AOP_CRY)
8699         {
8700           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8701           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8702           goto release;
8703         }
8704
8705       /* we need to or */
8706       toBoolean (right);
8707       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8708       goto release;
8709     }
8710
8711
8712   /* if they are the same size : or less */
8713   if (AOP_SIZE (result) <= AOP_SIZE (right))
8714     {
8715
8716       /* if they are in the same place */
8717       if (sameRegs (AOP (right), AOP (result)))
8718         goto release;
8719
8720       /* if they in different places then copy */
8721       size = AOP_SIZE (result);
8722       offset = 0;
8723       while (size--)
8724         {
8725           aopPut (AOP (result),
8726                   aopGet (AOP (right), offset, FALSE, FALSE),
8727                   offset,
8728                   isOperandVolatile (result, FALSE));
8729           offset++;
8730         }
8731       goto release;
8732     }
8733
8734
8735   /* if the result is of type pointer */
8736   if (IS_PTR (ctype))
8737     {
8738
8739       int p_type;
8740       sym_link *type = operandType (right);
8741       sym_link *etype = getSpec (type);
8742
8743       /* pointer to generic pointer */
8744       if (IS_GENPTR (ctype))
8745         {
8746           if (IS_PTR (type))
8747             p_type = DCL_TYPE (type);
8748           else
8749             {
8750               if (SPEC_SCLS(etype)==S_REGISTER) {
8751                 // let's assume it is a generic pointer
8752                 p_type=GPOINTER;
8753               } else {
8754                 /* we have to go by the storage class */
8755                 p_type = PTR_TYPE (SPEC_OCLS (etype));
8756               }
8757             }
8758
8759           /* the first two bytes are known */
8760           size = GPTRSIZE - 1;
8761           offset = 0;
8762           while (size--)
8763             {
8764               aopPut (AOP (result),
8765                       aopGet (AOP (right), offset, FALSE, FALSE),
8766                       offset,
8767                       isOperandVolatile (result, FALSE));
8768               offset++;
8769             }
8770           /* the last byte depending on type */
8771             {
8772                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8773                 char gpValStr[10];
8774             
8775                 if (gpVal == -1)
8776                 {
8777                     // pointerTypeToGPByte will have bitched.
8778                     exit(1);
8779                 }
8780             
8781                 sprintf(gpValStr, "#0x%d", gpVal);
8782                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8783             }       
8784           goto release;
8785         }
8786
8787       /* just copy the pointers */
8788       size = AOP_SIZE (result);
8789       offset = 0;
8790       while (size--)
8791         {
8792           aopPut (AOP (result),
8793                   aopGet (AOP (right), offset, FALSE, FALSE),
8794                   offset,
8795                   isOperandVolatile (result, FALSE));
8796           offset++;
8797         }
8798       goto release;
8799     }
8800
8801   /* so we now know that the size of destination is greater
8802      than the size of the source */
8803   /* we move to result for the size of source */
8804   size = AOP_SIZE (right);
8805   offset = 0;
8806   while (size--)
8807     {
8808       aopPut (AOP (result),
8809               aopGet (AOP (right), offset, FALSE, FALSE),
8810               offset,
8811               isOperandVolatile (result, FALSE));
8812       offset++;
8813     }
8814
8815   /* now depending on the sign of the source && destination */
8816   size = AOP_SIZE (result) - AOP_SIZE (right);
8817   /* if unsigned or not an integral type */
8818   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8819     {
8820       while (size--)
8821         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8822     }
8823   else
8824     {
8825       /* we need to extend the sign :{ */
8826       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8827                         FALSE, FALSE);
8828       MOVA (l);
8829       emitcode ("rlc", "a");
8830       emitcode ("subb", "a,acc");
8831       while (size--)
8832         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8833     }
8834
8835   /* we are done hurray !!!! */
8836
8837 release:
8838   freeAsmop (right, NULL, ic, TRUE);
8839   freeAsmop (result, NULL, ic, TRUE);
8840
8841 }
8842
8843 /*-----------------------------------------------------------------*/
8844 /* genDjnz - generate decrement & jump if not zero instrucion      */
8845 /*-----------------------------------------------------------------*/
8846 static int
8847 genDjnz (iCode * ic, iCode * ifx)
8848 {
8849   symbol *lbl, *lbl1;
8850   if (!ifx)
8851     return 0;
8852
8853   D(emitcode (";     genDjnz",""));
8854
8855   /* if the if condition has a false label
8856      then we cannot save */
8857   if (IC_FALSE (ifx))
8858     return 0;
8859
8860   /* if the minus is not of the form
8861      a = a - 1 */
8862   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8863       !IS_OP_LITERAL (IC_RIGHT (ic)))
8864     return 0;
8865
8866   if (operandLitValue (IC_RIGHT (ic)) != 1)
8867     return 0;
8868
8869   /* if the size of this greater than one then no
8870      saving */
8871   if (getSize (operandType (IC_RESULT (ic))) > 1)
8872     return 0;
8873
8874   /* otherwise we can save BIG */
8875   lbl = newiTempLabel (NULL);
8876   lbl1 = newiTempLabel (NULL);
8877
8878   aopOp (IC_RESULT (ic), ic, FALSE);
8879
8880   if (AOP_NEEDSACC(IC_RESULT(ic)))
8881   {
8882       /* If the result is accessed indirectly via
8883        * the accumulator, we must explicitly write
8884        * it back after the decrement.
8885        */
8886       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8887       
8888       if (strcmp(rByte, "a"))
8889       {
8890            /* Something is hopelessly wrong */
8891            fprintf(stderr, "*** warning: internal error at %s:%d\n",
8892                    __FILE__, __LINE__);
8893            /* We can just give up; the generated code will be inefficient,
8894             * but what the hey.
8895             */
8896            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8897            return 0;
8898       }
8899       emitcode ("dec", "%s", rByte);
8900       aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8901       emitcode ("jnz", "%05d$", lbl->key + 100);
8902   }
8903   else if (IS_AOP_PREG (IC_RESULT (ic)))
8904     {
8905       emitcode ("dec", "%s",
8906                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8907       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8908       emitcode ("jnz", "%05d$", lbl->key + 100);
8909     }
8910   else
8911     {
8912       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8913                 lbl->key + 100);
8914     }
8915   emitcode ("sjmp", "%05d$", lbl1->key + 100);
8916   emitcode ("", "%05d$:", lbl->key + 100);
8917   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8918   emitcode ("", "%05d$:", lbl1->key + 100);
8919
8920   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8921   ifx->generated = 1;
8922   return 1;
8923 }
8924
8925 /*-----------------------------------------------------------------*/
8926 /* genReceive - generate code for a receive iCode                  */
8927 /*-----------------------------------------------------------------*/
8928 static void
8929 genReceive (iCode * ic)
8930 {
8931     int size = getSize (operandType (IC_RESULT (ic)));
8932     int offset = 0;
8933   D(emitcode (";     genReceive",""));
8934
8935   if (ic->argreg == 1) { /* first parameter */
8936       if (isOperandInFarSpace (IC_RESULT (ic)) &&
8937           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8938            IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8939
8940           offset = fReturnSizeMCS51 - size;
8941           while (size--) {
8942               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8943                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8944               offset++;
8945           }
8946           aopOp (IC_RESULT (ic), ic, FALSE);
8947           size = AOP_SIZE (IC_RESULT (ic));
8948           offset = 0;
8949           while (size--) {
8950               emitcode ("pop", "acc");
8951               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8952           }
8953
8954       } else {
8955           _G.accInUse++;
8956           aopOp (IC_RESULT (ic), ic, FALSE);
8957           _G.accInUse--;
8958           assignResultValue (IC_RESULT (ic));
8959       }
8960   } else { /* second receive onwards */
8961       int rb1off ;
8962       aopOp (IC_RESULT (ic), ic, FALSE);
8963       rb1off = ic->argreg;
8964       while (size--) {
8965           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8966       }
8967   }
8968   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8969 }
8970
8971 /*-----------------------------------------------------------------*/
8972 /* genDummyRead - generate code for dummy read of volatiles        */
8973 /*-----------------------------------------------------------------*/
8974 static void
8975 genDummyRead (iCode * ic)
8976 {
8977   operand *right;
8978   int size, offset;
8979
8980   D(emitcode(";     genDummyRead",""));
8981
8982   right = IC_RIGHT (ic);
8983
8984   aopOp (right, ic, FALSE);
8985
8986   /* if the result is a bit */
8987   if (AOP_TYPE (right) == AOP_CRY)
8988     {
8989       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8990       goto release;
8991     }
8992
8993   /* bit variables done */
8994   /* general case */
8995   size = AOP_SIZE (right);
8996   offset = 0;
8997   while (size--)
8998     {
8999       MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9000       offset++;
9001     }
9002
9003 release:
9004   freeAsmop (right, NULL, ic, TRUE);
9005 }
9006
9007 /*-----------------------------------------------------------------*/
9008 /* gen51Code - generate code for 8051 based controllers            */
9009 /*-----------------------------------------------------------------*/
9010 void
9011 gen51Code (iCode * lic)
9012 {
9013   iCode *ic;
9014   int cln = 0;
9015
9016   lineHead = lineCurr = NULL;
9017
9018   /* print the allocation information */
9019   if (allocInfo && currFunc)
9020     printAllocInfo (currFunc, codeOutFile);
9021   /* if debug information required */
9022   if (options.debug && currFunc)
9023     {
9024       debugFile->writeFunction(currFunc);
9025       _G.debugLine = 1;
9026       if (IS_STATIC (currFunc->etype))
9027         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9028       else
9029         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9030       _G.debugLine = 0;
9031     }
9032   /* stack pointer name */
9033   if (options.useXstack)
9034     spname = "_spx";
9035   else
9036     spname = "sp";
9037
9038
9039   for (ic = lic; ic; ic = ic->next)
9040     {
9041       _G.current_iCode = ic;
9042       
9043       if (ic->lineno && cln != ic->lineno)
9044         {
9045           if (options.debug)
9046             {
9047               _G.debugLine = 1;
9048               emitcode ("", "C$%s$%d$%d$%d ==.",
9049                         FileBaseName (ic->filename), ic->lineno,
9050                         ic->level, ic->block);
9051               _G.debugLine = 0;
9052             }
9053           if (!options.noCcodeInAsm) {
9054             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
9055                       printCLine(ic->filename, ic->lineno));
9056           }
9057           cln = ic->lineno;
9058         }
9059       if (options.iCodeInAsm) {
9060         char regsInUse[80];
9061         int i;
9062
9063         for (i=0; i<8; i++) {
9064           sprintf (&regsInUse[i],
9065                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
9066         }
9067         regsInUse[i]=0;
9068         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9069       }
9070       /* if the result is marked as
9071          spilt and rematerializable or code for
9072          this has already been generated then
9073          do nothing */
9074       if (resultRemat (ic) || ic->generated)
9075         continue;
9076
9077       /* depending on the operation */
9078       switch (ic->op)
9079         {
9080         case '!':
9081           genNot (ic);
9082           break;
9083
9084         case '~':
9085           genCpl (ic);
9086           break;
9087
9088         case UNARYMINUS:
9089           genUminus (ic);
9090           break;
9091
9092         case IPUSH:
9093           genIpush (ic);
9094           break;
9095
9096         case IPOP:
9097           /* IPOP happens only when trying to restore a
9098              spilt live range, if there is an ifx statement
9099              following this pop then the if statement might
9100              be using some of the registers being popped which
9101              would destory the contents of the register so
9102              we need to check for this condition and handle it */
9103           if (ic->next &&
9104               ic->next->op == IFX &&
9105               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9106             genIfx (ic->next, ic);
9107           else
9108             genIpop (ic);
9109           break;
9110
9111         case CALL:
9112           genCall (ic);
9113           break;
9114
9115         case PCALL:
9116           genPcall (ic);
9117           break;
9118
9119         case FUNCTION:
9120           genFunction (ic);
9121           break;
9122
9123         case ENDFUNCTION:
9124           genEndFunction (ic);
9125           break;
9126
9127         case RETURN:
9128           genRet (ic);
9129           break;
9130
9131         case LABEL:
9132           genLabel (ic);
9133           break;
9134
9135         case GOTO:
9136           genGoto (ic);
9137           break;
9138
9139         case '+':
9140           genPlus (ic);
9141           break;
9142
9143         case '-':
9144           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9145             genMinus (ic);
9146           break;
9147
9148         case '*':
9149           genMult (ic);
9150           break;
9151
9152         case '/':
9153           genDiv (ic);
9154           break;
9155
9156         case '%':
9157           genMod (ic);
9158           break;
9159
9160         case '>':
9161           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9162           break;
9163
9164         case '<':
9165           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9166           break;
9167
9168         case LE_OP:
9169         case GE_OP:
9170         case NE_OP:
9171
9172           /* note these two are xlated by algebraic equivalence
9173              during parsing SDCC.y */
9174           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9175                   "got '>=' or '<=' shouldn't have come here");
9176           break;
9177
9178         case EQ_OP:
9179           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9180           break;
9181
9182         case AND_OP:
9183           genAndOp (ic);
9184           break;
9185
9186         case OR_OP:
9187           genOrOp (ic);
9188           break;
9189
9190         case '^':
9191           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9192           break;
9193
9194         case '|':
9195           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9196           break;
9197
9198         case BITWISEAND:
9199           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9200           break;
9201
9202         case INLINEASM:
9203           genInline (ic);
9204           break;
9205
9206         case RRC:
9207           genRRC (ic);
9208           break;
9209
9210         case RLC:
9211           genRLC (ic);
9212           break;
9213
9214         case GETHBIT:
9215           genGetHbit (ic);
9216           break;
9217
9218         case LEFT_OP:
9219           genLeftShift (ic);
9220           break;
9221
9222         case RIGHT_OP:
9223           genRightShift (ic);
9224           break;
9225
9226         case GET_VALUE_AT_ADDRESS:
9227           genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9228           break;
9229
9230         case '=':
9231           if (POINTER_SET (ic))
9232             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9233           else
9234             genAssign (ic);
9235           break;
9236
9237         case IFX:
9238           genIfx (ic, NULL);
9239           break;
9240
9241         case ADDRESS_OF:
9242           genAddrOf (ic);
9243           break;
9244
9245         case JUMPTABLE:
9246           genJumpTab (ic);
9247           break;
9248
9249         case CAST:
9250           genCast (ic);
9251           break;
9252
9253         case RECEIVE:
9254           genReceive (ic);
9255           break;
9256
9257         case SEND:
9258           addSet (&_G.sendSet, ic);
9259           break;
9260
9261         case DUMMY_READ_VOLATILE:
9262           genDummyRead (ic);
9263           break;
9264
9265         default:
9266           ic = ic;
9267         }
9268     }
9269
9270   _G.current_iCode = NULL;
9271
9272   /* now we are ready to call the
9273      peep hole optimizer */
9274   if (!options.nopeep)
9275     peepHole (&lineHead);
9276
9277   /* now do the actual printing */
9278   printLine (lineHead, codeOutFile);
9279   return;
9280 }