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