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