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