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