* src/mcs51/gen.c: removed non-standard C nameless struct/union
[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 #define R0INB   _G.bu.bs.r0InB
68 #define R1INB   _G.bu.bs.r1InB
69 #define OPINB   _G.bu.bs.OpInB
70 #define BINUSE  _G.bu.BInUse
71
72 static struct
73   {
74     short r0Pushed;
75     short r1Pushed;
76     union
77       {
78         struct
79           {
80             short r0InB : 2;//2 so we can see it overflow
81             short r1InB : 2;//2 so we can see it overflow
82             short OpInB : 2;//2 so we can see it overflow
83           } bs;
84         short BInUse;
85       } bu;
86     short accInUse;
87     short inLine;
88     short debugLine;
89     short nRegsSaved;
90     set *sendSet;
91     iCode *current_iCode;
92     symbol *currentFunc;
93   }
94 _G;
95
96 static char *rb1regs[] = {
97     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
98 };
99
100 extern int mcs51_ptrRegReq;
101 extern int mcs51_nRegs;
102 extern FILE *codeOutFile;
103 static void saveRBank (int, iCode *, bool);
104
105 #define RESULTONSTACK(x) \
106                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
107                          IC_RESULT(x)->aop->type == AOP_STK )
108
109 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
110 #define CLRC     emitcode("clr","c")
111 #define SETC     emitcode("setb","c")
112
113 static lineNode *lineHead = NULL;
114 static lineNode *lineCurr = NULL;
115
116 static unsigned char SLMask[] =
117 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
118  0xE0, 0xC0, 0x80, 0x00};
119 static unsigned char SRMask[] =
120 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
121  0x07, 0x03, 0x01, 0x00};
122
123 #define LSB     0
124 #define MSB16   1
125 #define MSB24   2
126 #define MSB32   3
127
128 /*-----------------------------------------------------------------*/
129 /* emitcode - writes the code into a file : for now it is simple    */
130 /*-----------------------------------------------------------------*/
131 static void
132 emitcode (char *inst, const char *fmt,...)
133 {
134   va_list ap;
135   char lb[INITIAL_INLINEASM];
136   char *lbp = lb;
137
138   va_start (ap, fmt);
139
140   if (inst && *inst)
141     {
142       if (fmt && *fmt)
143           SNPRINTF (lb, sizeof(lb), "%s\t", inst);
144       else
145           SNPRINTF (lb, sizeof(lb), "%s", inst);
146       tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
147     }
148   else
149       tvsprintf (lb, sizeof(lb), fmt, ap);
150
151   while (isspace (*lbp))
152       lbp++;
153
154   if (lbp && *lbp)
155       lineCurr = (lineCurr ?
156                   connectLine (lineCurr, newLineNode (lb)) :
157                   (lineHead = newLineNode (lb)));
158   lineCurr->isInline = _G.inLine;
159   lineCurr->isDebug = _G.debugLine;
160   lineCurr->ic = _G.current_iCode;
161   lineCurr->isComment = (*lbp==';');
162   va_end (ap);
163 }
164
165 /*-----------------------------------------------------------------*/
166 /* mcs51_emitDebuggerSymbol - associate the current code location  */
167 /*   with a debugger symbol                                        */
168 /*-----------------------------------------------------------------*/
169 void
170 mcs51_emitDebuggerSymbol (char * debugSym)
171 {
172   _G.debugLine = 1;
173   emitcode ("", "%s ==.", debugSym);
174   _G.debugLine = 0;
175 }
176
177 /*-----------------------------------------------------------------*/
178 /* mova - moves specified value into accumulator                   */
179 /*-----------------------------------------------------------------*/
180 static void
181 mova (const char *x)
182 {
183   /* do some early peephole optimization */
184   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
185     return;
186
187   emitcode("mov","a,%s", x);
188 }
189
190 /*-----------------------------------------------------------------*/
191 /* pushB - saves register B if necessary                           */
192 /*-----------------------------------------------------------------*/
193 static bool
194 pushB (void)
195 {
196   bool pushedB = FALSE;
197
198   if (BINUSE)
199     {
200       emitcode ("push", "b");
201 //    printf("B was in use !\n");
202       pushedB = TRUE;
203     }
204   else
205     {
206       OPINB++;
207     }
208   return pushedB;
209 }
210
211 /*-----------------------------------------------------------------*/
212 /* popB - restores value of register B if necessary                */
213 /*-----------------------------------------------------------------*/
214 static void
215 popB (bool pushedB)
216 {
217   if (pushedB)
218     {
219       emitcode ("pop", "b");
220     }
221   else
222     {
223       OPINB--;
224     }
225 }
226
227 /*-----------------------------------------------------------------*/
228 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
229 /*-----------------------------------------------------------------*/
230 static regs *
231 getFreePtr (iCode * ic, asmop ** aopp, bool result)
232 {
233   bool r0iu, r1iu;
234   bool r0ou, r1ou;
235
236   /* the logic: if r0 & r1 used in the instruction
237      then we are in trouble otherwise */
238
239   /* first check if r0 & r1 are used by this
240      instruction, in which case we are in trouble */
241   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
242   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
243   if (r0iu && r1iu) {
244       goto endOfWorld;
245     }
246
247   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
248   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
249
250   /* if no usage of r0 then return it */
251   if (!r0iu && !r0ou)
252     {
253       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
254       (*aopp)->type = AOP_R0;
255
256       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
257     }
258
259   /* if no usage of r1 then return it */
260   if (!r1iu && !r1ou)
261     {
262       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
263       (*aopp)->type = AOP_R1;
264
265       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
266     }
267
268   /* now we know they both have usage */
269   /* if r0 not used in this instruction */
270   if (!r0iu)
271     {
272       /* push it if not already pushed */
273       if (ic->op == IPUSH)
274         {
275           emitcode ("mov", "b,%s",
276                     mcs51_regWithIdx (R0_IDX)->dname);
277           R0INB++;
278         }
279       else if (!_G.r0Pushed)
280         {
281           emitcode ("push", "%s",
282                     mcs51_regWithIdx (R0_IDX)->dname);
283           _G.r0Pushed++;
284         }
285
286       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
287       (*aopp)->type = AOP_R0;
288
289       return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
290     }
291
292   /* if r1 not used then */
293
294   if (!r1iu)
295     {
296       /* push it if not already pushed */
297       if (ic->op == IPUSH)
298         {
299           emitcode ("mov", "b,%s",
300                     mcs51_regWithIdx (R1_IDX)->dname);
301           R1INB++;
302         }
303       else if (!_G.r1Pushed)
304         {
305           emitcode ("push", "%s",
306                     mcs51_regWithIdx (R1_IDX)->dname);
307           _G.r1Pushed++;
308         }
309
310       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
311       (*aopp)->type = AOP_R1;
312       return mcs51_regWithIdx (R1_IDX);
313     }
314 endOfWorld:
315   /* I said end of world, but not quite end of world yet */
316   if (result) {
317     /* we can push it on the stack */
318     (*aopp)->type = AOP_STK;
319     return NULL;
320   } else {
321     /* in the case that result AND left AND right needs a pointer reg
322        we can safely use the result's */
323     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
324       (*aopp)->type = AOP_R0;
325       return mcs51_regWithIdx (R0_IDX);
326     }
327     if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
328       (*aopp)->type = AOP_R1;
329       return mcs51_regWithIdx (R1_IDX);
330     }
331   }
332
333   /* now this is REALLY the end of the world */
334   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
335           "getFreePtr should never reach here");
336   exit (1);
337 }
338
339
340 /*-----------------------------------------------------------------*/
341 /* getTempRegs - initialize an array of pointers to GPR registers */
342 /*               that are not in use. Returns 1 if the requested   */
343 /*               number of registers were available, 0 otherwise.  */
344 /*-----------------------------------------------------------------*/
345 int
346 getTempRegs(regs **tempRegs, int size, iCode *ic)
347 {
348   bitVect * freeRegs;
349   int i;
350   int offset;
351
352   if (!ic)
353     ic = _G.current_iCode;
354   if (!ic)
355     return 0;
356   if (!_G.currentFunc)
357     return 0;
358
359   freeRegs = newBitVect(8);
360   bitVectSetBit (freeRegs, R2_IDX);
361   bitVectSetBit (freeRegs, R3_IDX);
362   bitVectSetBit (freeRegs, R4_IDX);
363   bitVectSetBit (freeRegs, R5_IDX);
364   bitVectSetBit (freeRegs, R6_IDX);
365   bitVectSetBit (freeRegs, R7_IDX);
366
367   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
368     {
369       bitVect * newfreeRegs;
370       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
371       freeBitVect(freeRegs);
372       freeRegs = newfreeRegs;
373     }
374   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
375
376   offset = 0;
377   for (i=0; i<freeRegs->size; i++)
378     {
379       if (bitVectBitValue(freeRegs,i))
380         tempRegs[offset++] = mcs51_regWithIdx(i);
381       if (offset>=size)
382         {
383           freeBitVect(freeRegs);
384           return 1;
385         }
386     }
387
388   freeBitVect(freeRegs);
389   return 1;
390 }
391
392
393 /*-----------------------------------------------------------------*/
394 /* newAsmop - creates a new asmOp                                  */
395 /*-----------------------------------------------------------------*/
396 static asmop *
397 newAsmop (short type)
398 {
399   asmop *aop;
400
401   aop = Safe_calloc (1, sizeof (asmop));
402   aop->type = type;
403   return aop;
404 }
405
406 /*-----------------------------------------------------------------*/
407 /* pointerCode - returns the code for a pointer type               */
408 /*-----------------------------------------------------------------*/
409 static int
410 pointerCode (sym_link * etype)
411 {
412
413   return PTR_TYPE (SPEC_OCLS (etype));
414
415 }
416
417 /*-----------------------------------------------------------------*/
418 /* leftRightUseAcc - returns size of accumulator use by operands   */
419 /*-----------------------------------------------------------------*/
420 static int
421 leftRightUseAcc(iCode *ic)
422 {
423   operand *op;
424   int size;
425   int accuseSize = 0;
426   int accuse = 0;
427
428   if (!ic)
429     {
430       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
431               "null iCode pointer");
432       return 0;
433     }
434
435   if (ic->op == IFX)
436     {
437       op = IC_COND (ic);
438       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
439         {
440           accuse = 1;
441           size = getSize (OP_SYMBOL (op)->type);
442           if (size>accuseSize)
443             accuseSize = size;
444         }
445     }
446   else if (ic->op == JUMPTABLE)
447     {
448       op = IC_JTCOND (ic);
449       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
450         {
451           accuse = 1;
452           size = getSize (OP_SYMBOL (op)->type);
453           if (size>accuseSize)
454             accuseSize = size;
455         }
456     }
457   else
458     {
459       op = IC_LEFT (ic);
460       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
461         {
462           accuse = 1;
463           size = getSize (OP_SYMBOL (op)->type);
464           if (size>accuseSize)
465             accuseSize = size;
466         }
467       op = IC_RIGHT (ic);
468       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
469         {
470           accuse = 1;
471           size = getSize (OP_SYMBOL (op)->type);
472           if (size>accuseSize)
473             accuseSize = size;
474         }
475     }
476
477   if (accuseSize)
478     return accuseSize;
479   else
480     return accuse;
481 }
482
483 /*-----------------------------------------------------------------*/
484 /* aopForSym - for a true symbol                                   */
485 /*-----------------------------------------------------------------*/
486 static asmop *
487 aopForSym (iCode * ic, symbol * sym, bool result)
488 {
489   asmop *aop;
490   memmap *space;
491
492   wassertl (ic != NULL, "Got a null iCode");
493   wassertl (sym != NULL, "Got a null symbol");
494
495   space = SPEC_OCLS (sym->etype);
496
497   /* if already has one */
498   if (sym->aop)
499     return sym->aop;
500
501   /* assign depending on the storage class */
502   /* if it is on the stack or indirectly addressable */
503   /* space we need to assign either r0 or r1 to it   */
504   if (sym->onStack || sym->iaccess)
505     {
506       sym->aop = aop = newAsmop (0);
507       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
508       aop->size = getSize (sym->type);
509
510       /* now assign the address of the variable to
511          the pointer register */
512       if (aop->type != AOP_STK)
513         {
514
515           if (sym->onStack)
516             {
517               if (_G.accInUse || leftRightUseAcc (ic))
518                 emitcode ("push", "acc");
519
520               emitcode ("mov", "a,_bp");
521               emitcode ("add", "a,#0x%02x",
522                         ((sym->stack < 0) ?
523                          ((char) (sym->stack - _G.nRegsSaved)) :
524                          ((char) sym->stack)) & 0xff);
525               emitcode ("mov", "%s,a",
526                         aop->aopu.aop_ptr->name);
527
528               if (_G.accInUse || leftRightUseAcc (ic))
529                 emitcode ("pop", "acc");
530             }
531           else
532             emitcode ("mov", "%s,#%s",
533                       aop->aopu.aop_ptr->name,
534                       sym->rname);
535           aop->paged = space->paged;
536         }
537       else
538         aop->aopu.aop_stk = sym->stack;
539       return aop;
540     }
541
542   /* if in bit space */
543   if (IN_BITSPACE (space))
544     {
545       sym->aop = aop = newAsmop (AOP_CRY);
546       aop->aopu.aop_dir = sym->rname;
547       aop->size = getSize (sym->type);
548       return aop;
549     }
550   /* if it is in direct space */
551   if (IN_DIRSPACE (space))
552     {
553       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
554       //printTypeChainRaw(sym->type, NULL);
555       //printf("space = %s\n", space ? space->sname : "NULL");
556       sym->aop = aop = newAsmop (AOP_DIR);
557       aop->aopu.aop_dir = sym->rname;
558       aop->size = getSize (sym->type);
559       return aop;
560     }
561
562   /* special case for a function */
563   if (IS_FUNC (sym->type))
564     {
565       sym->aop = aop = newAsmop (AOP_IMMD);
566       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
567       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
568       aop->size = FPTRSIZE;
569       return aop;
570     }
571
572   /* only remaining is far space */
573   /* in which case DPTR gets the address */
574   sym->aop = aop = newAsmop (AOP_DPTR);
575   emitcode ("mov", "dptr,#%s", sym->rname);
576   aop->size = getSize (sym->type);
577
578   /* if it is in code space */
579   if (IN_CODESPACE (space))
580     aop->code = 1;
581
582   return aop;
583 }
584
585 /*-----------------------------------------------------------------*/
586 /* aopForRemat - rematerialzes an object                           */
587 /*-----------------------------------------------------------------*/
588 static asmop *
589 aopForRemat (symbol * sym)
590 {
591   iCode *ic = sym->rematiCode;
592   asmop *aop = newAsmop (AOP_IMMD);
593   int ptr_type = 0;
594   int val = 0;
595
596   for (;;)
597     {
598       if (ic->op == '+')
599         val += (int) operandLitValue (IC_RIGHT (ic));
600       else if (ic->op == '-')
601         val -= (int) operandLitValue (IC_RIGHT (ic));
602       else if (IS_CAST_ICODE(ic)) {
603               sym_link *from_type = operandType(IC_RIGHT(ic));
604               aop->aopu.aop_immd.from_cast_remat = 1;
605               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
606               ptr_type = DCL_TYPE(from_type);
607               if (ptr_type == IPOINTER) {
608                 // bug #481053
609                 ptr_type = POINTER;
610               }
611               continue ;
612       } else break;
613
614       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
615     }
616
617   if (val)
618     sprintf (buffer, "(%s %c 0x%04x)",
619              OP_SYMBOL (IC_LEFT (ic))->rname,
620              val >= 0 ? '+' : '-',
621              abs (val) & 0xffff);
622   else
623     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
624
625   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
626   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
627   /* set immd2 field if required */
628   if (aop->aopu.aop_immd.from_cast_remat) {
629           sprintf(buffer,"#0x%02x",ptr_type);
630           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
631           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
632   }
633
634   return aop;
635 }
636
637 /*-----------------------------------------------------------------*/
638 /* regsInCommon - two operands have some registers in common       */
639 /*-----------------------------------------------------------------*/
640 static bool
641 regsInCommon (operand * op1, operand * op2)
642 {
643   symbol *sym1, *sym2;
644   int i;
645
646   /* if they have registers in common */
647   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
648     return FALSE;
649
650   sym1 = OP_SYMBOL (op1);
651   sym2 = OP_SYMBOL (op2);
652
653   if (sym1->nRegs == 0 || sym2->nRegs == 0)
654     return FALSE;
655
656   for (i = 0; i < sym1->nRegs; i++)
657     {
658       int j;
659       if (!sym1->regs[i])
660         continue;
661
662       for (j = 0; j < sym2->nRegs; j++)
663         {
664           if (!sym2->regs[j])
665             continue;
666
667           if (sym2->regs[j] == sym1->regs[i])
668             return TRUE;
669         }
670     }
671
672   return FALSE;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* operandsEqu - equivalent                                        */
677 /*-----------------------------------------------------------------*/
678 static bool
679 operandsEqu (operand * op1, operand * op2)
680 {
681   symbol *sym1, *sym2;
682
683   /* if they're not symbols */
684   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
685     return FALSE;
686
687   sym1 = OP_SYMBOL (op1);
688   sym2 = OP_SYMBOL (op2);
689
690   /* if both are itemps & one is spilt
691      and the other is not then false */
692   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
693       sym1->isspilt != sym2->isspilt)
694     return FALSE;
695
696   /* if they are the same */
697   if (sym1 == sym2)
698     return TRUE;
699
700   /* if they have the same rname */
701   if (sym1->rname[0] && sym2->rname[0]
702       && strcmp (sym1->rname, sym2->rname) == 0)
703     return TRUE;
704
705   /* if left is a tmp & right is not */
706   if (IS_ITEMP (op1) &&
707       !IS_ITEMP (op2) &&
708       sym1->isspilt &&
709       (sym1->usl.spillLoc == sym2))
710     return TRUE;
711
712   if (IS_ITEMP (op2) &&
713       !IS_ITEMP (op1) &&
714       sym2->isspilt &&
715       sym1->level > 0 &&
716       (sym2->usl.spillLoc == sym1))
717     return TRUE;
718
719   return FALSE;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* sameRegs - two asmops have the same registers                   */
724 /*-----------------------------------------------------------------*/
725 static bool
726 sameRegs (asmop * aop1, asmop * aop2)
727 {
728   int i;
729
730   if (aop1 == aop2)
731     return TRUE;
732
733   if (aop1->type != AOP_REG ||
734       aop2->type != AOP_REG)
735     return FALSE;
736
737   if (aop1->size != aop2->size)
738     return FALSE;
739
740   for (i = 0; i < aop1->size; i++)
741     if (aop1->aopu.aop_reg[i] !=
742         aop2->aopu.aop_reg[i])
743       return FALSE;
744
745   return TRUE;
746 }
747
748 /*-----------------------------------------------------------------*/
749 /* aopOp - allocates an asmop for an operand  :                    */
750 /*-----------------------------------------------------------------*/
751 static void
752 aopOp (operand * op, iCode * ic, bool result)
753 {
754   asmop *aop;
755   symbol *sym;
756   int i;
757
758   if (!op)
759     return;
760
761   /* if this a literal */
762   if (IS_OP_LITERAL (op))
763     {
764       op->aop = aop = newAsmop (AOP_LIT);
765       aop->aopu.aop_lit = op->operand.valOperand;
766       aop->size = getSize (operandType (op));
767       return;
768     }
769
770   /* if already has a asmop then continue */
771   if (op->aop )
772     return;
773
774   /* if the underlying symbol has a aop */
775   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
776     {
777       op->aop = OP_SYMBOL (op)->aop;
778       return;
779     }
780
781   /* if this is a true symbol */
782   if (IS_TRUE_SYMOP (op))
783     {
784       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
785       return;
786     }
787
788   /* this is a temporary : this has
789      only four choices :
790      a) register
791      b) spillocation
792      c) rematerialize
793      d) conditional
794      e) can be a return use only */
795
796   sym = OP_SYMBOL (op);
797
798   /* if the type is a conditional */
799   if (sym->regType == REG_CND)
800     {
801       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
802       aop->size = 0;
803       return;
804     }
805
806   /* if it is spilt then two situations
807      a) is rematerialize
808      b) has a spill location */
809   if (sym->isspilt || sym->nRegs == 0)
810     {
811
812       /* rematerialize it NOW */
813       if (sym->remat)
814         {
815           sym->aop = op->aop = aop =
816             aopForRemat (sym);
817           aop->size = getSize (sym->type);
818           return;
819         }
820
821       if (sym->accuse)
822         {
823           int i;
824           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
825           aop->size = getSize (sym->type);
826           for (i = 0; i < 2; i++)
827             aop->aopu.aop_str[i] = accUse[i];
828           return;
829         }
830
831       if (sym->ruonly)
832         {
833           unsigned i;
834
835           aop = op->aop = sym->aop = newAsmop (AOP_STR);
836           aop->size = getSize (sym->type);
837           for (i = 0; i < fReturnSizeMCS51; i++)
838             aop->aopu.aop_str[i] = fReturn[i];
839           return;
840         }
841
842       if (sym->usl.spillLoc)
843         {
844           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
845             {
846               /* force a new aop if sizes differ */
847               sym->usl.spillLoc->aop = NULL;
848             }
849           sym->aop = op->aop = aop =
850                      aopForSym (ic, sym->usl.spillLoc, result);
851           aop->size = getSize (sym->type);
852           return;
853         }
854
855       /* else must be a dummy iTemp */
856       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
857       aop->size = getSize (sym->type);
858       return;
859     }
860
861   /* must be in a register */
862   sym->aop = op->aop = aop = newAsmop (AOP_REG);
863   aop->size = sym->nRegs;
864   for (i = 0; i < sym->nRegs; i++)
865     aop->aopu.aop_reg[i] = sym->regs[i];
866 }
867
868 /*-----------------------------------------------------------------*/
869 /* freeAsmop - free up the asmop given to an operand               */
870 /*----------------------------------------------------------------*/
871 static void
872 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
873 {
874   asmop *aop;
875
876   if (!op)
877     aop = aaop;
878   else
879     aop = op->aop;
880
881   if (!aop)
882     return;
883
884   if (aop->freed)
885     goto dealloc;
886
887   aop->freed = 1;
888
889   /* depending on the asmop type only three cases need work AOP_RO
890      , AOP_R1 && AOP_STK */
891   switch (aop->type)
892     {
893     case AOP_R0:
894       if (R0INB)
895         {
896           emitcode ("mov", "r0,b");
897           R0INB--;
898         }
899       else if (_G.r0Pushed)
900         {
901           if (pop)
902             {
903               emitcode ("pop", "ar0");
904               _G.r0Pushed--;
905             }
906         }
907       bitVectUnSetBit (ic->rUsed, R0_IDX);
908       break;
909
910     case AOP_R1:
911       if (R1INB)
912         {
913           emitcode ("mov", "r1,b");
914           R1INB--;
915         }
916       if (_G.r1Pushed)
917         {
918           if (pop)
919             {
920               emitcode ("pop", "ar1");
921               _G.r1Pushed--;
922             }
923         }
924       bitVectUnSetBit (ic->rUsed, R1_IDX);
925       break;
926
927     case AOP_STK:
928       {
929         int sz = aop->size;
930         int stk = aop->aopu.aop_stk + aop->size - 1;
931         bitVectUnSetBit (ic->rUsed, R0_IDX);
932         bitVectUnSetBit (ic->rUsed, R1_IDX);
933
934         getFreePtr (ic, &aop, FALSE);
935
936         if (stk)
937           {
938             emitcode ("mov", "a,_bp");
939             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
940             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
941           }
942         else
943           {
944             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
945           }
946
947         while (sz--)
948           {
949             emitcode ("pop", "acc");
950             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
951             if (!sz)
952               break;
953             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
954           }
955         op->aop = aop;
956         freeAsmop (op, NULL, ic, TRUE);
957         if (_G.r1Pushed)
958           {
959             emitcode ("pop", "ar1");
960             _G.r1Pushed--;
961           }
962
963         if (_G.r0Pushed)
964           {
965             emitcode ("pop", "ar0");
966             _G.r0Pushed--;
967           }
968       }
969     }
970
971 dealloc:
972   /* all other cases just dealloc */
973   if (op)
974     {
975       op->aop = NULL;
976       if (IS_SYMOP (op))
977         {
978           OP_SYMBOL (op)->aop = NULL;
979           /* if the symbol has a spill */
980           if (SPIL_LOC (op))
981             SPIL_LOC (op)->aop = NULL;
982         }
983     }
984 }
985
986 /*------------------------------------------------------------------*/
987 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
988 /*                      pop r0 or r1 off stack if pushed            */
989 /*------------------------------------------------------------------*/
990 static void
991 freeForBranchAsmop (operand * op)
992 {
993   asmop *aop;
994
995   if (!op)
996     return;
997
998   aop = op->aop;
999
1000   if (!aop)
1001     return;
1002
1003   if (aop->freed)
1004     return;
1005
1006   switch (aop->type)
1007     {
1008     case AOP_R0:
1009       if (R0INB)
1010         {
1011           emitcode ("mov", "r0,b");
1012         }
1013       else if (_G.r0Pushed)
1014         {
1015           emitcode ("pop", "ar0");
1016         }
1017       break;
1018
1019     case AOP_R1:
1020       if (R1INB)
1021         {
1022           emitcode ("mov", "r1,b");
1023         }
1024       else if (_G.r1Pushed)
1025         {
1026           emitcode ("pop", "ar1");
1027         }
1028       break;
1029
1030     case AOP_STK:
1031       {
1032         int sz = aop->size;
1033         int stk = aop->aopu.aop_stk + aop->size - 1;
1034
1035         emitcode ("mov", "b,r0");
1036         if (stk)
1037           {
1038             emitcode ("mov", "a,_bp");
1039             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1040             emitcode ("mov", "r0,a");
1041           }
1042         else
1043           {
1044             emitcode ("mov", "r0,_bp");
1045           }
1046
1047         while (sz--)
1048           {
1049             emitcode ("pop", "acc");
1050             emitcode ("mov", "@r0,a");
1051             if (!sz)
1052               break;
1053             emitcode ("dec", "r0");
1054           }
1055         emitcode ("mov", "r0,b");
1056       }
1057     }
1058
1059 }
1060
1061 /*-----------------------------------------------------------------*/
1062 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1063 /*                 clobber the accumulator                         */
1064 /*-----------------------------------------------------------------*/
1065 static bool
1066 aopGetUsesAcc (asmop *aop, int offset)
1067 {
1068   if (offset > (aop->size - 1))
1069     return FALSE;
1070
1071   switch (aop->type)
1072     {
1073
1074     case AOP_R0:
1075     case AOP_R1:
1076       if (aop->paged)
1077         return TRUE;
1078       return FALSE;
1079     case AOP_DPTR:
1080       return TRUE;
1081     case AOP_IMMD:
1082       return FALSE;
1083     case AOP_DIR:
1084       return FALSE;
1085     case AOP_REG:
1086       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1087       return FALSE;
1088     case AOP_CRY:
1089       return TRUE;
1090     case AOP_ACC:
1091       return TRUE;
1092     case AOP_LIT:
1093       return FALSE;
1094     case AOP_STR:
1095       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1096         return TRUE;
1097       return FALSE;
1098     case AOP_DUMMY:
1099       return FALSE;
1100     default:
1101       /* Error case --- will have been caught already */
1102       wassert(0);
1103       return FALSE;
1104     }
1105 }
1106
1107 /*-----------------------------------------------------------------*/
1108 /* aopGet - for fetching value of the aop                          */
1109 /*-----------------------------------------------------------------*/
1110 static char *
1111 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1112 {
1113   char *s = buffer;
1114   char *rs;
1115
1116   /* offset is greater than
1117      size then zero */
1118   if (offset > (aop->size - 1) &&
1119       aop->type != AOP_LIT)
1120     return zero;
1121
1122   /* depending on type */
1123   switch (aop->type)
1124     {
1125     case AOP_DUMMY:
1126       return zero;
1127
1128     case AOP_R0:
1129     case AOP_R1:
1130       /* if we need to increment it */
1131       while (offset > aop->coff)
1132         {
1133           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1134           aop->coff++;
1135         }
1136
1137       while (offset < aop->coff)
1138         {
1139           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1140           aop->coff--;
1141         }
1142
1143       aop->coff = offset;
1144       if (aop->paged)
1145         {
1146           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1147           return (dname ? "acc" : "a");
1148         }
1149       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1150       rs = Safe_calloc (1, strlen (s) + 1);
1151       strcpy (rs, s);
1152       return rs;
1153
1154     case AOP_DPTR:
1155       if (aop->code && aop->coff==0 && offset>=1) {
1156         emitcode ("mov", "a,#0x%02x", offset);
1157         emitcode ("movc", "a,@a+dptr");
1158         return (dname ? "acc" : "a");
1159       }
1160
1161       while (offset > aop->coff)
1162         {
1163           emitcode ("inc", "dptr");
1164           aop->coff++;
1165         }
1166
1167       while (offset < aop->coff)
1168         {
1169           emitcode ("lcall", "__decdptr");
1170           aop->coff--;
1171         }
1172
1173       aop->coff = offset;
1174       if (aop->code)
1175         {
1176           emitcode ("clr", "a");
1177           emitcode ("movc", "a,@a+dptr");
1178         }
1179       else
1180         {
1181           emitcode ("movx", "a,@dptr");
1182         }
1183       return (dname ? "acc" : "a");
1184
1185
1186     case AOP_IMMD:
1187       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1188               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1189       } else if (bit16)
1190         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1191       else if (offset)
1192         sprintf (s, "#(%s >> %d)",
1193                  aop->aopu.aop_immd.aop_immd1,
1194                  offset * 8);
1195       else
1196         sprintf (s, "#%s",
1197                  aop->aopu.aop_immd.aop_immd1);
1198       rs = Safe_calloc (1, strlen (s) + 1);
1199       strcpy (rs, s);
1200       return rs;
1201
1202     case AOP_DIR:
1203       if (offset)
1204         sprintf (s, "(%s + %d)",
1205                  aop->aopu.aop_dir,
1206                  offset);
1207       else
1208         sprintf (s, "%s", aop->aopu.aop_dir);
1209       rs = Safe_calloc (1, strlen (s) + 1);
1210       strcpy (rs, s);
1211       return rs;
1212
1213     case AOP_REG:
1214       if (dname)
1215         return aop->aopu.aop_reg[offset]->dname;
1216       else
1217         return aop->aopu.aop_reg[offset]->name;
1218
1219     case AOP_CRY:
1220       emitcode ("clr", "a");
1221       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1222       emitcode ("rlc", "a");
1223       return (dname ? "acc" : "a");
1224
1225     case AOP_ACC:
1226       if (!offset && dname)
1227         return "acc";
1228       return aop->aopu.aop_str[offset];
1229
1230     case AOP_LIT:
1231       return aopLiteral (aop->aopu.aop_lit, offset);
1232
1233     case AOP_STR:
1234       aop->coff = offset;
1235       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1236           dname)
1237         return "acc";
1238
1239       return aop->aopu.aop_str[offset];
1240
1241     }
1242
1243   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1244           "aopget got unsupported aop->type");
1245   exit (1);
1246 }
1247 /*-----------------------------------------------------------------*/
1248 /* aopPut - puts a string for a aop                                */
1249 /*-----------------------------------------------------------------*/
1250 static void
1251 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1252 {
1253   char *d = buffer;
1254
1255   if (aop->size && offset > (aop->size - 1))
1256     {
1257       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1258               "aopPut got offset > aop->size");
1259       exit (1);
1260     }
1261
1262   /* will assign value to value */
1263   /* depending on where it is ofcourse */
1264   switch (aop->type)
1265     {
1266     case AOP_DUMMY:
1267       MOVA (s);         /* read s in case it was volatile */
1268       break;
1269
1270     case AOP_DIR:
1271       if (offset)
1272         sprintf (d, "(%s + %d)",
1273                  aop->aopu.aop_dir, offset);
1274       else
1275         sprintf (d, "%s", aop->aopu.aop_dir);
1276
1277       if (strcmp (d, s) ||
1278           bvolatile)
1279           emitcode ("mov", "%s,%s", d, s);
1280
1281       break;
1282
1283     case AOP_REG:
1284       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1285           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1286         {
1287           if (*s == '@' ||
1288               strcmp (s, "r0") == 0 ||
1289               strcmp (s, "r1") == 0 ||
1290               strcmp (s, "r2") == 0 ||
1291               strcmp (s, "r3") == 0 ||
1292               strcmp (s, "r4") == 0 ||
1293               strcmp (s, "r5") == 0 ||
1294               strcmp (s, "r6") == 0 ||
1295               strcmp (s, "r7") == 0)
1296             emitcode ("mov", "%s,%s",
1297                       aop->aopu.aop_reg[offset]->dname, s);
1298           else
1299             emitcode ("mov", "%s,%s",
1300                       aop->aopu.aop_reg[offset]->name, s);
1301         }
1302       break;
1303
1304     case AOP_DPTR:
1305       if (aop->code)
1306         {
1307           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1308                   "aopPut writing to code space");
1309           exit (1);
1310         }
1311
1312       while (offset > aop->coff)
1313         {
1314           aop->coff++;
1315           emitcode ("inc", "dptr");
1316         }
1317
1318       while (offset < aop->coff)
1319         {
1320           aop->coff--;
1321           emitcode ("lcall", "__decdptr");
1322         }
1323
1324       aop->coff = offset;
1325
1326       /* if not in accumulater */
1327       MOVA (s);
1328
1329       emitcode ("movx", "@dptr,a");
1330       break;
1331
1332     case AOP_R0:
1333     case AOP_R1:
1334       while (offset > aop->coff)
1335         {
1336           aop->coff++;
1337           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1338         }
1339       while (offset < aop->coff)
1340         {
1341           aop->coff--;
1342           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1343         }
1344       aop->coff = offset;
1345
1346       if (aop->paged)
1347         {
1348           MOVA (s);
1349           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1350
1351         }
1352       else if (*s == '@')
1353         {
1354           MOVA (s);
1355           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1356         }
1357       else if (strcmp (s, "r0") == 0 ||
1358                strcmp (s, "r1") == 0 ||
1359                strcmp (s, "r2") == 0 ||
1360                strcmp (s, "r3") == 0 ||
1361                strcmp (s, "r4") == 0 ||
1362                strcmp (s, "r5") == 0 ||
1363                strcmp (s, "r6") == 0 ||
1364                strcmp (s, "r7") == 0)
1365         {
1366           char buffer[10];
1367           sprintf (buffer, "a%s", s);
1368           emitcode ("mov", "@%s,%s",
1369                     aop->aopu.aop_ptr->name, buffer);
1370         }
1371       else
1372         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1373
1374       break;
1375
1376     case AOP_STK:
1377       if (strcmp (s, "a") == 0)
1378         emitcode ("push", "acc");
1379       else
1380         if (*s=='@') {
1381           MOVA(s);
1382           emitcode ("push", "acc");
1383         } else {
1384           emitcode ("push", s);
1385         }
1386
1387       break;
1388
1389     case AOP_CRY:
1390       /* if bit variable */
1391       if (!aop->aopu.aop_dir)
1392         {
1393           emitcode ("clr", "a");
1394           emitcode ("rlc", "a");
1395         }
1396       else
1397         {
1398           if (s == zero)
1399             emitcode ("clr", "%s", aop->aopu.aop_dir);
1400           else if (s == one)
1401             emitcode ("setb", "%s", aop->aopu.aop_dir);
1402           else if (!strcmp (s, "c"))
1403             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1404           else
1405             {
1406               if (strcmp (s, "a"))
1407                 {
1408                   MOVA (s);
1409                 }
1410               {
1411                 /* set C, if a >= 1 */
1412                 emitcode ("add", "a,#0xff");
1413                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1414               }
1415             }
1416         }
1417       break;
1418
1419     case AOP_STR:
1420       aop->coff = offset;
1421       if (strcmp (aop->aopu.aop_str[offset], s) ||
1422           bvolatile)
1423         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1424       break;
1425
1426     case AOP_ACC:
1427       aop->coff = offset;
1428       if (!offset && (strcmp (s, "acc") == 0) &&
1429           !bvolatile)
1430         break;
1431
1432       if (strcmp (aop->aopu.aop_str[offset], s) &&
1433           !bvolatile)
1434         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1435       break;
1436
1437     default:
1438       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1439               "aopPut got unsupported aop->type");
1440       exit (1);
1441     }
1442
1443 }
1444
1445
1446 #if 0
1447 /*-----------------------------------------------------------------*/
1448 /* pointToEnd :- points to the last byte of the operand            */
1449 /*-----------------------------------------------------------------*/
1450 static void
1451 pointToEnd (asmop * aop)
1452 {
1453   int count;
1454   if (!aop)
1455     return;
1456
1457   aop->coff = count = (aop->size - 1);
1458   switch (aop->type)
1459     {
1460     case AOP_R0:
1461     case AOP_R1:
1462       while (count--)
1463         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1464       break;
1465     case AOP_DPTR:
1466       while (count--)
1467         emitcode ("inc", "dptr");
1468       break;
1469     }
1470
1471 }
1472 #endif
1473
1474 /*-----------------------------------------------------------------*/
1475 /* reAdjustPreg - points a register back to where it should        */
1476 /*-----------------------------------------------------------------*/
1477 static void
1478 reAdjustPreg (asmop * aop)
1479 {
1480   if ((aop->coff==0) || aop->size <= 1)
1481     return;
1482
1483   switch (aop->type)
1484     {
1485     case AOP_R0:
1486     case AOP_R1:
1487       while (aop->coff--)
1488         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1489       break;
1490     case AOP_DPTR:
1491       while (aop->coff--)
1492         {
1493           emitcode ("lcall", "__decdptr");
1494         }
1495       break;
1496     }
1497   aop->coff = 0;
1498 }
1499
1500 #define AOP(op) op->aop
1501 #define AOP_TYPE(op) AOP(op)->type
1502 #define AOP_SIZE(op) AOP(op)->size
1503 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1504                        AOP_TYPE(x) == AOP_R0))
1505
1506 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1507                         AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1508
1509 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1510                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1511                       x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1512
1513
1514 /*-----------------------------------------------------------------*/
1515 /* opIsGptr: returns non-zero if the passed operand is       */
1516 /* a generic pointer type.             */
1517 /*-----------------------------------------------------------------*/
1518 static int
1519 opIsGptr (operand * op)
1520 {
1521   sym_link *type = operandType (op);
1522
1523   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1524     {
1525       return 1;
1526     }
1527   return 0;
1528 }
1529
1530 /*-----------------------------------------------------------------*/
1531 /* getDataSize - get the operand data size                         */
1532 /*-----------------------------------------------------------------*/
1533 static int
1534 getDataSize (operand * op)
1535 {
1536   int size;
1537   size = AOP_SIZE (op);
1538   if (size == GPTRSIZE)
1539     {
1540       sym_link *type = operandType (op);
1541       if (IS_GENPTR (type))
1542         {
1543           /* generic pointer; arithmetic operations
1544            * should ignore the high byte (pointer type).
1545            */
1546           size--;
1547         }
1548     }
1549   return size;
1550 }
1551
1552 /*-----------------------------------------------------------------*/
1553 /* outAcc - output Acc                                             */
1554 /*-----------------------------------------------------------------*/
1555 static void
1556 outAcc (operand * result)
1557 {
1558   int size, offset;
1559   size = getDataSize (result);
1560   if (size)
1561     {
1562       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1563       size--;
1564       offset = 1;
1565       /* unsigned or positive */
1566       while (size--)
1567         {
1568           aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1569         }
1570     }
1571 }
1572
1573 /*-----------------------------------------------------------------*/
1574 /* outBitC - output a bit C                                        */
1575 /*-----------------------------------------------------------------*/
1576 static void
1577 outBitC (operand * result)
1578 {
1579   /* if the result is bit */
1580   if (AOP_TYPE (result) == AOP_CRY)
1581     aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1582   else
1583     {
1584       emitcode ("clr", "a");
1585       emitcode ("rlc", "a");
1586       outAcc (result);
1587     }
1588 }
1589
1590 /*-----------------------------------------------------------------*/
1591 /* toBoolean - emit code for orl a,operator(sizeop)                */
1592 /*-----------------------------------------------------------------*/
1593 static void
1594 toBoolean (operand * oper)
1595 {
1596   int size = AOP_SIZE (oper) - 1;
1597   int offset = 1;
1598   bool AccUsed = FALSE;
1599   bool pushedB;
1600
1601   while (!AccUsed && size--)
1602     {
1603       AccUsed |= aopGetUsesAcc(AOP (oper), offset++);
1604     }
1605
1606   size = AOP_SIZE (oper) - 1;
1607   offset = 1;
1608   MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1609   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1610     {
1611       pushedB = pushB ();
1612       emitcode("mov", "b,a");
1613       while (size--)
1614         {
1615           MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1616           emitcode ("orl", "b,a");
1617         }
1618       popB (pushedB);
1619     }
1620   else
1621     {
1622       while (size--)
1623         {
1624           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1625         }
1626     }
1627 }
1628
1629
1630 /*-----------------------------------------------------------------*/
1631 /* genNot - generate code for ! operation                          */
1632 /*-----------------------------------------------------------------*/
1633 static void
1634 genNot (iCode * ic)
1635 {
1636   symbol *tlbl;
1637
1638   D(emitcode (";     genNot",""));
1639
1640   /* assign asmOps to operand & result */
1641   aopOp (IC_LEFT (ic), ic, FALSE);
1642   aopOp (IC_RESULT (ic), ic, TRUE);
1643
1644   /* if in bit space then a special case */
1645   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1646     {
1647       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1648       emitcode ("cpl", "c");
1649       outBitC (IC_RESULT (ic));
1650       goto release;
1651     }
1652
1653   toBoolean (IC_LEFT (ic));
1654
1655   tlbl = newiTempLabel (NULL);
1656   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1657   emitcode ("", "%05d$:", tlbl->key + 100);
1658   outBitC (IC_RESULT (ic));
1659
1660 release:
1661   /* release the aops */
1662   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1663   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1664 }
1665
1666
1667 /*-----------------------------------------------------------------*/
1668 /* genCpl - generate code for complement                           */
1669 /*-----------------------------------------------------------------*/
1670 static void
1671 genCpl (iCode * ic)
1672 {
1673   int offset = 0;
1674   int size;
1675   symbol *tlbl;
1676   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1677
1678   D(emitcode (";", "genCpl"));
1679
1680   /* assign asmOps to operand & result */
1681   aopOp (IC_LEFT (ic), ic, FALSE);
1682   aopOp (IC_RESULT (ic), ic, TRUE);
1683
1684   /* special case if in bit space */
1685   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1686     {
1687       char *l;
1688
1689       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1690           (SPEC_USIGN (letype) && IS_CHAR (letype)))
1691         {
1692           /* promotion rules are responsible for this strange result:
1693              bit -> int -> ~int -> bit
1694              uchar -> int -> ~int -> bit
1695           */
1696           werror(W_COMPLEMENT);
1697           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1698           goto release;
1699         }
1700
1701       tlbl=newiTempLabel(NULL);
1702       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE);
1703       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1704           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1705           IS_AOP_PREG (IC_LEFT (ic)))
1706         {
1707           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1708         }
1709       else
1710         {
1711           MOVA (l);
1712           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1713         }
1714       emitcode ("", "%05d$:", tlbl->key + 100);
1715       outBitC (IC_RESULT(ic));
1716       goto release;
1717     }
1718
1719   size = AOP_SIZE (IC_RESULT (ic));
1720   while (size--)
1721     {
1722       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1723       MOVA (l);
1724       emitcode ("cpl", "a");
1725       aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1726     }
1727
1728
1729 release:
1730   /* release the aops */
1731   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1732   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1733 }
1734
1735 /*-----------------------------------------------------------------*/
1736 /* genUminusFloat - unary minus for floating points                */
1737 /*-----------------------------------------------------------------*/
1738 static void
1739 genUminusFloat (operand * op, operand * result)
1740 {
1741   int size, offset = 0;
1742   char *l;
1743
1744   D(emitcode (";     genUminusFloat",""));
1745
1746   /* for this we just copy and then flip the bit */
1747
1748   size = AOP_SIZE (op) - 1;
1749
1750   while (size--)
1751     {
1752       aopPut (AOP (result),
1753               aopGet (AOP (op), offset, FALSE, FALSE),
1754               offset,
1755               isOperandVolatile (result, FALSE));
1756       offset++;
1757     }
1758
1759   l = aopGet (AOP (op), offset, FALSE, FALSE);
1760
1761   MOVA (l);
1762
1763   emitcode ("cpl", "acc.7");
1764   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1765 }
1766
1767 /*-----------------------------------------------------------------*/
1768 /* genUminus - unary minus code generation                         */
1769 /*-----------------------------------------------------------------*/
1770 static void
1771 genUminus (iCode * ic)
1772 {
1773   int offset, size;
1774   sym_link *optype, *rtype;
1775
1776
1777   D(emitcode (";     genUminus",""));
1778
1779   /* assign asmops */
1780   aopOp (IC_LEFT (ic), ic, FALSE);
1781   aopOp (IC_RESULT (ic), ic, TRUE);
1782
1783   /* if both in bit space then special
1784      case */
1785   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1786       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1787     {
1788
1789       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1790       emitcode ("cpl", "c");
1791       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1792       goto release;
1793     }
1794
1795   optype = operandType (IC_LEFT (ic));
1796   rtype = operandType (IC_RESULT (ic));
1797
1798   /* if float then do float stuff */
1799   if (IS_FLOAT (optype))
1800     {
1801       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1802       goto release;
1803     }
1804
1805   /* otherwise subtract from zero */
1806   size = AOP_SIZE (IC_LEFT (ic));
1807   offset = 0;
1808   //CLRC ;
1809   while (size--)
1810     {
1811       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1812       if (!strcmp (l, "a"))
1813         {
1814           if (offset == 0)
1815             SETC;
1816           emitcode ("cpl", "a");
1817           emitcode ("addc", "a,#0");
1818         }
1819       else
1820         {
1821           if (offset == 0)
1822             CLRC;
1823           emitcode ("clr", "a");
1824           emitcode ("subb", "a,%s", l);
1825         }
1826       aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1827     }
1828
1829   /* if any remaining bytes in the result */
1830   /* we just need to propagate the sign   */
1831   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1832     {
1833       emitcode ("rlc", "a");
1834       emitcode ("subb", "a,acc");
1835       while (size--)
1836         aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1837     }
1838
1839 release:
1840   /* release the aops */
1841   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* saveRegisters - will look for a call and save the registers     */
1847 /*-----------------------------------------------------------------*/
1848 static void
1849 saveRegisters (iCode * lic)
1850 {
1851   int i;
1852   iCode *ic;
1853   bitVect *rsave;
1854
1855   /* look for call */
1856   for (ic = lic; ic; ic = ic->next)
1857     if (ic->op == CALL || ic->op == PCALL)
1858       break;
1859
1860   if (!ic)
1861     {
1862       fprintf (stderr, "found parameter push with no function call\n");
1863       return;
1864     }
1865
1866   /* if the registers have been saved already or don't need to be then
1867      do nothing */
1868   if (ic->regsSaved)
1869     return;
1870   if (IS_SYMOP(IC_LEFT(ic)) &&
1871       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1872        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1873     return;
1874
1875   /* save the registers in use at this time but skip the
1876      ones for the result */
1877   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1878                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1879
1880   ic->regsSaved = 1;
1881   if (options.useXstack)
1882     {
1883       int count = bitVectnBitsOn (rsave);
1884
1885       if (count == 1)
1886         {
1887           i = bitVectFirstBit (rsave);
1888           emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1889           emitcode ("mov", "r0,%s", spname);
1890           emitcode ("inc", "%s", spname);// allocate before use
1891           emitcode ("movx", "@r0,a");
1892           if (bitVectBitValue (rsave, R0_IDX))
1893             emitcode ("mov", "r0,a");
1894         }
1895       else if (count != 0)
1896         {
1897           if (bitVectBitValue (rsave, R0_IDX))
1898             {
1899               emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1900             }
1901           emitcode ("mov", "r0,%s", spname);
1902           MOVA ("r0");
1903           emitcode ("add", "a,#%d", count);
1904           emitcode ("mov", "%s,a", spname);
1905           for (i = 0; i < mcs51_nRegs; i++)
1906             {
1907               if (bitVectBitValue (rsave, i))
1908                 {
1909                   if (i == R0_IDX)
1910                     {
1911                       emitcode ("pop", "acc");
1912                       emitcode ("push", "acc");
1913                     }
1914                   else
1915                     {
1916                       emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1917                     }
1918                   emitcode ("movx", "@r0,a");
1919                   if (--count)
1920                     {
1921                       emitcode ("inc", "r0");
1922                     }
1923                 }
1924             }
1925           if (bitVectBitValue (rsave, R0_IDX))
1926             {
1927               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1928             }
1929         }
1930     }
1931   else
1932     for (i = 0; i < mcs51_nRegs; i++)
1933       {
1934         if (bitVectBitValue (rsave, i))
1935           emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1936       }
1937 }
1938
1939 /*-----------------------------------------------------------------*/
1940 /* unsaveRegisters - pop the pushed registers                      */
1941 /*-----------------------------------------------------------------*/
1942 static void
1943 unsaveRegisters (iCode * ic)
1944 {
1945   int i;
1946   bitVect *rsave;
1947
1948   /* restore the registers in use at this time but skip the
1949      ones for the result */
1950   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1951                          mcs51_rUmaskForOp (IC_RESULT(ic)));
1952
1953   if (options.useXstack)
1954     {
1955       int count = bitVectnBitsOn (rsave);
1956
1957       if (count == 1)
1958         {
1959           emitcode ("mov", "r0,%s", spname);
1960           emitcode ("dec", "r0");
1961           emitcode ("movx", "a,@r0");
1962           i = bitVectFirstBit (rsave);
1963           emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1964           emitcode ("dec", "%s", spname);
1965         }
1966       else
1967         {
1968           emitcode ("mov", "r0,%s", spname);
1969           for (i = mcs51_nRegs; i >= 0; i--)
1970             {
1971               if (bitVectBitValue (rsave, i))
1972                 {
1973                   emitcode ("dec", "r0");
1974                   emitcode ("movx", "a,@r0");
1975                   if (i != R0_IDX)
1976                     emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1977                 }
1978             }
1979           emitcode ("mov", "%s,r0", spname);
1980           if (bitVectBitValue (rsave, R0_IDX))
1981             {
1982               emitcode ("mov", "r0,a");
1983             }
1984         }
1985     }
1986   else
1987     for (i = mcs51_nRegs; i >= 0; i--)
1988       {
1989         if (bitVectBitValue (rsave, i))
1990           emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1991       }
1992 }
1993
1994
1995 /*-----------------------------------------------------------------*/
1996 /* pushSide -                */
1997 /*-----------------------------------------------------------------*/
1998 static void
1999 pushSide (operand * oper, int size)
2000 {
2001   int offset = 0;
2002   while (size--)
2003     {
2004       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
2005       if (AOP_TYPE (oper) != AOP_REG &&
2006           AOP_TYPE (oper) != AOP_DIR &&
2007           strcmp (l, "a"))
2008         {
2009           MOVA (l);
2010           emitcode ("push", "acc");
2011         }
2012       else
2013           emitcode ("push", "%s", l);
2014         }
2015     }
2016
2017 /*-----------------------------------------------------------------*/
2018 /* assignResultValue -               */
2019 /*-----------------------------------------------------------------*/
2020 static void
2021 assignResultValue (operand * oper)
2022 {
2023   int offset = 0;
2024   int size = AOP_SIZE (oper);
2025   while (size--)
2026     {
2027       aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2028       offset++;
2029     }
2030 }
2031
2032
2033 /*-----------------------------------------------------------------*/
2034 /* genXpush - pushes onto the external stack                       */
2035 /*-----------------------------------------------------------------*/
2036 static void
2037 genXpush (iCode * ic)
2038 {
2039   asmop *aop = newAsmop (0);
2040   regs *r;
2041   int size, offset = 0;
2042
2043   D(emitcode (";     genXpush",""));
2044
2045   aopOp (IC_LEFT (ic), ic, FALSE);
2046   r = getFreePtr (ic, &aop, FALSE);
2047
2048   size = AOP_SIZE (IC_LEFT (ic));
2049
2050   if (size == 1)
2051     {
2052       MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2053       emitcode ("mov", "%s,%s", r->name, spname);
2054       emitcode ("inc", "%s", spname); // allocate space first
2055       emitcode ("movx", "@%s,a", r->name);
2056     }
2057   else
2058     {
2059       // allocate space first
2060       emitcode ("mov", "%s,%s", r->name, spname);
2061       MOVA (r->name);
2062       emitcode ("add", "a,#%d", size);
2063       emitcode ("mov", "%s,a", spname);
2064
2065       while (size--)
2066         {
2067           MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2068           emitcode ("movx", "@%s,a", r->name);
2069           emitcode ("inc", "%s", r->name);
2070         }
2071     }
2072
2073   freeAsmop (NULL, aop, ic, TRUE);
2074   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2075 }
2076
2077 /*-----------------------------------------------------------------*/
2078 /* genIpush - genrate code for pushing this gets a little complex  */
2079 /*-----------------------------------------------------------------*/
2080 static void
2081 genIpush (iCode * ic)
2082 {
2083   int size, offset = 0;
2084   char *l;
2085
2086   D(emitcode (";     genIpush",""));
2087
2088   /* if this is not a parm push : ie. it is spill push
2089      and spill push is always done on the local stack */
2090   if (!ic->parmPush)
2091     {
2092
2093       /* and the item is spilt then do nothing */
2094       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2095         return;
2096
2097       aopOp (IC_LEFT (ic), ic, FALSE);
2098       size = AOP_SIZE (IC_LEFT (ic));
2099       /* push it on the stack */
2100       while (size--)
2101         {
2102           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2103           if (*l == '#')
2104             {
2105               MOVA (l);
2106               l = "acc";
2107             }
2108           emitcode ("push", "%s", l);
2109         }
2110       return;
2111     }
2112
2113   /* this is a paramter push: in this case we call
2114      the routine to find the call and save those
2115      registers that need to be saved */
2116   saveRegisters (ic);
2117
2118   /* if use external stack then call the external
2119      stack pushing routine */
2120   if (options.useXstack)
2121     {
2122       genXpush (ic);
2123       return;
2124     }
2125
2126   /* then do the push */
2127   aopOp (IC_LEFT (ic), ic, FALSE);
2128
2129   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2130   size = AOP_SIZE (IC_LEFT (ic));
2131
2132   while (size--)
2133     {
2134       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2135       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2136           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2137           strcmp (l, "a"))
2138         {
2139           MOVA (l);
2140           emitcode ("push", "acc");
2141         }
2142       else
2143           emitcode ("push", "%s", l);
2144     }
2145
2146   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2147 }
2148
2149 /*-----------------------------------------------------------------*/
2150 /* genIpop - recover the registers: can happen only for spilling   */
2151 /*-----------------------------------------------------------------*/
2152 static void
2153 genIpop (iCode * ic)
2154 {
2155   int size, offset;
2156
2157   D(emitcode (";     genIpop",""));
2158
2159   /* if the temp was not pushed then */
2160   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2161     return;
2162
2163   aopOp (IC_LEFT (ic), ic, FALSE);
2164   size = AOP_SIZE (IC_LEFT (ic));
2165   offset = (size - 1);
2166   while (size--)
2167     emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2168                                    FALSE, TRUE));
2169
2170   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2171 }
2172
2173 /*-----------------------------------------------------------------*/
2174 /* saveRBank - saves an entire register bank on the stack          */
2175 /*-----------------------------------------------------------------*/
2176 static void
2177 saveRBank (int bank, iCode * ic, bool pushPsw)
2178 {
2179   int i;
2180   int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2181   asmop *aop = NULL;
2182   regs *r = NULL;
2183
2184   if (options.useXstack)
2185     {
2186       if (!ic)
2187       {
2188           /* Assume r0 is available for use. */
2189           r = mcs51_regWithIdx (R0_IDX);;
2190       }
2191       else
2192       {
2193           aop = newAsmop (0);
2194           r = getFreePtr (ic, &aop, FALSE);
2195       }
2196       // allocate space first
2197       emitcode ("mov", "%s,%s", r->name, spname);
2198       MOVA (r->name);
2199       emitcode ("add", "a,#%d", count);
2200       emitcode ("mov", "%s,a", spname);
2201     }
2202
2203   for (i = 0; i < mcs51_nRegs; i++)
2204     {
2205       if (options.useXstack)
2206         {
2207           emitcode ("mov", "a,(%s+%d)",
2208                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2209           emitcode ("movx", "@%s,a", r->name);
2210           if (--count)
2211             emitcode ("inc", "%s", r->name);
2212         }
2213       else
2214         emitcode ("push", "(%s+%d)",
2215                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2216     }
2217
2218   if (pushPsw)
2219     {
2220       if (options.useXstack)
2221         {
2222           emitcode ("mov", "a,psw");
2223           emitcode ("movx", "@%s,a", r->name);
2224
2225         }
2226       else
2227         {
2228           emitcode ("push", "psw");
2229         }
2230
2231       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2232     }
2233
2234   if (aop)
2235     {
2236       freeAsmop (NULL, aop, ic, TRUE);
2237     }
2238
2239   if (ic)
2240   {
2241     ic->bankSaved = 1;
2242   }
2243 }
2244
2245 /*-----------------------------------------------------------------*/
2246 /* unsaveRBank - restores the register bank from stack             */
2247 /*-----------------------------------------------------------------*/
2248 static void
2249 unsaveRBank (int bank, iCode * ic, bool popPsw)
2250 {
2251   int i;
2252   asmop *aop = NULL;
2253   regs *r = NULL;
2254
2255   if (options.useXstack)
2256     {
2257       if (!ic)
2258         {
2259           /* Assume r0 is available for use. */
2260           r = mcs51_regWithIdx (R0_IDX);;
2261         }
2262       else
2263         {
2264           aop = newAsmop (0);
2265           r = getFreePtr (ic, &aop, FALSE);
2266         }
2267       emitcode ("mov", "%s,%s", r->name, spname);
2268     }
2269
2270   if (popPsw)
2271     {
2272       if (options.useXstack)
2273         {
2274           emitcode ("dec", "%s", r->name);
2275           emitcode ("movx", "a,@%s", r->name);
2276           emitcode ("mov", "psw,a");
2277         }
2278       else
2279         {
2280           emitcode ("pop", "psw");
2281         }
2282     }
2283
2284   for (i = (mcs51_nRegs - 1); i >= 0; i--)
2285     {
2286       if (options.useXstack)
2287         {
2288           emitcode ("dec", "%s", r->name);
2289           emitcode ("movx", "a,@%s", r->name);
2290           emitcode ("mov", "(%s+%d),a",
2291                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2292         }
2293       else
2294         {
2295           emitcode ("pop", "(%s+%d)",
2296                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2297         }
2298     }
2299
2300   if (options.useXstack)
2301     {
2302       emitcode ("mov", "%s,%s", spname, r->name);
2303     }
2304
2305   if (aop)
2306     {
2307       freeAsmop (NULL, aop, ic, TRUE);
2308     }
2309 }
2310
2311 /*-----------------------------------------------------------------*/
2312 /* genSend - gen code for SEND                                     */
2313 /*-----------------------------------------------------------------*/
2314 static void genSend(set *sendSet)
2315 {
2316     iCode *sic;
2317     int rb1_count = 0 ;
2318
2319     for (sic = setFirstItem (sendSet); sic;
2320          sic = setNextItem (sendSet)) {
2321           int size, offset = 0;
2322           aopOp (IC_LEFT (sic), sic, FALSE);
2323           size = AOP_SIZE (IC_LEFT (sic));
2324
2325           if (sic->argreg == 1) {
2326               while (size--) {
2327                   char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2328                                     FALSE, FALSE);
2329                   if (strcmp (l, fReturn[offset]))
2330                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2331                   offset++;
2332               }
2333               rb1_count = 0;
2334           } else {
2335               while (size--) {
2336                   emitcode ("mov","b1_%d,%s",rb1_count++,
2337                             aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2338               }
2339           }
2340           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2341     }
2342 }
2343
2344 /*-----------------------------------------------------------------*/
2345 /* genCall - generates a call statement                            */
2346 /*-----------------------------------------------------------------*/
2347 static void
2348 genCall (iCode * ic)
2349 {
2350   sym_link *dtype;
2351 //  bool restoreBank = FALSE;
2352   bool swapBanks = FALSE;
2353
2354   D(emitcode(";     genCall",""));
2355
2356   dtype = operandType (IC_LEFT (ic));
2357   /* if send set is not empty then assign */
2358   if (_G.sendSet)
2359     {
2360         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2361             genSend(reverseSet(_G.sendSet));
2362         } else {
2363             genSend(_G.sendSet);
2364         }
2365
2366       _G.sendSet = NULL;
2367     }
2368
2369   /* if we are calling a not _naked function that is not using
2370      the same register bank then we need to save the
2371      destination registers on the stack */
2372   dtype = operandType (IC_LEFT (ic));
2373   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2374       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2375        !IFFUNC_ISISR (dtype))
2376   {
2377       swapBanks = TRUE;
2378   }
2379
2380   /* if caller saves & we have not saved then */
2381   if (!ic->regsSaved)
2382       saveRegisters (ic);
2383
2384   if (swapBanks)
2385   {
2386         emitcode ("mov", "psw,#0x%02x",
2387            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2388   }
2389
2390   /* make the call */
2391   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2392                             OP_SYMBOL (IC_LEFT (ic))->rname :
2393                             OP_SYMBOL (IC_LEFT (ic))->name));
2394
2395   if (swapBanks)
2396   {
2397        emitcode ("mov", "psw,#0x%02x",
2398           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2399   }
2400
2401   /* if we need assign a result value */
2402   if ((IS_ITEMP (IC_RESULT (ic)) &&
2403        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2404         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2405         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2406       IS_TRUE_SYMOP (IC_RESULT (ic)))
2407     {
2408
2409       _G.accInUse++;
2410       aopOp (IC_RESULT (ic), ic, FALSE);
2411       _G.accInUse--;
2412
2413       assignResultValue (IC_RESULT (ic));
2414
2415       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2416     }
2417
2418   /* adjust the stack for parameters if
2419      required */
2420   if (ic->parmBytes)
2421     {
2422       int i;
2423       if (ic->parmBytes > 3)
2424         {
2425           emitcode ("mov", "a,%s", spname);
2426           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2427           emitcode ("mov", "%s,a", spname);
2428         }
2429       else
2430         for (i = 0; i < ic->parmBytes; i++)
2431           emitcode ("dec", "%s", spname);
2432     }
2433
2434   /* if we hade saved some registers then unsave them */
2435   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2436     unsaveRegisters (ic);
2437
2438 //  /* if register bank was saved then pop them */
2439 //  if (restoreBank)
2440 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2441 }
2442
2443 /*-----------------------------------------------------------------*/
2444 /* -10l - generates a call by pointer statement                */
2445 /*-----------------------------------------------------------------*/
2446 static void
2447 genPcall (iCode * ic)
2448 {
2449   sym_link *dtype;
2450   symbol *rlbl = newiTempLabel (NULL);
2451 //  bool restoreBank=FALSE;
2452   bool swapBanks = FALSE;
2453
2454   D(emitcode(";     genPCall",""));
2455
2456   /* if caller saves & we have not saved then */
2457   if (!ic->regsSaved)
2458     saveRegisters (ic);
2459
2460   /* if we are calling a not _naked function that is not using
2461      the same register bank then we need to save the
2462      destination registers on the stack */
2463   dtype = operandType (IC_LEFT (ic))->next;
2464   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2465       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2466       !IFFUNC_ISISR (dtype))
2467   {
2468 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2469 //    restoreBank=TRUE;
2470       swapBanks = TRUE;
2471       // need caution message to user here
2472   }
2473
2474   /* push the return address on to the stack */
2475   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2476   emitcode ("push", "acc");
2477   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2478   emitcode ("push", "acc");
2479
2480   /* now push the calling address */
2481   aopOp (IC_LEFT (ic), ic, FALSE);
2482
2483   pushSide (IC_LEFT (ic), FPTRSIZE);
2484
2485   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2486
2487   /* if send set is not empty the assign */
2488   if (_G.sendSet)
2489     {
2490         genSend(reverseSet(_G.sendSet));
2491         _G.sendSet = NULL;
2492     }
2493
2494   if (swapBanks)
2495   {
2496         emitcode ("mov", "psw,#0x%02x",
2497            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2498   }
2499
2500   /* make the call */
2501   emitcode ("ret", "");
2502   emitcode ("", "%05d$:", (rlbl->key + 100));
2503
2504
2505   if (swapBanks)
2506   {
2507        emitcode ("mov", "psw,#0x%02x",
2508           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2509   }
2510
2511   /* if we need assign a result value */
2512   if ((IS_ITEMP (IC_RESULT (ic)) &&
2513        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2514         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2515       IS_TRUE_SYMOP (IC_RESULT (ic)))
2516     {
2517
2518       _G.accInUse++;
2519       aopOp (IC_RESULT (ic), ic, FALSE);
2520       _G.accInUse--;
2521
2522       assignResultValue (IC_RESULT (ic));
2523
2524       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2525     }
2526
2527   /* adjust the stack for parameters if
2528      required */
2529   if (ic->parmBytes)
2530     {
2531       int i;
2532       if (ic->parmBytes > 3)
2533         {
2534           emitcode ("mov", "a,%s", spname);
2535           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2536           emitcode ("mov", "%s,a", spname);
2537         }
2538       else
2539         for (i = 0; i < ic->parmBytes; i++)
2540           emitcode ("dec", "%s", spname);
2541
2542     }
2543
2544 //  /* if register bank was saved then unsave them */
2545 //  if (restoreBank)
2546 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2547
2548   /* if we hade saved some registers then
2549      unsave them */
2550   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2551     unsaveRegisters (ic);
2552 }
2553
2554 /*-----------------------------------------------------------------*/
2555 /* resultRemat - result  is rematerializable                       */
2556 /*-----------------------------------------------------------------*/
2557 static int
2558 resultRemat (iCode * ic)
2559 {
2560   if (SKIP_IC (ic) || ic->op == IFX)
2561     return 0;
2562
2563   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2564     {
2565       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2566       if (sym->remat && !POINTER_SET (ic))
2567         return 1;
2568     }
2569
2570   return 0;
2571 }
2572
2573 #if defined(__BORLANDC__) || defined(_MSC_VER)
2574 #define STRCASECMP stricmp
2575 #else
2576 #define STRCASECMP strcasecmp
2577 #endif
2578
2579 /*-----------------------------------------------------------------*/
2580 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2581 /*-----------------------------------------------------------------*/
2582 static int
2583 regsCmp(void *p1, void *p2)
2584 {
2585   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2586 }
2587
2588 static bool
2589 inExcludeList (char *s)
2590 {
2591   const char *p = setFirstItem(options.excludeRegsSet);
2592
2593   if (p == NULL || STRCASECMP(p, "none") == 0)
2594     return FALSE;
2595
2596
2597   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2598 }
2599
2600 /*-----------------------------------------------------------------*/
2601 /* genFunction - generated code for function entry                 */
2602 /*-----------------------------------------------------------------*/
2603 static void
2604 genFunction (iCode * ic)
2605 {
2606   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
2607   sym_link *ftype;
2608   bool     switchedPSW = FALSE;
2609   int      calleesaves_saved_register = -1;
2610   int      stackAdjust = sym->stack;
2611   int      accIsFree = sym->recvSize < 4;
2612   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2613   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2614
2615   _G.nRegsSaved = 0;
2616   /* create the function header */
2617   emitcode (";", "-----------------------------------------");
2618   emitcode (";", " function %s", sym->name);
2619   emitcode (";", "-----------------------------------------");
2620
2621   emitcode ("", "%s:", sym->rname);
2622   ftype = operandType (IC_LEFT (ic));
2623   _G.currentFunc = sym;
2624
2625   if (IFFUNC_ISNAKED(ftype))
2626   {
2627       emitcode(";", "naked function: no prologue.");
2628       return;
2629   }
2630
2631   /* here we need to generate the equates for the
2632      register bank if required */
2633   if (FUNC_REGBANK (ftype) != rbank)
2634     {
2635       int i;
2636
2637       rbank = FUNC_REGBANK (ftype);
2638       for (i = 0; i < mcs51_nRegs; i++)
2639         {
2640           if (strcmp (regs8051[i].base, "0") == 0)
2641             emitcode ("", "%s = 0x%02x",
2642                       regs8051[i].dname,
2643                       8 * rbank + regs8051[i].offset);
2644           else
2645             emitcode ("", "%s = %s + 0x%02x",
2646                       regs8051[i].dname,
2647                       regs8051[i].base,
2648                       8 * rbank + regs8051[i].offset);
2649         }
2650     }
2651
2652   /* if this is an interrupt service routine then
2653      save acc, b, dpl, dph  */
2654   if (IFFUNC_ISISR (sym->type))
2655     {
2656
2657       if (!inExcludeList ("acc"))
2658         emitcode ("push", "acc");
2659       if (!inExcludeList ("b"))
2660         emitcode ("push", "b");
2661       if (!inExcludeList ("dpl"))
2662         emitcode ("push", "dpl");
2663       if (!inExcludeList ("dph"))
2664         emitcode ("push", "dph");
2665       /* if this isr has no bank i.e. is going to
2666          run with bank 0 , then we need to save more
2667          registers :-) */
2668       if (!FUNC_REGBANK (sym->type))
2669         {
2670
2671           /* if this function does not call any other
2672              function then we can be economical and
2673              save only those registers that are used */
2674           if (!IFFUNC_HASFCALL(sym->type))
2675             {
2676               int i;
2677
2678               /* if any registers used */
2679               if (sym->regsUsed)
2680                 {
2681                   /* save the registers used */
2682                   for (i = 0; i < sym->regsUsed->size; i++)
2683                     {
2684                       if (bitVectBitValue (sym->regsUsed, i))
2685                         emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2686                     }
2687                 }
2688             }
2689           else
2690             {
2691
2692               /* this function has a function call. We cannot
2693                  determines register usage so we will have to push the
2694                  entire bank */
2695                 saveRBank (0, ic, FALSE);
2696                 if (options.parms_in_bank1) {
2697                     int i;
2698                     for (i=0; i < 8 ; i++ ) {
2699                         emitcode ("push","%s",rb1regs[i]);
2700                     }
2701                 }
2702             }
2703         }
2704         else
2705         {
2706             /* This ISR uses a non-zero bank.
2707              *
2708              * We assume that the bank is available for our
2709              * exclusive use.
2710              *
2711              * However, if this ISR calls a function which uses some
2712              * other bank, we must save that bank entirely.
2713              */
2714             unsigned long banksToSave = 0;
2715
2716             if (IFFUNC_HASFCALL(sym->type))
2717             {
2718
2719 #define MAX_REGISTER_BANKS 4
2720
2721                 iCode *i;
2722                 int ix;
2723
2724                 for (i = ic; i; i = i->next)
2725                 {
2726                     if (i->op == ENDFUNCTION)
2727                     {
2728                         /* we got to the end OK. */
2729                         break;
2730                     }
2731
2732                     if (i->op == CALL)
2733                     {
2734                         sym_link *dtype;
2735
2736                         dtype = operandType (IC_LEFT(i));
2737                         if (dtype
2738                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2739                         {
2740                              /* Mark this bank for saving. */
2741                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2742                              {
2743                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2744                              }
2745                              else
2746                              {
2747                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2748                              }
2749
2750                              /* And note that we don't need to do it in
2751                               * genCall.
2752                               */
2753                              i->bankSaved = 1;
2754                         }
2755                     }
2756                     if (i->op == PCALL)
2757                     {
2758                         /* This is a mess; we have no idea what
2759                          * register bank the called function might
2760                          * use.
2761                          *
2762                          * The only thing I can think of to do is
2763                          * throw a warning and hope.
2764                          */
2765                         werror(W_FUNCPTR_IN_USING_ISR);
2766                     }
2767                 }
2768
2769                 if (banksToSave && options.useXstack)
2770                 {
2771                     /* Since we aren't passing it an ic,
2772                      * saveRBank will assume r0 is available to abuse.
2773                      *
2774                      * So switch to our (trashable) bank now, so
2775                      * the caller's R0 isn't trashed.
2776                      */
2777                     emitcode ("push", "psw");
2778                     emitcode ("mov", "psw,#0x%02x",
2779                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2780                     switchedPSW = TRUE;
2781                 }
2782
2783                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2784                 {
2785                      if (banksToSave & (1 << ix))
2786                      {
2787                          saveRBank(ix, NULL, FALSE);
2788                      }
2789                 }
2790             }
2791             // TODO: this needs a closer look
2792             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2793         }
2794
2795       /* Set the register bank to the desired value if nothing else */
2796       /* has done so yet. */
2797       if (!switchedPSW)
2798         {
2799           emitcode ("push", "psw");
2800           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2801         }
2802     }
2803   else
2804     {
2805       /* This is a non-ISR function. The caller has already switched register */
2806       /* banks, if necessary, so just handle the callee-saves option. */
2807
2808       /* if callee-save to be used for this function
2809          then save the registers being used in this function */
2810       if (IFFUNC_CALLEESAVES(sym->type))
2811         {
2812           int i;
2813
2814           /* if any registers used */
2815           if (sym->regsUsed)
2816             {
2817               /* save the registers used */
2818               for (i = 0; i < sym->regsUsed->size; i++)
2819                 {
2820                   if (bitVectBitValue (sym->regsUsed, i))
2821                     {
2822                       /* remember one saved register for later usage */
2823                       if (calleesaves_saved_register < 0)
2824                         calleesaves_saved_register = i;
2825                       emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2826                       _G.nRegsSaved++;
2827                     }
2828                 }
2829             }
2830         }
2831     }
2832
2833
2834   if (fReentrant)
2835     {
2836       if (options.useXstack)
2837         {
2838           emitcode ("mov", "r0,%s", spname);
2839           emitcode ("inc", "%s", spname);
2840           emitcode ("xch", "a,_bp");
2841           emitcode ("movx", "@r0,a");
2842           emitcode ("inc", "r0");
2843           emitcode ("mov", "a,r0");
2844           emitcode ("xch", "a,_bp");
2845         }
2846       else
2847         {
2848           /* set up the stack */
2849           emitcode ("push", "_bp");     /* save the callers stack  */
2850           emitcode ("mov", "_bp,%s", spname);
2851         }
2852     }
2853
2854   /* For some cases it is worthwhile to perform a RECEIVE iCode */
2855   /* before setting up the stack frame completely. */
2856   if (ric && ric->argreg == 1 && IC_RESULT (ric))
2857     {
2858       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2859
2860       if (rsym->isitmp)
2861         {
2862           if (rsym && rsym->regType == REG_CND)
2863             rsym = NULL;
2864           if (rsym && (rsym->accuse || rsym->ruonly))
2865             rsym = NULL;
2866           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2867             rsym = rsym->usl.spillLoc;
2868         }
2869
2870       /* If the RECEIVE operand immediately spills to the first entry on the */
2871       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2872       /* rather than the usual @r0/r1 machinations. */
2873       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2874         {
2875           int ofs;
2876
2877           _G.current_iCode = ric;
2878           D(emitcode (";     genReceive",""));
2879           for (ofs=0; ofs < sym->recvSize; ofs++)
2880             {
2881               if (!strcmp (fReturn[ofs], "a"))
2882                 emitcode ("push", "acc");
2883               else
2884                 emitcode ("push", fReturn[ofs]);
2885             }
2886           stackAdjust -= sym->recvSize;
2887           if (stackAdjust<0)
2888             {
2889               assert (stackAdjust>=0);
2890               stackAdjust = 0;
2891             }
2892           _G.current_iCode = ic;
2893           ric->generated = 1;
2894           accIsFree = 1;
2895         }
2896       /* If the RECEIVE operand is 4 registers, we can do the moves now */
2897       /* to free up the accumulator. */
2898       else if (rsym && rsym->nRegs && sym->recvSize == 4)
2899         {
2900           int ofs;
2901
2902           _G.current_iCode = ric;
2903           D(emitcode (";     genReceive",""));
2904           for (ofs=0; ofs < sym->recvSize; ofs++)
2905             {
2906               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2907             }
2908           _G.current_iCode = ic;
2909           ric->generated = 1;
2910           accIsFree = 1;
2911         }
2912     }
2913
2914   /* adjust the stack for the function */
2915   if (stackAdjust)
2916     {
2917       int i = stackAdjust;
2918       if (i > 256)
2919         werror (W_STACK_OVERFLOW, sym->name);
2920
2921       if (i > 3 && accIsFree)
2922         {
2923           emitcode ("mov", "a,sp");
2924           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2925           emitcode ("mov", "sp,a");
2926         }
2927       else if (i > 5)
2928         {
2929           /* The accumulator is not free, so we will need another register */
2930           /* to clobber. No need to worry about a possible conflict with */
2931           /* the above early RECEIVE optimizations since they would have */
2932           /* freed the accumulator if they were generated. */
2933
2934           if (IFFUNC_CALLEESAVES(sym->type))
2935             {
2936               /* if it's a callee-saves function we need a saved register */
2937               if (calleesaves_saved_register >= 0)
2938                 {
2939                   emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2940                   emitcode ("mov", "a,sp");
2941                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2942                   emitcode ("mov", "sp,a");
2943                   emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2944                 }
2945               else
2946                 /* do it the hard way */
2947                 while (i--)
2948                   emitcode ("inc", "sp");
2949             }
2950           else
2951             {
2952               /* not callee-saves, we can clobber r0 */
2953               emitcode ("mov", "r0,a");
2954               emitcode ("mov", "a,sp");
2955               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2956               emitcode ("mov", "sp,a");
2957               emitcode ("mov", "a,r0");
2958             }
2959         }
2960       else
2961         while (i--)
2962           emitcode ("inc", "sp");
2963     }
2964
2965   if (sym->xstack)
2966     {
2967       char i = ((char) sym->xstack & 0xff);
2968
2969       if (i > 3 && accIsFree)
2970         {
2971           emitcode ("mov", "a,_spx");
2972           emitcode ("add", "a,#0x%02x", i);
2973           emitcode ("mov", "_spx,a");
2974         }
2975       else if (i > 5)
2976         {
2977           emitcode ("push", "acc");
2978           emitcode ("mov", "a,_spx");
2979           emitcode ("add", "a,#0x%02x", i);
2980           emitcode ("mov", "_spx,a");
2981           emitcode ("pop", "acc");
2982         }
2983       else
2984         {
2985           while (i--)
2986             emitcode ("inc", "_spx");
2987         }
2988     }
2989
2990   /* if critical function then turn interrupts off */
2991   if (IFFUNC_ISCRITICAL (ftype))
2992     {
2993       symbol *tlbl = newiTempLabel (NULL);
2994       emitcode ("setb", "c");
2995       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2996       emitcode ("clr", "c");
2997       emitcode ("", "%05d$:", (tlbl->key + 100));
2998       emitcode ("push", "psw"); /* save old ea via c in psw */
2999     }
3000 }
3001
3002 /*-----------------------------------------------------------------*/
3003 /* genEndFunction - generates epilogue for functions               */
3004 /*-----------------------------------------------------------------*/
3005 static void
3006 genEndFunction (iCode * ic)
3007 {
3008   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3009   lineNode *lnp = lineCurr;
3010   bitVect  *regsUsed;
3011   bitVect  *regsUsedPrologue;
3012   bitVect  *regsUnneeded;
3013   int      accIsFree = sym->recvSize < 4;
3014   int      idx;
3015
3016   _G.currentFunc = NULL;
3017   if (IFFUNC_ISNAKED(sym->type))
3018   {
3019       emitcode(";", "naked function: no epilogue.");
3020       if (options.debug && currFunc)
3021         debugFile->writeEndFunction (currFunc, ic, 0);
3022       return;
3023   }
3024
3025   if (IFFUNC_ISCRITICAL (sym->type))
3026     {
3027       emitcode ("pop", "psw"); /* restore ea via c in psw */
3028       emitcode ("mov", "ea,c");
3029     }
3030
3031   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && !options.useXstack)
3032     {
3033       emitcode ("mov", "%s,_bp", spname);
3034     }
3035
3036   /* if use external stack but some variables were
3037      added to the local stack then decrement the
3038      local stack */
3039   if (options.useXstack && sym->stack)
3040     {
3041       char count = sym->stack;
3042
3043       if ((count>3) && accIsFree)
3044         {
3045           emitcode ("mov", "a,sp");
3046           emitcode ("add", "a,#0x%02x", ((char) -count) & 0xff);
3047           emitcode ("mov", "sp,a");
3048         }
3049       else
3050         {
3051           while (count--)
3052             emitcode ("dec", "sp");
3053         }
3054     }
3055
3056   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3057     {
3058       if (options.useXstack)
3059         {
3060           emitcode ("xch", "a,_bp");
3061           emitcode ("mov", "r0,a");
3062           emitcode ("dec", "r0");
3063           emitcode ("movx", "a,@r0");
3064           emitcode ("xch", "a,_bp");
3065           emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3066         }
3067       else
3068         {
3069           emitcode ("pop", "_bp");
3070         }
3071     }
3072
3073   /* restore the register bank  */
3074   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3075   {
3076     if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3077      || !options.useXstack)
3078     {
3079         /* Special case of ISR using non-zero bank with useXstack
3080          * is handled below.
3081          */
3082         emitcode ("pop", "psw");
3083     }
3084   }
3085
3086   if (IFFUNC_ISISR (sym->type))
3087     {
3088
3089       /* now we need to restore the registers */
3090       /* if this isr has no bank i.e. is going to
3091          run with bank 0 , then we need to save more
3092          registers :-) */
3093       if (!FUNC_REGBANK (sym->type))
3094         {
3095           /* if this function does not call any other
3096              function then we can be economical and
3097              save only those registers that are used */
3098           if (!IFFUNC_HASFCALL(sym->type))
3099             {
3100               int i;
3101
3102               /* if any registers used */
3103               if (sym->regsUsed)
3104                 {
3105                   /* save the registers used */
3106                   for (i = sym->regsUsed->size; i >= 0; i--)
3107                     {
3108                       if (bitVectBitValue (sym->regsUsed, i))
3109                         emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3110                     }
3111                 }
3112             }
3113           else
3114             {
3115               if (options.parms_in_bank1) {
3116                   int i;
3117                   for (i = 7 ; i >= 0 ; i-- ) {
3118                       emitcode ("pop","%s",rb1regs[i]);
3119                   }
3120               }
3121               /* this function has  a function call cannot
3122                  determines register usage so we will have to pop the
3123                  entire bank */
3124               unsaveRBank (0, ic, FALSE);
3125             }
3126         }
3127         else
3128         {
3129             /* This ISR uses a non-zero bank.
3130              *
3131              * Restore any register banks saved by genFunction
3132              * in reverse order.
3133              */
3134             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3135             int ix;
3136
3137             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3138             {
3139                 if (savedBanks & (1 << ix))
3140                 {
3141                     unsaveRBank(ix, NULL, FALSE);
3142                 }
3143             }
3144
3145             if (options.useXstack)
3146             {
3147                 /* Restore bank AFTER calling unsaveRBank,
3148                  * since it can trash r0.
3149                  */
3150                 emitcode ("pop", "psw");
3151             }
3152         }
3153
3154       if (!inExcludeList ("dph"))
3155         emitcode ("pop", "dph");
3156       if (!inExcludeList ("dpl"))
3157         emitcode ("pop", "dpl");
3158       if (!inExcludeList ("b"))
3159         emitcode ("pop", "b");
3160       if (!inExcludeList ("acc"))
3161         emitcode ("pop", "acc");
3162
3163       /* if debug then send end of function */
3164       if (options.debug && currFunc)
3165         {
3166           debugFile->writeEndFunction (currFunc, ic, 1);
3167         }
3168
3169       emitcode ("reti", "");
3170     }
3171   else
3172     {
3173       if (IFFUNC_CALLEESAVES(sym->type))
3174         {
3175           int i;
3176
3177           /* if any registers used */
3178           if (sym->regsUsed)
3179             {
3180               /* save the registers used */
3181               for (i = sym->regsUsed->size; i >= 0; i--)
3182                 {
3183                   if (bitVectBitValue (sym->regsUsed, i) ||
3184                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3185                     emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3186                 }
3187             }
3188           else if (mcs51_ptrRegReq)
3189             {
3190               emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3191               emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3192             }
3193
3194         }
3195
3196       /* if debug then send end of function */
3197       if (options.debug && currFunc)
3198         {
3199           debugFile->writeEndFunction (currFunc, ic, 1);
3200         }
3201
3202       emitcode ("ret", "");
3203     }
3204
3205   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3206     return;
3207
3208   /* If this was an interrupt handler using bank 0 that called another */
3209   /* function, then all registers must be saved; nothing to optimized. */
3210   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3211       && !FUNC_REGBANK(sym->type))
3212     return;
3213
3214   /* There are no push/pops to optimize if not callee-saves or ISR */
3215   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3216     return;
3217
3218   /* If there were stack parameters, we cannot optimize without also    */
3219   /* fixing all of the stack offsets; this is too dificult to consider. */
3220   if (FUNC_HASSTACKPARM(sym->type))
3221     return;
3222
3223   /* Compute the registers actually used */
3224   regsUsed = newBitVect (mcs51_nRegs);
3225   regsUsedPrologue = newBitVect (mcs51_nRegs);
3226   while (lnp)
3227     {
3228       if (lnp->ic && lnp->ic->op == FUNCTION)
3229         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3230       else
3231         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3232
3233       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3234           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3235         break;
3236       if (!lnp->prev)
3237         break;
3238       lnp = lnp->prev;
3239     }
3240
3241   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3242       && !bitVectBitValue (regsUsed, CND_IDX))
3243     {
3244       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3245       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3246           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3247         bitVectUnSetBit (regsUsed, CND_IDX);
3248     }
3249   else
3250     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3251
3252   /* If this was an interrupt handler that called another function */
3253   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3254   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3255     {
3256       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3257       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3258       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3259       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3260       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3261     }
3262
3263   /* Remove the unneeded push/pops */
3264   regsUnneeded = newBitVect (mcs51_nRegs);
3265   while (lnp)
3266     {
3267       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3268         {
3269           if (!strncmp(lnp->line, "push", 4))
3270             {
3271               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3272               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3273                 {
3274                   connectLine (lnp->prev, lnp->next);
3275                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3276                 }
3277             }
3278           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3279             {
3280               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3281               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3282                 {
3283                   connectLine (lnp->prev, lnp->next);
3284                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3285                 }
3286             }
3287         }
3288       lnp = lnp->next;
3289     }
3290
3291   for (idx = 0; idx < regsUnneeded->size; idx++)
3292     if (bitVectBitValue (regsUnneeded, idx))
3293       emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3294
3295   freeBitVect (regsUnneeded);
3296   freeBitVect (regsUsed);
3297   freeBitVect (regsUsedPrologue);
3298 }
3299
3300 /*-----------------------------------------------------------------*/
3301 /* genRet - generate code for return statement                     */
3302 /*-----------------------------------------------------------------*/
3303 static void
3304 genRet (iCode * ic)
3305 {
3306   int size, offset = 0, pushed = 0;
3307
3308   D(emitcode (";     genRet",""));
3309
3310   /* if we have no return value then
3311      just generate the "ret" */
3312   if (!IC_LEFT (ic))
3313     goto jumpret;
3314
3315   /* we have something to return then
3316      move the return value into place */
3317   aopOp (IC_LEFT (ic), ic, FALSE);
3318   size = AOP_SIZE (IC_LEFT (ic));
3319
3320   while (size--)
3321     {
3322       char *l;
3323       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3324         {
3325           /* #NOCHANGE */
3326           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3327                       FALSE, TRUE);
3328           emitcode ("push", "%s", l);
3329           pushed++;
3330         }
3331       else
3332         {
3333           l = aopGet (AOP (IC_LEFT (ic)), offset,
3334                       FALSE, FALSE);
3335           if (strcmp (fReturn[offset], l))
3336             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3337         }
3338     }
3339
3340   if (pushed)
3341     {
3342       while (pushed)
3343         {
3344           pushed--;
3345           if (strcmp (fReturn[pushed], "a"))
3346             emitcode ("pop", fReturn[pushed]);
3347           else
3348             emitcode ("pop", "acc");
3349         }
3350     }
3351   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3352
3353 jumpret:
3354   /* generate a jump to the return label
3355      if the next is not the return statement */
3356   if (!(ic->next && ic->next->op == LABEL &&
3357         IC_LABEL (ic->next) == returnLabel))
3358
3359     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3360
3361 }
3362
3363 /*-----------------------------------------------------------------*/
3364 /* genLabel - generates a label                                    */
3365 /*-----------------------------------------------------------------*/
3366 static void
3367 genLabel (iCode * ic)
3368 {
3369   /* special case never generate */
3370   if (IC_LABEL (ic) == entryLabel)
3371     return;
3372
3373   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3374 }
3375
3376 /*-----------------------------------------------------------------*/
3377 /* genGoto - generates a ljmp                                      */
3378 /*-----------------------------------------------------------------*/
3379 static void
3380 genGoto (iCode * ic)
3381 {
3382   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3383 }
3384
3385 /*-----------------------------------------------------------------*/
3386 /* findLabelBackwards: walks back through the iCode chain looking  */
3387 /* for the given label. Returns number of iCode instructions     */
3388 /* between that label and given ic.          */
3389 /* Returns zero if label not found.          */
3390 /*-----------------------------------------------------------------*/
3391 static int
3392 findLabelBackwards (iCode * ic, int key)
3393 {
3394   int count = 0;
3395
3396   while (ic->prev)
3397     {
3398       ic = ic->prev;
3399       count++;
3400
3401       /* If we have any pushes or pops, we cannot predict the distance.
3402          I don't like this at all, this should be dealt with in the
3403          back-end */
3404       if (ic->op == IPUSH || ic->op == IPOP) {
3405         return 0;
3406       }
3407
3408       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3409         {
3410           return count;
3411         }
3412     }
3413
3414   return 0;
3415 }
3416
3417 /*-----------------------------------------------------------------*/
3418 /* genPlusIncr :- does addition with increment if possible         */
3419 /*-----------------------------------------------------------------*/
3420 static bool
3421 genPlusIncr (iCode * ic)
3422 {
3423   unsigned int icount;
3424   unsigned int size = getDataSize (IC_RESULT (ic));
3425
3426   /* will try to generate an increment */
3427   /* if the right side is not a literal
3428      we cannot */
3429   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3430     return FALSE;
3431
3432   /* if the literal value of the right hand side
3433      is greater than 4 then it is not worth it */
3434   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3435     return FALSE;
3436
3437   D(emitcode (";     genPlusIncr",""));
3438
3439   /* if increment >=16 bits in register or direct space */
3440   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3441       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3442       (size > 1) &&
3443       (icount == 1))
3444     {
3445       symbol *tlbl;
3446       int emitTlbl;
3447       int labelRange;
3448
3449       /* If the next instruction is a goto and the goto target
3450        * is < 10 instructions previous to this, we can generate
3451        * jumps straight to that target.
3452        */
3453       if (ic->next && ic->next->op == GOTO
3454           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3455           && labelRange <= 10)
3456         {
3457           emitcode (";", "tail increment optimized");
3458           tlbl = IC_LABEL (ic->next);
3459           emitTlbl = 0;
3460         }
3461       else
3462         {
3463           tlbl = newiTempLabel (NULL);
3464           emitTlbl = 1;
3465         }
3466       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3467       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3468           IS_AOP_PREG (IC_RESULT (ic)))
3469         emitcode ("cjne", "%s,#0x00,%05d$",
3470                   aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3471                   tlbl->key + 100);
3472       else
3473         {
3474           emitcode ("clr", "a");
3475           emitcode ("cjne", "a,%s,%05d$",
3476                     aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3477                     tlbl->key + 100);
3478         }
3479
3480       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3481       if (size > 2)
3482         {
3483           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3484               IS_AOP_PREG (IC_RESULT (ic)))
3485             emitcode ("cjne", "%s,#0x00,%05d$",
3486                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3487                       tlbl->key + 100);
3488           else
3489             emitcode ("cjne", "a,%s,%05d$",
3490                       aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3491                       tlbl->key + 100);
3492
3493           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3494         }
3495       if (size > 3)
3496         {
3497           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3498               IS_AOP_PREG (IC_RESULT (ic)))
3499             emitcode ("cjne", "%s,#0x00,%05d$",
3500                       aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3501                       tlbl->key + 100);
3502           else
3503             {
3504               emitcode ("cjne", "a,%s,%05d$",
3505                         aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3506                         tlbl->key + 100);
3507             }
3508           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3509         }
3510
3511       if (emitTlbl)
3512         {
3513           emitcode ("", "%05d$:", tlbl->key + 100);
3514         }
3515       return TRUE;
3516     }
3517
3518   /* if the sizes are greater than 1 then we cannot */
3519   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3520       AOP_SIZE (IC_LEFT (ic)) > 1)
3521     return FALSE;
3522
3523   /* we can if the aops of the left & result match or
3524      if they are in registers and the registers are the
3525      same */
3526   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3527     {
3528
3529       if (icount > 3)
3530         {
3531           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3532           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3533           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3534         }
3535       else
3536         {
3537
3538           while (icount--)
3539             emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3540         }
3541
3542       return TRUE;
3543     }
3544
3545   return FALSE;
3546 }
3547
3548 /*-----------------------------------------------------------------*/
3549 /* outBitAcc - output a bit in acc                                 */
3550 /*-----------------------------------------------------------------*/
3551 static void
3552 outBitAcc (operand * result)
3553 {
3554   symbol *tlbl = newiTempLabel (NULL);
3555   /* if the result is a bit */
3556   if (AOP_TYPE (result) == AOP_CRY)
3557     {
3558       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3559     }
3560   else
3561     {
3562       emitcode ("jz", "%05d$", tlbl->key + 100);
3563       emitcode ("mov", "a,%s", one);
3564       emitcode ("", "%05d$:", tlbl->key + 100);
3565       outAcc (result);
3566     }
3567 }
3568
3569 /*-----------------------------------------------------------------*/
3570 /* genPlusBits - generates code for addition of two bits           */
3571 /*-----------------------------------------------------------------*/
3572 static void
3573 genPlusBits (iCode * ic)
3574 {
3575   D(emitcode (";     genPlusBits",""));
3576
3577   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3578     {
3579       symbol *lbl = newiTempLabel (NULL);
3580       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3581       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3582       emitcode ("cpl", "c");
3583       emitcode ("", "%05d$:", (lbl->key + 100));
3584       outBitC (IC_RESULT (ic));
3585     }
3586   else
3587     {
3588       emitcode ("clr", "a");
3589       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3590       emitcode ("rlc", "a");
3591       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3592       emitcode ("addc", "a,#0x00");
3593       outAcc (IC_RESULT (ic));
3594     }
3595 }
3596
3597 #if 0
3598 /* This is the original version of this code.
3599
3600  * This is being kept around for reference,
3601  * because I am not entirely sure I got it right...
3602  */
3603 static void
3604 adjustArithmeticResult (iCode * ic)
3605 {
3606   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3607       AOP_SIZE (IC_LEFT (ic)) == 3 &&
3608       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3609     aopPut (AOP (IC_RESULT (ic)),
3610             aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3611             2,
3612             isOperandVolatile (IC_RESULT (ic), FALSE));
3613
3614   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3615       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3616       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3617     aopPut (AOP (IC_RESULT (ic)),
3618             aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3619             2,
3620             isOperandVolatile (IC_RESULT (ic), FALSE));
3621
3622   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3623       AOP_SIZE (IC_LEFT (ic)) < 3 &&
3624       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3625       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3626       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3627     {
3628       char buffer[5];
3629       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3630       aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3631     }
3632 }
3633 #else
3634 /* This is the pure and virtuous version of this code.
3635  * I'm pretty certain it's right, but not enough to toss the old
3636  * code just yet...
3637  */
3638 static void
3639 adjustArithmeticResult (iCode * ic)
3640 {
3641   if (opIsGptr (IC_RESULT (ic)) &&
3642       opIsGptr (IC_LEFT (ic)) &&
3643       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3644     {
3645       aopPut (AOP (IC_RESULT (ic)),
3646               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3647               GPTRSIZE - 1,
3648               isOperandVolatile (IC_RESULT (ic), FALSE));
3649     }
3650
3651   if (opIsGptr (IC_RESULT (ic)) &&
3652       opIsGptr (IC_RIGHT (ic)) &&
3653       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3654     {
3655       aopPut (AOP (IC_RESULT (ic)),
3656               aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3657               GPTRSIZE - 1,
3658               isOperandVolatile (IC_RESULT (ic), FALSE));
3659     }
3660
3661   if (opIsGptr (IC_RESULT (ic)) &&
3662       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3663       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3664       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3665       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3666     {
3667       char buffer[5];
3668       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3669       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3670     }
3671 }
3672 #endif
3673
3674 /*-----------------------------------------------------------------*/
3675 /* genPlus - generates code for addition                           */
3676 /*-----------------------------------------------------------------*/
3677 static void
3678 genPlus (iCode * ic)
3679 {
3680   int size, offset = 0;
3681   int skip_bytes = 0;
3682   char *add = "add";
3683   asmop *leftOp, *rightOp;
3684   operand * op;
3685
3686   /* special cases :- */
3687
3688   D(emitcode (";     genPlus",""));
3689
3690   aopOp (IC_LEFT (ic), ic, FALSE);
3691   aopOp (IC_RIGHT (ic), ic, FALSE);
3692   aopOp (IC_RESULT (ic), ic, TRUE);
3693
3694   /* if literal, literal on the right or
3695      if left requires ACC or right is already
3696      in ACC */
3697   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3698       (AOP_NEEDSACC (IC_LEFT (ic))) ||
3699       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3700     {
3701       operand *t = IC_RIGHT (ic);
3702       IC_RIGHT (ic) = IC_LEFT (ic);
3703       IC_LEFT (ic) = t;
3704     }
3705
3706   /* if both left & right are in bit
3707      space */
3708   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3709       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3710     {
3711       genPlusBits (ic);
3712       goto release;
3713     }
3714
3715   /* if left in bit space & right literal */
3716   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3717       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3718     {
3719       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3720       /* if result in bit space */
3721       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3722         {
3723           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3724             emitcode ("cpl", "c");
3725           outBitC (IC_RESULT (ic));
3726         }
3727       else
3728         {
3729           size = getDataSize (IC_RESULT (ic));
3730           while (size--)
3731             {
3732               MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3733               emitcode ("addc", "a,#00");
3734               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3735             }
3736         }
3737       goto release;
3738     }
3739
3740   /* if I can do an increment instead
3741      of add then GOOD for ME */
3742   if (genPlusIncr (ic) == TRUE)
3743     goto release;
3744
3745   size = getDataSize (IC_RESULT (ic));
3746   leftOp = AOP(IC_LEFT(ic));
3747   rightOp = AOP(IC_RIGHT(ic));
3748   op=IC_LEFT(ic);
3749
3750   /* if this is an add for an array access
3751      at a 256 byte boundary */
3752   if ( 2 == size
3753        && AOP_TYPE (op) == AOP_IMMD
3754        && IS_SYMOP (op)
3755        && IS_SPEC (OP_SYM_ETYPE (op))
3756        && SPEC_ABSA (OP_SYM_ETYPE (op))
3757        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3758      )
3759     {
3760       D(emitcode (";     genPlus aligned array",""));
3761       aopPut (AOP (IC_RESULT (ic)),
3762               aopGet (rightOp, 0, FALSE, FALSE),
3763               0,
3764               isOperandVolatile (IC_RESULT (ic), FALSE));
3765
3766       if( 1 == getDataSize (IC_RIGHT (ic)) )
3767         {
3768           aopPut (AOP (IC_RESULT (ic)),
3769                   aopGet (leftOp, 1, FALSE, FALSE),
3770                   1,
3771                   isOperandVolatile (IC_RESULT (ic), FALSE));
3772         }
3773       else
3774         {
3775           MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3776           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3777           aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3778         }
3779       goto release;
3780     }
3781
3782   /* if the lower bytes of a literal are zero skip the addition */
3783   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3784     {
3785        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3786               (skip_bytes+1 < size))
3787          {
3788            skip_bytes++;
3789          }
3790        if (skip_bytes)
3791          D(emitcode (";     genPlus shortcut",""));
3792     }
3793
3794   while (size--)
3795     {
3796       if( offset >= skip_bytes )
3797         {
3798           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3799             {
3800               bool pushedB;
3801               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
3802               pushedB = pushB ();
3803               emitcode("xch", "a,b");
3804               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3805               emitcode (add, "a,b");
3806               popB (pushedB);
3807             }
3808           else if (aopGetUsesAcc (leftOp, offset))
3809             {
3810               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3811               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3812             }
3813           else
3814             {
3815               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3816               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3817             }
3818           aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3819           add = "addc";  /* further adds must propagate carry */
3820         }
3821       else
3822         {
3823           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3824               isOperandVolatile (IC_RESULT (ic), FALSE))
3825             {
3826               /* just move */
3827               aopPut (AOP (IC_RESULT (ic)),
3828                       aopGet (leftOp, offset, FALSE, FALSE),
3829                       offset,
3830                       isOperandVolatile (IC_RESULT (ic), FALSE));
3831             }
3832         }
3833       offset++;
3834     }
3835
3836   adjustArithmeticResult (ic);
3837
3838 release:
3839   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3840   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3841   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3842 }
3843
3844 /*-----------------------------------------------------------------*/
3845 /* genMinusDec :- does subtraction with deccrement if possible     */
3846 /*-----------------------------------------------------------------*/
3847 static bool
3848 genMinusDec (iCode * ic)
3849 {
3850   unsigned int icount;
3851   unsigned int size = getDataSize (IC_RESULT (ic));
3852
3853   /* will try to generate an increment */
3854   /* if the right side is not a literal
3855      we cannot */
3856   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3857     return FALSE;
3858
3859   /* if the literal value of the right hand side
3860      is greater than 4 then it is not worth it */
3861   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3862     return FALSE;
3863
3864   D(emitcode (";     genMinusDec",""));
3865
3866   /* if decrement >=16 bits in register or direct space */
3867   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3868       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3869       (size > 1) &&
3870       (icount == 1))
3871     {
3872       symbol *tlbl;
3873       int emitTlbl;
3874       int labelRange;
3875
3876       /* If the next instruction is a goto and the goto target
3877        * is <= 10 instructions previous to this, we can generate
3878        * jumps straight to that target.
3879        */
3880       if (ic->next && ic->next->op == GOTO
3881           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3882           && labelRange <= 10)
3883         {
3884           emitcode (";", "tail decrement optimized");
3885           tlbl = IC_LABEL (ic->next);
3886           emitTlbl = 0;
3887         }
3888       else
3889         {
3890           tlbl = newiTempLabel (NULL);
3891           emitTlbl = 1;
3892         }
3893
3894       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3895       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3896           IS_AOP_PREG (IC_RESULT (ic)))
3897         emitcode ("cjne", "%s,#0xff,%05d$"
3898                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3899                   ,tlbl->key + 100);
3900       else
3901         {
3902           emitcode ("mov", "a,#0xff");
3903           emitcode ("cjne", "a,%s,%05d$"
3904                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3905                     ,tlbl->key + 100);
3906         }
3907       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3908       if (size > 2)
3909         {
3910           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3911               IS_AOP_PREG (IC_RESULT (ic)))
3912             emitcode ("cjne", "%s,#0xff,%05d$"
3913                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3914                       ,tlbl->key + 100);
3915           else
3916             {
3917               emitcode ("cjne", "a,%s,%05d$"
3918                         ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3919                         ,tlbl->key + 100);
3920             }
3921           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3922         }
3923       if (size > 3)
3924         {
3925           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3926               IS_AOP_PREG (IC_RESULT (ic)))
3927             emitcode ("cjne", "%s,#0xff,%05d$"
3928                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3929                       ,tlbl->key + 100);
3930           else
3931             {
3932               emitcode ("cjne", "a,%s,%05d$"
3933                         ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3934                         ,tlbl->key + 100);
3935             }
3936           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3937         }
3938       if (emitTlbl)
3939         {
3940           emitcode ("", "%05d$:", tlbl->key + 100);
3941         }
3942       return TRUE;
3943     }
3944
3945   /* if the sizes are greater than 1 then we cannot */
3946   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3947       AOP_SIZE (IC_LEFT (ic)) > 1)
3948     return FALSE;
3949
3950   /* we can if the aops of the left & result match or
3951      if they are in registers and the registers are the
3952      same */
3953   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3954     {
3955
3956       while (icount--)
3957         emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3958
3959       return TRUE;
3960     }
3961
3962   return FALSE;
3963 }
3964
3965 /*-----------------------------------------------------------------*/
3966 /* addSign - complete with sign                                    */
3967 /*-----------------------------------------------------------------*/
3968 static void
3969 addSign (operand * result, int offset, int sign)
3970 {
3971   int size = (getDataSize (result) - offset);
3972   if (size > 0)
3973     {
3974       if (sign)
3975         {
3976           emitcode ("rlc", "a");
3977           emitcode ("subb", "a,acc");
3978           while (size--)
3979             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3980         }
3981       else
3982         while (size--)
3983           aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3984     }
3985 }
3986
3987 /*-----------------------------------------------------------------*/
3988 /* genMinusBits - generates code for subtraction  of two bits      */
3989 /*-----------------------------------------------------------------*/
3990 static void
3991 genMinusBits (iCode * ic)
3992 {
3993   symbol *lbl = newiTempLabel (NULL);
3994
3995   D(emitcode (";     genMinusBits",""));
3996
3997   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3998     {
3999       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4000       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4001       emitcode ("cpl", "c");
4002       emitcode ("", "%05d$:", (lbl->key + 100));
4003       outBitC (IC_RESULT (ic));
4004     }
4005   else
4006     {
4007       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4008       emitcode ("subb", "a,acc");
4009       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4010       emitcode ("inc", "a");
4011       emitcode ("", "%05d$:", (lbl->key + 100));
4012       aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4013       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4014     }
4015 }
4016
4017 /*-----------------------------------------------------------------*/
4018 /* genMinus - generates code for subtraction                       */
4019 /*-----------------------------------------------------------------*/
4020 static void
4021 genMinus (iCode * ic)
4022 {
4023   int size, offset = 0;
4024
4025   D(emitcode (";     genMinus",""));
4026
4027   aopOp (IC_LEFT (ic), ic, FALSE);
4028   aopOp (IC_RIGHT (ic), ic, FALSE);
4029   aopOp (IC_RESULT (ic), ic, TRUE);
4030
4031   /* special cases :- */
4032   /* if both left & right are in bit space */
4033   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4034       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4035     {
4036       genMinusBits (ic);
4037       goto release;
4038     }
4039
4040   /* if I can do an decrement instead
4041      of subtract then GOOD for ME */
4042   if (genMinusDec (ic) == TRUE)
4043     goto release;
4044
4045   size = getDataSize (IC_RESULT (ic));
4046
4047   /* if literal, add a,#-lit, else normal subb */
4048   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4049     {
4050       unsigned long lit = 0L;
4051
4052       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4053       lit = -(long) lit;
4054
4055       while (size--)
4056         {
4057           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4058           /* first add without previous c */
4059           if (!offset) {
4060             if (!size && lit== (unsigned long) -1) {
4061               emitcode ("dec", "a");
4062             } else {
4063               emitcode ("add", "a,#0x%02x",
4064                         (unsigned int) (lit & 0x0FFL));
4065             }
4066           } else {
4067             emitcode ("addc", "a,#0x%02x",
4068                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4069           }
4070           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4071         }
4072     }
4073   else
4074     {
4075       asmop *leftOp, *rightOp;
4076
4077       leftOp = AOP(IC_LEFT(ic));
4078       rightOp = AOP(IC_RIGHT(ic));
4079
4080       while (size--)
4081         {
4082           if (aopGetUsesAcc(rightOp, offset)) {
4083             if (aopGetUsesAcc(leftOp, offset)) {
4084               bool pushedB;
4085
4086               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4087               pushedB = pushB ();
4088               emitcode ("mov", "b,a");
4089               if (offset == 0)
4090                 CLRC;
4091               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4092               emitcode ("subb", "a,b");
4093               popB (pushedB);
4094             } else {
4095               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4096               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4097               if (offset == 0) {
4098                 emitcode( "setb", "c");
4099               }
4100               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4101               emitcode("cpl", "a");
4102             }
4103           } else {
4104             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4105             if (offset == 0)
4106               CLRC;
4107             emitcode ("subb", "a,%s",
4108                       aopGet(rightOp, offset, FALSE, TRUE));
4109           }
4110
4111           aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4112         }
4113     }
4114
4115
4116   adjustArithmeticResult (ic);
4117
4118 release:
4119   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4120   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4121   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4122 }
4123
4124
4125 /*-----------------------------------------------------------------*/
4126 /* genMultbits :- multiplication of bits                           */
4127 /*-----------------------------------------------------------------*/
4128 static void
4129 genMultbits (operand * left,
4130              operand * right,
4131              operand * result)
4132 {
4133   D(emitcode (";     genMultbits",""));
4134
4135   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4136   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4137   outBitC (result);
4138 }
4139
4140 /*-----------------------------------------------------------------*/
4141 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4142 /*-----------------------------------------------------------------*/
4143 static void
4144 genMultOneByte (operand * left,
4145                 operand * right,
4146                 operand * result)
4147 {
4148   symbol *lbl;
4149   int size = AOP_SIZE (result);
4150   bool runtimeSign, compiletimeSign;
4151   bool lUnsigned, rUnsigned, pushedB;
4152
4153   D(emitcode (";     genMultOneByte",""));
4154
4155   if (size < 1 || size > 2)
4156     {
4157       /* this should never happen */
4158       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4159                AOP_SIZE(result), __FILE__, lineno);
4160       exit (1);
4161     }
4162
4163   /* (if two literals: the value is computed before) */
4164   /* if one literal, literal on the right */
4165   if (AOP_TYPE (left) == AOP_LIT)
4166     {
4167       operand *t = right;
4168       right = left;
4169       left = t;
4170       /* emitcode (";", "swapped left and right"); */
4171     }
4172   /* if no literal, unsigned on the right: shorter code */
4173   if (   AOP_TYPE (right) != AOP_LIT
4174       && SPEC_USIGN (getSpec (operandType (left))))
4175     {
4176       operand *t = right;
4177       right = left;
4178       left = t;
4179     }
4180
4181   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4182   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4183
4184   pushedB = pushB ();
4185
4186   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4187                    no need to take care about the signedness! */
4188       || (lUnsigned && rUnsigned))
4189     {
4190       /* just an unsigned 8 * 8 = 8 multiply
4191          or 8u * 8u = 16u */
4192       /* emitcode (";","unsigned"); */
4193       /* TODO: check for accumulator clash between left & right aops? */
4194
4195       if (AOP_TYPE (right) == AOP_LIT)
4196         {
4197           /* moving to accumulator first helps peepholes */
4198           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4199           emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4200         }
4201       else
4202         {
4203           emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4204           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4205         }
4206
4207       emitcode ("mul", "ab");
4208       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4209       if (size == 2)
4210         aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4211
4212       popB (pushedB);
4213       return;
4214     }
4215
4216   /* we have to do a signed multiply */
4217   /* emitcode (";", "signed"); */
4218
4219   /* now sign adjust for both left & right */
4220
4221   /* let's see what's needed: */
4222   /* apply negative sign during runtime */
4223   runtimeSign = FALSE;
4224   /* negative sign from literals */
4225   compiletimeSign = FALSE;
4226
4227   if (!lUnsigned)
4228     {
4229       if (AOP_TYPE(left) == AOP_LIT)
4230         {
4231           /* signed literal */
4232           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4233           if (val < 0)
4234             compiletimeSign = TRUE;
4235         }
4236       else
4237         /* signed but not literal */
4238         runtimeSign = TRUE;
4239     }
4240
4241   if (!rUnsigned)
4242     {
4243       if (AOP_TYPE(right) == AOP_LIT)
4244         {
4245           /* signed literal */
4246           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4247           if (val < 0)
4248             compiletimeSign ^= TRUE;
4249         }
4250       else
4251         /* signed but not literal */
4252         runtimeSign = TRUE;
4253     }
4254
4255   /* initialize F0, which stores the runtime sign */
4256   if (runtimeSign)
4257     {
4258       if (compiletimeSign)
4259         emitcode ("setb", "F0"); /* set sign flag */
4260       else
4261         emitcode ("clr", "F0"); /* reset sign flag */
4262     }
4263
4264   /* save the signs of the operands */
4265   if (AOP_TYPE(right) == AOP_LIT)
4266     {
4267       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4268
4269       if (!rUnsigned && val < 0)
4270         emitcode ("mov", "b,#0x%02x", -val);
4271       else
4272         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4273     }
4274   else /* ! literal */
4275     {
4276       if (rUnsigned)  /* emitcode (";", "signed"); */
4277
4278         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4279       else
4280         {
4281           MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4282           lbl = newiTempLabel (NULL);
4283           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4284           emitcode ("cpl", "F0"); /* complement sign flag */
4285           emitcode ("cpl", "a");  /* 2's complement */
4286           emitcode ("inc", "a");
4287           emitcode ("", "%05d$:", (lbl->key + 100));
4288           emitcode ("mov", "b,a");
4289         }
4290     }
4291
4292   if (AOP_TYPE(left) == AOP_LIT)
4293     {
4294       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4295
4296       if (!lUnsigned && val < 0)
4297         emitcode ("mov", "a,#0x%02x", -val);
4298       else
4299         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4300     }
4301   else /* ! literal */
4302     {
4303       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4304
4305       if (!lUnsigned)
4306         {
4307           lbl = newiTempLabel (NULL);
4308           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4309           emitcode ("cpl", "F0"); /* complement sign flag */
4310           emitcode ("cpl", "a"); /* 2's complement */
4311           emitcode ("inc", "a");
4312           emitcode ("", "%05d$:", (lbl->key + 100));
4313         }
4314     }
4315
4316   /* now the multiplication */
4317   emitcode ("mul", "ab");
4318   if (runtimeSign || compiletimeSign)
4319     {
4320       lbl = newiTempLabel (NULL);
4321       if (runtimeSign)
4322         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4323       emitcode ("cpl", "a"); /* lsb 2's complement */
4324       if (size != 2)
4325         emitcode ("inc", "a"); /* inc doesn't set carry flag */
4326       else
4327         {
4328           emitcode ("add", "a,#1"); /* this sets carry flag */
4329           emitcode ("xch", "a,b");
4330           emitcode ("cpl", "a"); /* msb 2's complement */
4331           emitcode ("addc", "a,#0");
4332           emitcode ("xch", "a,b");
4333         }
4334       emitcode ("", "%05d$:", (lbl->key + 100));
4335     }
4336   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4337   if (size == 2)
4338     aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4339
4340   popB (pushedB);
4341 }
4342
4343 /*-----------------------------------------------------------------*/
4344 /* genMult - generates code for multiplication                     */
4345 /*-----------------------------------------------------------------*/
4346 static void
4347 genMult (iCode * ic)
4348 {
4349   operand *left = IC_LEFT (ic);
4350   operand *right = IC_RIGHT (ic);
4351   operand *result = IC_RESULT (ic);
4352
4353   D(emitcode (";     genMult",""));
4354
4355   /* assign the amsops */
4356   aopOp (left, ic, FALSE);
4357   aopOp (right, ic, FALSE);
4358   aopOp (result, ic, TRUE);
4359
4360   /* special cases first */
4361   /* both are bits */
4362   if (AOP_TYPE (left) == AOP_CRY &&
4363       AOP_TYPE (right) == AOP_CRY)
4364     {
4365       genMultbits (left, right, result);
4366       goto release;
4367     }
4368
4369   /* if both are of size == 1 */
4370 #if 0 // one of them can be a sloc shared with the result
4371     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4372 #else
4373   if (getSize(operandType(left)) == 1 &&
4374       getSize(operandType(right)) == 1)
4375 #endif
4376     {
4377       genMultOneByte (left, right, result);
4378       goto release;
4379     }
4380
4381   /* should have been converted to function call */
4382     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4383              getSize(OP_SYMBOL(right)->type));
4384   assert (0);
4385
4386 release:
4387   freeAsmop (result, NULL, ic, TRUE);
4388   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4390 }
4391
4392 /*-----------------------------------------------------------------*/
4393 /* genDivbits :- division of bits                                  */
4394 /*-----------------------------------------------------------------*/
4395 static void
4396 genDivbits (operand * left,
4397             operand * right,
4398             operand * result)
4399 {
4400   char *l;
4401   bool pushedB;
4402
4403   D(emitcode (";     genDivbits",""));
4404
4405   pushedB = pushB ();
4406
4407   /* the result must be bit */
4408   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4409   l = aopGet (AOP (left), 0, FALSE, FALSE);
4410
4411   MOVA (l);
4412
4413   emitcode ("div", "ab");
4414   emitcode ("rrc", "a");
4415
4416   popB (pushedB);
4417
4418   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4419 }
4420
4421 /*-----------------------------------------------------------------*/
4422 /* genDivOneByte : 8 bit division                                  */
4423 /*-----------------------------------------------------------------*/
4424 static void
4425 genDivOneByte (operand * left,
4426                operand * right,
4427                operand * result)
4428 {
4429   bool lUnsigned, rUnsigned, pushedB;
4430   bool runtimeSign, compiletimeSign;
4431   symbol *lbl;
4432   int size, offset;
4433
4434   D(emitcode (";     genDivOneByte",""));
4435
4436   /* Why is it necessary that genDivOneByte() can return an int result?
4437      Have a look at:
4438
4439         volatile unsigned char uc;
4440         volatile signed char sc1, sc2;
4441         volatile int i;
4442
4443         uc  = 255;
4444         sc1 = -1;
4445         i = uc / sc1;
4446
4447      Or:
4448
4449         sc1 = -128;
4450         sc2 = -1;
4451         i = sc1 / sc2;
4452
4453      In all cases a one byte result would overflow, the following cast to int
4454      would return the wrong result.
4455
4456      Two possible solution:
4457         a) cast operands to int, if ((unsigned) / (signed)) or
4458            ((signed) / (signed))
4459         b) return an 16 bit signed int; this is what we're doing here!
4460   */
4461
4462   size = AOP_SIZE (result) - 1;
4463   offset = 1;
4464   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4465   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4466
4467   pushedB = pushB ();
4468
4469   /* signed or unsigned */
4470   if (lUnsigned && rUnsigned)
4471     {
4472       /* unsigned is easy */
4473       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4474       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4475       emitcode ("div", "ab");
4476       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4477       while (size--)
4478         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4479
4480       popB (pushedB);
4481       return;
4482     }
4483
4484   /* signed is a little bit more difficult */
4485
4486   /* now sign adjust for both left & right */
4487
4488   /* let's see what's needed: */
4489   /* apply negative sign during runtime */
4490   runtimeSign = FALSE;
4491   /* negative sign from literals */
4492   compiletimeSign = FALSE;
4493
4494   if (!lUnsigned)
4495     {
4496       if (AOP_TYPE(left) == AOP_LIT)
4497         {
4498           /* signed literal */
4499           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4500           if (val < 0)
4501             compiletimeSign = TRUE;
4502         }
4503       else
4504         /* signed but not literal */
4505         runtimeSign = TRUE;
4506     }
4507
4508   if (!rUnsigned)
4509     {
4510       if (AOP_TYPE(right) == AOP_LIT)
4511         {
4512           /* signed literal */
4513           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4514           if (val < 0)
4515             compiletimeSign ^= TRUE;
4516         }
4517       else
4518         /* signed but not literal */
4519         runtimeSign = TRUE;
4520     }
4521
4522   /* initialize F0, which stores the runtime sign */
4523   if (runtimeSign)
4524     {
4525       if (compiletimeSign)
4526         emitcode ("setb", "F0"); /* set sign flag */
4527       else
4528         emitcode ("clr", "F0"); /* reset sign flag */
4529     }
4530
4531   /* save the signs of the operands */
4532   if (AOP_TYPE(right) == AOP_LIT)
4533     {
4534       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4535
4536       if (!rUnsigned && val < 0)
4537         emitcode ("mov", "b,#0x%02x", -val);
4538       else
4539         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4540     }
4541   else /* ! literal */
4542     {
4543       if (rUnsigned)
4544         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4545       else
4546         {
4547           MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4548           lbl = newiTempLabel (NULL);
4549           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4550           emitcode ("cpl", "F0"); /* complement sign flag */
4551           emitcode ("cpl", "a");  /* 2's complement */
4552           emitcode ("inc", "a");
4553           emitcode ("", "%05d$:", (lbl->key + 100));
4554           emitcode ("mov", "b,a");
4555         }
4556     }
4557
4558   if (AOP_TYPE(left) == AOP_LIT)
4559     {
4560       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4561
4562       if (!lUnsigned && val < 0)
4563         emitcode ("mov", "a,#0x%02x", -val);
4564       else
4565         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4566     }
4567   else /* ! literal */
4568     {
4569       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4570
4571       if (!lUnsigned)
4572         {
4573           lbl = newiTempLabel (NULL);
4574           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4575           emitcode ("cpl", "F0"); /* complement sign flag */
4576           emitcode ("cpl", "a");  /* 2's complement */
4577           emitcode ("inc", "a");
4578           emitcode ("", "%05d$:", (lbl->key + 100));
4579         }
4580     }
4581
4582   /* now the division */
4583   emitcode ("div", "ab");
4584
4585   if (runtimeSign || compiletimeSign)
4586     {
4587       lbl = newiTempLabel (NULL);
4588       if (runtimeSign)
4589         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4590       emitcode ("cpl", "a"); /* lsb 2's complement */
4591       emitcode ("inc", "a");
4592       emitcode ("", "%05d$:", (lbl->key + 100));
4593
4594       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4595       if (size > 0)
4596         {
4597           /* msb is 0x00 or 0xff depending on the sign */
4598           if (runtimeSign)
4599             {
4600               emitcode ("mov", "c,F0");
4601               emitcode ("subb", "a,acc");
4602               while (size--)
4603                 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4604             }
4605           else /* compiletimeSign */
4606             while (size--)
4607               aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4608         }
4609     }
4610   else
4611     {
4612       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4613       while (size--)
4614         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4615     }
4616
4617   popB (pushedB);
4618 }
4619
4620 /*-----------------------------------------------------------------*/
4621 /* genDiv - generates code for division                            */
4622 /*-----------------------------------------------------------------*/
4623 static void
4624 genDiv (iCode * ic)
4625 {
4626   operand *left = IC_LEFT (ic);
4627   operand *right = IC_RIGHT (ic);
4628   operand *result = IC_RESULT (ic);
4629
4630   D(emitcode (";     genDiv",""));
4631
4632   /* assign the amsops */
4633   aopOp (left, ic, FALSE);
4634   aopOp (right, ic, FALSE);
4635   aopOp (result, ic, TRUE);
4636
4637   /* special cases first */
4638   /* both are bits */
4639   if (AOP_TYPE (left) == AOP_CRY &&
4640       AOP_TYPE (right) == AOP_CRY)
4641     {
4642       genDivbits (left, right, result);
4643       goto release;
4644     }
4645
4646   /* if both are of size == 1 */
4647   if (AOP_SIZE (left) == 1 &&
4648       AOP_SIZE (right) == 1)
4649     {
4650       genDivOneByte (left, right, result);
4651       goto release;
4652     }
4653
4654   /* should have been converted to function call */
4655   assert (0);
4656 release:
4657   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4658   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4659   freeAsmop (result, NULL, ic, TRUE);
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* genModbits :- modulus of bits                                   */
4664 /*-----------------------------------------------------------------*/
4665 static void
4666 genModbits (operand * left,
4667             operand * right,
4668             operand * result)
4669 {
4670   char *l;
4671   bool pushedB;
4672
4673   D(emitcode (";     genModbits",""));
4674
4675   pushedB = pushB ();
4676
4677   /* the result must be bit */
4678   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4679   l = aopGet (AOP (left), 0, FALSE, FALSE);
4680
4681   MOVA (l);
4682
4683   emitcode ("div", "ab");
4684   emitcode ("mov", "a,b");
4685   emitcode ("rrc", "a");
4686
4687   popB (pushedB);
4688
4689   aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4690 }
4691
4692 /*-----------------------------------------------------------------*/
4693 /* genModOneByte : 8 bit modulus                                   */
4694 /*-----------------------------------------------------------------*/
4695 static void
4696 genModOneByte (operand * left,
4697                operand * right,
4698                operand * result)
4699 {
4700   bool lUnsigned, rUnsigned, pushedB;
4701   bool runtimeSign, compiletimeSign;
4702   symbol *lbl;
4703   int size, offset;
4704
4705   D(emitcode (";     genModOneByte",""));
4706
4707   size = AOP_SIZE (result) - 1;
4708   offset = 1;
4709   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4710   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4711
4712   /* if right is a literal, check it for 2^n */
4713   if (AOP_TYPE(right) == AOP_LIT)
4714     {
4715       unsigned char val = abs(operandLitValue(right));
4716       symbol *lbl2 = NULL;
4717
4718       switch (val)
4719         {
4720           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4721           case 2:
4722           case 4:
4723           case 8:
4724           case 16:
4725           case 32:
4726           case 64:
4727           case 128:
4728             if (lUnsigned)
4729               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4730                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
4731               /* because iCode should have been changed to genAnd  */
4732               /* see file "SDCCopt.c", function "convertToFcall()" */
4733
4734             MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4735             emitcode ("mov", "c,acc.7");
4736             emitcode ("anl", "a,#0x%02x", val - 1);
4737             lbl = newiTempLabel (NULL);
4738             emitcode ("jz", "%05d$", (lbl->key + 100));
4739             emitcode ("jnc", "%05d$", (lbl->key + 100));
4740             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4741             if (size)
4742               {
4743                 int size2 = size;
4744                 int offs2 = offset;
4745
4746                 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4747                 while (size2--)
4748                   aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4749                 lbl2 = newiTempLabel (NULL);
4750                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4751               }
4752             emitcode ("", "%05d$:", (lbl->key + 100));
4753             aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4754             while (size--)
4755               aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4756             if (lbl2)
4757               {
4758                 emitcode ("", "%05d$:", (lbl2->key + 100));
4759               }
4760             return;
4761
4762           default:
4763             break;
4764         }
4765     }
4766
4767   pushedB = pushB ();
4768
4769   /* signed or unsigned */
4770   if (lUnsigned && rUnsigned)
4771     {
4772       /* unsigned is easy */
4773       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4774       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4775       emitcode ("div", "ab");
4776       aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4777       while (size--)
4778         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4779
4780       popB (pushedB);
4781       return;
4782     }
4783
4784   /* signed is a little bit more difficult */
4785
4786   /* now sign adjust for both left & right */
4787
4788   /* modulus: sign of the right operand has no influence on the result! */
4789   if (AOP_TYPE(right) == AOP_LIT)
4790     {
4791       signed char val = (char) operandLitValue(right);
4792
4793       if (!rUnsigned && val < 0)
4794         emitcode ("mov", "b,#0x%02x", -val);
4795       else
4796         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4797     }
4798   else /* not literal */
4799     {
4800       if (rUnsigned)
4801         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4802       else
4803         {
4804           MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4805           lbl = newiTempLabel (NULL);
4806           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4807           emitcode ("cpl", "a"); /* 2's complement */
4808           emitcode ("inc", "a");
4809           emitcode ("", "%05d$:", (lbl->key + 100));
4810           emitcode ("mov", "b,a");
4811         }
4812     }
4813
4814   /* let's see what's needed: */
4815   /* apply negative sign during runtime */
4816   runtimeSign = FALSE;
4817   /* negative sign from literals */
4818   compiletimeSign = FALSE;
4819
4820   /* sign adjust left side */
4821   if (AOP_TYPE(left) == AOP_LIT)
4822     {
4823       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4824
4825       if (!lUnsigned && val < 0)
4826         {
4827           compiletimeSign = TRUE; /* set sign flag */
4828           emitcode ("mov", "a,#0x%02x", -val);
4829         }
4830       else
4831         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4832     }
4833   else /* ! literal */
4834     {
4835       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4836
4837       if (!lUnsigned)
4838         {
4839           runtimeSign = TRUE;
4840           emitcode ("clr", "F0"); /* clear sign flag */
4841
4842           lbl = newiTempLabel (NULL);
4843           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4844           emitcode ("setb", "F0"); /* set sign flag */
4845           emitcode ("cpl", "a");   /* 2's complement */
4846           emitcode ("inc", "a");
4847           emitcode ("", "%05d$:", (lbl->key + 100));
4848         }
4849     }
4850
4851   /* now the modulus */
4852   emitcode ("div", "ab");
4853
4854   if (runtimeSign || compiletimeSign)
4855     {
4856       emitcode ("mov", "a,b");
4857       lbl = newiTempLabel (NULL);
4858       if (runtimeSign)
4859         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4860       emitcode ("cpl", "a"); /* 2's complement */
4861       emitcode ("inc", "a");
4862       emitcode ("", "%05d$:", (lbl->key + 100));
4863
4864       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4865       if (size > 0)
4866         {
4867           /* msb is 0x00 or 0xff depending on the sign */
4868           if (runtimeSign)
4869             {
4870               emitcode ("mov", "c,F0");
4871               emitcode ("subb", "a,acc");
4872               while (size--)
4873                 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4874             }
4875           else /* compiletimeSign */
4876             while (size--)
4877               aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4878         }
4879     }
4880   else
4881     {
4882       aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4883       while (size--)
4884         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4885     }
4886
4887   popB (pushedB);
4888 }
4889
4890 /*-----------------------------------------------------------------*/
4891 /* genMod - generates code for division                            */
4892 /*-----------------------------------------------------------------*/
4893 static void
4894 genMod (iCode * ic)
4895 {
4896   operand *left = IC_LEFT (ic);
4897   operand *right = IC_RIGHT (ic);
4898   operand *result = IC_RESULT (ic);
4899
4900   D(emitcode (";     genMod",""));
4901
4902   /* assign the asmops */
4903   aopOp (left, ic, FALSE);
4904   aopOp (right, ic, FALSE);
4905   aopOp (result, ic, TRUE);
4906
4907   /* special cases first */
4908   /* both are bits */
4909   if (AOP_TYPE (left) == AOP_CRY &&
4910       AOP_TYPE (right) == AOP_CRY)
4911     {
4912       genModbits (left, right, result);
4913       goto release;
4914     }
4915
4916   /* if both are of size == 1 */
4917   if (AOP_SIZE (left) == 1 &&
4918       AOP_SIZE (right) == 1)
4919     {
4920       genModOneByte (left, right, result);
4921       goto release;
4922     }
4923
4924   /* should have been converted to function call */
4925   assert (0);
4926
4927 release:
4928   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4929   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4930   freeAsmop (result, NULL, ic, TRUE);
4931 }
4932
4933 /*-----------------------------------------------------------------*/
4934 /* genIfxJump :- will create a jump depending on the ifx           */
4935 /*-----------------------------------------------------------------*/
4936 static void
4937 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4938 {
4939   symbol *jlbl;
4940   symbol *tlbl = newiTempLabel (NULL);
4941   char *inst;
4942
4943   D(emitcode (";     genIfxJump",""));
4944
4945   /* if true label then we jump if condition
4946      supplied is true */
4947   if (IC_TRUE (ic))
4948     {
4949       jlbl = IC_TRUE (ic);
4950       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4951                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4952     }
4953   else
4954     {
4955       /* false label is present */
4956       jlbl = IC_FALSE (ic);
4957       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4958                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4959     }
4960   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4961     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4962   else
4963     emitcode (inst, "%05d$", tlbl->key + 100);
4964   freeForBranchAsmop (result);
4965   freeForBranchAsmop (right);
4966   freeForBranchAsmop (left);
4967   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4968   emitcode ("", "%05d$:", tlbl->key + 100);
4969
4970   /* mark the icode as generated */
4971   ic->generated = 1;
4972 }
4973
4974 /*-----------------------------------------------------------------*/
4975 /* genCmp :- greater or less than comparison                       */
4976 /*-----------------------------------------------------------------*/
4977 static void
4978 genCmp (operand * left, operand * right,
4979         operand * result, iCode * ifx, int sign, iCode *ic)
4980 {
4981   int size, offset = 0;
4982   unsigned long lit = 0L;
4983   bool rightInB;
4984
4985   D(emitcode (";     genCmp",""));
4986
4987   /* if left & right are bit variables */
4988   if (AOP_TYPE (left) == AOP_CRY &&
4989       AOP_TYPE (right) == AOP_CRY)
4990     {
4991       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4992       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4993     }
4994   else
4995     {
4996       /* subtract right from left if at the
4997          end the carry flag is set then we know that
4998          left is greater than right */
4999       size = max (AOP_SIZE (left), AOP_SIZE (right));
5000
5001       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5002       if ((size == 1) && !sign &&
5003           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5004         {
5005           symbol *lbl = newiTempLabel (NULL);
5006           emitcode ("cjne", "%s,%s,%05d$",
5007                     aopGet (AOP (left), offset, FALSE, FALSE),
5008                     aopGet (AOP (right), offset, FALSE, FALSE),
5009                     lbl->key + 100);
5010           emitcode ("", "%05d$:", lbl->key + 100);
5011         }
5012       else
5013         {
5014           if (AOP_TYPE (right) == AOP_LIT)
5015             {
5016               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5017               /* optimize if(x < 0) or if(x >= 0) */
5018               if (lit == 0L)
5019                 {
5020                   if (!sign)
5021                     {
5022                       CLRC;
5023                     }
5024                   else
5025                     {
5026                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5027                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5028                         {
5029                           genIfxJump (ifx, "acc.7", left, right, result);
5030                           freeAsmop (right, NULL, ic, TRUE);
5031                           freeAsmop (left, NULL, ic, TRUE);
5032
5033                           return;
5034                         }
5035                       else
5036                         emitcode ("rlc", "a");
5037                     }
5038                   goto release;
5039                 }
5040             }
5041           CLRC;
5042           while (size--)
5043             {
5044               bool pushedB = FALSE;
5045               rightInB = aopGetUsesAcc(AOP (right), offset);
5046               if (rightInB)
5047                 {
5048                   pushedB = pushB ();
5049                   emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5050                 }
5051               MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5052               if (sign && size == 0)
5053                 {
5054                   emitcode ("xrl", "a,#0x80");
5055                   if (AOP_TYPE (right) == AOP_LIT)
5056                     {
5057                       unsigned long lit = (unsigned long)
5058                       floatFromVal (AOP (right)->aopu.aop_lit);
5059                       emitcode ("subb", "a,#0x%02x",
5060                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5061                     }
5062                   else
5063                     {
5064                       if (!rightInB)
5065                         {
5066                           pushedB = pushB ();
5067                           rightInB++;
5068                           emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5069                         }
5070                       emitcode ("xrl", "b,#0x80");
5071                       emitcode ("subb", "a,b");
5072                     }
5073                 }
5074               else
5075                 {
5076                   if (rightInB)
5077                     emitcode ("subb", "a,b");
5078                   else
5079                     emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5080                 }
5081               if (rightInB)
5082                 popB (pushedB);
5083               offset++;
5084             }
5085         }
5086     }
5087
5088 release:
5089   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5090   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5091   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5092     {
5093       outBitC (result);
5094     }
5095   else
5096     {
5097       /* if the result is used in the next
5098          ifx conditional branch then generate
5099          code a little differently */
5100       if (ifx)
5101         genIfxJump (ifx, "c", NULL, NULL, result);
5102       else
5103         outBitC (result);
5104       /* leave the result in acc */
5105     }
5106 }
5107
5108 /*-----------------------------------------------------------------*/
5109 /* genCmpGt :- greater than comparison                             */
5110 /*-----------------------------------------------------------------*/
5111 static void
5112 genCmpGt (iCode * ic, iCode * ifx)
5113 {
5114   operand *left, *right, *result;
5115   sym_link *letype, *retype;
5116   int sign;
5117
5118   D(emitcode (";     genCmpGt",""));
5119
5120   left = IC_LEFT (ic);
5121   right = IC_RIGHT (ic);
5122   result = IC_RESULT (ic);
5123
5124   letype = getSpec (operandType (left));
5125   retype = getSpec (operandType (right));
5126   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5127            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5128   /* assign the amsops */
5129   aopOp (left, ic, FALSE);
5130   aopOp (right, ic, FALSE);
5131   aopOp (result, ic, TRUE);
5132
5133   genCmp (right, left, result, ifx, sign, ic);
5134
5135   freeAsmop (result, NULL, ic, TRUE);
5136 }
5137
5138 /*-----------------------------------------------------------------*/
5139 /* genCmpLt - less than comparisons                                */
5140 /*-----------------------------------------------------------------*/
5141 static void
5142 genCmpLt (iCode * ic, iCode * ifx)
5143 {
5144   operand *left, *right, *result;
5145   sym_link *letype, *retype;
5146   int sign;
5147
5148   D(emitcode (";     genCmpLt",""));
5149
5150   left = IC_LEFT (ic);
5151   right = IC_RIGHT (ic);
5152   result = IC_RESULT (ic);
5153
5154   letype = getSpec (operandType (left));
5155   retype = getSpec (operandType (right));
5156   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5157            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5158   /* assign the amsops */
5159   aopOp (left, ic, FALSE);
5160   aopOp (right, ic, FALSE);
5161   aopOp (result, ic, TRUE);
5162
5163   genCmp (left, right, result, ifx, sign,ic);
5164
5165   freeAsmop (result, NULL, ic, TRUE);
5166 }
5167
5168 /*-----------------------------------------------------------------*/
5169 /* gencjneshort - compare and jump if not equal                    */
5170 /*-----------------------------------------------------------------*/
5171 static void
5172 gencjneshort (operand * left, operand * right, symbol * lbl)
5173 {
5174   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5175   int offset = 0;
5176   unsigned long lit = 0L;
5177
5178   /* if the left side is a literal or
5179      if the right is in a pointer register and left
5180      is not */
5181   if ((AOP_TYPE (left) == AOP_LIT) ||
5182       (AOP_TYPE (left) == AOP_IMMD) ||
5183       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5184     {
5185       operand *t = right;
5186       right = left;
5187       left = t;
5188     }
5189
5190   if (AOP_TYPE (right) == AOP_LIT)
5191     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5192
5193   /* if the right side is a literal then anything goes */
5194   if (AOP_TYPE (right) == AOP_LIT &&
5195       AOP_TYPE (left) != AOP_DIR  &&
5196       AOP_TYPE (left) != AOP_IMMD)
5197     {
5198       while (size--)
5199         {
5200           emitcode ("cjne", "%s,%s,%05d$",
5201                     aopGet (AOP (left), offset, FALSE, FALSE),
5202                     aopGet (AOP (right), offset, FALSE, FALSE),
5203                     lbl->key + 100);
5204           offset++;
5205         }
5206     }
5207
5208   /* if the right side is in a register or in direct space or
5209      if the left is a pointer register & right is not */
5210   else if (AOP_TYPE (right) == AOP_REG ||
5211            AOP_TYPE (right) == AOP_DIR ||
5212            AOP_TYPE (right) == AOP_LIT ||
5213            AOP_TYPE (right) == AOP_IMMD ||
5214            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5215            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5216     {
5217       while (size--)
5218         {
5219           MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5220           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5221               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5222             emitcode ("jnz", "%05d$", lbl->key + 100);
5223           else
5224             emitcode ("cjne", "a,%s,%05d$",
5225                       aopGet (AOP (right), offset, FALSE, TRUE),
5226                       lbl->key + 100);
5227           offset++;
5228         }
5229     }
5230   else
5231     {
5232       /* right is a pointer reg need both a & b */
5233       while (size--)
5234         {
5235           char *l;
5236           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5237           wassertl(!BINUSE, "B was in use");
5238           l = aopGet (AOP (left), offset, FALSE, FALSE);
5239           if (strcmp (l, "b"))
5240             emitcode ("mov", "b,%s", l);
5241           MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5242           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5243           offset++;
5244         }
5245     }
5246 }
5247
5248 /*-----------------------------------------------------------------*/
5249 /* gencjne - compare and jump if not equal                         */
5250 /*-----------------------------------------------------------------*/
5251 static void
5252 gencjne (operand * left, operand * right, symbol * lbl)
5253 {
5254   symbol *tlbl = newiTempLabel (NULL);
5255
5256   gencjneshort (left, right, lbl);
5257
5258   emitcode ("mov", "a,%s", one);
5259   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5260   emitcode ("", "%05d$:", lbl->key + 100);
5261   emitcode ("clr", "a");
5262   emitcode ("", "%05d$:", tlbl->key + 100);
5263 }
5264
5265 /*-----------------------------------------------------------------*/
5266 /* genCmpEq - generates code for equal to                          */
5267 /*-----------------------------------------------------------------*/
5268 static void
5269 genCmpEq (iCode * ic, iCode * ifx)
5270 {
5271   operand *left, *right, *result;
5272
5273   D(emitcode (";     genCmpEq",""));
5274
5275   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5276   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5277   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5278
5279   /* if literal, literal on the right or
5280      if the right is in a pointer register and left
5281      is not */
5282   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5283       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5284     {
5285       operand *t = IC_RIGHT (ic);
5286       IC_RIGHT (ic) = IC_LEFT (ic);
5287       IC_LEFT (ic) = t;
5288     }
5289
5290   if (ifx && !AOP_SIZE (result))
5291     {
5292       symbol *tlbl;
5293       /* if they are both bit variables */
5294       if (AOP_TYPE (left) == AOP_CRY &&
5295           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5296         {
5297           if (AOP_TYPE (right) == AOP_LIT)
5298             {
5299               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5300               if (lit == 0L)
5301                 {
5302                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5303                   emitcode ("cpl", "c");
5304                 }
5305               else if (lit == 1L)
5306                 {
5307                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5308                 }
5309               else
5310                 {
5311                   emitcode ("clr", "c");
5312                 }
5313               /* AOP_TYPE(right) == AOP_CRY */
5314             }
5315           else
5316             {
5317               symbol *lbl = newiTempLabel (NULL);
5318               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5319               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5320               emitcode ("cpl", "c");
5321               emitcode ("", "%05d$:", (lbl->key + 100));
5322             }
5323           /* if true label then we jump if condition
5324              supplied is true */
5325           tlbl = newiTempLabel (NULL);
5326           if (IC_TRUE (ifx))
5327             {
5328               emitcode ("jnc", "%05d$", tlbl->key + 100);
5329               freeForBranchAsmop (result);
5330               freeForBranchAsmop (right);
5331               freeForBranchAsmop (left);
5332               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5333             }
5334           else
5335             {
5336               emitcode ("jc", "%05d$", tlbl->key + 100);
5337               freeForBranchAsmop (result);
5338               freeForBranchAsmop (right);
5339               freeForBranchAsmop (left);
5340               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5341             }
5342           emitcode ("", "%05d$:", tlbl->key + 100);
5343         }
5344       else
5345         {
5346           tlbl = newiTempLabel (NULL);
5347           gencjneshort (left, right, tlbl);
5348           if (IC_TRUE (ifx))
5349             {
5350               freeForBranchAsmop (result);
5351               freeForBranchAsmop (right);
5352               freeForBranchAsmop (left);
5353               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5354               emitcode ("", "%05d$:", tlbl->key + 100);
5355             }
5356           else
5357             {
5358               symbol *lbl = newiTempLabel (NULL);
5359               emitcode ("sjmp", "%05d$", lbl->key + 100);
5360               emitcode ("", "%05d$:", tlbl->key + 100);
5361               freeForBranchAsmop (result);
5362               freeForBranchAsmop (right);
5363               freeForBranchAsmop (left);
5364               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5365               emitcode ("", "%05d$:", lbl->key + 100);
5366             }
5367         }
5368       /* mark the icode as generated */
5369       ifx->generated = 1;
5370       goto release;
5371     }
5372
5373   /* if they are both bit variables */
5374   if (AOP_TYPE (left) == AOP_CRY &&
5375       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5376     {
5377       if (AOP_TYPE (right) == AOP_LIT)
5378         {
5379           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5380           if (lit == 0L)
5381             {
5382               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5383               emitcode ("cpl", "c");
5384             }
5385           else if (lit == 1L)
5386             {
5387               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5388             }
5389           else
5390             {
5391               emitcode ("clr", "c");
5392             }
5393           /* AOP_TYPE(right) == AOP_CRY */
5394         }
5395       else
5396         {
5397           symbol *lbl = newiTempLabel (NULL);
5398           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5399           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5400           emitcode ("cpl", "c");
5401           emitcode ("", "%05d$:", (lbl->key + 100));
5402         }
5403       /* c = 1 if egal */
5404       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5405         {
5406           outBitC (result);
5407           goto release;
5408         }
5409       if (ifx)
5410         {
5411           genIfxJump (ifx, "c", left, right, result);
5412           goto release;
5413         }
5414       /* if the result is used in an arithmetic operation
5415          then put the result in place */
5416       outBitC (result);
5417     }
5418   else
5419     {
5420       gencjne (left, right, newiTempLabel (NULL));
5421       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5422         {
5423           aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5424           goto release;
5425         }
5426       if (ifx)
5427         {
5428           genIfxJump (ifx, "a", left, right, result);
5429           goto release;
5430         }
5431       /* if the result is used in an arithmetic operation
5432          then put the result in place */
5433       if (AOP_TYPE (result) != AOP_CRY)
5434         outAcc (result);
5435       /* leave the result in acc */
5436     }
5437
5438 release:
5439   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5440   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5441   freeAsmop (result, NULL, ic, TRUE);
5442 }
5443
5444 /*-----------------------------------------------------------------*/
5445 /* ifxForOp - returns the icode containing the ifx for operand     */
5446 /*-----------------------------------------------------------------*/
5447 static iCode *
5448 ifxForOp (operand * op, iCode * ic)
5449 {
5450   /* if true symbol then needs to be assigned */
5451   if (IS_TRUE_SYMOP (op))
5452     return NULL;
5453
5454   /* if this has register type condition and
5455      the next instruction is ifx with the same operand
5456      and live to of the operand is upto the ifx only then */
5457   if (ic->next &&
5458       ic->next->op == IFX &&
5459       IC_COND (ic->next)->key == op->key &&
5460       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5461     return ic->next;
5462
5463   return NULL;
5464 }
5465
5466 /*-----------------------------------------------------------------*/
5467 /* hasInc - operand is incremented before any other use            */
5468 /*-----------------------------------------------------------------*/
5469 static iCode *
5470 hasInc (operand *op, iCode *ic,int osize)
5471 {
5472   sym_link *type = operandType(op);
5473   sym_link *retype = getSpec (type);
5474   iCode *lic = ic->next;
5475   int isize ;
5476
5477   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5478   if (!IS_SYMOP(op)) return NULL;
5479
5480   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5481   if (IS_AGGREGATE(type->next)) return NULL;
5482   if (osize != (isize = getSize(type->next))) return NULL;
5483
5484   while (lic) {
5485     /* if operand of the form op = op + <sizeof *op> */
5486     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5487         isOperandEqual(IC_RESULT(lic),op) &&
5488         isOperandLiteral(IC_RIGHT(lic)) &&
5489         operandLitValue(IC_RIGHT(lic)) == isize) {
5490       return lic;
5491     }
5492     /* if the operand used or deffed */
5493     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5494       return NULL;
5495     }
5496     /* if GOTO or IFX */
5497     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5498     lic = lic->next;
5499   }
5500   return NULL;
5501 }
5502
5503 /*-----------------------------------------------------------------*/
5504 /* genAndOp - for && operation                                     */
5505 /*-----------------------------------------------------------------*/
5506 static void
5507 genAndOp (iCode * ic)
5508 {
5509   operand *left, *right, *result;
5510   symbol *tlbl;
5511
5512   D(emitcode (";     genAndOp",""));
5513
5514   /* note here that && operations that are in an
5515      if statement are taken away by backPatchLabels
5516      only those used in arthmetic operations remain */
5517   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5518   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5519   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5520
5521   /* if both are bit variables */
5522   if (AOP_TYPE (left) == AOP_CRY &&
5523       AOP_TYPE (right) == AOP_CRY)
5524     {
5525       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5526       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5527       outBitC (result);
5528     }
5529   else
5530     {
5531       tlbl = newiTempLabel (NULL);
5532       toBoolean (left);
5533       emitcode ("jz", "%05d$", tlbl->key + 100);
5534       toBoolean (right);
5535       emitcode ("", "%05d$:", tlbl->key + 100);
5536       outBitAcc (result);
5537     }
5538
5539   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5540   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5541   freeAsmop (result, NULL, ic, TRUE);
5542 }
5543
5544
5545 /*-----------------------------------------------------------------*/
5546 /* genOrOp - for || operation                                      */
5547 /*-----------------------------------------------------------------*/
5548 static void
5549 genOrOp (iCode * ic)
5550 {
5551   operand *left, *right, *result;
5552   symbol *tlbl;
5553
5554   D(emitcode (";     genOrOp",""));
5555
5556   /* note here that || operations that are in an
5557      if statement are taken away by backPatchLabels
5558      only those used in arthmetic operations remain */
5559   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5560   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5561   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5562
5563   /* if both are bit variables */
5564   if (AOP_TYPE (left) == AOP_CRY &&
5565       AOP_TYPE (right) == AOP_CRY)
5566     {
5567       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5568       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5569       outBitC (result);
5570     }
5571   else
5572     {
5573       tlbl = newiTempLabel (NULL);
5574       toBoolean (left);
5575       emitcode ("jnz", "%05d$", tlbl->key + 100);
5576       toBoolean (right);
5577       emitcode ("", "%05d$:", tlbl->key + 100);
5578       outBitAcc (result);
5579     }
5580
5581   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5582   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5583   freeAsmop (result, NULL, ic, TRUE);
5584 }
5585
5586 /*-----------------------------------------------------------------*/
5587 /* isLiteralBit - test if lit == 2^n                               */
5588 /*-----------------------------------------------------------------*/
5589 static int
5590 isLiteralBit (unsigned long lit)
5591 {
5592   unsigned long pw[32] =
5593   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5594    0x100L, 0x200L, 0x400L, 0x800L,
5595    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5596    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5597    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5598    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5599    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5600   int idx;
5601
5602   for (idx = 0; idx < 32; idx++)
5603     if (lit == pw[idx])
5604       return idx + 1;
5605   return 0;
5606 }
5607
5608 /*-----------------------------------------------------------------*/
5609 /* continueIfTrue -                                                */
5610 /*-----------------------------------------------------------------*/
5611 static void
5612 continueIfTrue (iCode * ic)
5613 {
5614   if (IC_TRUE (ic))
5615     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5616   ic->generated = 1;
5617 }
5618
5619 /*-----------------------------------------------------------------*/
5620 /* jmpIfTrue -                                                     */
5621 /*-----------------------------------------------------------------*/
5622 static void
5623 jumpIfTrue (iCode * ic)
5624 {
5625   if (!IC_TRUE (ic))
5626     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5627   ic->generated = 1;
5628 }
5629
5630 /*-----------------------------------------------------------------*/
5631 /* jmpTrueOrFalse -                                                */
5632 /*-----------------------------------------------------------------*/
5633 static void
5634 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5635 {
5636   // ugly but optimized by peephole
5637   if (IC_TRUE (ic))
5638     {
5639       symbol *nlbl = newiTempLabel (NULL);
5640       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5641       emitcode ("", "%05d$:", tlbl->key + 100);
5642       freeForBranchAsmop (result);
5643       freeForBranchAsmop (right);
5644       freeForBranchAsmop (left);
5645       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5646       emitcode ("", "%05d$:", nlbl->key + 100);
5647     }
5648   else
5649     {
5650       freeForBranchAsmop (result);
5651       freeForBranchAsmop (right);
5652       freeForBranchAsmop (left);
5653       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5654       emitcode ("", "%05d$:", tlbl->key + 100);
5655     }
5656   ic->generated = 1;
5657 }
5658
5659 /*-----------------------------------------------------------------*/
5660 /* genAnd  - code for and                                          */
5661 /*-----------------------------------------------------------------*/
5662 static void
5663 genAnd (iCode * ic, iCode * ifx)
5664 {
5665   operand *left, *right, *result;
5666   int size, offset = 0;
5667   unsigned long lit = 0L;
5668   int bytelit = 0;
5669   char buffer[10];
5670
5671   D(emitcode (";     genAnd",""));
5672
5673   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5674   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5675   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5676
5677 #ifdef DEBUG_TYPE
5678   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5679             AOP_TYPE (result),
5680             AOP_TYPE (left), AOP_TYPE (right));
5681   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5682             AOP_SIZE (result),
5683             AOP_SIZE (left), AOP_SIZE (right));
5684 #endif
5685
5686   /* if left is a literal & right is not then exchange them */
5687   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5688       AOP_NEEDSACC (left))
5689     {
5690       operand *tmp = right;
5691       right = left;
5692       left = tmp;
5693     }
5694
5695   /* if result = right then exchange left and right */
5696   if (sameRegs (AOP (result), AOP (right)))
5697     {
5698       operand *tmp = right;
5699       right = left;
5700       left = tmp;
5701     }
5702
5703   /* if right is bit then exchange them */
5704   if (AOP_TYPE (right) == AOP_CRY &&
5705       AOP_TYPE (left) != AOP_CRY)
5706     {
5707       operand *tmp = right;
5708       right = left;
5709       left = tmp;
5710     }
5711   if (AOP_TYPE (right) == AOP_LIT)
5712     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5713
5714   size = AOP_SIZE (result);
5715
5716   // if(bit & yy)
5717   // result = bit & yy;
5718   if (AOP_TYPE (left) == AOP_CRY)
5719     {
5720       // c = bit & literal;
5721       if (AOP_TYPE (right) == AOP_LIT)
5722         {
5723           if (lit & 1)
5724             {
5725               if (size && sameRegs (AOP (result), AOP (left)))
5726                 // no change
5727                 goto release;
5728               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5729             }
5730           else
5731             {
5732               // bit(result) = 0;
5733               if (size && (AOP_TYPE (result) == AOP_CRY))
5734                 {
5735                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5736                   goto release;
5737                 }
5738               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5739                 {
5740                   jumpIfTrue (ifx);
5741                   goto release;
5742                 }
5743               emitcode ("clr", "c");
5744             }
5745         }
5746       else
5747         {
5748           if (AOP_TYPE (right) == AOP_CRY)
5749             {
5750               // c = bit & bit;
5751               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5752               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5753             }
5754           else
5755             {
5756               // c = bit & val;
5757               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5758               // c = lsb
5759               emitcode ("rrc", "a");
5760               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5761             }
5762         }
5763       // bit = c
5764       // val = c
5765       if (size)
5766         outBitC (result);
5767       // if(bit & ...)
5768       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5769         genIfxJump (ifx, "c", left, right, result);
5770       goto release;
5771     }
5772
5773   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5774   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5775   if ((AOP_TYPE (right) == AOP_LIT) &&
5776       (AOP_TYPE (result) == AOP_CRY) &&
5777       (AOP_TYPE (left) != AOP_CRY))
5778     {
5779       int posbit = isLiteralBit (lit);
5780       /* left &  2^n */
5781       if (posbit)
5782         {
5783           posbit--;
5784           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5785           // bit = left & 2^n
5786           if (size)
5787             {
5788               switch (posbit & 0x07)
5789                 {
5790                   case 0: emitcode ("rrc", "a");
5791                           break;
5792                   case 7: emitcode ("rlc", "a");
5793                           break;
5794                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5795                           break;
5796                 }
5797             }
5798           // if(left &  2^n)
5799           else
5800             {
5801               if (ifx)
5802                 {
5803                   SNPRINTF (buffer, sizeof(buffer),
5804                             "acc.%d", posbit & 0x07);
5805                   genIfxJump (ifx, buffer, left, right, result);
5806                 }
5807               else
5808                 {// what is this case? just found it in ds390/gen.c
5809                    emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5810                 }
5811               goto release;
5812             }
5813         }
5814       else
5815         {
5816           symbol *tlbl = newiTempLabel (NULL);
5817           int sizel = AOP_SIZE (left);
5818           if (size)
5819             emitcode ("setb", "c");
5820           while (sizel--)
5821             {
5822               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5823                 {
5824                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5825                   // byte ==  2^n ?
5826                   if ((posbit = isLiteralBit (bytelit)) != 0)
5827                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5828                   else
5829                     {
5830                       if (bytelit != 0x0FFL)
5831                         emitcode ("anl", "a,%s",
5832                                   aopGet (AOP (right), offset, FALSE, TRUE));
5833                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5834                     }
5835                 }
5836               offset++;
5837             }
5838           // bit = left & literal
5839           if (size)
5840             {
5841               emitcode ("clr", "c");
5842               emitcode ("", "%05d$:", tlbl->key + 100);
5843             }
5844           // if(left & literal)
5845           else
5846             {
5847               if (ifx)
5848                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5849               else
5850                 emitcode ("", "%05d$:", tlbl->key + 100);
5851               goto release;
5852             }
5853         }
5854       outBitC (result);
5855       goto release;
5856     }
5857
5858   /* if left is same as result */
5859   if (sameRegs (AOP (result), AOP (left)))
5860     {
5861       for (; size--; offset++)
5862         {
5863           if (AOP_TYPE (right) == AOP_LIT)
5864             {
5865               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5866               if (bytelit == 0x0FF)
5867                 {
5868                   /* dummy read of volatile operand */
5869                   if (isOperandVolatile (left, FALSE))
5870                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5871                   else
5872                     continue;
5873                 }
5874               else if (bytelit == 0)
5875                 {
5876                   aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5877                 }
5878               else if (IS_AOP_PREG (result))
5879                 {
5880                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5881                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5882                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5883                 }
5884               else
5885                 emitcode ("anl", "%s,%s",
5886                           aopGet (AOP (left), offset, FALSE, TRUE),
5887                           aopGet (AOP (right), offset, FALSE, FALSE));
5888             }
5889           else
5890             {
5891               if (AOP_TYPE (left) == AOP_ACC)
5892                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5893               else
5894                 {
5895                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5896                   if (IS_AOP_PREG (result))
5897                     {
5898                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5899                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5900                     }
5901                   else
5902                     emitcode ("anl", "%s,a",
5903                               aopGet (AOP (left), offset, FALSE, TRUE));
5904                 }
5905             }
5906         }
5907     }
5908   else
5909     {
5910       // left & result in different registers
5911       if (AOP_TYPE (result) == AOP_CRY)
5912         {
5913           // result = bit
5914           // if(size), result in bit
5915           // if(!size && ifx), conditional oper: if(left & right)
5916           symbol *tlbl = newiTempLabel (NULL);
5917           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5918           if (size)
5919             emitcode ("setb", "c");
5920           while (sizer--)
5921             {
5922               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5923                 emitcode ("anl", "a,%s",
5924                           aopGet (AOP (right), offset, FALSE, FALSE));
5925               } else {
5926                 if (AOP_TYPE(left)==AOP_ACC) {
5927                   bool pushedB = pushB ();
5928                   emitcode("mov", "b,a");
5929                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5930                   emitcode("anl", "a,b");
5931                   popB (pushedB);
5932                 }else {
5933                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5934                   emitcode ("anl", "a,%s",
5935                             aopGet (AOP (left), offset, FALSE, FALSE));
5936                 }
5937               }
5938               emitcode ("jnz", "%05d$", tlbl->key + 100);
5939               offset++;
5940             }
5941           if (size)
5942             {
5943               CLRC;
5944               emitcode ("", "%05d$:", tlbl->key + 100);
5945               outBitC (result);
5946             }
5947           else if (ifx)
5948             jmpTrueOrFalse (ifx, tlbl, left, right, result);
5949           else
5950             emitcode ("", "%05d$:", tlbl->key + 100);
5951         }
5952       else
5953         {
5954           for (; (size--); offset++)
5955             {
5956               // normal case
5957               // result = left & right
5958               if (AOP_TYPE (right) == AOP_LIT)
5959                 {
5960                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5961                   if (bytelit == 0x0FF)
5962                     {
5963                       aopPut (AOP (result),
5964                               aopGet (AOP (left), offset, FALSE, FALSE),
5965                               offset,
5966                               isOperandVolatile (result, FALSE));
5967                       continue;
5968                     }
5969                   else if (bytelit == 0)
5970                     {
5971                       /* dummy read of volatile operand */
5972                       if (isOperandVolatile (left, FALSE))
5973                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5974                       aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5975                       continue;
5976                     }
5977                 }
5978               // faster than result <- left, anl result,right
5979               // and better if result is SFR
5980               if (AOP_TYPE (left) == AOP_ACC)
5981                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5982               else
5983                 {
5984                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5985                   emitcode ("anl", "a,%s",
5986                             aopGet (AOP (left), offset, FALSE, FALSE));
5987                 }
5988               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5989             }
5990         }
5991     }
5992
5993 release:
5994   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5995   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5996   freeAsmop (result, NULL, ic, TRUE);
5997 }
5998
5999 /*-----------------------------------------------------------------*/
6000 /* genOr  - code for or                                            */
6001 /*-----------------------------------------------------------------*/
6002 static void
6003 genOr (iCode * ic, iCode * ifx)
6004 {
6005   operand *left, *right, *result;
6006   int size, offset = 0;
6007   unsigned long lit = 0L;
6008   int bytelit = 0;
6009
6010   D(emitcode (";     genOr",""));
6011
6012   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6013   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6014   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6015
6016 #ifdef DEBUG_TYPE
6017   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6018             AOP_TYPE (result),
6019             AOP_TYPE (left), AOP_TYPE (right));
6020   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6021             AOP_SIZE (result),
6022             AOP_SIZE (left), AOP_SIZE (right));
6023 #endif
6024
6025   /* if left is a literal & right is not then exchange them */
6026   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6027       AOP_NEEDSACC (left))
6028     {
6029       operand *tmp = right;
6030       right = left;
6031       left = tmp;
6032     }
6033
6034   /* if result = right then exchange them */
6035   if (sameRegs (AOP (result), AOP (right)))
6036     {
6037       operand *tmp = right;
6038       right = left;
6039       left = tmp;
6040     }
6041
6042   /* if right is bit then exchange them */
6043   if (AOP_TYPE (right) == AOP_CRY &&
6044       AOP_TYPE (left) != AOP_CRY)
6045     {
6046       operand *tmp = right;
6047       right = left;
6048       left = tmp;
6049     }
6050   if (AOP_TYPE (right) == AOP_LIT)
6051     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6052
6053   size = AOP_SIZE (result);
6054
6055   // if(bit | yy)
6056   // xx = bit | yy;
6057   if (AOP_TYPE (left) == AOP_CRY)
6058     {
6059       if (AOP_TYPE (right) == AOP_LIT)
6060         {
6061           // c = bit | literal;
6062           if (lit)
6063             {
6064               // lit != 0 => result = 1
6065               if (AOP_TYPE (result) == AOP_CRY)
6066                 {
6067                   if (size)
6068                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6069                   else if (ifx)
6070                     continueIfTrue (ifx);
6071                   goto release;
6072                 }
6073               emitcode ("setb", "c");
6074             }
6075           else
6076             {
6077               // lit == 0 => result = left
6078               if (size && sameRegs (AOP (result), AOP (left)))
6079                 goto release;
6080               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6081             }
6082         }
6083       else
6084         {
6085           if (AOP_TYPE (right) == AOP_CRY)
6086             {
6087               // c = bit | bit;
6088               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6089               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6090             }
6091           else
6092             {
6093               // c = bit | val;
6094               symbol *tlbl = newiTempLabel (NULL);
6095               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6096                 emitcode ("setb", "c");
6097               emitcode ("jb", "%s,%05d$",
6098                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6099               toBoolean (right);
6100               emitcode ("jnz", "%05d$", tlbl->key + 100);
6101               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6102                 {
6103                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
6104                   goto release;
6105                 }
6106               else
6107                 {
6108                   CLRC;
6109                   emitcode ("", "%05d$:", tlbl->key + 100);
6110                 }
6111             }
6112         }
6113       // bit = c
6114       // val = c
6115       if (size)
6116         outBitC (result);
6117       // if(bit | ...)
6118       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6119         genIfxJump (ifx, "c", left, right, result);
6120       goto release;
6121     }
6122
6123   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6124   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6125   if ((AOP_TYPE (right) == AOP_LIT) &&
6126       (AOP_TYPE (result) == AOP_CRY) &&
6127       (AOP_TYPE (left) != AOP_CRY))
6128     {
6129       if (lit)
6130         {
6131           // result = 1
6132           if (size)
6133             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6134           else
6135             continueIfTrue (ifx);
6136           goto release;
6137         }
6138       else
6139         {
6140           // lit = 0, result = boolean(left)
6141           if (size)
6142             emitcode ("setb", "c");
6143           toBoolean (right);
6144           if (size)
6145             {
6146               symbol *tlbl = newiTempLabel (NULL);
6147               emitcode ("jnz", "%05d$", tlbl->key + 100);
6148               CLRC;
6149               emitcode ("", "%05d$:", tlbl->key + 100);
6150             }
6151           else
6152             {
6153               genIfxJump (ifx, "a", left, right, result);
6154               goto release;
6155             }
6156         }
6157       outBitC (result);
6158       goto release;
6159     }
6160
6161   /* if left is same as result */
6162   if (sameRegs (AOP (result), AOP (left)))
6163     {
6164       for (; size--; offset++)
6165         {
6166           if (AOP_TYPE (right) == AOP_LIT)
6167             {
6168               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6169               if (bytelit == 0)
6170                 {
6171                   /* dummy read of volatile operand */
6172                   if (isOperandVolatile (left, FALSE))
6173                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6174                   else
6175                     continue;
6176                 }
6177               else if (bytelit == 0x0FF)
6178                 {
6179                   aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6180                 }
6181               else if (IS_AOP_PREG (left))
6182                 {
6183                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6184                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6185                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6186                 }
6187               else
6188                 {
6189                   emitcode ("orl", "%s,%s",
6190                             aopGet (AOP (left), offset, FALSE, TRUE),
6191                             aopGet (AOP (right), offset, FALSE, FALSE));
6192                 }
6193             }
6194           else
6195             {
6196               if (AOP_TYPE (left) == AOP_ACC)
6197                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6198               else
6199                 {
6200                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6201                   if (IS_AOP_PREG (left))
6202                     {
6203                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6204                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6205                     }
6206                   else
6207                     {
6208                       emitcode ("orl", "%s,a",
6209                                 aopGet (AOP (left), offset, FALSE, TRUE));
6210                     }
6211                 }
6212             }
6213         }
6214     }
6215   else
6216     {
6217       // left & result in different registers
6218       if (AOP_TYPE (result) == AOP_CRY)
6219         {
6220           // result = bit
6221           // if(size), result in bit
6222           // if(!size && ifx), conditional oper: if(left | right)
6223           symbol *tlbl = newiTempLabel (NULL);
6224           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6225           if (size)
6226             emitcode ("setb", "c");
6227           while (sizer--)
6228             {
6229               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6230                 emitcode ("orl", "a,%s",
6231                           aopGet (AOP (right), offset, FALSE, FALSE));
6232               } else {
6233                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6234                 emitcode ("orl", "a,%s",
6235                           aopGet (AOP (left), offset, FALSE, FALSE));
6236               }
6237               emitcode ("jnz", "%05d$", tlbl->key + 100);
6238               offset++;
6239             }
6240           if (size)
6241             {
6242               CLRC;
6243               emitcode ("", "%05d$:", tlbl->key + 100);
6244               outBitC (result);
6245             }
6246           else if (ifx)
6247             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6248           else
6249             emitcode ("", "%05d$:", tlbl->key + 100);
6250         }
6251       else
6252         {
6253           for (; (size--); offset++)
6254             {
6255               // normal case
6256               // result = left | right
6257               if (AOP_TYPE (right) == AOP_LIT)
6258                 {
6259                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6260                   if (bytelit == 0)
6261                     {
6262                       aopPut (AOP (result),
6263                               aopGet (AOP (left), offset, FALSE, FALSE),
6264                               offset,
6265                               isOperandVolatile (result, FALSE));
6266                       continue;
6267                     }
6268                   else if (bytelit == 0x0FF)
6269                     {
6270                       /* dummy read of volatile operand */
6271                       if (isOperandVolatile (left, FALSE))
6272                         MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6273                       aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6274                       continue;
6275                     }
6276                 }
6277               // faster than result <- left, anl result,right
6278               // and better if result is SFR
6279               if (AOP_TYPE (left) == AOP_ACC)
6280                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6281               else
6282                 {
6283                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6284                   emitcode ("orl", "a,%s",
6285                             aopGet (AOP (left), offset, FALSE, FALSE));
6286                 }
6287               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6288             }
6289         }
6290     }
6291
6292 release:
6293   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6294   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6295   freeAsmop (result, NULL, ic, TRUE);
6296 }
6297
6298 /*-----------------------------------------------------------------*/
6299 /* genXor - code for xclusive or                                   */
6300 /*-----------------------------------------------------------------*/
6301 static void
6302 genXor (iCode * ic, iCode * ifx)
6303 {
6304   operand *left, *right, *result;
6305   int size, offset = 0;
6306   unsigned long lit = 0L;
6307   int bytelit = 0;
6308
6309   D(emitcode (";     genXor",""));
6310
6311   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6312   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6313   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6314
6315 #ifdef DEBUG_TYPE
6316   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6317             AOP_TYPE (result),
6318             AOP_TYPE (left), AOP_TYPE (right));
6319   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6320             AOP_SIZE (result),
6321             AOP_SIZE (left), AOP_SIZE (right));
6322 #endif
6323
6324   /* if left is a literal & right is not ||
6325      if left needs acc & right does not */
6326   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6327       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6328     {
6329       operand *tmp = right;
6330       right = left;
6331       left = tmp;
6332     }
6333
6334   /* if result = right then exchange them */
6335   if (sameRegs (AOP (result), AOP (right)))
6336     {
6337       operand *tmp = right;
6338       right = left;
6339       left = tmp;
6340     }
6341
6342   /* if right is bit then exchange them */
6343   if (AOP_TYPE (right) == AOP_CRY &&
6344       AOP_TYPE (left) != AOP_CRY)
6345     {
6346       operand *tmp = right;
6347       right = left;
6348       left = tmp;
6349     }
6350   if (AOP_TYPE (right) == AOP_LIT)
6351     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6352
6353   size = AOP_SIZE (result);
6354
6355   // if(bit ^ yy)
6356   // xx = bit ^ yy;
6357   if (AOP_TYPE (left) == AOP_CRY)
6358     {
6359       if (AOP_TYPE (right) == AOP_LIT)
6360         {
6361           // c = bit & literal;
6362           if (lit >> 1)
6363             {
6364               // lit>>1  != 0 => result = 1
6365               if (AOP_TYPE (result) == AOP_CRY)
6366                 {
6367                   if (size)
6368                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6369                   else if (ifx)
6370                     continueIfTrue (ifx);
6371                   goto release;
6372                 }
6373               emitcode ("setb", "c");
6374             }
6375           else
6376             {
6377               // lit == (0 or 1)
6378               if (lit == 0)
6379                 {
6380                   // lit == 0, result = left
6381                   if (size && sameRegs (AOP (result), AOP (left)))
6382                     goto release;
6383                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6384                 }
6385               else
6386                 {
6387                   // lit == 1, result = not(left)
6388                   if (size && sameRegs (AOP (result), AOP (left)))
6389                     {
6390                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6391                       goto release;
6392                     }
6393                   else
6394                     {
6395                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6396                       emitcode ("cpl", "c");
6397                     }
6398                 }
6399             }
6400
6401         }
6402       else
6403         {
6404           // right != literal
6405           symbol *tlbl = newiTempLabel (NULL);
6406           if (AOP_TYPE (right) == AOP_CRY)
6407             {
6408               // c = bit ^ bit;
6409               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6410             }
6411           else
6412             {
6413               int sizer = AOP_SIZE (right);
6414               // c = bit ^ val
6415               // if val>>1 != 0, result = 1
6416               emitcode ("setb", "c");
6417               while (sizer)
6418                 {
6419                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6420                   if (sizer == 1)
6421                     // test the msb of the lsb
6422                     emitcode ("anl", "a,#0xfe");
6423                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6424                   sizer--;
6425                 }
6426               // val = (0,1)
6427               emitcode ("rrc", "a");
6428             }
6429           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6430           emitcode ("cpl", "c");
6431           emitcode ("", "%05d$:", (tlbl->key + 100));
6432         }
6433       // bit = c
6434       // val = c
6435       if (size)
6436         outBitC (result);
6437       // if(bit | ...)
6438       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6439         genIfxJump (ifx, "c", left, right, result);
6440       goto release;
6441     }
6442
6443   /* if left is same as result */
6444   if (sameRegs (AOP (result), AOP (left)))
6445     {
6446       for (; size--; offset++)
6447         {
6448           if (AOP_TYPE (right) == AOP_LIT)
6449             {
6450               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6451               if (bytelit == 0)
6452                 {
6453                   /* dummy read of volatile operand */
6454                   if (isOperandVolatile (left, FALSE))
6455                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6456                   else
6457                     continue;
6458                 }
6459               else if (IS_AOP_PREG (left))
6460                 {
6461                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6462                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6463                   aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6464                 }
6465               else
6466                 {
6467                   emitcode ("xrl", "%s,%s",
6468                             aopGet (AOP (left), offset, FALSE, TRUE),
6469                             aopGet (AOP (right), offset, FALSE, FALSE));
6470                 }
6471             }
6472           else
6473             {
6474               if (AOP_TYPE (left) == AOP_ACC)
6475                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6476               else
6477                 {
6478                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6479                   if (IS_AOP_PREG (left))
6480                     {
6481                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6482                       aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6483                     }
6484                   else
6485                     emitcode ("xrl", "%s,a",
6486                               aopGet (AOP (left), offset, FALSE, TRUE));
6487                 }
6488             }
6489         }
6490     }
6491   else
6492     {
6493       // left & result in different registers
6494       if (AOP_TYPE (result) == AOP_CRY)
6495         {
6496           // result = bit
6497           // if(size), result in bit
6498           // if(!size && ifx), conditional oper: if(left ^ right)
6499           symbol *tlbl = newiTempLabel (NULL);
6500           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6501           if (size)
6502             emitcode ("setb", "c");
6503           while (sizer--)
6504             {
6505               if ((AOP_TYPE (right) == AOP_LIT) &&
6506                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6507                 {
6508                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6509                 }
6510               else
6511                 {
6512                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6513                     emitcode ("xrl", "a,%s",
6514                               aopGet (AOP (right), offset, FALSE, FALSE));
6515                   } else {
6516                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6517                     emitcode ("xrl", "a,%s",
6518                               aopGet (AOP (left), offset, FALSE, FALSE));
6519                   }
6520                 }
6521               emitcode ("jnz", "%05d$", tlbl->key + 100);
6522               offset++;
6523             }
6524           if (size)
6525             {
6526               CLRC;
6527               emitcode ("", "%05d$:", tlbl->key + 100);
6528               outBitC (result);
6529             }
6530           else if (ifx)
6531             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6532         }
6533       else
6534         {
6535           for (; (size--); offset++)
6536             {
6537               // normal case
6538               // result = left & right
6539               if (AOP_TYPE (right) == AOP_LIT)
6540                 {
6541                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6542                   if (bytelit == 0)
6543                     {
6544                       aopPut (AOP (result),
6545                               aopGet (AOP (left), offset, FALSE, FALSE),
6546                               offset,
6547                               isOperandVolatile (result, FALSE));
6548                       continue;
6549                     }
6550                 }
6551               // faster than result <- left, anl result,right
6552               // and better if result is SFR
6553               if (AOP_TYPE (left) == AOP_ACC)
6554                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6555               else
6556                 {
6557                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6558                   emitcode ("xrl", "a,%s",
6559                             aopGet (AOP (left), offset, FALSE, TRUE));
6560                 }
6561               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6562             }
6563         }
6564     }
6565
6566 release:
6567   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6568   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6569   freeAsmop (result, NULL, ic, TRUE);
6570 }
6571
6572 /*-----------------------------------------------------------------*/
6573 /* genInline - write the inline code out                           */
6574 /*-----------------------------------------------------------------*/
6575 static void
6576 genInline (iCode * ic)
6577 {
6578   char *buffer, *bp, *bp1;
6579
6580   D(emitcode (";     genInline",""));
6581
6582   _G.inLine += (!options.asmpeep);
6583
6584   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6585   strcpy (buffer, IC_INLINE (ic));
6586
6587   /* emit each line as a code */
6588   while (*bp)
6589     {
6590       if (*bp == '\n')
6591         {
6592           *bp++ = '\0';
6593           emitcode (bp1, "");
6594           bp1 = bp;
6595         }
6596       else
6597         {
6598           /* Add \n for labels, not dirs such as c:\mydir */
6599           if ( (*bp == ':') && (isspace(bp[1])) )
6600             {
6601               bp++;
6602               *bp = '\0';
6603               bp++;
6604               emitcode (bp1, "");
6605               bp1 = bp;
6606             }
6607           else
6608             bp++;
6609         }
6610     }
6611   if (bp1 != bp)
6612     emitcode (bp1, "");
6613   /*     emitcode("",buffer); */
6614   _G.inLine -= (!options.asmpeep);
6615 }
6616
6617 /*-----------------------------------------------------------------*/
6618 /* genRRC - rotate right with carry                                */
6619 /*-----------------------------------------------------------------*/
6620 static void
6621 genRRC (iCode * ic)
6622 {
6623   operand *left, *result;
6624   int size, offset = 0;
6625   char *l;
6626
6627   D(emitcode (";     genRRC",""));
6628
6629   /* rotate right with carry */
6630   left = IC_LEFT (ic);
6631   result = IC_RESULT (ic);
6632   aopOp (left, ic, FALSE);
6633   aopOp (result, ic, FALSE);
6634
6635   /* move it to the result */
6636   size = AOP_SIZE (result);
6637   offset = size - 1;
6638   if (size == 1) { /* special case for 1 byte */
6639       l = aopGet (AOP (left), offset, FALSE, FALSE);
6640       MOVA (l);
6641       emitcode ("rr", "a");
6642       goto release;
6643   }
6644   /* no need to clear carry, bit7 will be written later */
6645   while (size--)
6646     {
6647       l = aopGet (AOP (left), offset, FALSE, FALSE);
6648       MOVA (l);
6649       emitcode ("rrc", "a");
6650       if (AOP_SIZE (result) > 1)
6651         aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6652     }
6653   /* now we need to put the carry into the
6654      highest order byte of the result */
6655   if (AOP_SIZE (result) > 1)
6656     {
6657       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6658       MOVA (l);
6659     }
6660   emitcode ("mov", "acc.7,c");
6661  release:
6662   aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6663   freeAsmop (left, NULL, ic, TRUE);
6664   freeAsmop (result, NULL, ic, TRUE);
6665 }
6666
6667 /*-----------------------------------------------------------------*/
6668 /* genRLC - generate code for rotate left with carry               */
6669 /*-----------------------------------------------------------------*/
6670 static void
6671 genRLC (iCode * ic)
6672 {
6673   operand *left, *result;
6674   int size, offset = 0;
6675   char *l;
6676
6677   D(emitcode (";     genRLC",""));
6678
6679   /* rotate right with carry */
6680   left = IC_LEFT (ic);
6681   result = IC_RESULT (ic);
6682   aopOp (left, ic, FALSE);
6683   aopOp (result, ic, FALSE);
6684
6685   /* move it to the result */
6686   size = AOP_SIZE (result);
6687   offset = 0;
6688   if (size--)
6689     {
6690       l = aopGet (AOP (left), offset, FALSE, FALSE);
6691       MOVA (l);
6692       if (size == 0) { /* special case for 1 byte */
6693               emitcode("rl","a");
6694               goto release;
6695       }
6696       emitcode("rlc","a"); /* bit0 will be written later */
6697       if (AOP_SIZE (result) > 1)
6698         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6699       while (size--)
6700         {
6701           l = aopGet (AOP (left), offset, FALSE, FALSE);
6702           MOVA (l);
6703           emitcode ("rlc", "a");
6704           if (AOP_SIZE (result) > 1)
6705             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6706         }
6707     }
6708   /* now we need to put the carry into the
6709      highest order byte of the result */
6710   if (AOP_SIZE (result) > 1)
6711     {
6712       l = aopGet (AOP (result), 0, FALSE, FALSE);
6713       MOVA (l);
6714     }
6715   emitcode ("mov", "acc.0,c");
6716  release:
6717   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6718   freeAsmop (left, NULL, ic, TRUE);
6719   freeAsmop (result, NULL, ic, TRUE);
6720 }
6721
6722 /*-----------------------------------------------------------------*/
6723 /* genGetHbit - generates code get highest order bit               */
6724 /*-----------------------------------------------------------------*/
6725 static void
6726 genGetHbit (iCode * ic)
6727 {
6728   operand *left, *result;
6729
6730   D(emitcode (";     genGetHbit",""));
6731
6732   left = IC_LEFT (ic);
6733   result = IC_RESULT (ic);
6734   aopOp (left, ic, FALSE);
6735   aopOp (result, ic, FALSE);
6736
6737   /* get the highest order byte into a */
6738   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6739   if (AOP_TYPE (result) == AOP_CRY)
6740     {
6741       emitcode ("rlc", "a");
6742       outBitC (result);
6743     }
6744   else
6745     {
6746       emitcode ("rl", "a");
6747       emitcode ("anl", "a,#0x01");
6748       outAcc (result);
6749     }
6750
6751
6752   freeAsmop (left, NULL, ic, TRUE);
6753   freeAsmop (result, NULL, ic, TRUE);
6754 }
6755
6756 /*-----------------------------------------------------------------*/
6757 /* genSwap - generates code to swap nibbles or bytes               */
6758 /*-----------------------------------------------------------------*/
6759 static void
6760 genSwap (iCode * ic)
6761 {
6762   operand *left, *result;
6763
6764   D(emitcode (";     genSwap",""));
6765
6766   left = IC_LEFT (ic);
6767   result = IC_RESULT (ic);
6768   aopOp (left, ic, FALSE);
6769   aopOp (result, ic, FALSE);
6770
6771   switch (AOP_SIZE (left))
6772     {
6773     case 1: /* swap nibbles in byte */
6774       MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6775       emitcode ("swap", "a");
6776       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6777       break;
6778     case 2: /* swap bytes in word */
6779       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6780         {
6781           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6782           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6783                   0, isOperandVolatile (result, FALSE));
6784           aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6785         }
6786       else if (operandsEqu (left, result))
6787         {
6788           char * reg = "a";
6789           bool pushedB = FALSE, leftInB = FALSE;
6790
6791           MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6792           if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6793             {
6794               pushedB = pushB ();
6795               emitcode ("mov", "b,a");
6796               reg = "b";
6797               leftInB = TRUE;
6798             }
6799           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6800                   0, isOperandVolatile (result, FALSE));
6801           aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6802
6803           if (leftInB)
6804             popB (pushedB);
6805         }
6806       else
6807         {
6808           aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6809                   0, isOperandVolatile (result, FALSE));
6810           aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6811                   1, isOperandVolatile (result, FALSE));
6812         }
6813       break;
6814     default:
6815       wassertl(FALSE, "unsupported SWAP operand size");
6816     }
6817
6818   freeAsmop (left, NULL, ic, TRUE);
6819   freeAsmop (result, NULL, ic, TRUE);
6820 }
6821
6822
6823 /*-----------------------------------------------------------------*/
6824 /* AccRol - rotate left accumulator by known count                 */
6825 /*-----------------------------------------------------------------*/
6826 static void
6827 AccRol (int shCount)
6828 {
6829   shCount &= 0x0007;            // shCount : 0..7
6830
6831   switch (shCount)
6832     {
6833     case 0:
6834       break;
6835     case 1:
6836       emitcode ("rl", "a");
6837       break;
6838     case 2:
6839       emitcode ("rl", "a");
6840       emitcode ("rl", "a");
6841       break;
6842     case 3:
6843       emitcode ("swap", "a");
6844       emitcode ("rr", "a");
6845       break;
6846     case 4:
6847       emitcode ("swap", "a");
6848       break;
6849     case 5:
6850       emitcode ("swap", "a");
6851       emitcode ("rl", "a");
6852       break;
6853     case 6:
6854       emitcode ("rr", "a");
6855       emitcode ("rr", "a");
6856       break;
6857     case 7:
6858       emitcode ("rr", "a");
6859       break;
6860     }
6861 }
6862
6863 /*-----------------------------------------------------------------*/
6864 /* AccLsh - left shift accumulator by known count                  */
6865 /*-----------------------------------------------------------------*/
6866 static void
6867 AccLsh (int shCount)
6868 {
6869   if (shCount != 0)
6870     {
6871       if (shCount == 1)
6872         emitcode ("add", "a,acc");
6873       else if (shCount == 2)
6874         {
6875           emitcode ("add", "a,acc");
6876           emitcode ("add", "a,acc");
6877         }
6878       else
6879         {
6880           /* rotate left accumulator */
6881           AccRol (shCount);
6882           /* and kill the lower order bits */
6883           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6884         }
6885     }
6886 }
6887
6888 /*-----------------------------------------------------------------*/
6889 /* AccRsh - right shift accumulator by known count                 */
6890 /*-----------------------------------------------------------------*/
6891 static void
6892 AccRsh (int shCount)
6893 {
6894   if (shCount != 0)
6895     {
6896       if (shCount == 1)
6897         {
6898           CLRC;
6899           emitcode ("rrc", "a");
6900         }
6901       else
6902         {
6903           /* rotate right accumulator */
6904           AccRol (8 - shCount);
6905           /* and kill the higher order bits */
6906           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6907         }
6908     }
6909 }
6910
6911 /*-----------------------------------------------------------------*/
6912 /* AccSRsh - signed right shift accumulator by known count                 */
6913 /*-----------------------------------------------------------------*/
6914 static void
6915 AccSRsh (int shCount)
6916 {
6917   symbol *tlbl;
6918   if (shCount != 0)
6919     {
6920       if (shCount == 1)
6921         {
6922           emitcode ("mov", "c,acc.7");
6923           emitcode ("rrc", "a");
6924         }
6925       else if (shCount == 2)
6926         {
6927           emitcode ("mov", "c,acc.7");
6928           emitcode ("rrc", "a");
6929           emitcode ("mov", "c,acc.7");
6930           emitcode ("rrc", "a");
6931         }
6932       else
6933         {
6934           tlbl = newiTempLabel (NULL);
6935           /* rotate right accumulator */
6936           AccRol (8 - shCount);
6937           /* and kill the higher order bits */
6938           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6939           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6940           emitcode ("orl", "a,#0x%02x",
6941                     (unsigned char) ~SRMask[shCount]);
6942           emitcode ("", "%05d$:", tlbl->key + 100);
6943         }
6944     }
6945 }
6946
6947 /*-----------------------------------------------------------------*/
6948 /* shiftR1Left2Result - shift right one byte from left to result   */
6949 /*-----------------------------------------------------------------*/
6950 static void
6951 shiftR1Left2Result (operand * left, int offl,
6952                     operand * result, int offr,
6953                     int shCount, int sign)
6954 {
6955   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6956   /* shift right accumulator */
6957   if (sign)
6958     AccSRsh (shCount);
6959   else
6960     AccRsh (shCount);
6961   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6962 }
6963
6964 /*-----------------------------------------------------------------*/
6965 /* shiftL1Left2Result - shift left one byte from left to result    */
6966 /*-----------------------------------------------------------------*/
6967 static void
6968 shiftL1Left2Result (operand * left, int offl,
6969                     operand * result, int offr, int shCount)
6970 {
6971   char *l;
6972   l = aopGet (AOP (left), offl, FALSE, FALSE);
6973   MOVA (l);
6974   /* shift left accumulator */
6975   AccLsh (shCount);
6976   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6977 }
6978
6979 /*-----------------------------------------------------------------*/
6980 /* movLeft2Result - move byte from left to result                  */
6981 /*-----------------------------------------------------------------*/
6982 static void
6983 movLeft2Result (operand * left, int offl,
6984                 operand * result, int offr, int sign)
6985 {
6986   char *l;
6987   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6988     {
6989       l = aopGet (AOP (left), offl, FALSE, FALSE);
6990
6991       if (*l == '@' && (IS_AOP_PREG (result)))
6992         {
6993           emitcode ("mov", "a,%s", l);
6994           aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6995         }
6996       else
6997         {
6998           if (!sign)
6999             aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
7000           else
7001             {
7002               /* MSB sign in acc.7 ! */
7003               if (getDataSize (left) == offl + 1)
7004                 {
7005                   emitcode ("mov", "a,%s", l);
7006                   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7007                 }
7008             }
7009         }
7010     }
7011 }
7012
7013 /*-----------------------------------------------------------------*/
7014 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7015 /*-----------------------------------------------------------------*/
7016 static void
7017 AccAXRrl1 (char *x)
7018 {
7019   emitcode ("rrc", "a");
7020   emitcode ("xch", "a,%s", x);
7021   emitcode ("rrc", "a");
7022   emitcode ("xch", "a,%s", x);
7023 }
7024
7025 /*-----------------------------------------------------------------*/
7026 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7027 /*-----------------------------------------------------------------*/
7028 static void
7029 AccAXLrl1 (char *x)
7030 {
7031   emitcode ("xch", "a,%s", x);
7032   emitcode ("rlc", "a");
7033   emitcode ("xch", "a,%s", x);
7034   emitcode ("rlc", "a");
7035 }
7036
7037 /*-----------------------------------------------------------------*/
7038 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7039 /*-----------------------------------------------------------------*/
7040 static void
7041 AccAXLsh1 (char *x)
7042 {
7043   emitcode ("xch", "a,%s", x);
7044   emitcode ("add", "a,acc");
7045   emitcode ("xch", "a,%s", x);
7046   emitcode ("rlc", "a");
7047 }
7048
7049 /*-----------------------------------------------------------------*/
7050 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7051 /*-----------------------------------------------------------------*/
7052 static void
7053 AccAXLsh (char *x, int shCount)
7054 {
7055   switch (shCount)
7056     {
7057     case 0:
7058       break;
7059     case 1:
7060       AccAXLsh1 (x);
7061       break;
7062     case 2:
7063       AccAXLsh1 (x);
7064       AccAXLsh1 (x);
7065       break;
7066     case 3:
7067     case 4:
7068     case 5:                     // AAAAABBB:CCCCCDDD
7069
7070       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7071
7072       emitcode ("anl", "a,#0x%02x",
7073                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7074
7075       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7076
7077       AccRol (shCount);         // DDDCCCCC:BBB00000
7078
7079       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7080
7081       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7082
7083       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7084
7085       emitcode ("anl", "a,#0x%02x",
7086                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7087
7088       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7089
7090       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7091
7092       break;
7093     case 6:                     // AAAAAABB:CCCCCCDD
7094       emitcode ("anl", "a,#0x%02x",
7095                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7096       emitcode ("mov", "c,acc.0");      // c = B
7097       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7098 #if 0 // REMOVE ME
7099       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7100       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7101 #else
7102       emitcode("rrc","a");
7103       emitcode("xch","a,%s", x);
7104       emitcode("rrc","a");
7105       emitcode("mov","c,acc.0"); //<< get correct bit
7106       emitcode("xch","a,%s", x);
7107
7108       emitcode("rrc","a");
7109       emitcode("xch","a,%s", x);
7110       emitcode("rrc","a");
7111       emitcode("xch","a,%s", x);
7112 #endif
7113       break;
7114     case 7:                     // a:x <<= 7
7115
7116       emitcode ("anl", "a,#0x%02x",
7117                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7118
7119       emitcode ("mov", "c,acc.0");      // c = B
7120
7121       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7122
7123       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7124
7125       break;
7126     default:
7127       break;
7128     }
7129 }
7130
7131 /*-----------------------------------------------------------------*/
7132 /* AccAXRsh - right shift a:x known count (0..7)                   */
7133 /*-----------------------------------------------------------------*/
7134 static void
7135 AccAXRsh (char *x, int shCount)
7136 {
7137   switch (shCount)
7138     {
7139     case 0:
7140       break;
7141     case 1:
7142       CLRC;
7143       AccAXRrl1 (x);            // 0->a:x
7144
7145       break;
7146     case 2:
7147       CLRC;
7148       AccAXRrl1 (x);            // 0->a:x
7149
7150       CLRC;
7151       AccAXRrl1 (x);            // 0->a:x
7152
7153       break;
7154     case 3:
7155     case 4:
7156     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7157
7158       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7159
7160       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7161
7162       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7163
7164       emitcode ("anl", "a,#0x%02x",
7165                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7166
7167       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7168
7169       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7170
7171       emitcode ("anl", "a,#0x%02x",
7172                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7173
7174       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7175
7176       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7177
7178       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7179
7180       break;
7181     case 6:                     // AABBBBBB:CCDDDDDD
7182
7183       emitcode ("mov", "c,acc.7");
7184       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7185
7186       emitcode ("mov", "c,acc.7");
7187       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7188
7189       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7190
7191       emitcode ("anl", "a,#0x%02x",
7192                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7193
7194       break;
7195     case 7:                     // ABBBBBBB:CDDDDDDD
7196
7197       emitcode ("mov", "c,acc.7");      // c = A
7198
7199       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7200
7201       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7202
7203       emitcode ("anl", "a,#0x%02x",
7204                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7205
7206       break;
7207     default:
7208       break;
7209     }
7210 }
7211
7212 /*-----------------------------------------------------------------*/
7213 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7214 /*-----------------------------------------------------------------*/
7215 static void
7216 AccAXRshS (char *x, int shCount)
7217 {
7218   symbol *tlbl;
7219   switch (shCount)
7220     {
7221     case 0:
7222       break;
7223     case 1:
7224       emitcode ("mov", "c,acc.7");
7225       AccAXRrl1 (x);            // s->a:x
7226
7227       break;
7228     case 2:
7229       emitcode ("mov", "c,acc.7");
7230       AccAXRrl1 (x);            // s->a:x
7231
7232       emitcode ("mov", "c,acc.7");
7233       AccAXRrl1 (x);            // s->a:x
7234
7235       break;
7236     case 3:
7237     case 4:
7238     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7239
7240       tlbl = newiTempLabel (NULL);
7241       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7242
7243       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7244
7245       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7246
7247       emitcode ("anl", "a,#0x%02x",
7248                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7249
7250       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7251
7252       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7253
7254       emitcode ("anl", "a,#0x%02x",
7255                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7256
7257       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7258
7259       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7260
7261       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7262
7263       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7264       emitcode ("orl", "a,#0x%02x",
7265                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7266
7267       emitcode ("", "%05d$:", tlbl->key + 100);
7268       break;                    // SSSSAAAA:BBBCCCCC
7269
7270     case 6:                     // AABBBBBB:CCDDDDDD
7271
7272       tlbl = newiTempLabel (NULL);
7273       emitcode ("mov", "c,acc.7");
7274       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7275
7276       emitcode ("mov", "c,acc.7");
7277       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7278
7279       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7280
7281       emitcode ("anl", "a,#0x%02x",
7282                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7283
7284       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7285       emitcode ("orl", "a,#0x%02x",
7286                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7287
7288       emitcode ("", "%05d$:", tlbl->key + 100);
7289       break;
7290     case 7:                     // ABBBBBBB:CDDDDDDD
7291
7292       tlbl = newiTempLabel (NULL);
7293       emitcode ("mov", "c,acc.7");      // c = A
7294
7295       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7296
7297       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7298
7299       emitcode ("anl", "a,#0x%02x",
7300                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7301
7302       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7303       emitcode ("orl", "a,#0x%02x",
7304                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7305
7306       emitcode ("", "%05d$:", tlbl->key + 100);
7307       break;
7308     default:
7309       break;
7310     }
7311 }
7312
7313 /*-----------------------------------------------------------------*/
7314 /* shiftL2Left2Result - shift left two bytes from left to result   */
7315 /*-----------------------------------------------------------------*/
7316 static void
7317 shiftL2Left2Result (operand * left, int offl,
7318                     operand * result, int offr, int shCount)
7319 {
7320   if (sameRegs (AOP (result), AOP (left)) &&
7321       ((offl + MSB16) == offr))
7322     {
7323       /* don't crash result[offr] */
7324       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7325       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7326     }
7327   else
7328     {
7329       movLeft2Result (left, offl, result, offr, 0);
7330       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7331     }
7332   /* ax << shCount (x = lsb(result)) */
7333   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7334   aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7335 }
7336
7337
7338 /*-----------------------------------------------------------------*/
7339 /* shiftR2Left2Result - shift right two bytes from left to result  */
7340 /*-----------------------------------------------------------------*/
7341 static void
7342 shiftR2Left2Result (operand * left, int offl,
7343                     operand * result, int offr,
7344                     int shCount, int sign)
7345 {
7346   if (sameRegs (AOP (result), AOP (left)) &&
7347       ((offl + MSB16) == offr))
7348     {
7349       /* don't crash result[offr] */
7350       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7351       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7352     }
7353   else
7354     {
7355       movLeft2Result (left, offl, result, offr, 0);
7356       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7357     }
7358   /* a:x >> shCount (x = lsb(result)) */
7359   if (sign)
7360     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7361   else
7362     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7363   if (getDataSize (result) > 1)
7364     aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7365 }
7366
7367 /*-----------------------------------------------------------------*/
7368 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7369 /*-----------------------------------------------------------------*/
7370 static void
7371 shiftLLeftOrResult (operand * left, int offl,
7372                     operand * result, int offr, int shCount)
7373 {
7374   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7375   /* shift left accumulator */
7376   AccLsh (shCount);
7377   /* or with result */
7378   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7379   /* back to result */
7380   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7381 }
7382
7383 /*-----------------------------------------------------------------*/
7384 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7385 /*-----------------------------------------------------------------*/
7386 static void
7387 shiftRLeftOrResult (operand * left, int offl,
7388                     operand * result, int offr, int shCount)
7389 {
7390   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7391   /* shift right accumulator */
7392   AccRsh (shCount);
7393   /* or with result */
7394   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7395   /* back to result */
7396   aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7397 }
7398
7399 /*-----------------------------------------------------------------*/
7400 /* genlshOne - left shift a one byte quantity by known count       */
7401 /*-----------------------------------------------------------------*/
7402 static void
7403 genlshOne (operand * result, operand * left, int shCount)
7404 {
7405   D(emitcode (";     genlshOne",""));
7406
7407   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7408 }
7409
7410 /*-----------------------------------------------------------------*/
7411 /* genlshTwo - left shift two bytes by known amount != 0           */
7412 /*-----------------------------------------------------------------*/
7413 static void
7414 genlshTwo (operand * result, operand * left, int shCount)
7415 {
7416   int size;
7417
7418   D(emitcode (";     genlshTwo",""));
7419
7420   size = getDataSize (result);
7421
7422   /* if shCount >= 8 */
7423   if (shCount >= 8)
7424     {
7425       shCount -= 8;
7426
7427       if (size > 1)
7428         {
7429           if (shCount)
7430             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7431           else
7432             movLeft2Result (left, LSB, result, MSB16, 0);
7433         }
7434       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7435     }
7436
7437   /*  1 <= shCount <= 7 */
7438   else
7439     {
7440       if (size == 1)
7441         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7442       else
7443         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7444     }
7445 }
7446
7447 /*-----------------------------------------------------------------*/
7448 /* shiftLLong - shift left one long from left to result            */
7449 /* offl = LSB or MSB16                                             */
7450 /*-----------------------------------------------------------------*/
7451 static void
7452 shiftLLong (operand * left, operand * result, int offr)
7453 {
7454   char *l;
7455   int size = AOP_SIZE (result);
7456
7457   if (size >= LSB + offr)
7458     {
7459       l = aopGet (AOP (left), LSB, FALSE, FALSE);
7460       MOVA (l);
7461       emitcode ("add", "a,acc");
7462       if (sameRegs (AOP (left), AOP (result)) &&
7463           size >= MSB16 + offr && offr != LSB)
7464         emitcode ("xch", "a,%s",
7465                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7466       else
7467         aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7468     }
7469
7470   if (size >= MSB16 + offr)
7471     {
7472       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7473         {
7474           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7475           MOVA (l);
7476         }
7477       emitcode ("rlc", "a");
7478       if (sameRegs (AOP (left), AOP (result)) &&
7479           size >= MSB24 + offr && offr != LSB)
7480         emitcode ("xch", "a,%s",
7481                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7482       else
7483         aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7484     }
7485
7486   if (size >= MSB24 + offr)
7487     {
7488       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7489         {
7490           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7491           MOVA (l);
7492         }
7493       emitcode ("rlc", "a");
7494       if (sameRegs (AOP (left), AOP (result)) &&
7495           size >= MSB32 + offr && offr != LSB)
7496         emitcode ("xch", "a,%s",
7497                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7498       else
7499         aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7500     }
7501
7502   if (size > MSB32 + offr)
7503     {
7504       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7505         {
7506           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7507           MOVA (l);
7508         }
7509       emitcode ("rlc", "a");
7510       aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7511     }
7512   if (offr != LSB)
7513     aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7514 }
7515
7516 /*-----------------------------------------------------------------*/
7517 /* genlshFour - shift four byte by a known amount != 0             */
7518 /*-----------------------------------------------------------------*/
7519 static void
7520 genlshFour (operand * result, operand * left, int shCount)
7521 {
7522   int size;
7523
7524   D(emitcode (";     genlshFour",""));
7525
7526   size = AOP_SIZE (result);
7527
7528   /* if shifting more that 3 bytes */
7529   if (shCount >= 24)
7530     {
7531       shCount -= 24;
7532       if (shCount)
7533         /* lowest order of left goes to the highest
7534            order of the destination */
7535         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7536       else
7537         movLeft2Result (left, LSB, result, MSB32, 0);
7538       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7539       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7540       aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7541       return;
7542     }
7543
7544   /* more than two bytes */
7545   else if (shCount >= 16)
7546     {
7547       /* lower order two bytes goes to higher order two bytes */
7548       shCount -= 16;
7549       /* if some more remaining */
7550       if (shCount)
7551         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7552       else
7553         {
7554           movLeft2Result (left, MSB16, result, MSB32, 0);
7555           movLeft2Result (left, LSB, result, MSB24, 0);
7556         }
7557       aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7558       aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7559       return;
7560     }
7561
7562   /* if more than 1 byte */
7563   else if (shCount >= 8)
7564     {
7565       /* lower order three bytes goes to higher order  three bytes */
7566       shCount -= 8;
7567       if (size == 2)
7568         {
7569           if (shCount)
7570             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7571           else
7572             movLeft2Result (left, LSB, result, MSB16, 0);
7573         }
7574       else
7575         {                       /* size = 4 */
7576           if (shCount == 0)
7577             {
7578               movLeft2Result (left, MSB24, result, MSB32, 0);
7579               movLeft2Result (left, MSB16, result, MSB24, 0);
7580               movLeft2Result (left, LSB, result, MSB16, 0);
7581               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7582             }
7583           else if (shCount == 1)
7584             shiftLLong (left, result, MSB16);
7585           else
7586             {
7587               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7588               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7589               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7590               aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7591             }
7592         }
7593     }
7594
7595   /* 1 <= shCount <= 7 */
7596   else if (shCount <= 2)
7597     {
7598       shiftLLong (left, result, LSB);
7599       if (shCount == 2)
7600         shiftLLong (result, result, LSB);
7601     }
7602   /* 3 <= shCount <= 7, optimize */
7603   else
7604     {
7605       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7606       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7607       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7608     }
7609 }
7610
7611 /*-----------------------------------------------------------------*/
7612 /* genLeftShiftLiteral - left shifting by known count              */
7613 /*-----------------------------------------------------------------*/
7614 static void
7615 genLeftShiftLiteral (operand * left,
7616                      operand * right,
7617                      operand * result,
7618                      iCode * ic)
7619 {
7620   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7621   int size;
7622
7623   D(emitcode (";     genLeftShiftLiteral",""));
7624
7625   freeAsmop (right, NULL, ic, TRUE);
7626
7627   aopOp (left, ic, FALSE);
7628   aopOp (result, ic, FALSE);
7629
7630   size = getSize (operandType (result));
7631
7632 #if VIEW_SIZE
7633   emitcode ("; shift left ", "result %d, left %d", size,
7634             AOP_SIZE (left));
7635 #endif
7636
7637   /* I suppose that the left size >= result size */
7638   if (shCount == 0)
7639     {
7640       while (size--)
7641         {
7642           movLeft2Result (left, size, result, size, 0);
7643         }
7644     }
7645
7646   else if (shCount >= (size * 8))
7647     while (size--)
7648       aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7649   else
7650     {
7651       switch (size)
7652         {
7653         case 1:
7654           genlshOne (result, left, shCount);
7655           break;
7656
7657         case 2:
7658           genlshTwo (result, left, shCount);
7659           break;
7660
7661         case 4:
7662           genlshFour (result, left, shCount);
7663           break;
7664         default:
7665           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7666                   "*** ack! mystery literal shift!\n");
7667           break;
7668         }
7669     }
7670   freeAsmop (left, NULL, ic, TRUE);
7671   freeAsmop (result, NULL, ic, TRUE);
7672 }
7673
7674 /*-----------------------------------------------------------------*/
7675 /* genLeftShift - generates code for left shifting                 */
7676 /*-----------------------------------------------------------------*/
7677 static void
7678 genLeftShift (iCode * ic)
7679 {
7680   operand *left, *right, *result;
7681   int size, offset;
7682   char *l;
7683   symbol *tlbl, *tlbl1;
7684   bool pushedB;
7685
7686   D(emitcode (";     genLeftShift",""));
7687
7688   right = IC_RIGHT (ic);
7689   left = IC_LEFT (ic);
7690   result = IC_RESULT (ic);
7691
7692   aopOp (right, ic, FALSE);
7693
7694   /* if the shift count is known then do it
7695      as efficiently as possible */
7696   if (AOP_TYPE (right) == AOP_LIT)
7697     {
7698       genLeftShiftLiteral (left, right, result, ic);
7699       return;
7700     }
7701
7702   /* shift count is unknown then we have to form
7703      a loop get the loop count in B : Note: we take
7704      only the lower order byte since shifting
7705      more that 32 bits make no sense anyway, ( the
7706      largest size of an object can be only 32 bits ) */
7707
7708   pushedB = pushB ();
7709   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7710   emitcode ("inc", "b");
7711   freeAsmop (right, NULL, ic, TRUE);
7712   aopOp (left, ic, FALSE);
7713   aopOp (result, ic, FALSE);
7714
7715   /* now move the left to the result if they are not the same */
7716   if (!sameRegs (AOP (left), AOP (result)) &&
7717       AOP_SIZE (result) > 1)
7718     {
7719
7720       size = AOP_SIZE (result);
7721       offset = 0;
7722       while (size--)
7723         {
7724           l = aopGet (AOP (left), offset, FALSE, TRUE);
7725           if (*l == '@' && (IS_AOP_PREG (result)))
7726             {
7727
7728               emitcode ("mov", "a,%s", l);
7729               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7730             }
7731           else
7732             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7733           offset++;
7734         }
7735     }
7736
7737   tlbl = newiTempLabel (NULL);
7738   size = AOP_SIZE (result);
7739   offset = 0;
7740   tlbl1 = newiTempLabel (NULL);
7741
7742   /* if it is only one byte then */
7743   if (size == 1)
7744     {
7745       symbol *tlbl1 = newiTempLabel (NULL);
7746
7747       l = aopGet (AOP (left), 0, FALSE, FALSE);
7748       MOVA (l);
7749       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7750       emitcode ("", "%05d$:", tlbl->key + 100);
7751       emitcode ("add", "a,acc");
7752       emitcode ("", "%05d$:", tlbl1->key + 100);
7753       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7754       popB (pushedB);
7755       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7756       goto release;
7757     }
7758
7759   reAdjustPreg (AOP (result));
7760
7761   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7762   emitcode ("", "%05d$:", tlbl->key + 100);
7763   l = aopGet (AOP (result), offset, FALSE, FALSE);
7764   MOVA (l);
7765   emitcode ("add", "a,acc");
7766   aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7767   while (--size)
7768     {
7769       l = aopGet (AOP (result), offset, FALSE, FALSE);
7770       MOVA (l);
7771       emitcode ("rlc", "a");
7772       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7773     }
7774   reAdjustPreg (AOP (result));
7775
7776   emitcode ("", "%05d$:", tlbl1->key + 100);
7777   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7778   popB (pushedB);
7779 release:
7780   freeAsmop (left, NULL, ic, TRUE);
7781   freeAsmop (result, NULL, ic, TRUE);
7782 }
7783
7784 /*-----------------------------------------------------------------*/
7785 /* genrshOne - right shift a one byte quantity by known count      */
7786 /*-----------------------------------------------------------------*/
7787 static void
7788 genrshOne (operand * result, operand * left,
7789            int shCount, int sign)
7790 {
7791   D(emitcode (";     genrshOne",""));
7792
7793   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7794 }
7795
7796 /*-----------------------------------------------------------------*/
7797 /* genrshTwo - right shift two bytes by known amount != 0          */
7798 /*-----------------------------------------------------------------*/
7799 static void
7800 genrshTwo (operand * result, operand * left,
7801            int shCount, int sign)
7802 {
7803   D(emitcode (";     genrshTwo",""));
7804
7805   /* if shCount >= 8 */
7806   if (shCount >= 8)
7807     {
7808       shCount -= 8;
7809       if (shCount)
7810         shiftR1Left2Result (left, MSB16, result, LSB,
7811                             shCount, sign);
7812       else
7813         movLeft2Result (left, MSB16, result, LSB, sign);
7814       addSign (result, MSB16, sign);
7815     }
7816
7817   /*  1 <= shCount <= 7 */
7818   else
7819     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7820 }
7821
7822 /*-----------------------------------------------------------------*/
7823 /* shiftRLong - shift right one long from left to result           */
7824 /* offl = LSB or MSB16                                             */
7825 /*-----------------------------------------------------------------*/
7826 static void
7827 shiftRLong (operand * left, int offl,
7828             operand * result, int sign)
7829 {
7830   int isSameRegs=sameRegs(AOP(left),AOP(result));
7831
7832   if (isSameRegs && offl>1) {
7833     // we are in big trouble, but this shouldn't happen
7834     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7835   }
7836
7837   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7838
7839   if (offl==MSB16) {
7840     // shift is > 8
7841     if (sign) {
7842       emitcode ("rlc", "a");
7843       emitcode ("subb", "a,acc");
7844       if (isSameRegs)
7845         emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7846       else {
7847         aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7848         MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7849       }
7850     } else {
7851       aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7852     }
7853   }
7854
7855   if (!sign) {
7856     emitcode ("clr", "c");
7857   } else {
7858     emitcode ("mov", "c,acc.7");
7859   }
7860
7861   emitcode ("rrc", "a");
7862
7863   if (isSameRegs && offl==MSB16) {
7864     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7865   } else {
7866     aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7867     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7868   }
7869
7870   emitcode ("rrc", "a");
7871   if (isSameRegs && offl==1) {
7872     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7873   } else {
7874     aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7875     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7876   }
7877   emitcode ("rrc", "a");
7878   aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7879
7880   if (offl == LSB)
7881     {
7882       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7883       emitcode ("rrc", "a");
7884       aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7885     }
7886 }
7887
7888 /*-----------------------------------------------------------------*/
7889 /* genrshFour - shift four byte by a known amount != 0             */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 genrshFour (operand * result, operand * left,
7893             int shCount, int sign)
7894 {
7895   D(emitcode (";     genrshFour",""));
7896
7897   /* if shifting more that 3 bytes */
7898   if (shCount >= 24)
7899     {
7900       shCount -= 24;
7901       if (shCount)
7902         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7903       else
7904         movLeft2Result (left, MSB32, result, LSB, sign);
7905       addSign (result, MSB16, sign);
7906     }
7907   else if (shCount >= 16)
7908     {
7909       shCount -= 16;
7910       if (shCount)
7911         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7912       else
7913         {
7914           movLeft2Result (left, MSB24, result, LSB, 0);
7915           movLeft2Result (left, MSB32, result, MSB16, sign);
7916         }
7917       addSign (result, MSB24, sign);
7918     }
7919   else if (shCount >= 8)
7920     {
7921       shCount -= 8;
7922       if (shCount == 1)
7923         shiftRLong (left, MSB16, result, sign);
7924       else if (shCount == 0)
7925         {
7926           movLeft2Result (left, MSB16, result, LSB, 0);
7927           movLeft2Result (left, MSB24, result, MSB16, 0);
7928           movLeft2Result (left, MSB32, result, MSB24, sign);
7929           addSign (result, MSB32, sign);
7930         }
7931       else
7932         {
7933           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7934           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7935           /* the last shift is signed */
7936           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7937           addSign (result, MSB32, sign);
7938         }
7939     }
7940   else
7941     {                           /* 1 <= shCount <= 7 */
7942       if (shCount <= 2)
7943         {
7944           shiftRLong (left, LSB, result, sign);
7945           if (shCount == 2)
7946             shiftRLong (result, LSB, result, sign);
7947         }
7948       else
7949         {
7950           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7951           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7952           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7953         }
7954     }
7955 }
7956
7957 /*-----------------------------------------------------------------*/
7958 /* genRightShiftLiteral - right shifting by known count            */
7959 /*-----------------------------------------------------------------*/
7960 static void
7961 genRightShiftLiteral (operand * left,
7962                       operand * right,
7963                       operand * result,
7964                       iCode * ic,
7965                       int sign)
7966 {
7967   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7968   int size;
7969
7970   D(emitcode (";     genRightShiftLiteral",""));
7971
7972   freeAsmop (right, NULL, ic, TRUE);
7973
7974   aopOp (left, ic, FALSE);
7975   aopOp (result, ic, FALSE);
7976
7977 #if VIEW_SIZE
7978   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7979             AOP_SIZE (left));
7980 #endif
7981
7982   size = getDataSize (left);
7983   /* test the LEFT size !!! */
7984
7985   /* I suppose that the left size >= result size */
7986   if (shCount == 0)
7987     {
7988       size = getDataSize (result);
7989       while (size--)
7990         movLeft2Result (left, size, result, size, 0);
7991     }
7992
7993   else if (shCount >= (size * 8))
7994     {
7995       if (sign) {
7996         /* get sign in acc.7 */
7997         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7998       }
7999       addSign (result, LSB, sign);
8000     }
8001   else
8002     {
8003       switch (size)
8004         {
8005         case 1:
8006           genrshOne (result, left, shCount, sign);
8007           break;
8008
8009         case 2:
8010           genrshTwo (result, left, shCount, sign);
8011           break;
8012
8013         case 4:
8014           genrshFour (result, left, shCount, sign);
8015           break;
8016         default:
8017           break;
8018         }
8019     }
8020   freeAsmop (left, NULL, ic, TRUE);
8021   freeAsmop (result, NULL, ic, TRUE);
8022 }
8023
8024 /*-----------------------------------------------------------------*/
8025 /* genSignedRightShift - right shift of signed number              */
8026 /*-----------------------------------------------------------------*/
8027 static void
8028 genSignedRightShift (iCode * ic)
8029 {
8030   operand *right, *left, *result;
8031   int size, offset;
8032   char *l;
8033   symbol *tlbl, *tlbl1;
8034   bool pushedB;
8035
8036   D(emitcode (";     genSignedRightShift",""));
8037
8038   /* we do it the hard way put the shift count in b
8039      and loop thru preserving the sign */
8040
8041   right = IC_RIGHT (ic);
8042   left = IC_LEFT (ic);
8043   result = IC_RESULT (ic);
8044
8045   aopOp (right, ic, FALSE);
8046
8047
8048   if (AOP_TYPE (right) == AOP_LIT)
8049     {
8050       genRightShiftLiteral (left, right, result, ic, 1);
8051       return;
8052     }
8053   /* shift count is unknown then we have to form
8054      a loop get the loop count in B : Note: we take
8055      only the lower order byte since shifting
8056      more that 32 bits make no sense anyway, ( the
8057      largest size of an object can be only 32 bits ) */
8058
8059   pushedB = pushB ();
8060   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8061   emitcode ("inc", "b");
8062   freeAsmop (right, NULL, ic, TRUE);
8063   aopOp (left, ic, FALSE);
8064   aopOp (result, ic, FALSE);
8065
8066   /* now move the left to the result if they are not the
8067      same */
8068   if (!sameRegs (AOP (left), AOP (result)) &&
8069       AOP_SIZE (result) > 1)
8070     {
8071
8072       size = AOP_SIZE (result);
8073       offset = 0;
8074       while (size--)
8075         {
8076           l = aopGet (AOP (left), offset, FALSE, TRUE);
8077           if (*l == '@' && IS_AOP_PREG (result))
8078             {
8079
8080               emitcode ("mov", "a,%s", l);
8081               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8082             }
8083           else
8084             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8085           offset++;
8086         }
8087     }
8088
8089   /* mov the highest order bit to OVR */
8090   tlbl = newiTempLabel (NULL);
8091   tlbl1 = newiTempLabel (NULL);
8092
8093   size = AOP_SIZE (result);
8094   offset = size - 1;
8095   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8096   emitcode ("rlc", "a");
8097   emitcode ("mov", "ov,c");
8098   /* if it is only one byte then */
8099   if (size == 1)
8100     {
8101       l = aopGet (AOP (left), 0, FALSE, FALSE);
8102       MOVA (l);
8103       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8104       emitcode ("", "%05d$:", tlbl->key + 100);
8105       emitcode ("mov", "c,ov");
8106       emitcode ("rrc", "a");
8107       emitcode ("", "%05d$:", tlbl1->key + 100);
8108       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8109       popB (pushedB);
8110       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8111       goto release;
8112     }
8113
8114   reAdjustPreg (AOP (result));
8115   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8116   emitcode ("", "%05d$:", tlbl->key + 100);
8117   emitcode ("mov", "c,ov");
8118   while (size--)
8119     {
8120       l = aopGet (AOP (result), offset, FALSE, FALSE);
8121       MOVA (l);
8122       emitcode ("rrc", "a");
8123       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8124     }
8125   reAdjustPreg (AOP (result));
8126   emitcode ("", "%05d$:", tlbl1->key + 100);
8127   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8128   popB (pushedB);
8129
8130 release:
8131   freeAsmop (left, NULL, ic, TRUE);
8132   freeAsmop (result, NULL, ic, TRUE);
8133 }
8134
8135 /*-----------------------------------------------------------------*/
8136 /* genRightShift - generate code for right shifting                */
8137 /*-----------------------------------------------------------------*/
8138 static void
8139 genRightShift (iCode * ic)
8140 {
8141   operand *right, *left, *result;
8142   sym_link *letype;
8143   int size, offset;
8144   char *l;
8145   symbol *tlbl, *tlbl1;
8146   bool pushedB;
8147
8148   D(emitcode (";     genRightShift",""));
8149
8150   /* if signed then we do it the hard way preserve the
8151      sign bit moving it inwards */
8152   letype = getSpec (operandType (IC_LEFT (ic)));
8153
8154   if (!SPEC_USIGN (letype))
8155     {
8156       genSignedRightShift (ic);
8157       return;
8158     }
8159
8160   /* signed & unsigned types are treated the same : i.e. the
8161      signed is NOT propagated inwards : quoting from the
8162      ANSI - standard : "for E1 >> E2, is equivalent to division
8163      by 2**E2 if unsigned or if it has a non-negative value,
8164      otherwise the result is implementation defined ", MY definition
8165      is that the sign does not get propagated */
8166
8167   right = IC_RIGHT (ic);
8168   left = IC_LEFT (ic);
8169   result = IC_RESULT (ic);
8170
8171   aopOp (right, ic, FALSE);
8172
8173   /* if the shift count is known then do it
8174      as efficiently as possible */
8175   if (AOP_TYPE (right) == AOP_LIT)
8176     {
8177       genRightShiftLiteral (left, right, result, ic, 0);
8178       return;
8179     }
8180
8181   /* shift count is unknown then we have to form
8182      a loop get the loop count in B : Note: we take
8183      only the lower order byte since shifting
8184      more that 32 bits make no sense anyway, ( the
8185      largest size of an object can be only 32 bits ) */
8186
8187   pushedB = pushB ();
8188   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8189   emitcode ("inc", "b");
8190   freeAsmop (right, NULL, ic, TRUE);
8191   aopOp (left, ic, FALSE);
8192   aopOp (result, ic, FALSE);
8193
8194   /* now move the left to the result if they are not the
8195      same */
8196   if (!sameRegs (AOP (left), AOP (result)) &&
8197       AOP_SIZE (result) > 1)
8198     {
8199
8200       size = AOP_SIZE (result);
8201       offset = 0;
8202       while (size--)
8203         {
8204           l = aopGet (AOP (left), offset, FALSE, TRUE);
8205           if (*l == '@' && IS_AOP_PREG (result))
8206             {
8207
8208               emitcode ("mov", "a,%s", l);
8209               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8210             }
8211           else
8212             aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8213           offset++;
8214         }
8215     }
8216
8217   tlbl = newiTempLabel (NULL);
8218   tlbl1 = newiTempLabel (NULL);
8219   size = AOP_SIZE (result);
8220   offset = size - 1;
8221
8222   /* if it is only one byte then */
8223   if (size == 1)
8224     {
8225       l = aopGet (AOP (left), 0, FALSE, FALSE);
8226       MOVA (l);
8227       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8228       emitcode ("", "%05d$:", tlbl->key + 100);
8229       CLRC;
8230       emitcode ("rrc", "a");
8231       emitcode ("", "%05d$:", tlbl1->key + 100);
8232       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8233       popB (pushedB);
8234       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8235       goto release;
8236     }
8237
8238   reAdjustPreg (AOP (result));
8239   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8240   emitcode ("", "%05d$:", tlbl->key + 100);
8241   CLRC;
8242   while (size--)
8243     {
8244       l = aopGet (AOP (result), offset, FALSE, FALSE);
8245       MOVA (l);
8246       emitcode ("rrc", "a");
8247       aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8248     }
8249   reAdjustPreg (AOP (result));
8250
8251   emitcode ("", "%05d$:", tlbl1->key + 100);
8252   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8253   popB (pushedB);
8254
8255 release:
8256   freeAsmop (left, NULL, ic, TRUE);
8257   freeAsmop (result, NULL, ic, TRUE);
8258 }
8259
8260 /*-----------------------------------------------------------------*/
8261 /* emitPtrByteGet - emits code to get a byte into A through a      */
8262 /*                  pointer register (R0, R1, or DPTR). The        */
8263 /*                  original value of A can be preserved in B.     */
8264 /*-----------------------------------------------------------------*/
8265 static void
8266 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8267 {
8268   switch (p_type)
8269     {
8270     case IPOINTER:
8271     case POINTER:
8272       if (preserveAinB)
8273         emitcode ("mov", "b,a");
8274       emitcode ("mov", "a,@%s", rname);
8275       break;
8276
8277     case PPOINTER:
8278       if (preserveAinB)
8279         emitcode ("mov", "b,a");
8280       emitcode ("movx", "a,@%s", rname);
8281       break;
8282
8283     case FPOINTER:
8284       if (preserveAinB)
8285         emitcode ("mov", "b,a");
8286       emitcode ("movx", "a,@dptr");
8287       break;
8288
8289     case CPOINTER:
8290       if (preserveAinB)
8291         emitcode ("mov", "b,a");
8292       emitcode ("clr", "a");
8293       emitcode ("movc", "a,@a+dptr");
8294       break;
8295
8296     case GPOINTER:
8297       if (preserveAinB)
8298         {
8299           emitcode ("push", "b");
8300           emitcode ("push", "acc");
8301         }
8302       emitcode ("lcall", "__gptrget");
8303       if (preserveAinB)
8304         emitcode ("pop", "b");
8305       break;
8306     }
8307 }
8308
8309 /*-----------------------------------------------------------------*/
8310 /* emitPtrByteSet - emits code to set a byte from src through a    */
8311 /*                  pointer register (R0, R1, or DPTR).            */
8312 /*-----------------------------------------------------------------*/
8313 static void
8314 emitPtrByteSet (char *rname, int p_type, char *src)
8315 {
8316   switch (p_type)
8317     {
8318     case IPOINTER:
8319     case POINTER:
8320       if (*src=='@')
8321         {
8322           MOVA (src);
8323           emitcode ("mov", "@%s,a", rname);
8324         }
8325       else
8326         emitcode ("mov", "@%s,%s", rname, src);
8327       break;
8328
8329     case PPOINTER:
8330       MOVA (src);
8331       emitcode ("movx", "@%s,a", rname);
8332       break;
8333
8334     case FPOINTER:
8335       MOVA (src);
8336       emitcode ("movx", "@dptr,a");
8337       break;
8338
8339     case GPOINTER:
8340       MOVA (src);
8341       emitcode ("lcall", "__gptrput");
8342       break;
8343     }
8344 }
8345
8346 /*-----------------------------------------------------------------*/
8347 /* genUnpackBits - generates code for unpacking bits               */
8348 /*-----------------------------------------------------------------*/
8349 static void
8350 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8351 {
8352   int offset = 0;       /* result byte offset */
8353   int rsize;            /* result size */
8354   int rlen = 0;         /* remaining bitfield length */
8355   sym_link *etype;      /* bitfield type information */
8356   int blen;             /* bitfield length */
8357   int bstr;             /* bitfield starting bit within byte */
8358   char buffer[10];
8359
8360   D(emitcode (";     genUnpackBits",""));
8361
8362   etype = getSpec (operandType (result));
8363   rsize = getSize (operandType (result));
8364   blen = SPEC_BLEN (etype);
8365   bstr = SPEC_BSTR (etype);
8366
8367   if (ifx && blen <= 8)
8368     {
8369       emitPtrByteGet (rname, ptype, FALSE);
8370       if (blen == 1)
8371         {
8372           SNPRINTF (buffer, sizeof(buffer),
8373                     "acc.%d", bstr);
8374           genIfxJump (ifx, buffer, NULL, NULL, NULL);
8375         }
8376       else
8377         {
8378           if (blen < 8)
8379             emitcode ("anl", "a,#0x%02x",
8380                       (((unsigned char) -1) >> (8 - blen)) << bstr);
8381           genIfxJump (ifx, "a", NULL, NULL, NULL);
8382         }
8383       return;
8384     }
8385   wassert (!ifx);
8386
8387   /* If the bitfield length is less than a byte */
8388   if (blen < 8)
8389     {
8390       emitPtrByteGet (rname, ptype, FALSE);
8391       AccRsh (bstr);
8392       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8393       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8394       goto finish;
8395     }
8396
8397   /* Bit field did not fit in a byte. Copy all
8398      but the partial byte at the end.  */
8399   for (rlen=blen;rlen>=8;rlen-=8)
8400     {
8401       emitPtrByteGet (rname, ptype, FALSE);
8402       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8403       if (rlen>8)
8404         emitcode ("inc", "%s", rname);
8405     }
8406
8407   /* Handle the partial byte at the end */
8408   if (rlen)
8409     {
8410       emitPtrByteGet (rname, ptype, FALSE);
8411       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8412       aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8413     }
8414
8415 finish:
8416   if (offset < rsize)
8417     {
8418       rsize -= offset;
8419       while (rsize--)
8420         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8421     }
8422 }
8423
8424
8425 /*-----------------------------------------------------------------*/
8426 /* genDataPointerGet - generates code when ptr offset is known     */
8427 /*-----------------------------------------------------------------*/
8428 static void
8429 genDataPointerGet (operand * left,
8430                    operand * result,
8431                    iCode * ic)
8432 {
8433   char *l;
8434   char buffer[256];
8435   int size, offset = 0;
8436
8437   D(emitcode (";     genDataPointerGet",""));
8438
8439   aopOp (result, ic, TRUE);
8440
8441   /* get the string representation of the name */
8442   l = aopGet (AOP (left), 0, FALSE, TRUE);
8443   size = AOP_SIZE (result);
8444   while (size--)
8445     {
8446       if (offset)
8447         sprintf (buffer, "(%s + %d)", l + 1, offset);
8448       else
8449         sprintf (buffer, "%s", l + 1);
8450       aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8451     }
8452
8453   freeAsmop (left, NULL, ic, TRUE);
8454   freeAsmop (result, NULL, ic, TRUE);
8455 }
8456
8457 /*-----------------------------------------------------------------*/
8458 /* genNearPointerGet - emitcode for near pointer fetch             */
8459 /*-----------------------------------------------------------------*/
8460 static void
8461 genNearPointerGet (operand * left,
8462                    operand * result,
8463                    iCode * ic,
8464                    iCode * pi,
8465                    iCode * ifx)
8466 {
8467   asmop *aop = NULL;
8468   regs *preg = NULL;
8469   char *rname;
8470   sym_link *rtype, *retype;
8471   sym_link *ltype = operandType (left);
8472   char buffer[80];
8473
8474   D(emitcode (";     genNearPointerGet",""));
8475
8476   rtype = operandType (result);
8477   retype = getSpec (rtype);
8478
8479   aopOp (left, ic, FALSE);
8480
8481   /* if left is rematerialisable and
8482      result is not bitfield variable type and
8483      the left is pointer to data space i.e
8484      lower 128 bytes of space */
8485   if (AOP_TYPE (left) == AOP_IMMD &&
8486       !IS_BITFIELD (retype) &&
8487       DCL_TYPE (ltype) == POINTER)
8488     {
8489       genDataPointerGet (left, result, ic);
8490       return;
8491     }
8492
8493  /* if the value is already in a pointer register
8494      then don't need anything more */
8495   if (!AOP_INPREG (AOP (left)))
8496     {
8497       if (IS_AOP_PREG (left))
8498         {
8499           // Aha, it is a pointer, just in disguise.
8500           rname = aopGet (AOP (left), 0, FALSE, FALSE);
8501           if (*rname != '@')
8502             {
8503               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8504                       __FILE__, __LINE__);
8505             }
8506           else
8507             {
8508               // Expected case.
8509               emitcode ("mov", "a%s,%s", rname + 1, rname);
8510               rname++;  // skip the '@'.
8511             }
8512         }
8513       else
8514         {
8515           /* otherwise get a free pointer register */
8516           aop = newAsmop (0);
8517           preg = getFreePtr (ic, &aop, FALSE);
8518           emitcode ("mov", "%s,%s",
8519                     preg->name,
8520                     aopGet (AOP (left), 0, FALSE, TRUE));
8521           rname = preg->name;
8522         }
8523     }
8524   else
8525     rname = aopGet (AOP (left), 0, FALSE, FALSE);
8526
8527   //aopOp (result, ic, FALSE);
8528   aopOp (result, ic, result?TRUE:FALSE);
8529
8530   /* if bitfield then unpack the bits */
8531   if (IS_BITFIELD (retype))
8532     genUnpackBits (result, rname, POINTER, ifx);
8533   else
8534     {
8535       /* we have can just get the values */
8536       int size = AOP_SIZE (result);
8537       int offset = 0;
8538
8539       while (size--)
8540         {
8541           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8542             {
8543
8544               emitcode ("mov", "a,@%s", rname);
8545               if (!ifx)
8546               aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8547             }
8548           else
8549             {
8550               sprintf (buffer, "@%s", rname);
8551               aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8552             }
8553           offset++;
8554           if (size || pi)
8555             emitcode ("inc", "%s", rname);
8556         }
8557     }
8558
8559   /* now some housekeeping stuff */
8560   if (aop)       /* we had to allocate for this iCode */
8561     {
8562       if (pi) { /* post increment present */
8563         aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8564       }
8565       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8566     }
8567   else
8568     {
8569       /* we did not allocate which means left
8570          already in a pointer register, then
8571          if size > 0 && this could be used again
8572          we have to point it back to where it
8573          belongs */
8574       if ((AOP_SIZE (result) > 1 &&
8575            !OP_SYMBOL (left)->remat &&
8576            (OP_SYMBOL (left)->liveTo > ic->seq ||
8577             ic->depth)) &&
8578           !pi)
8579         {
8580           int size = AOP_SIZE (result) - 1;
8581           while (size--)
8582             emitcode ("dec", "%s", rname);
8583         }
8584     }
8585
8586   if (ifx && !ifx->generated)
8587     {
8588       genIfxJump (ifx, "a", left, NULL, result);
8589     }
8590
8591   /* done */
8592   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8593   freeAsmop (left, NULL, ic, TRUE);
8594   if (pi) pi->generated = 1;
8595 }
8596
8597 /*-----------------------------------------------------------------*/
8598 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8599 /*-----------------------------------------------------------------*/
8600 static void
8601 genPagedPointerGet (operand * left,
8602                     operand * result,
8603                     iCode * ic,
8604                     iCode *pi,
8605                     iCode *ifx)
8606 {
8607   asmop *aop = NULL;
8608   regs *preg = NULL;
8609   char *rname;
8610   sym_link *rtype, *retype;
8611
8612   D(emitcode (";     genPagedPointerGet",""));
8613
8614   rtype = operandType (result);
8615   retype = getSpec (rtype);
8616
8617   aopOp (left, ic, FALSE);
8618
8619   /* if the value is already in a pointer register
8620      then don't need anything more */
8621   if (!AOP_INPREG (AOP (left)))
8622     {
8623       /* otherwise get a free pointer register */
8624       aop = newAsmop (0);
8625       preg = getFreePtr (ic, &aop, FALSE);
8626       emitcode ("mov", "%s,%s",
8627                 preg->name,
8628                 aopGet (AOP (left), 0, FALSE, TRUE));
8629       rname = preg->name;
8630     }
8631   else
8632     rname = aopGet (AOP (left), 0, FALSE, FALSE);
8633
8634   aopOp (result, ic, FALSE);
8635
8636   /* if bitfield then unpack the bits */
8637   if (IS_BITFIELD (retype))
8638     genUnpackBits (result, rname, PPOINTER, ifx);
8639   else
8640     {
8641       /* we have can just get the values */
8642       int size = AOP_SIZE (result);
8643       int offset = 0;
8644
8645       while (size--)
8646         {
8647
8648           emitcode ("movx", "a,@%s", rname);
8649           if (!ifx)
8650           aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8651
8652           offset++;
8653
8654           if (size || pi)
8655             emitcode ("inc", "%s", rname);
8656         }
8657     }
8658
8659   /* now some housekeeping stuff */
8660   if (aop) /* we had to allocate for this iCode */
8661     {
8662       if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8663       freeAsmop (NULL, aop, ic, TRUE);
8664     }
8665   else
8666     {
8667       /* we did not allocate which means left
8668          already in a pointer register, then
8669          if size > 0 && this could be used again
8670          we have to point it back to where it
8671          belongs */
8672       if ((AOP_SIZE (result) > 1 &&
8673            !OP_SYMBOL (left)->remat &&
8674            (OP_SYMBOL (left)->liveTo > ic->seq ||
8675             ic->depth)) &&
8676           !pi)
8677         {
8678           int size = AOP_SIZE (result) - 1;
8679           while (size--)
8680             emitcode ("dec", "%s", rname);
8681         }
8682     }
8683
8684   if (ifx && !ifx->generated)
8685     {
8686       genIfxJump (ifx, "a", left, NULL, result);
8687     }
8688
8689   /* done */
8690   freeAsmop (left, NULL, ic, TRUE);
8691   freeAsmop (result, NULL, ic, TRUE);
8692   if (pi) pi->generated = 1;
8693
8694 }
8695
8696 /*--------------------------------------------------------------------*/
8697 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8698 /*--------------------------------------------------------------------*/
8699 static void
8700 loadDptrFromOperand (operand *op, bool loadBToo)
8701 {
8702   if (AOP_TYPE (op) != AOP_STR)
8703     {
8704       /* if this is rematerializable */
8705       if (AOP_TYPE (op) == AOP_IMMD)
8706         {
8707           emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8708           if (loadBToo)
8709             {
8710               if (AOP(op)->aopu.aop_immd.from_cast_remat)
8711                 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8712               else
8713                 {
8714                   wassertl(FALSE, "need pointerCode");
8715                   emitcode ("", "; mov b,???");
8716                   /* genPointerGet and genPointerSet originally did different
8717                   ** things for this case. Both seem wrong.
8718                   ** from genPointerGet:
8719                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
8720                   ** from genPointerSet:
8721                   **  emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8722                   */
8723                 }
8724             }
8725         }
8726       else if (AOP_TYPE (op) == AOP_DPTR)
8727         {
8728           if (loadBToo)
8729             {
8730               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8731               emitcode ("push", "acc");
8732               MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8733               emitcode ("push", "acc");
8734               emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8735               emitcode ("pop", "dph");
8736               emitcode ("pop", "dpl");
8737             }
8738           else
8739             {
8740               MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8741               emitcode ("push", "acc");
8742               emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8743               emitcode ("pop", "dpl");
8744             }
8745         }
8746       else
8747         {                       /* we need to get it byte by byte */
8748           emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8749           emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8750           if (loadBToo)
8751             emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8752         }
8753     }
8754 }
8755
8756 /*-----------------------------------------------------------------*/
8757 /* genFarPointerGet - gget value from far space                    */
8758 /*-----------------------------------------------------------------*/
8759 static void
8760 genFarPointerGet (operand * left,
8761                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
8762 {
8763   int size, offset;
8764   sym_link *retype = getSpec (operandType (result));
8765
8766   D(emitcode (";     genFarPointerGet",""));
8767
8768   aopOp (left, ic, FALSE);
8769   loadDptrFromOperand (left, FALSE);
8770
8771   /* so dptr now contains the address */
8772   aopOp (result, ic, FALSE);
8773
8774   /* if bit then unpack */
8775   if (IS_BITFIELD (retype))
8776     genUnpackBits (result, "dptr", FPOINTER, ifx);
8777   else
8778     {
8779       size = AOP_SIZE (result);
8780       offset = 0;
8781
8782       while (size--)
8783         {
8784           emitcode ("movx", "a,@dptr");
8785           if (!ifx)
8786             aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8787           if (size || pi)
8788             emitcode ("inc", "dptr");
8789         }
8790     }
8791
8792   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8793     {
8794     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8795     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8796     pi->generated = 1;
8797   }
8798
8799   if (ifx && !ifx->generated)
8800     {
8801       genIfxJump (ifx, "a", left, NULL, result);
8802     }
8803
8804   freeAsmop (left, NULL, ic, TRUE);
8805   freeAsmop (result, NULL, ic, TRUE);
8806 }
8807
8808 /*-----------------------------------------------------------------*/
8809 /* genCodePointerGet - gget value from code space                  */
8810 /*-----------------------------------------------------------------*/
8811 static void
8812 genCodePointerGet (operand * left,
8813                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
8814 {
8815   int size, offset;
8816   sym_link *retype = getSpec (operandType (result));
8817
8818   D(emitcode (";     genCodePointerGet",""));
8819
8820   aopOp (left, ic, FALSE);
8821   loadDptrFromOperand (left, FALSE);
8822
8823   /* so dptr now contains the address */
8824   aopOp (result, ic, FALSE);
8825
8826   /* if bit then unpack */
8827   if (IS_BITFIELD (retype))
8828     genUnpackBits (result, "dptr", CPOINTER, ifx);
8829   else
8830     {
8831       size = AOP_SIZE (result);
8832       offset = 0;
8833
8834       while (size--)
8835         {
8836           if (pi)
8837             {
8838               emitcode ("clr", "a");
8839               emitcode ("movc", "a,@a+dptr");
8840               if (!ifx)
8841               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8842               emitcode ("inc", "dptr");
8843             }
8844           else
8845             {
8846               emitcode ("mov", "a,#0x%02x", offset);
8847               emitcode ("movc", "a,@a+dptr");
8848               if (!ifx)
8849               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8850             }
8851         }
8852     }
8853
8854   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8855     {
8856     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8857     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8858     pi->generated = 1;
8859   }
8860
8861   if (ifx && !ifx->generated)
8862     {
8863       genIfxJump (ifx, "a", left, NULL, result);
8864     }
8865
8866   freeAsmop (left, NULL, ic, TRUE);
8867   freeAsmop (result, NULL, ic, TRUE);
8868 }
8869
8870 /*-----------------------------------------------------------------*/
8871 /* genGenPointerGet - gget value from generic pointer space        */
8872 /*-----------------------------------------------------------------*/
8873 static void
8874 genGenPointerGet (operand * left,
8875                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
8876 {
8877   int size, offset;
8878   sym_link *retype = getSpec (operandType (result));
8879
8880   D(emitcode (";     genGenPointerGet",""));
8881
8882   aopOp (left, ic, FALSE);
8883   loadDptrFromOperand (left, TRUE);
8884
8885   /* so dptr know contains the address */
8886   aopOp (result, ic, FALSE);
8887
8888   /* if bit then unpack */
8889   if (IS_BITFIELD (retype))
8890     genUnpackBits (result, "dptr", GPOINTER, ifx);
8891   else
8892     {
8893       size = AOP_SIZE (result);
8894       offset = 0;
8895
8896       while (size--)
8897         {
8898           emitcode ("lcall", "__gptrget");
8899           if (!ifx)
8900           aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8901           if (size || pi)
8902             emitcode ("inc", "dptr");
8903         }
8904     }
8905
8906   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8907     {
8908     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8909     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8910     pi->generated = 1;
8911   }
8912
8913   if (ifx && !ifx->generated)
8914     {
8915       genIfxJump (ifx, "a", left, NULL, result);
8916     }
8917
8918
8919   freeAsmop (left, NULL, ic, TRUE);
8920   freeAsmop (result, NULL, ic, TRUE);
8921 }
8922
8923 /*-----------------------------------------------------------------*/
8924 /* genPointerGet - generate code for pointer get                   */
8925 /*-----------------------------------------------------------------*/
8926 static void
8927 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8928 {
8929   operand *left, *result;
8930   sym_link *type, *etype;
8931   int p_type;
8932
8933   D(emitcode (";     genPointerGet",""));
8934
8935   left = IC_LEFT (ic);
8936   result = IC_RESULT (ic);
8937
8938   if (getSize (operandType (result))>1)
8939     ifx = NULL;
8940
8941   /* depending on the type of pointer we need to
8942      move it to the correct pointer register */
8943   type = operandType (left);
8944   etype = getSpec (type);
8945   /* if left is of type of pointer then it is simple */
8946   if (IS_PTR (type) && !IS_FUNC (type->next))
8947     p_type = DCL_TYPE (type);
8948   else
8949     {
8950       /* we have to go by the storage class */
8951       p_type = PTR_TYPE (SPEC_OCLS (etype));
8952     }
8953
8954   /* special case when cast remat */
8955   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8956       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8957           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8958           type = operandType (left);
8959           p_type = DCL_TYPE (type);
8960   }
8961   /* now that we have the pointer type we assign
8962      the pointer values */
8963   switch (p_type)
8964     {
8965
8966     case POINTER:
8967     case IPOINTER:
8968       genNearPointerGet (left, result, ic, pi, ifx);
8969       break;
8970
8971     case PPOINTER:
8972       genPagedPointerGet (left, result, ic, pi, ifx);
8973       break;
8974
8975     case FPOINTER:
8976       genFarPointerGet (left, result, ic, pi, ifx);
8977       break;
8978
8979     case CPOINTER:
8980       genCodePointerGet (left, result, ic, pi, ifx);
8981       break;
8982
8983     case GPOINTER:
8984       genGenPointerGet (left, result, ic, pi, ifx);
8985       break;
8986     }
8987
8988 }
8989
8990
8991
8992 /*-----------------------------------------------------------------*/
8993 /* genPackBits - generates code for packed bit storage             */
8994 /*-----------------------------------------------------------------*/
8995 static void
8996 genPackBits (sym_link * etype,
8997              operand * right,
8998              char *rname, int p_type)
8999 {
9000   int offset = 0;       /* source byte offset */
9001   int rlen = 0;         /* remaining bitfield length */
9002   int blen;             /* bitfield length */
9003   int bstr;             /* bitfield starting bit within byte */
9004   int litval;           /* source literal value (if AOP_LIT) */
9005   unsigned char mask;   /* bitmask within current byte */
9006
9007   D(emitcode (";     genPackBits",""));
9008
9009   blen = SPEC_BLEN (etype);
9010   bstr = SPEC_BSTR (etype);
9011
9012   /* If the bitfield length is less than a byte */
9013   if (blen < 8)
9014     {
9015       mask = ((unsigned char) (0xFF << (blen + bstr)) |
9016               (unsigned char) (0xFF >> (8 - bstr)));
9017
9018       if (AOP_TYPE (right) == AOP_LIT)
9019         {
9020           /* Case with a bitfield length <8 and literal source
9021           */
9022           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9023           litval <<= bstr;
9024           litval &= (~mask) & 0xff;
9025           emitPtrByteGet (rname, p_type, FALSE);
9026           if ((mask|litval)!=0xff)
9027             emitcode ("anl","a,#0x%02x", mask);
9028           if (litval)
9029             emitcode ("orl","a,#0x%02x", litval);
9030         }
9031       else
9032         {
9033           if ((blen==1) && (p_type!=GPOINTER))
9034             {
9035               /* Case with a bitfield length == 1 and no generic pointer
9036               */
9037               if (AOP_TYPE (right) == AOP_CRY)
9038                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9039               else
9040                 {
9041                   MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9042                   emitcode ("rrc","a");
9043                 }
9044               emitPtrByteGet (rname, p_type, FALSE);
9045               emitcode ("mov","acc.%d,c",bstr);
9046             }
9047           else
9048             {
9049               bool pushedB;
9050               /* Case with a bitfield length < 8 and arbitrary source
9051               */
9052               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9053               /* shift and mask source value */
9054               AccLsh (bstr);
9055               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9056
9057               pushedB = pushB ();
9058               /* transfer A to B and get next byte */
9059               emitPtrByteGet (rname, p_type, TRUE);
9060
9061               emitcode ("anl", "a,#0x%02x", mask);
9062               emitcode ("orl", "a,b");
9063               if (p_type == GPOINTER)
9064                 emitcode ("pop", "b");
9065
9066               popB (pushedB);
9067            }
9068         }
9069
9070       emitPtrByteSet (rname, p_type, "a");
9071       return;
9072     }
9073
9074   /* Bit length is greater than 7 bits. In this case, copy  */
9075   /* all except the partial byte at the end                 */
9076   for (rlen=blen;rlen>=8;rlen-=8)
9077     {
9078       emitPtrByteSet (rname, p_type,
9079                       aopGet (AOP (right), offset++, FALSE, TRUE) );
9080       if (rlen>8)
9081         emitcode ("inc", "%s", rname);
9082     }
9083
9084   /* If there was a partial byte at the end */
9085   if (rlen)
9086     {
9087       mask = (((unsigned char) -1 << rlen) & 0xff);
9088
9089       if (AOP_TYPE (right) == AOP_LIT)
9090         {
9091           /* Case with partial byte and literal source
9092           */
9093           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9094           litval >>= (blen-rlen);
9095           litval &= (~mask) & 0xff;
9096           emitPtrByteGet (rname, p_type, FALSE);
9097           if ((mask|litval)!=0xff)
9098             emitcode ("anl","a,#0x%02x", mask);
9099           if (litval)
9100             emitcode ("orl","a,#0x%02x", litval);
9101         }
9102       else
9103         {
9104           bool pushedB;
9105           /* Case with partial byte and arbitrary source
9106           */
9107           MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9108           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9109
9110           pushedB = pushB ();
9111           /* transfer A to B and get next byte */
9112           emitPtrByteGet (rname, p_type, TRUE);
9113
9114           emitcode ("anl", "a,#0x%02x", mask);
9115           emitcode ("orl", "a,b");
9116           if (p_type == GPOINTER)
9117             emitcode ("pop", "b");
9118
9119           popB (pushedB);
9120         }
9121       emitPtrByteSet (rname, p_type, "a");
9122     }
9123
9124 }
9125
9126
9127 /*-----------------------------------------------------------------*/
9128 /* genDataPointerSet - remat pointer to data space                 */
9129 /*-----------------------------------------------------------------*/
9130 static void
9131 genDataPointerSet (operand * right,
9132                    operand * result,
9133                    iCode * ic)
9134 {
9135   int size, offset = 0;
9136   char *l, buffer[256];
9137
9138   D(emitcode (";     genDataPointerSet",""));
9139
9140   aopOp (right, ic, FALSE);
9141
9142   l = aopGet (AOP (result), 0, FALSE, TRUE);
9143   size = AOP_SIZE (right);
9144   while (size--)
9145     {
9146       if (offset)
9147         sprintf (buffer, "(%s + %d)", l + 1, offset);
9148       else
9149         sprintf (buffer, "%s", l + 1);
9150       emitcode ("mov", "%s,%s", buffer,
9151                 aopGet (AOP (right), offset++, FALSE, FALSE));
9152     }
9153
9154   freeAsmop (right, NULL, ic, TRUE);
9155   freeAsmop (result, NULL, ic, TRUE);
9156 }
9157
9158 /*-----------------------------------------------------------------*/
9159 /* genNearPointerSet - emitcode for near pointer put                */
9160 /*-----------------------------------------------------------------*/
9161 static void
9162 genNearPointerSet (operand * right,
9163                    operand * result,
9164                    iCode * ic,
9165                    iCode * pi)
9166 {
9167   asmop *aop = NULL;
9168   regs *preg = NULL;
9169   char *rname, *l;
9170   sym_link *retype, *letype;
9171   sym_link *ptype = operandType (result);
9172
9173   D(emitcode (";     genNearPointerSet",""));
9174
9175   retype = getSpec (operandType (right));
9176   letype = getSpec (ptype);
9177   aopOp (result, ic, FALSE);
9178
9179   /* if the result is rematerializable &
9180      in data space & not a bit variable */
9181   if (AOP_TYPE (result) == AOP_IMMD &&
9182       DCL_TYPE (ptype) == POINTER &&
9183       !IS_BITVAR (retype) &&
9184       !IS_BITVAR (letype))
9185     {
9186       genDataPointerSet (right, result, ic);
9187       return;
9188     }
9189
9190   /* if the value is already in a pointer register
9191      then don't need anything more */
9192   if (!AOP_INPREG (AOP (result)))
9193     {
9194         if (
9195             //AOP_TYPE (result) == AOP_STK
9196             IS_AOP_PREG(result)
9197             )
9198         {
9199             // Aha, it is a pointer, just in disguise.
9200             rname = aopGet (AOP (result), 0, FALSE, FALSE);
9201             if (*rname != '@')
9202             {
9203                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9204                         __FILE__, __LINE__);
9205             }
9206             else
9207             {
9208                 // Expected case.
9209                 emitcode ("mov", "a%s,%s", rname + 1, rname);
9210                 rname++;  // skip the '@'.
9211             }
9212         }
9213         else
9214         {
9215             /* otherwise get a free pointer register */
9216             aop = newAsmop (0);
9217             preg = getFreePtr (ic, &aop, FALSE);
9218             emitcode ("mov", "%s,%s",
9219                       preg->name,
9220                       aopGet (AOP (result), 0, FALSE, TRUE));
9221             rname = preg->name;
9222         }
9223     }
9224     else
9225     {
9226         rname = aopGet (AOP (result), 0, FALSE, FALSE);
9227     }
9228
9229   aopOp (right, ic, FALSE);
9230
9231   /* if bitfield then unpack the bits */
9232   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9233     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9234   else
9235     {
9236       /* we have can just get the values */
9237       int size = AOP_SIZE (right);
9238       int offset = 0;
9239
9240       while (size--)
9241         {
9242           l = aopGet (AOP (right), offset, FALSE, TRUE);
9243           if (*l == '@')
9244             {
9245               MOVA (l);
9246               emitcode ("mov", "@%s,a", rname);
9247             }
9248           else
9249             emitcode ("mov", "@%s,%s", rname, l);
9250           if (size || pi)
9251             emitcode ("inc", "%s", rname);
9252           offset++;
9253         }
9254     }
9255
9256   /* now some housekeeping stuff */
9257   if (aop) /* we had to allocate for this iCode */
9258     {
9259       if (pi)
9260         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9261       freeAsmop (NULL, aop, ic, TRUE);
9262     }
9263   else
9264     {
9265       /* we did not allocate which means left
9266          already in a pointer register, then
9267          if size > 0 && this could be used again
9268          we have to point it back to where it
9269          belongs */
9270       if ((AOP_SIZE (right) > 1 &&
9271            !OP_SYMBOL (result)->remat &&
9272            (OP_SYMBOL (result)->liveTo > ic->seq ||
9273             ic->depth)) &&
9274           !pi)
9275         {
9276           int size = AOP_SIZE (right) - 1;
9277           while (size--)
9278             emitcode ("dec", "%s", rname);
9279         }
9280     }
9281
9282   /* done */
9283   if (pi) pi->generated = 1;
9284   freeAsmop (result, NULL, ic, TRUE);
9285   freeAsmop (right, NULL, ic, TRUE);
9286 }
9287
9288 /*-----------------------------------------------------------------*/
9289 /* genPagedPointerSet - emitcode for Paged pointer put             */
9290 /*-----------------------------------------------------------------*/
9291 static void
9292 genPagedPointerSet (operand * right,
9293                     operand * result,
9294                     iCode * ic,
9295                     iCode * pi)
9296 {
9297   asmop *aop = NULL;
9298   regs *preg = NULL;
9299   char *rname, *l;
9300   sym_link *retype, *letype;
9301
9302   D(emitcode (";     genPagedPointerSet",""));
9303
9304   retype = getSpec (operandType (right));
9305   letype = getSpec (operandType (result));
9306
9307   aopOp (result, ic, FALSE);
9308
9309   /* if the value is already in a pointer register
9310      then don't need anything more */
9311   if (!AOP_INPREG (AOP (result)))
9312     {
9313       /* otherwise get a free pointer register */
9314       aop = newAsmop (0);
9315       preg = getFreePtr (ic, &aop, FALSE);
9316       emitcode ("mov", "%s,%s",
9317                 preg->name,
9318                 aopGet (AOP (result), 0, FALSE, TRUE));
9319       rname = preg->name;
9320     }
9321   else
9322     rname = aopGet (AOP (result), 0, FALSE, FALSE);
9323
9324   aopOp (right, ic, FALSE);
9325
9326   /* if bitfield then unpack the bits */
9327   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9328     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9329   else
9330     {
9331       /* we have can just get the values */
9332       int size = AOP_SIZE (right);
9333       int offset = 0;
9334
9335       while (size--)
9336         {
9337           l = aopGet (AOP (right), offset, FALSE, TRUE);
9338
9339           MOVA (l);
9340           emitcode ("movx", "@%s,a", rname);
9341
9342           if (size || pi)
9343             emitcode ("inc", "%s", rname);
9344
9345           offset++;
9346         }
9347     }
9348
9349   /* now some housekeeping stuff */
9350   if (aop) /* we had to allocate for this iCode */
9351     {
9352       if (pi)
9353         aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9354       freeAsmop (NULL, aop, ic, TRUE);
9355     }
9356   else
9357     {
9358       /* we did not allocate which means left
9359          already in a pointer register, then
9360          if size > 0 && this could be used again
9361          we have to point it back to where it
9362          belongs */
9363       if (AOP_SIZE (right) > 1 &&
9364           !OP_SYMBOL (result)->remat &&
9365           (OP_SYMBOL (result)->liveTo > ic->seq ||
9366            ic->depth))
9367         {
9368           int size = AOP_SIZE (right) - 1;
9369           while (size--)
9370             emitcode ("dec", "%s", rname);
9371         }
9372     }
9373
9374   /* done */
9375   if (pi) pi->generated = 1;
9376   freeAsmop (result, NULL, ic, TRUE);
9377   freeAsmop (right, NULL, ic, TRUE);
9378
9379
9380 }
9381
9382 /*-----------------------------------------------------------------*/
9383 /* genFarPointerSet - set value from far space                     */
9384 /*-----------------------------------------------------------------*/
9385 static void
9386 genFarPointerSet (operand * right,
9387                   operand * result, iCode * ic, iCode * pi)
9388 {
9389   int size, offset;
9390   sym_link *retype = getSpec (operandType (right));
9391   sym_link *letype = getSpec (operandType (result));
9392
9393   D(emitcode (";     genFarPointerSet",""));
9394
9395   aopOp (result, ic, FALSE);
9396   loadDptrFromOperand (result, FALSE);
9397
9398   /* so dptr know contains the address */
9399   aopOp (right, ic, FALSE);
9400
9401   /* if bit then unpack */
9402   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9403     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9404   else
9405     {
9406       size = AOP_SIZE (right);
9407       offset = 0;
9408
9409       while (size--)
9410         {
9411           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9412           MOVA (l);
9413           emitcode ("movx", "@dptr,a");
9414           if (size || pi)
9415             emitcode ("inc", "dptr");
9416         }
9417     }
9418   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9419     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9420     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9421     pi->generated=1;
9422   }
9423   freeAsmop (result, NULL, ic, TRUE);
9424   freeAsmop (right, NULL, ic, TRUE);
9425 }
9426
9427 /*-----------------------------------------------------------------*/
9428 /* genGenPointerSet - set value from generic pointer space         */
9429 /*-----------------------------------------------------------------*/
9430 static void
9431 genGenPointerSet (operand * right,
9432                   operand * result, iCode * ic, iCode * pi)
9433 {
9434   int size, offset;
9435   sym_link *retype = getSpec (operandType (right));
9436   sym_link *letype = getSpec (operandType (result));
9437
9438   D(emitcode (";     genGenPointerSet",""));
9439
9440   aopOp (result, ic, FALSE);
9441   loadDptrFromOperand (result, TRUE);
9442
9443   /* so dptr know contains the address */
9444   aopOp (right, ic, FALSE);
9445
9446   /* if bit then unpack */
9447   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9448     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9449   else
9450     {
9451       size = AOP_SIZE (right);
9452       offset = 0;
9453
9454       while (size--)
9455         {
9456           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9457           MOVA (l);
9458           emitcode ("lcall", "__gptrput");
9459           if (size || pi)
9460             emitcode ("inc", "dptr");
9461         }
9462     }
9463
9464   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9465     aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9466     aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9467     pi->generated=1;
9468   }
9469   freeAsmop (result, NULL, ic, TRUE);
9470   freeAsmop (right, NULL, ic, TRUE);
9471 }
9472
9473 /*-----------------------------------------------------------------*/
9474 /* genPointerSet - stores the value into a pointer location        */
9475 /*-----------------------------------------------------------------*/
9476 static void
9477 genPointerSet (iCode * ic, iCode *pi)
9478 {
9479   operand *right, *result;
9480   sym_link *type, *etype;
9481   int p_type;
9482
9483   D(emitcode (";     genPointerSet",""));
9484
9485   right = IC_RIGHT (ic);
9486   result = IC_RESULT (ic);
9487
9488   /* depending on the type of pointer we need to
9489      move it to the correct pointer register */
9490   type = operandType (result);
9491   etype = getSpec (type);
9492   /* if left is of type of pointer then it is simple */
9493   if (IS_PTR (type) && !IS_FUNC (type->next))
9494     {
9495       p_type = DCL_TYPE (type);
9496     }
9497   else
9498     {
9499       /* we have to go by the storage class */
9500       p_type = PTR_TYPE (SPEC_OCLS (etype));
9501     }
9502
9503   /* special case when cast remat */
9504   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9505       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9506           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9507           type = operandType (result);
9508           p_type = DCL_TYPE (type);
9509   }
9510   /* now that we have the pointer type we assign
9511      the pointer values */
9512   switch (p_type)
9513     {
9514
9515     case POINTER:
9516     case IPOINTER:
9517       genNearPointerSet (right, result, ic, pi);
9518       break;
9519
9520     case PPOINTER:
9521       genPagedPointerSet (right, result, ic, pi);
9522       break;
9523
9524     case FPOINTER:
9525       genFarPointerSet (right, result, ic, pi);
9526       break;
9527
9528     case GPOINTER:
9529       genGenPointerSet (right, result, ic, pi);
9530       break;
9531
9532     default:
9533       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9534               "genPointerSet: illegal pointer type");
9535     }
9536
9537 }
9538
9539 /*-----------------------------------------------------------------*/
9540 /* genIfx - generate code for Ifx statement                        */
9541 /*-----------------------------------------------------------------*/
9542 static void
9543 genIfx (iCode * ic, iCode * popIc)
9544 {
9545   operand *cond = IC_COND (ic);
9546   int isbit = 0;
9547
9548   D(emitcode (";     genIfx",""));
9549
9550   aopOp (cond, ic, FALSE);
9551
9552   /* get the value into acc */
9553   if (AOP_TYPE (cond) != AOP_CRY)
9554     toBoolean (cond);
9555   else
9556     isbit = 1;
9557   /* the result is now in the accumulator */
9558   freeAsmop (cond, NULL, ic, TRUE);
9559
9560   /* if there was something to be popped then do it */
9561   if (popIc)
9562     genIpop (popIc);
9563
9564   /* if the condition is a bit variable */
9565   if (isbit && IS_ITEMP (cond) &&
9566       SPIL_LOC (cond))
9567     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9568   else if (isbit && !IS_ITEMP (cond))
9569     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9570   else
9571     genIfxJump (ic, "a", NULL, NULL, NULL);
9572
9573   ic->generated = 1;
9574 }
9575
9576 /*-----------------------------------------------------------------*/
9577 /* genAddrOf - generates code for address of                       */
9578 /*-----------------------------------------------------------------*/
9579 static void
9580 genAddrOf (iCode * ic)
9581 {
9582   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9583   int size, offset;
9584
9585   D(emitcode (";     genAddrOf",""));
9586
9587   aopOp (IC_RESULT (ic), ic, FALSE);
9588
9589   /* if the operand is on the stack then we
9590      need to get the stack offset of this
9591      variable */
9592   if (sym->onStack)
9593     {
9594       /* if it has an offset then we need to compute
9595          it */
9596       if (sym->stack)
9597         {
9598           emitcode ("mov", "a,_bp");
9599           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9600                                          ((char) (sym->stack - _G.nRegsSaved)) :
9601                                          ((char) sym->stack)) & 0xff);
9602           aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9603         }
9604       else
9605         {
9606           /* we can just move _bp */
9607           aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9608         }
9609       /* fill the result with zero */
9610       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9611
9612       offset = 1;
9613       while (size--)
9614         {
9615           aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9616         }
9617
9618       goto release;
9619     }
9620
9621   /* object not on stack then we need the name */
9622   size = AOP_SIZE (IC_RESULT (ic));
9623   offset = 0;
9624
9625   while (size--)
9626     {
9627       char s[SDCC_NAME_MAX];
9628       if (offset)
9629         sprintf (s, "#(%s >> %d)",
9630                  sym->rname,
9631                  offset * 8);
9632       else
9633         sprintf (s, "#%s", sym->rname);
9634       aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9635     }
9636
9637 release:
9638   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9639
9640 }
9641
9642 /*-----------------------------------------------------------------*/
9643 /* genFarFarAssign - assignment when both are in far space         */
9644 /*-----------------------------------------------------------------*/
9645 static void
9646 genFarFarAssign (operand * result, operand * right, iCode * ic)
9647 {
9648   int size = AOP_SIZE (right);
9649   int offset = 0;
9650   char *l;
9651
9652   D(emitcode (";     genFarFarAssign",""));
9653
9654   /* first push the right side on to the stack */
9655   while (size--)
9656     {
9657       l = aopGet (AOP (right), offset++, FALSE, FALSE);
9658       MOVA (l);
9659       emitcode ("push", "acc");
9660     }
9661
9662   freeAsmop (right, NULL, ic, FALSE);
9663   /* now assign DPTR to result */
9664   aopOp (result, ic, FALSE);
9665   size = AOP_SIZE (result);
9666   while (size--)
9667     {
9668       emitcode ("pop", "acc");
9669       aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9670     }
9671   freeAsmop (result, NULL, ic, FALSE);
9672
9673 }
9674
9675 /*-----------------------------------------------------------------*/
9676 /* genAssign - generate code for assignment                        */
9677 /*-----------------------------------------------------------------*/
9678 static void
9679 genAssign (iCode * ic)
9680 {
9681   operand *result, *right;
9682   int size, offset;
9683   unsigned long lit = 0L;
9684
9685   D(emitcode(";     genAssign",""));
9686
9687   result = IC_RESULT (ic);
9688   right = IC_RIGHT (ic);
9689
9690   /* if they are the same */
9691   if (operandsEqu (result, right) &&
9692       !isOperandVolatile (result, FALSE) &&
9693       !isOperandVolatile (right, FALSE))
9694     return;
9695
9696   aopOp (right, ic, FALSE);
9697
9698   /* special case both in far space */
9699   if (AOP_TYPE (right) == AOP_DPTR &&
9700       IS_TRUE_SYMOP (result) &&
9701       isOperandInFarSpace (result))
9702     {
9703
9704       genFarFarAssign (result, right, ic);
9705       return;
9706     }
9707
9708   aopOp (result, ic, TRUE);
9709
9710   /* if they are the same registers */
9711   if (sameRegs (AOP (right), AOP (result)) &&
9712       !isOperandVolatile (result, FALSE) &&
9713       !isOperandVolatile (right, FALSE))
9714     goto release;
9715
9716   /* if the result is a bit */
9717   if (AOP_TYPE (result) == AOP_CRY)
9718     {
9719
9720       /* if the right size is a literal then
9721          we know what the value is */
9722       if (AOP_TYPE (right) == AOP_LIT)
9723         {
9724           if (((int) operandLitValue (right)))
9725             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9726           else
9727             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9728           goto release;
9729         }
9730
9731       /* the right is also a bit variable */
9732       if (AOP_TYPE (right) == AOP_CRY)
9733         {
9734           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9735           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9736           goto release;
9737         }
9738
9739       /* we need to or */
9740       toBoolean (right);
9741       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9742       goto release;
9743     }
9744
9745   /* bit variables done */
9746   /* general case */
9747   size = AOP_SIZE (result);
9748   offset = 0;
9749   if (AOP_TYPE (right) == AOP_LIT)
9750     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9751   if ((size > 1) &&
9752       (AOP_TYPE (result) != AOP_REG) &&
9753       (AOP_TYPE (right) == AOP_LIT) &&
9754       !IS_FLOAT (operandType (right)) &&
9755       (lit < 256L))
9756     {
9757       while ((size) && (lit))
9758         {
9759           aopPut (AOP (result),
9760                   aopGet (AOP (right), offset, FALSE, FALSE),
9761                   offset,
9762                   isOperandVolatile (result, FALSE));
9763           lit >>= 8;
9764           offset++;
9765           size--;
9766         }
9767       emitcode ("clr", "a");
9768       while (size--)
9769         {
9770           aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9771           offset++;
9772         }
9773     }
9774   else
9775     {
9776       while (size--)
9777         {
9778           aopPut (AOP (result),
9779                   aopGet (AOP (right), offset, FALSE, FALSE),
9780                   offset,
9781                   isOperandVolatile (result, FALSE));
9782           offset++;
9783         }
9784     }
9785
9786 release:
9787   freeAsmop (right, NULL, ic, TRUE);
9788   freeAsmop (result, NULL, ic, TRUE);
9789 }
9790
9791 /*-----------------------------------------------------------------*/
9792 /* genJumpTab - genrates code for jump table                       */
9793 /*-----------------------------------------------------------------*/
9794 static void
9795 genJumpTab (iCode * ic)
9796 {
9797   symbol *jtab,*jtablo,*jtabhi;
9798   char *l;
9799   unsigned int count;
9800
9801   D(emitcode (";     genJumpTab",""));
9802
9803   count = elementsInSet( IC_JTLABELS (ic) );
9804
9805   if( count <= 16 )
9806     {
9807       /* this algorithm needs 9 cycles and 7 + 3*n bytes
9808          if the switch argument is in a register.
9809          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9810       /* (MB) What if peephole converts ljmp to sjmp or ret ???
9811          How will multiply by three be updated ???*/
9812       aopOp (IC_JTCOND (ic), ic, FALSE);
9813       /* get the condition into accumulator */
9814       l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9815       MOVA (l);
9816       /* multiply by three */
9817       emitcode ("add", "a,acc");
9818       emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9819       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9820
9821       jtab = newiTempLabel (NULL);
9822       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9823       emitcode ("jmp", "@a+dptr");
9824       emitcode ("", "%05d$:", jtab->key + 100);
9825       /* now generate the jump labels */
9826       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9827            jtab = setNextItem (IC_JTLABELS (ic)))
9828         emitcode ("ljmp", "%05d$", jtab->key + 100);
9829     }
9830   else
9831     {
9832       /* this algorithm needs 14 cycles and 13 + 2*n bytes
9833          if the switch argument is in a register.
9834          For n>6 this algorithm may be more compact */
9835       jtablo = newiTempLabel (NULL);
9836       jtabhi = newiTempLabel (NULL);
9837
9838       /* get the condition into accumulator.
9839          Using b as temporary storage, if register push/pop is needed */
9840       aopOp (IC_JTCOND (ic), ic, FALSE);
9841       l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9842       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9843           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9844         {
9845           // (MB) what if B is in use???
9846           wassertl(!BINUSE, "B was in use");
9847           emitcode ("mov", "b,%s", l);
9848           l = "b";
9849         }
9850       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9851       MOVA (l);
9852       if( count <= 112 )
9853         {
9854           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9855           emitcode ("movc", "a,@a+pc");
9856           emitcode ("push", "acc");
9857
9858           MOVA (l);
9859           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9860           emitcode ("movc", "a,@a+pc");
9861           emitcode ("push", "acc");
9862         }
9863       else
9864         {
9865           /* this scales up to n<=255, but needs two more bytes
9866              and changes dptr */
9867           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9868           emitcode ("movc", "a,@a+dptr");
9869           emitcode ("push", "acc");
9870
9871           MOVA (l);
9872           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9873           emitcode ("movc", "a,@a+dptr");
9874           emitcode ("push", "acc");
9875         }
9876
9877       emitcode ("ret", "");
9878
9879       /* now generate jump table, LSB */
9880       emitcode ("", "%05d$:", jtablo->key + 100);
9881       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9882            jtab = setNextItem (IC_JTLABELS (ic)))
9883         emitcode (".db", "%05d$", jtab->key + 100);
9884
9885       /* now generate jump table, MSB */
9886       emitcode ("", "%05d$:", jtabhi->key + 100);
9887       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9888            jtab = setNextItem (IC_JTLABELS (ic)))
9889          emitcode (".db", "%05d$>>8", jtab->key + 100);
9890     }
9891 }
9892
9893 /*-----------------------------------------------------------------*/
9894 /* genCast - gen code for casting                                  */
9895 /*-----------------------------------------------------------------*/
9896 static void
9897 genCast (iCode * ic)
9898 {
9899   operand *result = IC_RESULT (ic);
9900   sym_link *ctype = operandType (IC_LEFT (ic));
9901   sym_link *rtype = operandType (IC_RIGHT (ic));
9902   operand *right = IC_RIGHT (ic);
9903   int size, offset;
9904
9905   D(emitcode(";     genCast",""));
9906
9907   /* if they are equivalent then do nothing */
9908   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9909     return;
9910
9911   aopOp (right, ic, FALSE);
9912   aopOp (result, ic, FALSE);
9913
9914   /* if the result is a bit (and not a bitfield) */
9915   // if (AOP_TYPE (result) == AOP_CRY)
9916   if (IS_BITVAR (OP_SYMBOL (result)->type)
9917       && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9918     {
9919       /* if the right size is a literal then
9920          we know what the value is */
9921       if (AOP_TYPE (right) == AOP_LIT)
9922         {
9923           if (((int) operandLitValue (right)))
9924             aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9925           else
9926             aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9927
9928           goto release;
9929         }
9930
9931       /* the right is also a bit variable */
9932       if (AOP_TYPE (right) == AOP_CRY)
9933         {
9934           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9935           aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9936           goto release;
9937         }
9938
9939       /* we need to or */
9940       toBoolean (right);
9941       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9942       goto release;
9943     }
9944
9945
9946   /* if they are the same size : or less */
9947   if (AOP_SIZE (result) <= AOP_SIZE (right))
9948     {
9949
9950       /* if they are in the same place */
9951       if (sameRegs (AOP (right), AOP (result)))
9952         goto release;
9953
9954       /* if they in different places then copy */
9955       size = AOP_SIZE (result);
9956       offset = 0;
9957       while (size--)
9958         {
9959           aopPut (AOP (result),
9960                   aopGet (AOP (right), offset, FALSE, FALSE),
9961                   offset,
9962                   isOperandVolatile (result, FALSE));
9963           offset++;
9964         }
9965       goto release;
9966     }
9967
9968
9969   /* if the result is of type pointer */
9970   if (IS_PTR (ctype))
9971     {
9972
9973       int p_type;
9974       sym_link *type = operandType (right);
9975       sym_link *etype = getSpec (type);
9976
9977       /* pointer to generic pointer */
9978       if (IS_GENPTR (ctype))
9979         {
9980           if (IS_PTR (type))
9981             p_type = DCL_TYPE (type);
9982           else
9983             {
9984               if (SPEC_SCLS(etype)==S_REGISTER) {
9985                 // let's assume it is a generic pointer
9986                 p_type=GPOINTER;
9987               } else {
9988                 /* we have to go by the storage class */
9989                 p_type = PTR_TYPE (SPEC_OCLS (etype));
9990               }
9991             }
9992
9993           /* the first two bytes are known */
9994           size = GPTRSIZE - 1;
9995           offset = 0;
9996           while (size--)
9997             {
9998               aopPut (AOP (result),
9999                       aopGet (AOP (right), offset, FALSE, FALSE),
10000                       offset,
10001                       isOperandVolatile (result, FALSE));
10002               offset++;
10003             }
10004           /* the last byte depending on type */
10005             {
10006                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10007                 char gpValStr[10];
10008
10009                 if (gpVal == -1)
10010                 {
10011                     // pointerTypeToGPByte will have bitched.
10012                     exit(1);
10013                 }
10014
10015                 sprintf(gpValStr, "#0x%d", gpVal);
10016                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10017             }
10018           goto release;
10019         }
10020
10021       /* just copy the pointers */
10022       size = AOP_SIZE (result);
10023       offset = 0;
10024       while (size--)
10025         {
10026           aopPut (AOP (result),
10027                   aopGet (AOP (right), offset, FALSE, FALSE),
10028                   offset,
10029                   isOperandVolatile (result, FALSE));
10030           offset++;
10031         }
10032       goto release;
10033     }
10034
10035   /* so we now know that the size of destination is greater
10036      than the size of the source */
10037   /* we move to result for the size of source */
10038   size = AOP_SIZE (right);
10039   offset = 0;
10040   while (size--)
10041     {
10042       aopPut (AOP (result),
10043               aopGet (AOP (right), offset, FALSE, FALSE),
10044               offset,
10045               isOperandVolatile (result, FALSE));
10046       offset++;
10047     }
10048
10049   /* now depending on the sign of the source && destination */
10050   size = AOP_SIZE (result) - AOP_SIZE (right);
10051   /* if unsigned or not an integral type */
10052   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10053     {
10054       while (size--)
10055         aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10056     }
10057   else
10058     {
10059       /* we need to extend the sign :{ */
10060       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10061                         FALSE, FALSE);
10062       MOVA (l);
10063       emitcode ("rlc", "a");
10064       emitcode ("subb", "a,acc");
10065       while (size--)
10066         aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10067     }
10068
10069   /* we are done hurray !!!! */
10070
10071 release:
10072   freeAsmop (right, NULL, ic, TRUE);
10073   freeAsmop (result, NULL, ic, TRUE);
10074
10075 }
10076
10077 /*-----------------------------------------------------------------*/
10078 /* genDjnz - generate decrement & jump if not zero instrucion      */
10079 /*-----------------------------------------------------------------*/
10080 static int
10081 genDjnz (iCode * ic, iCode * ifx)
10082 {
10083   symbol *lbl, *lbl1;
10084   if (!ifx)
10085     return 0;
10086
10087   D(emitcode (";     genDjnz",""));
10088
10089   /* if the if condition has a false label
10090      then we cannot save */
10091   if (IC_FALSE (ifx))
10092     return 0;
10093
10094   /* if the minus is not of the form
10095      a = a - 1 */
10096   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10097       !IS_OP_LITERAL (IC_RIGHT (ic)))
10098     return 0;
10099
10100   if (operandLitValue (IC_RIGHT (ic)) != 1)
10101     return 0;
10102
10103   /* if the size of this greater than one then no
10104      saving */
10105   if (getSize (operandType (IC_RESULT (ic))) > 1)
10106     return 0;
10107
10108   /* otherwise we can save BIG */
10109   lbl = newiTempLabel (NULL);
10110   lbl1 = newiTempLabel (NULL);
10111
10112   aopOp (IC_RESULT (ic), ic, FALSE);
10113
10114   if (AOP_NEEDSACC(IC_RESULT(ic)))
10115   {
10116       /* If the result is accessed indirectly via
10117        * the accumulator, we must explicitly write
10118        * it back after the decrement.
10119        */
10120       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10121
10122       if (strcmp(rByte, "a"))
10123       {
10124            /* Something is hopelessly wrong */
10125            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10126                    __FILE__, __LINE__);
10127            /* We can just give up; the generated code will be inefficient,
10128             * but what the hey.
10129             */
10130            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10131            return 0;
10132       }
10133       emitcode ("dec", "%s", rByte);
10134       aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10135       emitcode ("jnz", "%05d$", lbl->key + 100);
10136   }
10137   else if (IS_AOP_PREG (IC_RESULT (ic)))
10138     {
10139       emitcode ("dec", "%s",
10140                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10141       MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10142       emitcode ("jnz", "%05d$", lbl->key + 100);
10143     }
10144   else
10145     {
10146       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10147                 lbl->key + 100);
10148     }
10149   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10150   emitcode ("", "%05d$:", lbl->key + 100);
10151   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10152   emitcode ("", "%05d$:", lbl1->key + 100);
10153
10154   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10155   ifx->generated = 1;
10156   return 1;
10157 }
10158
10159 /*-----------------------------------------------------------------*/
10160 /* genReceive - generate code for a receive iCode                  */
10161 /*-----------------------------------------------------------------*/
10162 static void
10163 genReceive (iCode * ic)
10164 {
10165     int size = getSize (operandType (IC_RESULT (ic)));
10166     int offset = 0;
10167   D(emitcode (";     genReceive",""));
10168
10169   if (ic->argreg == 1) { /* first parameter */
10170       if (isOperandInFarSpace (IC_RESULT (ic)) &&
10171           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10172            IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10173
10174           regs *tempRegs[4];
10175           int receivingA = 0;
10176           int roffset = 0;
10177
10178           for (offset = 0; offset<size; offset++)
10179             if (!strcmp (fReturn[offset], "a"))
10180               receivingA = 1;
10181
10182           if (!receivingA)
10183             {
10184               if (size==1 || getTempRegs(tempRegs, size-1, ic))
10185                 {
10186                   for (offset = size-1; offset>0; offset--)
10187                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10188                   emitcode("mov","a,%s", fReturn[0]);
10189                   _G.accInUse++;
10190                   aopOp (IC_RESULT (ic), ic, FALSE);
10191                   _G.accInUse--;
10192                   aopPut (AOP (IC_RESULT (ic)), "a", offset,
10193                           isOperandVolatile (IC_RESULT (ic), FALSE));
10194                   for (offset = 1; offset<size; offset++)
10195                     aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10196                             isOperandVolatile (IC_RESULT (ic), FALSE));
10197                   goto release;
10198                 }
10199             }
10200           else
10201             {
10202               if (getTempRegs(tempRegs, size, ic))
10203                 {
10204                   for (offset = 0; offset<size; offset++)
10205                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10206                   aopOp (IC_RESULT (ic), ic, FALSE);
10207                   for (offset = 0; offset<size; offset++)
10208                     aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10209                             isOperandVolatile (IC_RESULT (ic), FALSE));
10210                   goto release;
10211                 }
10212             }
10213
10214           offset = fReturnSizeMCS51 - size;
10215           while (size--) {
10216               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10217                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10218               offset++;
10219           }
10220           aopOp (IC_RESULT (ic), ic, FALSE);
10221           size = AOP_SIZE (IC_RESULT (ic));
10222           offset = 0;
10223           while (size--) {
10224               emitcode ("pop", "acc");
10225               aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10226           }
10227
10228       } else {
10229           _G.accInUse++;
10230           aopOp (IC_RESULT (ic), ic, FALSE);
10231           _G.accInUse--;
10232           assignResultValue (IC_RESULT (ic));
10233       }
10234   } else { /* second receive onwards */
10235       int rb1off ;
10236       aopOp (IC_RESULT (ic), ic, FALSE);
10237       rb1off = ic->argreg;
10238       while (size--) {
10239           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10240       }
10241   }
10242
10243 release:
10244   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10245 }
10246
10247 /*-----------------------------------------------------------------*/
10248 /* genDummyRead - generate code for dummy read of volatiles        */
10249 /*-----------------------------------------------------------------*/
10250 static void
10251 genDummyRead (iCode * ic)
10252 {
10253   operand *op;
10254   int size, offset;
10255
10256   D(emitcode(";     genDummyRead",""));
10257
10258   op = IC_RIGHT (ic);
10259   if (op && IS_SYMOP (op))
10260     {
10261       aopOp (op, ic, FALSE);
10262
10263       /* if the result is a bit */
10264       if (AOP_TYPE (op) == AOP_CRY)
10265         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10266       else
10267         {
10268           /* bit variables done */
10269           /* general case */
10270           size = AOP_SIZE (op);
10271           offset = 0;
10272           while (size--)
10273           {
10274             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10275             offset++;
10276           }
10277         }
10278
10279       freeAsmop (op, NULL, ic, TRUE);
10280     }
10281
10282   op = IC_LEFT (ic);
10283   if (op && IS_SYMOP (op))
10284     {
10285       aopOp (op, ic, FALSE);
10286
10287       /* if the result is a bit */
10288       if (AOP_TYPE (op) == AOP_CRY)
10289         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10290       else
10291         {
10292           /* bit variables done */
10293           /* general case */
10294           size = AOP_SIZE (op);
10295           offset = 0;
10296           while (size--)
10297           {
10298             MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10299             offset++;
10300           }
10301         }
10302
10303       freeAsmop (op, NULL, ic, TRUE);
10304     }
10305 }
10306
10307 /*-----------------------------------------------------------------*/
10308 /* genCritical - generate code for start of a critical sequence    */
10309 /*-----------------------------------------------------------------*/
10310 static void
10311 genCritical (iCode *ic)
10312 {
10313   symbol *tlbl = newiTempLabel (NULL);
10314
10315   D(emitcode(";     genCritical",""));
10316
10317   if (IC_RESULT (ic))
10318     {
10319       aopOp (IC_RESULT (ic), ic, TRUE);
10320       aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10321       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10322       aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10323       emitcode ("", "%05d$:", (tlbl->key + 100));
10324       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10325     }
10326   else
10327     {
10328       emitcode ("setb", "c");
10329       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10330       emitcode ("clr", "c");
10331       emitcode ("", "%05d$:", (tlbl->key + 100));
10332       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10333     }
10334 }
10335
10336 /*-----------------------------------------------------------------*/
10337 /* genEndCritical - generate code for end of a critical sequence   */
10338 /*-----------------------------------------------------------------*/
10339 static void
10340 genEndCritical (iCode *ic)
10341 {
10342   D(emitcode(";     genEndCritical",""));
10343
10344   if (IC_RIGHT (ic))
10345     {
10346       aopOp (IC_RIGHT (ic), ic, FALSE);
10347       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10348         {
10349           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10350           emitcode ("mov", "ea,c");
10351         }
10352       else
10353         {
10354           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10355             MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10356           emitcode ("rrc", "a");
10357           emitcode ("mov", "ea,c");
10358         }
10359       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10360     }
10361   else
10362     {
10363       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10364       emitcode ("mov", "ea,c");
10365     }
10366 }
10367
10368 /*-----------------------------------------------------------------*/
10369 /* gen51Code - generate code for 8051 based controllers            */
10370 /*-----------------------------------------------------------------*/
10371 void
10372 gen51Code (iCode * lic)
10373 {
10374   iCode *ic;
10375   int cln = 0;
10376   /* int cseq = 0; */
10377
10378   _G.currentFunc = NULL;
10379   lineHead = lineCurr = NULL;
10380
10381   /* print the allocation information */
10382   if (allocInfo && currFunc)
10383     printAllocInfo (currFunc, codeOutFile);
10384   /* if debug information required */
10385   if (options.debug && currFunc)
10386     {
10387       debugFile->writeFunction (currFunc, lic);
10388     }
10389   /* stack pointer name */
10390   if (options.useXstack)
10391     spname = "_spx";
10392   else
10393     spname = "sp";
10394
10395
10396   for (ic = lic; ic; ic = ic->next)
10397     {
10398       _G.current_iCode = ic;
10399
10400       if (ic->lineno && cln != ic->lineno)
10401         {
10402           if (options.debug)
10403             {
10404               debugFile->writeCLine (ic);
10405             }
10406           if (!options.noCcodeInAsm) {
10407             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10408                       printCLine(ic->filename, ic->lineno));
10409           }
10410           cln = ic->lineno;
10411         }
10412       #if 0
10413       if (ic->seqPoint && ic->seqPoint != cseq)
10414         {
10415           emitcode ("", "; sequence point %d", ic->seqPoint);
10416           cseq = ic->seqPoint;
10417         }
10418       #endif
10419       if (options.iCodeInAsm) {
10420         char regsInUse[80];
10421         int i;
10422
10423         for (i=0; i<8; i++) {
10424           sprintf (&regsInUse[i],
10425                    "%c", ic->riu & (1<<i) ? i+'0' : '-');
10426         }
10427         regsInUse[i]=0;
10428         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10429       }
10430       /* if the result is marked as
10431          spilt and rematerializable or code for
10432          this has already been generated then
10433          do nothing */
10434       if (resultRemat (ic) || ic->generated)
10435         continue;
10436
10437       /* depending on the operation */
10438       switch (ic->op)
10439         {
10440         case '!':
10441           genNot (ic);
10442           break;
10443
10444         case '~':
10445           genCpl (ic);
10446           break;
10447
10448         case UNARYMINUS:
10449           genUminus (ic);
10450           break;
10451
10452         case IPUSH:
10453           genIpush (ic);
10454           break;
10455
10456         case IPOP:
10457           /* IPOP happens only when trying to restore a
10458              spilt live range, if there is an ifx statement
10459              following this pop then the if statement might
10460              be using some of the registers being popped which
10461              would destory the contents of the register so
10462              we need to check for this condition and handle it */
10463           if (ic->next &&
10464               ic->next->op == IFX &&
10465               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10466             genIfx (ic->next, ic);
10467           else
10468             genIpop (ic);
10469           break;
10470
10471         case CALL:
10472           genCall (ic);
10473           break;
10474
10475         case PCALL:
10476           genPcall (ic);
10477           break;
10478
10479         case FUNCTION:
10480           genFunction (ic);
10481           break;
10482
10483         case ENDFUNCTION:
10484           genEndFunction (ic);
10485           break;
10486
10487         case RETURN:
10488           genRet (ic);
10489           break;
10490
10491         case LABEL:
10492           genLabel (ic);
10493           break;
10494
10495         case GOTO:
10496           genGoto (ic);
10497           break;
10498
10499         case '+':
10500           genPlus (ic);
10501           break;
10502
10503         case '-':
10504           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10505             genMinus (ic);
10506           break;
10507
10508         case '*':
10509           genMult (ic);
10510           break;
10511
10512         case '/':
10513           genDiv (ic);
10514           break;
10515
10516         case '%':
10517           genMod (ic);
10518           break;
10519
10520         case '>':
10521           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10522           break;
10523
10524         case '<':
10525           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10526           break;
10527
10528         case LE_OP:
10529         case GE_OP:
10530         case NE_OP:
10531
10532           /* note these two are xlated by algebraic equivalence
10533              during parsing SDCC.y */
10534           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10535                   "got '>=' or '<=' shouldn't have come here");
10536           break;
10537
10538         case EQ_OP:
10539           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10540           break;
10541
10542         case AND_OP:
10543           genAndOp (ic);
10544           break;
10545
10546         case OR_OP:
10547           genOrOp (ic);
10548           break;
10549
10550         case '^':
10551           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10552           break;
10553
10554         case '|':
10555           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10556           break;
10557
10558         case BITWISEAND:
10559           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10560           break;
10561
10562         case INLINEASM:
10563           genInline (ic);
10564           break;
10565
10566         case RRC:
10567           genRRC (ic);
10568           break;
10569
10570         case RLC:
10571           genRLC (ic);
10572           break;
10573
10574         case GETHBIT:
10575           genGetHbit (ic);
10576           break;
10577
10578         case LEFT_OP:
10579           genLeftShift (ic);
10580           break;
10581
10582         case RIGHT_OP:
10583           genRightShift (ic);
10584           break;
10585
10586         case GET_VALUE_AT_ADDRESS:
10587           genPointerGet (ic,
10588                          hasInc (IC_LEFT (ic), ic,
10589                                  getSize (operandType (IC_RESULT (ic)))),
10590                          ifxForOp (IC_RESULT (ic), ic) );
10591           break;
10592
10593         case '=':
10594           if (POINTER_SET (ic))
10595             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10596           else
10597             genAssign (ic);
10598           break;
10599
10600         case IFX:
10601           genIfx (ic, NULL);
10602           break;
10603
10604         case ADDRESS_OF:
10605           genAddrOf (ic);
10606           break;
10607
10608         case JUMPTABLE:
10609           genJumpTab (ic);
10610           break;
10611
10612         case CAST:
10613           genCast (ic);
10614           break;
10615
10616         case RECEIVE:
10617           genReceive (ic);
10618           break;
10619
10620         case SEND:
10621           addSet (&_G.sendSet, ic);
10622           break;
10623
10624         case DUMMY_READ_VOLATILE:
10625           genDummyRead (ic);
10626           break;
10627
10628         case CRITICAL:
10629           genCritical (ic);
10630           break;
10631
10632         case ENDCRITICAL:
10633           genEndCritical (ic);
10634           break;
10635
10636         case SWAP:
10637           genSwap (ic);
10638           break;
10639
10640         default:
10641           ic = ic;
10642         }
10643     }
10644
10645   _G.current_iCode = NULL;
10646
10647   /* now we are ready to call the
10648      peep hole optimizer */
10649   if (!options.nopeep)
10650     peepHole (&lineHead);
10651
10652   /* now do the actual printing */
10653   printLine (lineHead, codeOutFile);
10654   return;
10655 }