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