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