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