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