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