* doc/sdccman.lyx, src/SDCCmain.c, src/SDCCglobal.h, src/ds390/gen.c,
[fw/sdcc] / src / mcs51 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.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) do if (options.verboseAsm) {x;} while(0)
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "rtrack.h"
44 #include "gen.h"
45 #include "dbuf_string.h"
46
47 char *aopLiteral (value * val, int offset);
48 char *aopLiteralLong (value * val, int offset, int size);
49 extern int allocInfo;
50
51 /* this is the down and dirty file with all kinds of
52    kludgy & hacky stuff. This is what it is all about
53    CODE GENERATION for a specific MCU . some of the
54    routines may be reusable, will have to see */
55
56 static char *zero = "#0x00";
57 static char *one = "#0x01";
58 static char *spname;
59
60 char *fReturn8051[] =
61 {"dpl", "dph", "b", "a"};
62 unsigned fReturnSizeMCS51 = 4;  /* shared with ralloc.c */
63 char **fReturn = fReturn8051;
64 static char *accUse[] =
65 {"a", "b"};
66
67 static unsigned short rbank = -1;
68
69 #define REG_WITH_INDEX   mcs51_regWithIdx
70
71 #define AOP(op) op->aop
72 #define AOP_TYPE(op) AOP(op)->type
73 #define AOP_SIZE(op) AOP(op)->size
74 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
75                         AOP_TYPE(x) == AOP_R0))
76
77 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
78                          AOP_TYPE(x) == AOP_DPTR || \
79                          AOP(x)->paged))
80
81 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
82                        (x->aopu.aop_reg[0] == REG_WITH_INDEX(R0_IDX) || \
83                         x->aopu.aop_reg[0] == REG_WITH_INDEX(R1_IDX) )))
84
85 #define SYM_BP(sym)   (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
86
87 #define R0INB   _G.bu.bs.r0InB
88 #define R1INB   _G.bu.bs.r1InB
89 #define OPINB   _G.bu.bs.OpInB
90 #define BINUSE  _G.bu.BInUse
91
92 static struct
93   {
94     short r0Pushed;
95     short r1Pushed;
96     union
97       {
98         struct
99           {
100             short r0InB : 2;//2 so we can see it overflow
101             short r1InB : 2;//2 so we can see it overflow
102             short OpInB : 2;//2 so we can see it overflow
103           } bs;
104         short BInUse;
105       } bu;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111     iCode *current_iCode;
112     symbol *currentFunc;
113   }
114 _G;
115
116 static char *rb1regs[] = {
117     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
118     "b0",  "b1",  "b2",  "b3",  "b4",  "b5",  "b6",  "b7"
119 };
120
121 extern struct dbuf_s *codeOutBuf;
122
123 #define RESULTONSTACK(x) \
124                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
125                          IC_RESULT(x)->aop->type == AOP_STK )
126
127 #define MOVA(x)  mova(x)  /* use function to avoid multiple eval */
128 #define MOVB(x)  movb(x)
129
130 #define CLRC     emitcode("clr","c")
131 #define SETC     emitcode("setb","c")
132
133 static lineNode *lineHead = NULL;
134 static lineNode *lineCurr = NULL;
135
136 static unsigned char SLMask[] =
137 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
138  0xE0, 0xC0, 0x80, 0x00};
139 static unsigned char SRMask[] =
140 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
141  0x07, 0x03, 0x01, 0x00};
142
143 #define LSB     0
144 #define MSB16   1
145 #define MSB24   2
146 #define MSB32   3
147
148 /*-----------------------------------------------------------------*/
149 /* emitcode - writes the code into a file : for now it is simple    */
150 /*-----------------------------------------------------------------*/
151 void
152 emitcode (const char *inst, const char *fmt,...)
153 {
154   va_list ap;
155   struct dbuf_s dbuf;
156   const char *lbp, *lb;
157
158   dbuf_init (&dbuf, INITIAL_INLINEASM);
159
160   va_start (ap, fmt);
161
162   if (inst && *inst)
163     {
164       dbuf_append_str (&dbuf, inst);
165
166       if (fmt && *fmt)
167         {
168           dbuf_append_char (&dbuf, '\t');
169           dbuf_tvprintf (&dbuf, fmt, ap);
170         }
171     }
172   else
173     {
174       dbuf_tvprintf (&dbuf, fmt, ap);
175     }
176
177   lbp = lb = dbuf_c_str(&dbuf);
178
179   while (isspace ((unsigned char)*lbp))
180     {
181       lbp++;
182     }
183
184   if (lbp && *lbp)
185     {
186       rtrackUpdate (lbp);
187
188       lineCurr = (lineCurr ?
189                   connectLine (lineCurr, newLineNode (lb)) :
190                   (lineHead = newLineNode (lb)));
191     }
192
193   lineCurr->isInline = _G.inLine;
194   lineCurr->isDebug = _G.debugLine;
195   lineCurr->ic = _G.current_iCode;
196   lineCurr->isComment = (*lbp==';');
197   va_end (ap);
198
199   dbuf_destroy(&dbuf);
200 }
201
202 static void
203 emitLabel (symbol *tlbl)
204 {
205   emitcode ("", "%05d$:", tlbl->key + 100);
206   lineCurr->isLabel = 1;
207 }
208
209 /*-----------------------------------------------------------------*/
210 /* mcs51_emitDebuggerSymbol - associate the current code location  */
211 /*   with a debugger symbol                                        */
212 /*-----------------------------------------------------------------*/
213 void
214 mcs51_emitDebuggerSymbol (char * debugSym)
215 {
216   _G.debugLine = 1;
217   emitcode ("", "%s ==.", debugSym);
218   _G.debugLine = 0;
219 }
220
221 /*-----------------------------------------------------------------*/
222 /* mova - moves specified value into accumulator                   */
223 /*-----------------------------------------------------------------*/
224 static void
225 mova (const char *x)
226 {
227   /* do some early peephole optimization */
228   if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
229     return;
230
231   /* if it is a literal mov try to get it cheaper */
232   if (*x == '#' &&
233       rtrackMoveALit(x))
234     return;
235
236   emitcode("mov", "a,%s", x);
237 }
238
239 /*-----------------------------------------------------------------*/
240 /* movb - moves specified value into register b                    */
241 /*-----------------------------------------------------------------*/
242 static void
243 movb (const char *x)
244 {
245   /* do some early peephole optimization */
246   if (!strncmp(x, "b", 2))
247     return;
248
249   /* if it is a literal mov try to get it cheaper */
250   if (*x == '#')
251     {
252       emitcode("mov","b,%s", rtrackGetLit(x));
253       return;
254     }
255
256   emitcode("mov","b,%s", x);
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* pushB - saves register B if necessary                           */
261 /*-----------------------------------------------------------------*/
262 static bool
263 pushB (void)
264 {
265   bool pushedB = FALSE;
266
267   if (BINUSE)
268     {
269       emitcode ("push", "b");
270 //    printf("B was in use !\n");
271       pushedB = TRUE;
272     }
273   else
274     {
275       OPINB++;
276     }
277   return pushedB;
278 }
279
280 /*-----------------------------------------------------------------*/
281 /* popB - restores value of register B if necessary                */
282 /*-----------------------------------------------------------------*/
283 static void
284 popB (bool pushedB)
285 {
286   if (pushedB)
287     {
288       emitcode ("pop", "b");
289     }
290   else
291     {
292       OPINB--;
293     }
294 }
295
296 /*-----------------------------------------------------------------*/
297 /* pushReg - saves register                                        */
298 /*-----------------------------------------------------------------*/
299 static bool
300 pushReg (int index, bool bits_pushed)
301 {
302   regs * reg = REG_WITH_INDEX (index);
303   if (reg->type == REG_BIT)
304     {
305       if (!bits_pushed)
306         emitcode ("push", "%s", reg->base);
307       return TRUE;
308     }
309   else
310     emitcode ("push", "%s", reg->dname);
311   return bits_pushed;
312 }
313
314 /*-----------------------------------------------------------------*/
315 /* popReg - restores register                                      */
316 /*-----------------------------------------------------------------*/
317 static bool
318 popReg (int index, bool bits_popped)
319 {
320   regs * reg = REG_WITH_INDEX (index);
321   if (reg->type == REG_BIT)
322     {
323       if (!bits_popped)
324         emitcode ("pop", "%s", reg->base);
325       return TRUE;
326     }
327   else
328     emitcode ("pop", "%s", reg->dname);
329   return bits_popped;
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
334 /*-----------------------------------------------------------------*/
335 static regs *
336 getFreePtr (iCode * ic, asmop ** aopp, bool result)
337 {
338   bool r0iu, r1iu;
339   bool r0ou, r1ou;
340
341   /* the logic: if r0 & r1 used in the instruction
342      then we are in trouble otherwise */
343
344   /* first check if r0 & r1 are used by this
345      instruction, in which case we are in trouble */
346   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
347   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
348   if (r0iu && r1iu) {
349       goto endOfWorld;
350     }
351
352   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
353   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
354
355   /* if no usage of r0 then return it */
356   if (!r0iu && !r0ou)
357     {
358       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359       (*aopp)->type = AOP_R0;
360
361       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
362     }
363
364   /* if no usage of r1 then return it */
365   if (!r1iu && !r1ou)
366     {
367       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
368       (*aopp)->type = AOP_R1;
369
370       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R1_IDX);
371     }
372
373   /* now we know they both have usage */
374   /* if r0 not used in this instruction */
375   if (!r0iu)
376     {
377       /* push it if not already pushed */
378       if (ic->op == IPUSH)
379         {
380           MOVB (REG_WITH_INDEX (R0_IDX)->dname);
381           R0INB++;
382         }
383       else if (!_G.r0Pushed)
384         {
385           emitcode ("push", "%s",
386                     REG_WITH_INDEX (R0_IDX)->dname);
387           _G.r0Pushed++;
388         }
389
390       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
391       (*aopp)->type = AOP_R0;
392
393       return (*aopp)->aopu.aop_ptr = REG_WITH_INDEX (R0_IDX);
394     }
395
396   /* if r1 not used then */
397
398   if (!r1iu)
399     {
400       /* push it if not already pushed */
401       if (ic->op == IPUSH)
402         {
403           MOVB (REG_WITH_INDEX (R1_IDX)->dname);
404           R1INB++;
405         }
406       else if (!_G.r1Pushed)
407         {
408           emitcode ("push", "%s",
409                     REG_WITH_INDEX (R1_IDX)->dname);
410           _G.r1Pushed++;
411         }
412
413       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
414       (*aopp)->type = AOP_R1;
415       return REG_WITH_INDEX (R1_IDX);
416     }
417
418 endOfWorld:
419   /* I said end of world, but not quite end of world yet */
420   /* if this is a result then we can push it on the stack */
421   if (result)
422     {
423       (*aopp)->type = AOP_STK;
424       return NULL;
425     }
426   /* in the case that result AND left AND right needs a pointer reg
427      we can safely use the result's */
428   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX))
429     {
430       (*aopp)->type = AOP_R0;
431       return REG_WITH_INDEX (R0_IDX);
432     }
433   if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX))
434     {
435       (*aopp)->type = AOP_R1;
436       return REG_WITH_INDEX (R1_IDX);
437     }
438
439   /* now this is REALLY the end of the world */
440   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
441           "getFreePtr should never reach here");
442   exit (1);
443 }
444
445
446 /*-----------------------------------------------------------------*/
447 /* getTempRegs - initialize an array of pointers to GPR registers */
448 /*               that are not in use. Returns 1 if the requested   */
449 /*               number of registers were available, 0 otherwise.  */
450 /*-----------------------------------------------------------------*/
451 int
452 getTempRegs(regs **tempRegs, int size, iCode *ic)
453 {
454   bitVect * freeRegs;
455   int i;
456   int offset;
457
458   if (!ic)
459     ic = _G.current_iCode;
460   if (!ic)
461     return 0;
462   if (!_G.currentFunc)
463     return 0;
464
465   freeRegs = newBitVect(8);
466   bitVectSetBit (freeRegs, R2_IDX);
467   bitVectSetBit (freeRegs, R3_IDX);
468   bitVectSetBit (freeRegs, R4_IDX);
469   bitVectSetBit (freeRegs, R5_IDX);
470   bitVectSetBit (freeRegs, R6_IDX);
471   bitVectSetBit (freeRegs, R7_IDX);
472
473   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
474     {
475       bitVect * newfreeRegs;
476       newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
477       freeBitVect(freeRegs);
478       freeRegs = newfreeRegs;
479     }
480   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
481
482   offset = 0;
483   for (i=0; i<freeRegs->size; i++)
484     {
485       if (bitVectBitValue(freeRegs,i))
486         tempRegs[offset++] = REG_WITH_INDEX(i);
487       if (offset>=size)
488         {
489           freeBitVect(freeRegs);
490           return 1;
491         }
492     }
493
494   freeBitVect(freeRegs);
495   return 0;
496 }
497
498
499 /*-----------------------------------------------------------------*/
500 /* newAsmop - creates a new asmOp                                  */
501 /*-----------------------------------------------------------------*/
502 static asmop *
503 newAsmop (short type)
504 {
505   asmop *aop;
506
507   aop = Safe_calloc (1, sizeof (asmop));
508   aop->type = type;
509   aop->allocated = 1;
510   return aop;
511 }
512
513 /*-----------------------------------------------------------------*/
514 /* pointerCode - returns the code for a pointer type               */
515 /*-----------------------------------------------------------------*/
516 static int
517 pointerCode (sym_link * etype)
518 {
519
520   return PTR_TYPE (SPEC_OCLS (etype));
521
522 }
523
524 /*-----------------------------------------------------------------*/
525 /* leftRightUseAcc - returns size of accumulator use by operands   */
526 /*-----------------------------------------------------------------*/
527 static int
528 leftRightUseAcc(iCode *ic)
529 {
530   operand *op;
531   int size;
532   int accuseSize = 0;
533   int accuse = 0;
534
535   if (!ic)
536     {
537       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
538               "null iCode pointer");
539       return 0;
540     }
541
542   if (ic->op == IFX)
543     {
544       op = IC_COND (ic);
545       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
546         {
547           accuse = 1;
548           size = getSize (OP_SYMBOL (op)->type);
549           if (size>accuseSize)
550             accuseSize = size;
551         }
552     }
553   else if (ic->op == JUMPTABLE)
554     {
555       op = IC_JTCOND (ic);
556       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
557         {
558           accuse = 1;
559           size = getSize (OP_SYMBOL (op)->type);
560           if (size>accuseSize)
561             accuseSize = size;
562         }
563     }
564   else
565     {
566       op = IC_LEFT (ic);
567       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
568         {
569           accuse = 1;
570           size = getSize (OP_SYMBOL (op)->type);
571           if (size>accuseSize)
572             accuseSize = size;
573         }
574       op = IC_RIGHT (ic);
575       if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
576         {
577           accuse = 1;
578           size = getSize (OP_SYMBOL (op)->type);
579           if (size>accuseSize)
580             accuseSize = size;
581         }
582     }
583
584   if (accuseSize)
585     return accuseSize;
586   else
587     return accuse;
588 }
589
590 /*-----------------------------------------------------------------*/
591 /* aopForSym - for a true symbol                                   */
592 /*-----------------------------------------------------------------*/
593 static asmop *
594 aopForSym (iCode * ic, symbol * sym, bool result)
595 {
596   asmop *aop;
597   memmap *space;
598   bool accuse = leftRightUseAcc (ic) || _G.accInUse;
599
600   wassertl (ic != NULL, "Got a null iCode");
601   wassertl (sym != NULL, "Got a null symbol");
602
603   space = SPEC_OCLS (sym->etype);
604
605   /* if already has one */
606   if (sym->aop)
607     {
608       sym->aop->allocated++;
609       return sym->aop;
610     }
611
612   /* assign depending on the storage class */
613   /* if it is on the stack or indirectly addressable */
614   /* space we need to assign either r0 or r1 to it   */
615   if (sym->onStack || sym->iaccess)
616     {
617       sym->aop = aop = newAsmop (0);
618       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
619       aop->size = getSize (sym->type);
620
621       /* now assign the address of the variable to
622          the pointer register */
623       if (aop->type != AOP_STK)
624         {
625           if (sym->onStack)
626             {
627               signed char offset = ((sym->stack < 0) ?
628                          ((signed char) (sym->stack - _G.nRegsSaved)) :
629                          ((signed char) sym->stack)) & 0xff;
630
631               if ((abs(offset) <= 3) ||
632                   (accuse && (abs(offset) <= 7)))
633                 {
634                   emitcode ("mov", "%s,%s",
635                             aop->aopu.aop_ptr->name, SYM_BP (sym));
636                   while (offset < 0)
637                     {
638                       emitcode ("dec", aop->aopu.aop_ptr->name);
639                       offset++;
640                     }
641                   while (offset > 0)
642                     {
643                       emitcode ("inc", aop->aopu.aop_ptr->name);
644                       offset--;
645                     }
646                 }
647               else
648                 {
649                   if (accuse)
650                     emitcode ("push", "acc");
651                   emitcode ("mov", "a,%s", SYM_BP (sym));
652                   emitcode ("add", "a,#0x%02x", offset & 0xff);
653                   emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
654                   if (accuse)
655                     emitcode ("pop", "acc");
656                 }
657             }
658           else
659             {
660               emitcode ("mov", "%s,#%s",
661                         aop->aopu.aop_ptr->name,
662                         sym->rname);
663             }
664           aop->paged = space->paged;
665         }
666       else
667         aop->aopu.aop_stk = sym->stack;
668       return aop;
669     }
670
671   /* if in bit space */
672   if (IN_BITSPACE (space))
673     {
674       sym->aop = aop = newAsmop (AOP_CRY);
675       aop->aopu.aop_dir = sym->rname;
676       aop->size = getSize (sym->type);
677       return aop;
678     }
679   /* if it is in direct space */
680   if (IN_DIRSPACE (space))
681     {
682       //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
683       //printTypeChainRaw(sym->type, NULL);
684       //printf("space = %s\n", space ? space->sname : "NULL");
685       sym->aop = aop = newAsmop (AOP_DIR);
686       aop->aopu.aop_dir = sym->rname;
687       aop->size = getSize (sym->type);
688       return aop;
689     }
690
691   /* special case for a function */
692   if (IS_FUNC (sym->type))
693     {
694       sym->aop = aop = newAsmop (AOP_IMMD);
695       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
696       aop->size = getSize (sym->type);
697       return aop;
698     }
699
700   /* only remaining is far space */
701   /* in which case DPTR gets the address */
702   sym->aop = aop = newAsmop (AOP_DPTR);
703   emitcode ("mov", "dptr,#%s", sym->rname);
704   aop->size = getSize (sym->type);
705
706   /* if it is in code space */
707   if (IN_CODESPACE (space))
708     aop->code = 1;
709
710   return aop;
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* aopForRemat - rematerialzes an object                           */
715 /*-----------------------------------------------------------------*/
716 static asmop *
717 aopForRemat (symbol * sym)
718 {
719   iCode *ic = sym->rematiCode;
720   asmop *aop = newAsmop (AOP_IMMD);
721   int ptr_type = 0;
722   int val = 0;
723
724   for (;;)
725     {
726       if (ic->op == '+')
727         val += (int) operandLitValue (IC_RIGHT (ic));
728       else if (ic->op == '-')
729         val -= (int) operandLitValue (IC_RIGHT (ic));
730       else if (IS_CAST_ICODE(ic)) {
731               sym_link *from_type = operandType(IC_RIGHT(ic));
732               aop->aopu.aop_immd.from_cast_remat = 1;
733               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
734               ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
735               continue;
736       } else break;
737
738       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
739     }
740
741   if (val)
742     {
743       SNPRINTF (buffer, sizeof(buffer),
744                 "(%s %c 0x%04x)",
745                 OP_SYMBOL (IC_LEFT (ic))->rname,
746                 val >= 0 ? '+' : '-',
747                 abs (val) & 0xffff);
748     }
749   else
750     {
751       strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
752     }
753
754   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
755   /* set immd2 field if required */
756   if (aop->aopu.aop_immd.from_cast_remat)
757     {
758       SNPRINTF (buffer, sizeof(buffer), "#0x%02x", ptr_type);
759       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
760     }
761
762   return aop;
763 }
764
765 /*-----------------------------------------------------------------*/
766 /* regsInCommon - two operands have some registers in common       */
767 /*-----------------------------------------------------------------*/
768 static bool
769 regsInCommon (operand * op1, operand * op2)
770 {
771   symbol *sym1, *sym2;
772   int i;
773
774   /* if they have registers in common */
775   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
776     return FALSE;
777
778   sym1 = OP_SYMBOL (op1);
779   sym2 = OP_SYMBOL (op2);
780
781   if (sym1->nRegs == 0 || sym2->nRegs == 0)
782     return FALSE;
783
784   for (i = 0; i < sym1->nRegs; i++)
785     {
786       int j;
787       if (!sym1->regs[i])
788         continue;
789
790       for (j = 0; j < sym2->nRegs; j++)
791         {
792           if (!sym2->regs[j])
793             continue;
794
795           if (sym2->regs[j] == sym1->regs[i])
796             return TRUE;
797         }
798     }
799
800   return FALSE;
801 }
802
803 /*-----------------------------------------------------------------*/
804 /* operandsEqu - equivalent                                        */
805 /*-----------------------------------------------------------------*/
806 static bool
807 operandsEqu (operand * op1, operand * op2)
808 {
809   symbol *sym1, *sym2;
810
811   /* if they're not symbols */
812   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
813     return FALSE;
814
815   sym1 = OP_SYMBOL (op1);
816   sym2 = OP_SYMBOL (op2);
817
818   /* if both are itemps & one is spilt
819      and the other is not then false */
820   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
821       sym1->isspilt != sym2->isspilt)
822     return FALSE;
823
824   /* if they are the same */
825   if (sym1 == sym2)
826     return TRUE;
827
828   /* if they have the same rname */
829   if (sym1->rname[0] && sym2->rname[0] &&
830       strcmp (sym1->rname, sym2->rname) == 0 &&
831       !(IS_PARM (op2) && IS_ITEMP (op1)))
832     return TRUE;
833
834   /* if left is a tmp & right is not */
835   if (IS_ITEMP (op1) &&
836       !IS_ITEMP (op2) &&
837       sym1->isspilt &&
838       (sym1->usl.spillLoc == sym2))
839     return TRUE;
840
841   if (IS_ITEMP (op2) &&
842       !IS_ITEMP (op1) &&
843       sym2->isspilt &&
844       sym1->level > 0 &&
845       (sym2->usl.spillLoc == sym1))
846     return TRUE;
847
848   return FALSE;
849 }
850
851 /*-----------------------------------------------------------------*/
852 /* sameByte - two asmops have the same address at given offsets    */
853 /*-----------------------------------------------------------------*/
854 static bool
855 sameByte (asmop * aop1, int off1, asmop * aop2, int off2)
856 {
857   if (aop1 == aop2 && off1 == off2)
858     return TRUE;
859
860   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
861     return FALSE;
862
863   if (aop1->type != aop2->type)
864     return FALSE;
865
866   if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
867     return FALSE;
868
869   return TRUE;
870 }
871
872 /*-----------------------------------------------------------------*/
873 /* sameRegs - two asmops have the same registers                   */
874 /*-----------------------------------------------------------------*/
875 static bool
876 sameRegs (asmop * aop1, asmop * aop2)
877 {
878   int i;
879
880   if (aop1 == aop2)
881     return TRUE;
882
883   if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
884     return FALSE;
885
886   if (aop1->type != aop2->type)
887     return FALSE;
888
889   if (aop1->size != aop2->size)
890     return FALSE;
891
892   for (i = 0; i < aop1->size; i++)
893     if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
894       return FALSE;
895
896   return TRUE;
897 }
898
899 /*-----------------------------------------------------------------*/
900 /* aopOp - allocates an asmop for an operand  :                    */
901 /*-----------------------------------------------------------------*/
902 static void
903 aopOp (operand * op, iCode * ic, bool result)
904 {
905   asmop *aop;
906   symbol *sym;
907   int i;
908
909   if (!op)
910     return;
911
912   /* if this a literal */
913   if (IS_OP_LITERAL (op))
914     {
915       op->aop = aop = newAsmop (AOP_LIT);
916       aop->aopu.aop_lit = op->operand.valOperand;
917       aop->size = getSize (operandType (op));
918       return;
919     }
920
921   /* if already has a asmop then continue */
922   if (op->aop)
923     {
924       op->aop->allocated++;
925       return;
926     }
927
928   /* if the underlying symbol has a aop */
929   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
930     {
931       op->aop = OP_SYMBOL (op)->aop;
932       op->aop->allocated++;
933       return;
934     }
935
936   /* if this is a true symbol */
937   if (IS_TRUE_SYMOP (op))
938     {
939       op->aop = aopForSym (ic, OP_SYMBOL (op), result);
940       return;
941     }
942
943   /* this is a temporary : this has
944      only five choices :
945      a) register
946      b) spillocation
947      c) rematerialize
948      d) conditional
949      e) can be a return use only */
950
951   sym = OP_SYMBOL (op);
952
953   /* if the type is a conditional */
954   if (sym->regType == REG_CND)
955     {
956       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
957       aop->size = sym->ruonly ? 1 : 0;
958       return;
959     }
960
961   /* if it is spilt then two situations
962      a) is rematerialize
963      b) has a spill location */
964   if (sym->isspilt || sym->nRegs == 0)
965     {
966
967       /* rematerialize it NOW */
968       if (sym->remat)
969         {
970           sym->aop = op->aop = aop = aopForRemat (sym);
971           aop->size = getSize (sym->type);
972           return;
973         }
974
975       if (sym->accuse)
976         {
977           int i;
978           sym->aop = op->aop = aop = newAsmop (AOP_ACC);
979           aop->size = getSize (sym->type);
980           for (i = 0; i < 2; i++)
981             aop->aopu.aop_str[i] = accUse[i];
982           return;
983         }
984
985       if (sym->ruonly)
986         {
987           unsigned i;
988
989           sym->aop = op->aop = aop = newAsmop (AOP_STR);
990           aop->size = getSize (sym->type);
991           for (i = 0; i < fReturnSizeMCS51; i++)
992             aop->aopu.aop_str[i] = fReturn[i];
993           return;
994         }
995
996       if (sym->usl.spillLoc)
997         {
998           asmop *oldAsmOp = NULL;
999
1000           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1001             {
1002               /* force a new aop if sizes differ */
1003               oldAsmOp = sym->usl.spillLoc->aop;
1004               sym->usl.spillLoc->aop = NULL;
1005             }
1006           sym->aop = op->aop = aop =
1007                      aopForSym (ic, sym->usl.spillLoc, result);
1008           if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
1009             {
1010               /* Don't reuse the new aop, go with the last one */
1011               sym->usl.spillLoc->aop = oldAsmOp;
1012             }
1013           aop->size = getSize (sym->type);
1014           return;
1015         }
1016
1017       /* else must be a dummy iTemp */
1018       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1019       aop->size = getSize (sym->type);
1020       return;
1021     }
1022
1023   /* if the type is a bit register */
1024   if (sym->regType == REG_BIT)
1025     {
1026       sym->aop = op->aop = aop = newAsmop (AOP_CRY);
1027       aop->size = sym->nRegs;//1???
1028       aop->aopu.aop_reg[0] = sym->regs[0];
1029       aop->aopu.aop_dir = sym->regs[0]->name;
1030       return;
1031     }
1032
1033   /* must be in a register */
1034   sym->aop = op->aop = aop = newAsmop (AOP_REG);
1035   aop->size = sym->nRegs;
1036   for (i = 0; i < sym->nRegs; i++)
1037     aop->aopu.aop_reg[i] = sym->regs[i];
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* freeAsmop - free up the asmop given to an operand               */
1042 /*----------------------------------------------------------------*/
1043 static void
1044 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1045 {
1046   asmop *aop;
1047
1048   if (!op)
1049     aop = aaop;
1050   else
1051     aop = op->aop;
1052
1053   if (!aop)
1054     return;
1055
1056   aop->allocated--;
1057
1058   if (aop->allocated)
1059     goto dealloc;
1060
1061   /* depending on the asmop type only three cases need work
1062      AOP_R0, AOP_R1 & AOP_STK */
1063   switch (aop->type)
1064     {
1065     case AOP_R0:
1066       if (R0INB)
1067         {
1068           emitcode ("mov", "r0,b");
1069           R0INB--;
1070         }
1071       else if (_G.r0Pushed)
1072         {
1073           if (pop)
1074             {
1075               emitcode ("pop", "ar0");
1076               _G.r0Pushed--;
1077             }
1078         }
1079       bitVectUnSetBit (ic->rUsed, R0_IDX);
1080       break;
1081
1082     case AOP_R1:
1083       if (R1INB)
1084         {
1085           emitcode ("mov", "r1,b");
1086           R1INB--;
1087         }
1088       else if (_G.r1Pushed)
1089         {
1090           if (pop)
1091             {
1092               emitcode ("pop", "ar1");
1093               _G.r1Pushed--;
1094             }
1095         }
1096       bitVectUnSetBit (ic->rUsed, R1_IDX);
1097       break;
1098
1099     case AOP_STK:
1100       {
1101         int sz = aop->size;
1102         int stk = aop->aopu.aop_stk + aop->size - 1;
1103         bitVectUnSetBit (ic->rUsed, R0_IDX);
1104         bitVectUnSetBit (ic->rUsed, R1_IDX);
1105
1106         getFreePtr (ic, &aop, FALSE);
1107
1108         if (stk)
1109           {
1110             emitcode ("mov", "a,_bp");
1111             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1112             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1113           }
1114         else
1115           {
1116             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1117           }
1118
1119         while (sz--)
1120           {
1121             emitcode ("pop", "acc");
1122             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1123             if (!sz)
1124               break;
1125             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1126           }
1127         op->aop = aop;
1128         freeAsmop (op, NULL, ic, TRUE);
1129         if (_G.r1Pushed)
1130           {
1131             emitcode ("pop", "ar1");
1132             _G.r1Pushed--;
1133           }
1134         if (_G.r0Pushed)
1135           {
1136             emitcode ("pop", "ar0");
1137             _G.r0Pushed--;
1138           }
1139       }
1140       break;
1141     }
1142
1143 dealloc:
1144   /* all other cases just dealloc */
1145   if (op)
1146     {
1147       op->aop = NULL;
1148       if (IS_SYMOP (op))
1149         {
1150           OP_SYMBOL (op)->aop = NULL;
1151           /* if the symbol has a spill */
1152           if (SPIL_LOC (op))
1153             SPIL_LOC (op)->aop = NULL;
1154         }
1155     }
1156 }
1157
1158 /*------------------------------------------------------------------*/
1159 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1160 /*                      pop r0 or r1 off stack if pushed            */
1161 /*------------------------------------------------------------------*/
1162 static void
1163 freeForBranchAsmop (operand * op)
1164 {
1165   asmop *aop;
1166
1167   if (!op)
1168     return;
1169
1170   aop = op->aop;
1171
1172   if (!aop)
1173     return;
1174
1175   if (!aop->allocated)
1176     return;
1177
1178   switch (aop->type)
1179     {
1180     case AOP_R0:
1181       if (R0INB)
1182         {
1183           emitcode ("mov", "r0,b");
1184         }
1185       else if (_G.r0Pushed)
1186         {
1187           emitcode ("pop", "ar0");
1188         }
1189       break;
1190
1191     case AOP_R1:
1192       if (R1INB)
1193         {
1194           emitcode ("mov", "r1,b");
1195         }
1196       else if (_G.r1Pushed)
1197         {
1198           emitcode ("pop", "ar1");
1199         }
1200       break;
1201
1202     case AOP_STK:
1203       {
1204         int sz = aop->size;
1205         int stk = aop->aopu.aop_stk + aop->size - 1;
1206
1207         emitcode ("mov", "b,r0");
1208         if (stk)
1209           {
1210             emitcode ("mov", "a,_bp");
1211             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1212             emitcode ("mov", "r0,a");
1213           }
1214         else
1215           {
1216             emitcode ("mov", "r0,_bp");
1217           }
1218
1219         while (sz--)
1220           {
1221             emitcode ("pop", "acc");
1222             emitcode ("mov", "@r0,a");
1223             if (!sz)
1224               break;
1225             emitcode ("dec", "r0");
1226           }
1227         emitcode ("mov", "r0,b");
1228       }
1229     }
1230
1231 }
1232
1233 /*-----------------------------------------------------------------*/
1234 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will   */
1235 /*                 clobber the accumulator                         */
1236 /*-----------------------------------------------------------------*/
1237 static bool
1238 aopGetUsesAcc (operand * oper, int offset)
1239 {
1240   asmop * aop = AOP (oper);
1241
1242   if (offset > (aop->size - 1))
1243     return FALSE;
1244
1245   switch (aop->type)
1246     {
1247
1248     case AOP_R0:
1249     case AOP_R1:
1250       if (aop->paged)
1251         return TRUE;
1252       return FALSE;
1253     case AOP_DPTR:
1254       return TRUE;
1255     case AOP_IMMD:
1256       return FALSE;
1257     case AOP_DIR:
1258       return FALSE;
1259     case AOP_REG:
1260       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1261       return FALSE;
1262     case AOP_CRY:
1263       return TRUE;
1264     case AOP_ACC:
1265       if (offset)
1266         return FALSE;
1267       return TRUE;
1268     case AOP_LIT:
1269       return FALSE;
1270     case AOP_STR:
1271       if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1272         return TRUE;
1273       return FALSE;
1274     case AOP_DUMMY:
1275       return FALSE;
1276     default:
1277       /* Error case --- will have been caught already */
1278       wassert(0);
1279       return FALSE;
1280     }
1281 }
1282
1283 /*-------------------------------------------------------------------*/
1284 /* aopGet - for fetching value of the aop                            */
1285 /*-------------------------------------------------------------------*/
1286 static char *
1287 aopGet (operand * oper, int offset, bool bit16, bool dname)
1288 {
1289   asmop * aop = AOP (oper);
1290
1291   /* offset is greater than
1292      size then zero */
1293   if (offset > (aop->size - 1) &&
1294       aop->type != AOP_LIT)
1295     return zero;
1296
1297   /* depending on type */
1298   switch (aop->type)
1299     {
1300     case AOP_DUMMY:
1301       return zero;
1302
1303     case AOP_R0:
1304     case AOP_R1:
1305       /* if we need to increment it */
1306       while (offset > aop->coff)
1307         {
1308           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1309           aop->coff++;
1310         }
1311
1312       while (offset < aop->coff)
1313         {
1314           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1315           aop->coff--;
1316         }
1317
1318       aop->coff = offset;
1319       if (aop->paged)
1320         {
1321           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1322           return (dname ? "acc" : "a");
1323         }
1324       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1325       return Safe_strdup(buffer);
1326
1327     case AOP_DPTR:
1328       if (aop->code && aop->coff==0 && offset>=1) {
1329         emitcode ("mov", "a,#0x%02x", offset);
1330         emitcode ("movc", "a,@a+dptr");
1331         return (dname ? "acc" : "a");
1332       }
1333
1334       while (offset > aop->coff)
1335         {
1336           emitcode ("inc", "dptr");
1337           aop->coff++;
1338         }
1339
1340       while (offset < aop->coff)
1341         {
1342           emitcode ("lcall", "__decdptr");
1343           aop->coff--;
1344         }
1345
1346       aop->coff = offset;
1347       if (aop->code)
1348         {
1349           emitcode ("clr", "a");
1350           emitcode ("movc", "a,@a+dptr");
1351         }
1352       else
1353         {
1354           emitcode ("movx", "a,@dptr");
1355         }
1356       return (dname ? "acc" : "a");
1357
1358     case AOP_IMMD:
1359       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1360         {
1361           SNPRINTF(buffer, sizeof(buffer),
1362                    "%s",aop->aopu.aop_immd.aop_immd2);
1363         }
1364       else if (bit16)
1365         {
1366           SNPRINTF(buffer, sizeof(buffer),
1367                    "#%s", aop->aopu.aop_immd.aop_immd1);
1368         }
1369       else if (offset)
1370         {
1371           SNPRINTF (buffer, sizeof(buffer),
1372                     "#(%s >> %d)",
1373                     aop->aopu.aop_immd.aop_immd1,
1374                     offset * 8);
1375         }
1376       else
1377         {
1378           SNPRINTF (buffer, sizeof(buffer),
1379                     "#%s",
1380                     aop->aopu.aop_immd.aop_immd1);
1381         }
1382       return Safe_strdup(buffer);
1383
1384     case AOP_DIR:
1385       if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1386         {
1387           SNPRINTF (buffer, sizeof(buffer),
1388                     "(%s >> %d)",
1389                     aop->aopu.aop_dir, offset * 8);
1390         }
1391       else if (offset)
1392         {
1393           SNPRINTF (buffer, sizeof(buffer),
1394                     "(%s + %d)",
1395                     aop->aopu.aop_dir,
1396                     offset);
1397         }
1398       else
1399         {
1400           SNPRINTF (buffer, sizeof(buffer),
1401                     "%s",
1402                     aop->aopu.aop_dir);
1403         }
1404
1405       return Safe_strdup(buffer);
1406
1407     case AOP_REG:
1408       if (dname)
1409         return aop->aopu.aop_reg[offset]->dname;
1410       else
1411         return aop->aopu.aop_reg[offset]->name;
1412
1413     case AOP_CRY:
1414       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1415       emitcode ("clr", "a");
1416       emitcode ("rlc", "a");
1417       return (dname ? "acc" : "a");
1418
1419     case AOP_ACC:
1420       if (!offset && dname)
1421         return "acc";
1422       return aop->aopu.aop_str[offset];
1423
1424     case AOP_LIT:
1425       return aopLiteral (aop->aopu.aop_lit, offset);
1426
1427     case AOP_STR:
1428       aop->coff = offset;
1429       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1430           dname)
1431         return "acc";
1432
1433       return aop->aopu.aop_str[offset];
1434
1435     }
1436
1437   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1438           "aopget got unsupported aop->type");
1439   exit (1);
1440 }
1441
1442 /*-----------------------------------------------------------------*/
1443 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will   */
1444 /*                 clobber the accumulator                         */
1445 /*-----------------------------------------------------------------*/
1446 static bool
1447 aopPutUsesAcc (operand * oper, const char *s, int offset)
1448 {
1449   asmop * aop = AOP (oper);
1450
1451   if (offset > (aop->size - 1))
1452     return FALSE;
1453
1454   switch (aop->type)
1455     {
1456     case AOP_DUMMY:
1457       return TRUE;
1458     case AOP_DIR:
1459       return FALSE;
1460     case AOP_REG:
1461       wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1462       return FALSE;
1463     case AOP_DPTR:
1464       return TRUE;
1465     case AOP_R0:
1466     case AOP_R1:
1467       return ((aop->paged) || (*s == '@'));
1468     case AOP_STK:
1469       return (*s == '@');
1470     case AOP_CRY:
1471       return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1472     case AOP_STR:
1473       return FALSE;
1474     case AOP_IMMD:
1475       return FALSE;
1476     case AOP_ACC:
1477       return FALSE;
1478     default:
1479       /* Error case --- will have been caught already */
1480       wassert(0);
1481       return FALSE;
1482     }
1483 }
1484
1485 /*-----------------------------------------------------------------*/
1486 /* aopPut - puts a string for a aop and indicates if acc is in use */
1487 /*-----------------------------------------------------------------*/
1488 static bool
1489 aopPut (operand * result, const char *s, int offset)
1490 {
1491   bool bvolatile = isOperandVolatile (result, FALSE);
1492   bool accuse = FALSE;
1493   asmop * aop = AOP (result);
1494
1495   if (aop->size && offset > (aop->size - 1))
1496     {
1497       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1498               "aopPut got offset > aop->size");
1499       exit (1);
1500     }
1501
1502   /* will assign value to value */
1503   /* depending on where it is ofcourse */
1504   switch (aop->type)
1505     {
1506     case AOP_DUMMY:
1507       MOVA (s);         /* read s in case it was volatile */
1508       accuse = TRUE;
1509       break;
1510
1511     case AOP_DIR:
1512       if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1513         {
1514           SNPRINTF (buffer, sizeof(buffer),
1515                     "(%s >> %d)",
1516                     aop->aopu.aop_dir, offset * 8);
1517         }
1518       else if (offset)
1519         {
1520           SNPRINTF (buffer, sizeof(buffer),
1521                     "(%s + %d)",
1522                     aop->aopu.aop_dir, offset);
1523         }
1524       else
1525         {
1526           SNPRINTF (buffer, sizeof(buffer),
1527                     "%s",
1528                     aop->aopu.aop_dir);
1529         }
1530
1531       if (strcmp (buffer, s) || bvolatile)
1532         {
1533           emitcode ("mov", "%s,%s", buffer, s);
1534         }
1535       if (!strcmp (buffer, "acc"))
1536         {
1537           accuse = TRUE;
1538         }
1539       break;
1540
1541     case AOP_REG:
1542       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1543           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1544         {
1545           if (*s == '@' ||
1546               strcmp (s, "r0") == 0 ||
1547               strcmp (s, "r1") == 0 ||
1548               strcmp (s, "r2") == 0 ||
1549               strcmp (s, "r3") == 0 ||
1550               strcmp (s, "r4") == 0 ||
1551               strcmp (s, "r5") == 0 ||
1552               strcmp (s, "r6") == 0 ||
1553               strcmp (s, "r7") == 0)
1554             {
1555               emitcode ("mov", "%s,%s",
1556                         aop->aopu.aop_reg[offset]->dname, s);
1557             }
1558           else
1559             {
1560               emitcode ("mov", "%s,%s",
1561                         aop->aopu.aop_reg[offset]->name, s);
1562             }
1563         }
1564       break;
1565
1566     case AOP_DPTR:
1567       if (aop->code)
1568         {
1569           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1570                   "aopPut writing to code space");
1571           exit (1);
1572         }
1573
1574       while (offset > aop->coff)
1575         {
1576           aop->coff++;
1577           emitcode ("inc", "dptr");
1578         }
1579
1580       while (offset < aop->coff)
1581         {
1582           aop->coff--;
1583           emitcode ("lcall", "__decdptr");
1584         }
1585
1586       aop->coff = offset;
1587
1588       /* if not in accumulator */
1589       MOVA (s);
1590
1591       emitcode ("movx", "@dptr,a");
1592       break;
1593
1594     case AOP_R0:
1595     case AOP_R1:
1596       while (offset > aop->coff)
1597         {
1598           aop->coff++;
1599           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1600         }
1601       while (offset < aop->coff)
1602         {
1603           aop->coff--;
1604           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1605         }
1606       aop->coff = offset;
1607
1608       if (aop->paged)
1609         {
1610           MOVA (s);
1611           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1612         }
1613       else if (*s == '@')
1614         {
1615           MOVA (s);
1616           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1617         }
1618       else if (strcmp (s, "r0") == 0 ||
1619                strcmp (s, "r1") == 0 ||
1620                strcmp (s, "r2") == 0 ||
1621                strcmp (s, "r3") == 0 ||
1622                strcmp (s, "r4") == 0 ||
1623                strcmp (s, "r5") == 0 ||
1624                strcmp (s, "r6") == 0 ||
1625                strcmp (s, "r7") == 0)
1626         {
1627           char buffer[10];
1628           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1629           emitcode ("mov", "@%s,%s",
1630                     aop->aopu.aop_ptr->name, buffer);
1631         }
1632       else
1633         {
1634           emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1635         }
1636       break;
1637
1638     case AOP_STK:
1639       if (strcmp (s, "a") == 0)
1640         {
1641           emitcode ("push", "acc");
1642         }
1643       else if (*s=='@')
1644         {
1645           MOVA(s);
1646           emitcode ("push", "acc");
1647         }
1648       else if (strcmp (s, "r0") == 0 ||
1649                strcmp (s, "r1") == 0 ||
1650                strcmp (s, "r2") == 0 ||
1651                strcmp (s, "r3") == 0 ||
1652                strcmp (s, "r4") == 0 ||
1653                strcmp (s, "r5") == 0 ||
1654                strcmp (s, "r6") == 0 ||
1655                strcmp (s, "r7") == 0)
1656         {
1657           char buffer[10];
1658           SNPRINTF (buffer, sizeof(buffer), "a%s", s);
1659           emitcode ("push", buffer);
1660         }
1661       else
1662         {
1663           emitcode ("push", s);
1664         }
1665
1666       break;
1667
1668     case AOP_CRY:
1669       /* if result no bit variable */
1670       if (!aop->aopu.aop_dir)
1671         {
1672           assert (!strcmp (s, "c"));
1673           /* inefficient: move carry into A and use jz/jnz */
1674           emitcode ("clr", "a");
1675           emitcode ("rlc", "a");
1676           accuse = TRUE;
1677         }
1678       else if (s == zero)
1679           emitcode ("clr", "%s", aop->aopu.aop_dir);
1680       else if (s == one)
1681           emitcode ("setb", "%s", aop->aopu.aop_dir);
1682       else if (!strcmp (s, "c"))
1683           emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1684       else if (strcmp (s, aop->aopu.aop_dir))
1685         {
1686           MOVA (s);
1687           /* set C, if a >= 1 */
1688           emitcode ("add", "a,#0xff");
1689           emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1690         }
1691       break;
1692
1693     case AOP_STR:
1694       aop->coff = offset;
1695       if (strcmp (aop->aopu.aop_str[offset], s) || bvolatile)
1696         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1697       break;
1698
1699     case AOP_ACC:
1700       accuse = TRUE;
1701       aop->coff = offset;
1702       if (!offset && (strcmp (s, "acc") == 0) && !bvolatile)
1703         break;
1704
1705       if (strcmp (aop->aopu.aop_str[offset], s) && !bvolatile)
1706         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1707       break;
1708
1709     default:
1710       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1711               "aopPut got unsupported aop->type");
1712       exit (1);
1713     }
1714
1715     return accuse;
1716 }
1717
1718
1719 #if 0
1720 /*-----------------------------------------------------------------*/
1721 /* pointToEnd :- points to the last byte of the operand            */
1722 /*-----------------------------------------------------------------*/
1723 static void
1724 pointToEnd (asmop * aop)
1725 {
1726   int count;
1727   if (!aop)
1728     return;
1729
1730   aop->coff = count = (aop->size - 1);
1731   switch (aop->type)
1732     {
1733     case AOP_R0:
1734     case AOP_R1:
1735       while (count--)
1736         emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1737       break;
1738     case AOP_DPTR:
1739       while (count--)
1740         emitcode ("inc", "dptr");
1741       break;
1742     }
1743
1744 }
1745 #endif
1746
1747 /*-----------------------------------------------------------------*/
1748 /* reAdjustPreg - points a register back to where it should        */
1749 /*-----------------------------------------------------------------*/
1750 static void
1751 reAdjustPreg (asmop * aop)
1752 {
1753   if ((aop->coff==0) || (aop->size <= 1))
1754     return;
1755
1756   switch (aop->type)
1757     {
1758     case AOP_R0:
1759     case AOP_R1:
1760       while (aop->coff--)
1761         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1762       break;
1763     case AOP_DPTR:
1764       while (aop->coff--)
1765         {
1766           emitcode ("lcall", "__decdptr");
1767         }
1768       break;
1769     }
1770   aop->coff = 0;
1771 }
1772
1773 /*-----------------------------------------------------------------*/
1774 /* opIsGptr: returns non-zero if the passed operand is       */
1775 /* a generic pointer type.             */
1776 /*-----------------------------------------------------------------*/
1777 static int
1778 opIsGptr (operand * op)
1779 {
1780   sym_link *type = operandType (op);
1781
1782   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1783     {
1784       return 1;
1785     }
1786   return 0;
1787 }
1788
1789 /*-----------------------------------------------------------------*/
1790 /* getDataSize - get the operand data size                         */
1791 /*-----------------------------------------------------------------*/
1792 static int
1793 getDataSize (operand * op)
1794 {
1795   int size;
1796   size = AOP_SIZE (op);
1797   if (size == GPTRSIZE)
1798     {
1799       sym_link *type = operandType (op);
1800       if (IS_GENPTR (type))
1801         {
1802           /* generic pointer; arithmetic operations
1803            * should ignore the high byte (pointer type).
1804            */
1805           size--;
1806         }
1807     }
1808   return size;
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /* outAcc - output Acc                                             */
1813 /*-----------------------------------------------------------------*/
1814 static void
1815 outAcc (operand * result)
1816 {
1817   int size, offset;
1818   size = getDataSize (result);
1819   if (size)
1820     {
1821       aopPut (result, "a", 0);
1822       size--;
1823       offset = 1;
1824       /* unsigned or positive */
1825       while (size--)
1826         {
1827           aopPut (result, zero, offset++);
1828         }
1829     }
1830 }
1831
1832 /*-----------------------------------------------------------------*/
1833 /* outBitC - output a bit C                                        */
1834 /*-----------------------------------------------------------------*/
1835 static void
1836 outBitC (operand * result)
1837 {
1838   /* if the result is bit */
1839   if (AOP_TYPE (result) == AOP_CRY)
1840     {
1841       if (!OP_SYMBOL (result)->ruonly)
1842         aopPut (result, "c", 0);
1843     }
1844   else
1845     {
1846       emitcode ("clr", "a");
1847       emitcode ("rlc", "a");
1848       outAcc (result);
1849     }
1850 }
1851
1852 /*-----------------------------------------------------------------*/
1853 /* toBoolean - emit code for orl a,operator(sizeop)                */
1854 /*-----------------------------------------------------------------*/
1855 static void
1856 toBoolean (operand * oper)
1857 {
1858   int size = AOP_SIZE (oper) - 1;
1859   int offset = 1;
1860   bool AccUsed = FALSE;
1861   bool pushedB;
1862
1863   while (!AccUsed && size--)
1864     {
1865       AccUsed |= aopGetUsesAcc(oper, offset++);
1866     }
1867
1868   size = AOP_SIZE (oper) - 1;
1869   offset = 1;
1870   MOVA (aopGet (oper, 0, FALSE, FALSE));
1871   if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1872     {
1873       pushedB = pushB ();
1874       emitcode("mov", "b,a");
1875       while (--size)
1876         {
1877           MOVA (aopGet (oper, offset++, FALSE, FALSE));
1878           emitcode ("orl", "b,a");
1879         }
1880       MOVA (aopGet (oper, offset++, FALSE, FALSE));
1881       emitcode ("orl", "a,b");
1882       popB (pushedB);
1883     }
1884   else
1885     {
1886       while (size--)
1887         {
1888           emitcode ("orl", "a,%s",
1889                     aopGet (oper, offset++, FALSE, FALSE));
1890         }
1891     }
1892 }
1893
1894 /*-----------------------------------------------------------------*/
1895 /* toCarry - make boolean and move into carry                      */
1896 /*-----------------------------------------------------------------*/
1897 static void
1898 toCarry (operand * oper)
1899 {
1900   /* if the operand is a literal then
1901      we know what the value is */
1902   if (AOP_TYPE (oper) == AOP_LIT)
1903     {
1904       if ((int) operandLitValue (oper))
1905         SETC;
1906       else
1907         CLRC;
1908     }
1909   else if (AOP_TYPE (oper) == AOP_CRY)
1910     {
1911       emitcode ("mov", "c,%s", oper->aop->aopu.aop_dir);
1912     }
1913   else
1914     {
1915       /* or the operand into a */
1916       toBoolean (oper);
1917       /* set C, if a >= 1 */
1918       emitcode ("add", "a,#0xff");
1919     }
1920 }
1921
1922 /*-----------------------------------------------------------------*/
1923 /* assignBit - assign operand to bit operand                       */
1924 /*-----------------------------------------------------------------*/
1925 static void
1926 assignBit (operand * result, operand * right)
1927 {
1928   /* if the right side is a literal then
1929      we know what the value is */
1930   if (AOP_TYPE (right) == AOP_LIT)
1931     {
1932       if ((int) operandLitValue (right))
1933         aopPut (result, one, 0);
1934       else
1935         aopPut (result, zero, 0);
1936     }
1937   else
1938     {
1939       toCarry (right);
1940       aopPut (result, "c", 0);
1941     }
1942 }
1943
1944
1945 /*-------------------------------------------------------------------*/
1946 /* xch_a_aopGet - for exchanging acc with value of the aop           */
1947 /*-------------------------------------------------------------------*/
1948 static char *
1949 xch_a_aopGet (operand * oper, int offset, bool bit16, bool dname)
1950 {
1951   char * l;
1952
1953   if (aopGetUsesAcc (oper, offset))
1954     {
1955       emitcode("mov", "b,a");
1956       MOVA (aopGet (oper, offset, bit16, dname));
1957       emitcode("xch", "a,b");
1958       aopPut (oper, "a", offset);
1959       emitcode("xch", "a,b");
1960       l = "b";
1961     }
1962   else
1963     {
1964       l = aopGet (oper, offset, bit16, dname);
1965       emitcode("xch", "a,%s", l);
1966     }
1967   return l;
1968 }
1969
1970
1971 /*-----------------------------------------------------------------*/
1972 /* genNot - generate code for ! operation                          */
1973 /*-----------------------------------------------------------------*/
1974 static void
1975 genNot (iCode * ic)
1976 {
1977   symbol *tlbl;
1978
1979   D (emitcode (";", "genNot"));
1980
1981   /* assign asmOps to operand & result */
1982   aopOp (IC_LEFT (ic), ic, FALSE);
1983   aopOp (IC_RESULT (ic), ic, TRUE);
1984
1985   /* if in bit space then a special case */
1986   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1987     {
1988       /* if left==result then cpl bit */
1989       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1990         {
1991           emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1992         }
1993       else
1994         {
1995           emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1996           emitcode ("cpl", "c");
1997           outBitC (IC_RESULT (ic));
1998         }
1999       goto release;
2000     }
2001
2002   toBoolean (IC_LEFT (ic));
2003
2004   /* set C, if a == 0 */
2005   tlbl = newiTempLabel (NULL);
2006   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
2007   emitLabel (tlbl);
2008   outBitC (IC_RESULT (ic));
2009
2010 release:
2011   /* release the aops */
2012   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2013   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2014 }
2015
2016
2017 /*-----------------------------------------------------------------*/
2018 /* genCpl - generate code for complement                           */
2019 /*-----------------------------------------------------------------*/
2020 static void
2021 genCpl (iCode * ic)
2022 {
2023   int offset = 0;
2024   int size;
2025   symbol *tlbl;
2026   sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
2027
2028   D(emitcode (";", "genCpl"));
2029
2030   /* assign asmOps to operand & result */
2031   aopOp (IC_LEFT (ic), ic, FALSE);
2032   aopOp (IC_RESULT (ic), ic, TRUE);
2033
2034   /* special case if in bit space */
2035   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2036     {
2037       char *l;
2038
2039       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
2040           (SPEC_USIGN (letype) && IS_CHAR (letype)))
2041         {
2042           /* promotion rules are responsible for this strange result:
2043              bit -> int -> ~int -> bit
2044              uchar -> int -> ~int -> bit
2045           */
2046           emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
2047           goto release;
2048         }
2049
2050       tlbl=newiTempLabel(NULL);
2051       l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
2052       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
2053           AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
2054           IS_AOP_PREG (IC_LEFT (ic)))
2055         {
2056           emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
2057         }
2058       else
2059         {
2060           MOVA (l);
2061           emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
2062         }
2063       emitLabel (tlbl);
2064       outBitC (IC_RESULT(ic));
2065       goto release;
2066     }
2067
2068   size = AOP_SIZE (IC_RESULT (ic));
2069   while (size--)
2070     {
2071       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2072       MOVA (l);
2073       emitcode ("cpl", "a");
2074       aopPut (IC_RESULT (ic), "a", offset++);
2075     }
2076
2077
2078 release:
2079   /* release the aops */
2080   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2081   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2082 }
2083
2084 /*-----------------------------------------------------------------*/
2085 /* genUminusFloat - unary minus for floating points                */
2086 /*-----------------------------------------------------------------*/
2087 static void
2088 genUminusFloat (operand * op, operand * result)
2089 {
2090   int size, offset = 0;
2091   char *l;
2092
2093   D (emitcode (";", "genUminusFloat"));
2094
2095   /* for this we just copy and then flip the bit */
2096
2097   size = AOP_SIZE (op) - 1;
2098
2099   while (size--)
2100     {
2101       aopPut (result,
2102               aopGet (op, offset, FALSE, FALSE),
2103               offset);
2104       offset++;
2105     }
2106
2107   l = aopGet (op, offset, FALSE, FALSE);
2108   MOVA (l);
2109
2110   emitcode ("cpl", "acc.7");
2111   aopPut (result, "a", offset);
2112 }
2113
2114 /*-----------------------------------------------------------------*/
2115 /* genUminus - unary minus code generation                         */
2116 /*-----------------------------------------------------------------*/
2117 static void
2118 genUminus (iCode * ic)
2119 {
2120   int offset, size;
2121   sym_link *optype;
2122
2123   D (emitcode (";", "genUminus"));
2124
2125   /* assign asmops */
2126   aopOp (IC_LEFT (ic), ic, FALSE);
2127   aopOp (IC_RESULT (ic), ic, TRUE);
2128
2129   /* if both in bit space then special
2130      case */
2131   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
2132       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
2133     {
2134
2135       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
2136       emitcode ("cpl", "c");
2137       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
2138       goto release;
2139     }
2140
2141   optype = operandType (IC_LEFT (ic));
2142
2143   /* if float then do float stuff */
2144   if (IS_FLOAT (optype))
2145     {
2146       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2147       goto release;
2148     }
2149
2150   /* otherwise subtract from zero */
2151   size = AOP_SIZE (IC_LEFT (ic));
2152   offset = 0;
2153   while (size--)
2154     {
2155       char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
2156       if (!strcmp (l, "a"))
2157         {
2158           if (offset == 0)
2159             SETC;
2160           emitcode ("cpl", "a");
2161           emitcode ("addc", "a,#0");
2162         }
2163       else
2164         {
2165           if (offset == 0)
2166             CLRC;
2167           emitcode ("clr", "a");
2168           emitcode ("subb", "a,%s", l);
2169         }
2170       aopPut (IC_RESULT (ic), "a", offset++);
2171     }
2172
2173   /* if any remaining bytes in the result */
2174   /* we just need to propagate the sign   */
2175   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2176     {
2177       emitcode ("rlc", "a");
2178       emitcode ("subb", "a,acc");
2179       while (size--)
2180         aopPut (IC_RESULT (ic), "a", offset++);
2181     }
2182
2183 release:
2184   /* release the aops */
2185   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2186   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2187 }
2188
2189 /*-----------------------------------------------------------------*/
2190 /* saveRegisters - will look for a call and save the registers     */
2191 /*-----------------------------------------------------------------*/
2192 static void
2193 saveRegisters (iCode * lic)
2194 {
2195   int i;
2196   iCode *ic;
2197   bitVect *rsave;
2198
2199   /* look for call */
2200   for (ic = lic; ic; ic = ic->next)
2201     if (ic->op == CALL || ic->op == PCALL)
2202       break;
2203
2204   if (!ic)
2205     {
2206       fprintf (stderr, "found parameter push with no function call\n");
2207       return;
2208     }
2209
2210   /* if the registers have been saved already or don't need to be then
2211      do nothing */
2212   if (ic->regsSaved)
2213     return;
2214   if (IS_SYMOP(IC_LEFT(ic)) &&
2215       (IFFUNC_CALLEESAVES (OP_SYMBOL (IC_LEFT (ic))->type) ||
2216        IFFUNC_ISNAKED (OP_SYM_TYPE (IC_LEFT (ic)))))
2217     return;
2218
2219   /* save the registers in use at this time but skip the
2220      ones for the result */
2221   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2222                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2223
2224   ic->regsSaved = 1;
2225   if (options.useXstack)
2226     {
2227       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2228       int nBits = bitVectnBitsOn (rsavebits);
2229       int count = bitVectnBitsOn (rsave);
2230
2231       if (nBits != 0)
2232         {
2233           count = count - nBits + 1;
2234           /* remove all but the first bits as they are pushed all at once */
2235           rsave = bitVectCplAnd (rsave, rsavebits);
2236           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2237         }
2238       freeBitVect (rsavebits);
2239
2240       if (count == 1)
2241         {
2242           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2243           if (reg->type == REG_BIT)
2244             {
2245               emitcode ("mov", "a,%s", reg->base);
2246             }
2247           else
2248             {
2249               emitcode ("mov", "a,%s", reg->name);
2250             }
2251           emitcode ("mov", "r0,%s", spname);
2252           emitcode ("inc", "%s", spname);// allocate before use
2253           emitcode ("movx", "@r0,a");
2254           if (bitVectBitValue (rsave, R0_IDX))
2255             emitcode ("mov", "r0,a");
2256         }
2257       else if (count != 0)
2258         {
2259           if (bitVectBitValue (rsave, R0_IDX))
2260             {
2261               emitcode ("push", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2262             }
2263           emitcode ("mov", "r0,%s", spname);
2264           MOVA ("r0");
2265           emitcode ("add", "a,#%d", count);
2266           emitcode ("mov", "%s,a", spname);
2267           for (i = 0; i < mcs51_nRegs; i++)
2268             {
2269               if (bitVectBitValue (rsave, i))
2270                 {
2271                   regs * reg = REG_WITH_INDEX (i);
2272                   if (i == R0_IDX)
2273                     {
2274                       emitcode ("pop", "acc");
2275                       emitcode ("push", "acc");
2276                     }
2277                   else if (reg->type == REG_BIT)
2278                     {
2279                       emitcode ("mov", "a,%s", reg->base);
2280                     }
2281                   else
2282                     {
2283                       emitcode ("mov", "a,%s", reg->name);
2284                     }
2285                   emitcode ("movx", "@r0,a");
2286                   if (--count)
2287                     {
2288                       emitcode ("inc", "r0");
2289                     }
2290                 }
2291             }
2292           if (bitVectBitValue (rsave, R0_IDX))
2293             {
2294               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
2295             }
2296         }
2297     }
2298   else
2299     {
2300       bool bits_pushed = FALSE;
2301       for (i = 0; i < mcs51_nRegs; i++)
2302         {
2303           if (bitVectBitValue (rsave, i))
2304             {
2305               bits_pushed = pushReg (i, bits_pushed);
2306             }
2307         }
2308     }
2309   freeBitVect (rsave);
2310 }
2311
2312 /*-----------------------------------------------------------------*/
2313 /* unsaveRegisters - pop the pushed registers                      */
2314 /*-----------------------------------------------------------------*/
2315 static void
2316 unsaveRegisters (iCode * ic)
2317 {
2318   int i;
2319   bitVect *rsave;
2320
2321   /* restore the registers in use at this time but skip the
2322      ones for the result */
2323   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2324                          mcs51_rUmaskForOp (IC_RESULT(ic)));
2325
2326   if (options.useXstack)
2327     {
2328       bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2329       int nBits = bitVectnBitsOn (rsavebits);
2330       int count = bitVectnBitsOn (rsave);
2331
2332       if (nBits != 0)
2333         {
2334           count = count - nBits + 1;
2335           /* remove all but the first bits as they are popped all at once */
2336           rsave = bitVectCplAnd (rsave, rsavebits);
2337           rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2338         }
2339       freeBitVect (rsavebits);
2340
2341       if (count == 1)
2342         {
2343           regs * reg = REG_WITH_INDEX (bitVectFirstBit (rsave));
2344           emitcode ("mov", "r0,%s", spname);
2345           emitcode ("dec", "r0");
2346           emitcode ("movx", "a,@r0");
2347           if (reg->type == REG_BIT)
2348             {
2349               emitcode ("mov", "%s,a", reg->base);
2350             }
2351           else
2352             {
2353               emitcode ("mov", "%s,a", reg->name);
2354             }
2355           emitcode ("dec", "%s", spname);
2356         }
2357       else if (count != 0)
2358         {
2359           emitcode ("mov", "r0,%s", spname);
2360           for (i = mcs51_nRegs; i >= 0; i--)
2361             {
2362               if (bitVectBitValue (rsave, i))
2363                 {
2364                   regs * reg = REG_WITH_INDEX (i);
2365                   emitcode ("dec", "r0");
2366                   emitcode ("movx", "a,@r0");
2367                   if (i == R0_IDX)
2368                     {
2369                       emitcode ("push", "acc");
2370                     }
2371                   else if (reg->type == REG_BIT)
2372                     {
2373                       emitcode ("mov", "%s,a", reg->base);
2374                     }
2375                   else
2376                     {
2377                       emitcode ("mov", "%s,a", reg->name);
2378                     }
2379                 }
2380             }
2381           emitcode ("mov", "%s,r0", spname);
2382           if (bitVectBitValue (rsave, R0_IDX))
2383             {
2384               emitcode ("pop", "ar0");
2385             }
2386         }
2387     }
2388   else
2389     {
2390       bool bits_popped = FALSE;
2391       for (i = mcs51_nRegs; i >= 0; i--)
2392         {
2393           if (bitVectBitValue (rsave, i))
2394             {
2395               bits_popped = popReg (i, bits_popped);
2396             }
2397         }
2398     }
2399   freeBitVect (rsave);
2400 }
2401
2402
2403 /*-----------------------------------------------------------------*/
2404 /* pushSide -                                                      */
2405 /*-----------------------------------------------------------------*/
2406 static void
2407 pushSide (operand * oper, int size)
2408 {
2409   int offset = 0;
2410   while (size--)
2411     {
2412       char *l = aopGet (oper, offset++, FALSE, TRUE);
2413       if (AOP_TYPE (oper) != AOP_REG &&
2414           AOP_TYPE (oper) != AOP_DIR &&
2415           strcmp (l, "a"))
2416         {
2417           MOVA (l);
2418           emitcode ("push", "acc");
2419         }
2420       else
2421         {
2422           emitcode ("push", "%s", l);
2423         }
2424     }
2425 }
2426
2427 /*-----------------------------------------------------------------*/
2428 /* assignResultValue - also indicates if acc is in use afterwards  */
2429 /*-----------------------------------------------------------------*/
2430 static bool
2431 assignResultValue (operand * oper, operand * func)
2432 {
2433   int offset = 0;
2434   int size = AOP_SIZE (oper);
2435   bool accuse = FALSE;
2436   bool pushedA = FALSE;
2437
2438   if (func && IS_BIT (OP_SYM_ETYPE (func)))
2439     {
2440       outBitC (oper);
2441       return FALSE;
2442     }
2443
2444   if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2445     {
2446       emitcode ("push", "acc");
2447       pushedA = TRUE;
2448     }
2449   while (size--)
2450     {
2451       if ((offset == 3) && pushedA)
2452         emitcode ("pop", "acc");
2453       accuse |= aopPut (oper, fReturn[offset], offset);
2454       offset++;
2455     }
2456   return accuse;
2457 }
2458
2459
2460 /*-----------------------------------------------------------------*/
2461 /* genXpush - pushes onto the external stack                       */
2462 /*-----------------------------------------------------------------*/
2463 static void
2464 genXpush (iCode * ic)
2465 {
2466   asmop *aop = newAsmop (0);
2467   regs *r;
2468   int size, offset = 0;
2469
2470   D (emitcode (";", "genXpush"));
2471
2472   aopOp (IC_LEFT (ic), ic, FALSE);
2473   r = getFreePtr (ic, &aop, FALSE);
2474
2475   size = AOP_SIZE (IC_LEFT (ic));
2476
2477   if (size == 1)
2478     {
2479       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2480       emitcode ("mov", "%s,%s", r->name, spname);
2481       emitcode ("inc", "%s", spname); // allocate space first
2482       emitcode ("movx", "@%s,a", r->name);
2483     }
2484   else
2485     {
2486       // allocate space first
2487       emitcode ("mov", "%s,%s", r->name, spname);
2488       MOVA (r->name);
2489       emitcode ("add", "a,#%d", size);
2490       emitcode ("mov", "%s,a", spname);
2491
2492       while (size--)
2493         {
2494           MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2495           emitcode ("movx", "@%s,a", r->name);
2496           emitcode ("inc", "%s", r->name);
2497         }
2498     }
2499
2500   freeAsmop (NULL, aop, ic, TRUE);
2501   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2502 }
2503
2504 /*-----------------------------------------------------------------*/
2505 /* genIpush - generate code for pushing this gets a little complex */
2506 /*-----------------------------------------------------------------*/
2507 static void
2508 genIpush (iCode * ic)
2509 {
2510   int size, offset = 0;
2511   char *l;
2512   char *prev = "";
2513
2514   D (emitcode (";", "genIpush"));
2515
2516   /* if this is not a parm push : ie. it is spill push
2517      and spill push is always done on the local stack */
2518   if (!ic->parmPush)
2519     {
2520
2521       /* and the item is spilt then do nothing */
2522       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2523         return;
2524
2525       aopOp (IC_LEFT (ic), ic, FALSE);
2526       size = AOP_SIZE (IC_LEFT (ic));
2527       /* push it on the stack */
2528       while (size--)
2529         {
2530           l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2531           if (*l == '#')
2532             {
2533               MOVA (l);
2534               l = "acc";
2535             }
2536           emitcode ("push", "%s", l);
2537         }
2538       return;
2539     }
2540
2541   /* this is a parameter push: in this case we call
2542      the routine to find the call and save those
2543      registers that need to be saved */
2544   saveRegisters (ic);
2545
2546   /* if use external stack then call the external
2547      stack pushing routine */
2548   if (options.useXstack)
2549     {
2550       genXpush (ic);
2551       return;
2552     }
2553
2554   /* then do the push */
2555   aopOp (IC_LEFT (ic), ic, FALSE);
2556
2557   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2558   size = AOP_SIZE (IC_LEFT (ic));
2559
2560   while (size--)
2561     {
2562       l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2563       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2564           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR)
2565         {
2566           if (strcmp (l, prev) || *l == '@')
2567             MOVA (l);
2568           emitcode ("push", "acc");
2569         }
2570       else
2571         {
2572           emitcode ("push", "%s", l);
2573         }
2574       prev = l;
2575     }
2576
2577   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2578 }
2579
2580 /*-----------------------------------------------------------------*/
2581 /* genIpop - recover the registers: can happen only for spilling   */
2582 /*-----------------------------------------------------------------*/
2583 static void
2584 genIpop (iCode * ic)
2585 {
2586   int size, offset;
2587
2588   D (emitcode (";", "genIpop"));
2589
2590   /* if the temp was not pushed then */
2591   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2592     return;
2593
2594   aopOp (IC_LEFT (ic), ic, FALSE);
2595   size = AOP_SIZE (IC_LEFT (ic));
2596   offset = (size - 1);
2597   while (size--)
2598     {
2599       emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2600                                      FALSE, TRUE));
2601     }
2602
2603   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2604 }
2605
2606 /*-----------------------------------------------------------------*/
2607 /* saveRBank - saves an entire register bank on the stack          */
2608 /*-----------------------------------------------------------------*/
2609 static void
2610 saveRBank (int bank, iCode * ic, bool pushPsw)
2611 {
2612   int i;
2613   int count = 8 + (pushPsw ? 1 : 0);
2614   asmop *aop = NULL;
2615   regs *r = NULL;
2616
2617   if (options.useXstack)
2618     {
2619       if (!ic)
2620         {
2621           /* Assume r0 is available for use. */
2622           r = REG_WITH_INDEX (R0_IDX);
2623         }
2624       else
2625         {
2626           aop = newAsmop (0);
2627           r = getFreePtr (ic, &aop, FALSE);
2628         }
2629       // allocate space first
2630       emitcode ("mov", "%s,%s", r->name, spname);
2631       MOVA (r->name);
2632       emitcode ("add", "a,#%d", count);
2633       emitcode ("mov", "%s,a", spname);
2634     }
2635
2636   for (i = 0; i < 8; i++)
2637     {
2638       if (options.useXstack)
2639         {
2640           emitcode ("mov", "a,(%s+%d)",
2641                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2642           emitcode ("movx", "@%s,a", r->name);
2643           if (--count)
2644             emitcode ("inc", "%s", r->name);
2645         }
2646       else
2647         emitcode ("push", "(%s+%d)",
2648                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2649     }
2650
2651   if (pushPsw)
2652     {
2653       if (options.useXstack)
2654         {
2655           emitcode ("mov", "a,psw");
2656           emitcode ("movx", "@%s,a", r->name);
2657         }
2658       else
2659         {
2660           emitcode ("push", "psw");
2661         }
2662
2663       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2664     }
2665
2666   if (aop)
2667     {
2668       freeAsmop (NULL, aop, ic, TRUE);
2669     }
2670
2671   if (ic)
2672   {
2673     ic->bankSaved = 1;
2674   }
2675 }
2676
2677 /*-----------------------------------------------------------------*/
2678 /* unsaveRBank - restores the register bank from stack             */
2679 /*-----------------------------------------------------------------*/
2680 static void
2681 unsaveRBank (int bank, iCode * ic, bool popPsw)
2682 {
2683   int i;
2684   asmop *aop = NULL;
2685   regs *r = NULL;
2686
2687   if (options.useXstack)
2688     {
2689       if (!ic)
2690         {
2691           /* Assume r0 is available for use. */
2692           r = REG_WITH_INDEX (R0_IDX);;
2693         }
2694       else
2695         {
2696           aop = newAsmop (0);
2697           r = getFreePtr (ic, &aop, FALSE);
2698         }
2699       emitcode ("mov", "%s,%s", r->name, spname);
2700     }
2701
2702   if (popPsw)
2703     {
2704       if (options.useXstack)
2705         {
2706           emitcode ("dec", "%s", r->name);
2707           emitcode ("movx", "a,@%s", r->name);
2708           emitcode ("mov", "psw,a");
2709         }
2710       else
2711         {
2712           emitcode ("pop", "psw");
2713         }
2714     }
2715
2716   for (i = 7; i >= 0; i--)
2717     {
2718       if (options.useXstack)
2719         {
2720           emitcode ("dec", "%s", r->name);
2721           emitcode ("movx", "a,@%s", r->name);
2722           emitcode ("mov", "(%s+%d),a",
2723                     regs8051[i].base, 8 * bank + regs8051[i].offset);
2724         }
2725       else
2726         {
2727           emitcode ("pop", "(%s+%d)",
2728                   regs8051[i].base, 8 * bank + regs8051[i].offset);
2729         }
2730     }
2731
2732   if (options.useXstack)
2733     {
2734       emitcode ("mov", "%s,%s", spname, r->name);
2735     }
2736
2737   if (aop)
2738     {
2739       freeAsmop (NULL, aop, ic, TRUE);
2740     }
2741 }
2742
2743 /*-----------------------------------------------------------------*/
2744 /* genSend - gen code for SEND                                     */
2745 /*-----------------------------------------------------------------*/
2746 static void genSend(set *sendSet)
2747 {
2748   iCode *sic;
2749   int bit_count = 0;
2750
2751   /* first we do all bit parameters */
2752   for (sic = setFirstItem (sendSet); sic;
2753        sic = setNextItem (sendSet))
2754     {
2755       if (sic->argreg > 12)
2756         {
2757           int bit = sic->argreg-13;
2758
2759           aopOp (IC_LEFT (sic), sic, FALSE);
2760
2761           /* if left is a literal then
2762              we know what the value is */
2763           if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2764             {
2765               if (((int) operandLitValue (IC_LEFT (sic))))
2766                   emitcode ("setb", "b[%d]", bit);
2767               else
2768                   emitcode ("clr", "b[%d]", bit);
2769             }
2770           else
2771             {
2772               /* we need to or */
2773               toCarry (IC_LEFT (sic));
2774               emitcode ("mov", "b[%d],c", bit);
2775             }
2776           bit_count++;
2777           BitBankUsed = 1;
2778
2779           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2780         }
2781     }
2782
2783   if (bit_count)
2784     {
2785       saveRegisters (setFirstItem (sendSet));
2786       emitcode ("mov", "bits,b");
2787     }
2788
2789   /* then we do all other parameters */
2790   for (sic = setFirstItem (sendSet); sic;
2791        sic = setNextItem (sendSet))
2792     {
2793       if (sic->argreg <= 12)
2794         {
2795           int size, offset = 0;
2796           aopOp (IC_LEFT (sic), sic, FALSE);
2797           size = AOP_SIZE (IC_LEFT (sic));
2798
2799           if (sic->argreg == 1)
2800             {
2801               while (size--)
2802                 {
2803                   char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2804                   if (strcmp (l, fReturn[offset]))
2805                     {
2806                       emitcode ("mov", "%s,%s", fReturn[offset], l);
2807                     }
2808                   offset++;
2809                 }
2810             }
2811           else
2812             {
2813               while (size--)
2814                 {
2815                   emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2816                             aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2817                   offset++;
2818                 }
2819             }
2820           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2821         }
2822     }
2823 }
2824
2825 /*-----------------------------------------------------------------*/
2826 /* selectRegBank - emit code to select the register bank           */
2827 /*-----------------------------------------------------------------*/
2828 static void
2829 selectRegBank (short bank, bool keepFlags)
2830 {
2831   /* if f.e. result is in carry */
2832   if (keepFlags)
2833     {
2834       emitcode ("anl", "psw,#0xE7");
2835       if (bank)
2836         emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2837     }
2838   else
2839     {
2840       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2841     }
2842 }
2843
2844 /*-----------------------------------------------------------------*/
2845 /* genCall - generates a call statement                            */
2846 /*-----------------------------------------------------------------*/
2847 static void
2848 genCall (iCode * ic)
2849 {
2850   sym_link *dtype;
2851   sym_link *etype;
2852 //  bool restoreBank = FALSE;
2853   bool swapBanks = FALSE;
2854   bool accuse = FALSE;
2855   bool accPushed = FALSE;
2856   bool resultInF0 = FALSE;
2857   bool assignResultGenerated = FALSE;
2858
2859   D (emitcode (";", "genCall"));
2860
2861   dtype = operandType (IC_LEFT (ic));
2862   etype = getSpec(dtype);
2863   /* if send set is not empty then assign */
2864   if (_G.sendSet)
2865     {
2866         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2867             genSend(reverseSet(_G.sendSet));
2868         } else {
2869             genSend(_G.sendSet);
2870         }
2871       _G.sendSet = NULL;
2872     }
2873
2874   /* if we are calling a not _naked function that is not using
2875      the same register bank then we need to save the
2876      destination registers on the stack */
2877   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2878       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2879        !IFFUNC_ISISR (dtype))
2880     {
2881       swapBanks = TRUE;
2882     }
2883
2884   /* if caller saves & we have not saved then */
2885   if (!ic->regsSaved)
2886       saveRegisters (ic);
2887
2888   if (swapBanks)
2889     {
2890         emitcode ("mov", "psw,#0x%02x",
2891            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2892     }
2893
2894   /* make the call */
2895   if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2896     {
2897       if (IFFUNC_CALLEESAVES(dtype))
2898         {
2899           werror (E_BANKED_WITH_CALLEESAVES);
2900         }
2901       else
2902         {
2903           char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2904                      OP_SYMBOL (IC_LEFT (ic))->rname :
2905                      OP_SYMBOL (IC_LEFT (ic))->name);
2906
2907           emitcode ("mov", "r0,#%s", l);
2908           emitcode ("mov", "r1,#(%s >> 8)", l);
2909           emitcode ("mov", "r2,#(%s >> 16)", l);
2910           emitcode ("lcall", "__sdcc_banked_call");
2911         }
2912     }
2913   else
2914     {
2915       emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2916                                 OP_SYMBOL (IC_LEFT (ic))->rname :
2917                                 OP_SYMBOL (IC_LEFT (ic))->name));
2918     }
2919
2920   if (swapBanks)
2921     {
2922       selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2923     }
2924
2925   /* if we need assign a result value */
2926   if ((IS_ITEMP (IC_RESULT (ic)) &&
2927        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2928        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2929         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2930         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2931       IS_TRUE_SYMOP (IC_RESULT (ic)))
2932     {
2933
2934       _G.accInUse++;
2935       aopOp (IC_RESULT (ic), ic, FALSE);
2936       _G.accInUse--;
2937
2938       accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2939       assignResultGenerated = TRUE;
2940
2941       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2942     }
2943
2944   /* adjust the stack for parameters if required */
2945   if (ic->parmBytes)
2946     {
2947       int i;
2948       if (ic->parmBytes > 3)
2949         {
2950           if (accuse)
2951             {
2952               emitcode ("push", "acc");
2953               accPushed = TRUE;
2954             }
2955           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2956               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2957               !assignResultGenerated)
2958             {
2959               emitcode ("mov", "F0,c");
2960               resultInF0 = TRUE;
2961             }
2962
2963           emitcode ("mov", "a,%s", spname);
2964           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2965           emitcode ("mov", "%s,a", spname);
2966
2967           /* unsaveRegisters from xstack needs acc, but */
2968           /* unsaveRegisters from stack needs this popped */
2969           if (accPushed && !options.useXstack)
2970             {
2971               emitcode ("pop", "acc");
2972               accPushed = FALSE;
2973             }
2974         }
2975       else
2976         for (i = 0; i < ic->parmBytes; i++)
2977           emitcode ("dec", "%s", spname);
2978     }
2979
2980   /* if we had saved some registers then unsave them */
2981   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2982     {
2983       if (accuse && !accPushed && options.useXstack)
2984         {
2985           /* xstack needs acc, but doesn't touch normal stack */
2986           emitcode ("push", "acc");
2987           accPushed = TRUE;
2988         }
2989       unsaveRegisters (ic);
2990     }
2991
2992 //  /* if register bank was saved then pop them */
2993 //  if (restoreBank)
2994 //    unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2995
2996   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2997     {
2998       if (resultInF0)
2999           emitcode ("mov", "c,F0");
3000
3001       aopOp (IC_RESULT (ic), ic, FALSE);
3002       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3003       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3004     }
3005
3006   if (accPushed)
3007     emitcode ("pop", "acc");
3008 }
3009
3010 /*-----------------------------------------------------------------*/
3011 /* genPcall - generates a call by pointer statement                */
3012 /*-----------------------------------------------------------------*/
3013 static void
3014 genPcall (iCode * ic)
3015 {
3016   sym_link *dtype;
3017   sym_link *etype;
3018   symbol *rlbl = newiTempLabel (NULL);
3019 //  bool restoreBank=FALSE;
3020   bool swapBanks = FALSE;
3021   bool resultInF0 = FALSE;
3022
3023   D (emitcode (";", "genPcall"));
3024
3025   dtype = operandType (IC_LEFT (ic))->next;
3026   etype = getSpec(dtype);
3027   /* if caller saves & we have not saved then */
3028   if (!ic->regsSaved)
3029     saveRegisters (ic);
3030
3031   /* if we are calling a not _naked function that is not using
3032      the same register bank then we need to save the
3033      destination registers on the stack */
3034   if (currFunc && dtype && !IFFUNC_ISNAKED (dtype) &&
3035       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
3036       !IFFUNC_ISISR (dtype))
3037     {
3038 //    saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3039 //    restoreBank=TRUE;
3040       swapBanks = TRUE;
3041       // need caution message to user here
3042     }
3043
3044   if (IS_LITERAL (etype))
3045     {
3046       /* if send set is not empty then assign */
3047       if (_G.sendSet)
3048         {
3049           genSend(reverseSet(_G.sendSet));
3050           _G.sendSet = NULL;
3051         }
3052
3053       if (swapBanks)
3054         {
3055           emitcode ("mov", "psw,#0x%02x",
3056            ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3057         }
3058
3059       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3060         {
3061           if (IFFUNC_CALLEESAVES (dtype))
3062             {
3063               werror (E_BANKED_WITH_CALLEESAVES);
3064             }
3065           else
3066             {
3067               char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
3068
3069               emitcode ("mov", "r0,#%s", l);
3070               emitcode ("mov", "r1,#(%s >> 8)", l);
3071               emitcode ("mov", "r2,#(%s >> 16)", l);
3072               emitcode ("lcall", "__sdcc_banked_call");
3073             }
3074         }
3075       else
3076         {
3077           emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
3078         }
3079     }
3080   else
3081     {
3082       if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT (getSpec(dtype)))
3083         {
3084           if (IFFUNC_CALLEESAVES (dtype))
3085             {
3086               werror (E_BANKED_WITH_CALLEESAVES);
3087             }
3088           else
3089             {
3090               aopOp (IC_LEFT (ic), ic, FALSE);
3091
3092               if (!swapBanks)
3093                 {
3094                   /* what if aopGet needs r0 or r1 ??? */
3095                   emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3096                   emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3097                   emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3098                 }
3099               else
3100                 {
3101                   int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
3102                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
3103                   emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
3104                   emitcode ("mov", "0x%02x,%s", reg,   aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
3105                 }
3106
3107               freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3108
3109               /* if send set is not empty then assign */
3110               if (_G.sendSet)
3111                 {
3112                   genSend(reverseSet(_G.sendSet));
3113                   _G.sendSet = NULL;
3114                 }
3115
3116               if (swapBanks)
3117                 {
3118                   emitcode ("mov", "psw,#0x%02x",
3119                    ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3120                 }
3121
3122               /* make the call */
3123               emitcode ("lcall", "__sdcc_banked_call");
3124             }
3125         }
3126       else if (_G.sendSet)
3127         {
3128           /* push the return address on to the stack */
3129           emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3130           emitcode ("push", "acc");
3131           emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3132           emitcode ("push", "acc");
3133
3134           /* now push the calling address */
3135           aopOp (IC_LEFT (ic), ic, FALSE);
3136
3137           pushSide (IC_LEFT (ic), FPTRSIZE);
3138
3139           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3140
3141           /* if send set is not empty the assign */
3142           if (_G.sendSet)
3143             {
3144               genSend(reverseSet(_G.sendSet));
3145               _G.sendSet = NULL;
3146             }
3147
3148           if (swapBanks)
3149             {
3150               emitcode ("mov", "psw,#0x%02x",
3151                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3152             }
3153
3154           /* make the call */
3155           emitcode ("ret", "");
3156           emitLabel (rlbl);
3157         }
3158       else /* the send set is empty */
3159         {
3160           char *l;
3161           /* now get the calling address into dptr */
3162           aopOp (IC_LEFT (ic), ic, FALSE);
3163
3164           l = aopGet (IC_LEFT (ic), 0, FALSE, FALSE);
3165           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3166             {
3167               emitcode ("mov", "r0,%s", l);
3168               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3169               emitcode ("mov", "dph,%s", l);
3170               emitcode ("mov", "dpl,r0");
3171             }
3172           else
3173             {
3174               emitcode ("mov", "dpl,%s", l);
3175               l = aopGet (IC_LEFT (ic), 1, FALSE, FALSE);
3176               emitcode ("mov", "dph,%s", l);
3177             }
3178
3179           freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3180
3181           if (swapBanks)
3182             {
3183               emitcode ("mov", "psw,#0x%02x",
3184                ((FUNC_REGBANK (dtype)) << 3) & 0xff);
3185             }
3186
3187           /* make the call */
3188           emitcode ("lcall", "__sdcc_call_dptr");
3189         }
3190     }
3191   if (swapBanks)
3192     {
3193       selectRegBank (FUNC_REGBANK (currFunc->type), IS_BIT (etype));
3194     }
3195
3196   /* if we need assign a result value */
3197   if ((IS_ITEMP (IC_RESULT (ic)) &&
3198        !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3199        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3200         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3201       IS_TRUE_SYMOP (IC_RESULT (ic)))
3202     {
3203
3204       _G.accInUse++;
3205       aopOp (IC_RESULT (ic), ic, FALSE);
3206       _G.accInUse--;
3207
3208       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3209
3210       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3211     }
3212
3213   /* adjust the stack for parameters if required */
3214   if (ic->parmBytes)
3215     {
3216       int i;
3217       if (ic->parmBytes > 3)
3218         {
3219           if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3220               IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3221             {
3222               emitcode ("mov", "F0,c");
3223               resultInF0 = TRUE;
3224             }
3225
3226           emitcode ("mov", "a,%s", spname);
3227           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3228           emitcode ("mov", "%s,a", spname);
3229         }
3230       else
3231         for (i = 0; i < ic->parmBytes; i++)
3232           emitcode ("dec", "%s", spname);
3233     }
3234
3235 //  /* if register bank was saved then unsave them */
3236 //  if (restoreBank)
3237 //    unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3238
3239   /* if we had saved some registers then unsave them */
3240   if (ic->regsSaved && !IFFUNC_CALLEESAVES (dtype))
3241     unsaveRegisters (ic);
3242
3243   if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3244     {
3245       if (resultInF0)
3246           emitcode ("mov", "c,F0");
3247
3248       aopOp (IC_RESULT (ic), ic, FALSE);
3249       assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3250       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3251     }
3252 }
3253
3254 /*-----------------------------------------------------------------*/
3255 /* resultRemat - result  is rematerializable                       */
3256 /*-----------------------------------------------------------------*/
3257 static int
3258 resultRemat (iCode * ic)
3259 {
3260   if (SKIP_IC (ic) || ic->op == IFX)
3261     return 0;
3262
3263   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3264     {
3265       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3266       if (sym->remat && !POINTER_SET (ic))
3267         return 1;
3268     }
3269
3270   return 0;
3271 }
3272
3273 /*-----------------------------------------------------------------*/
3274 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3275 /*-----------------------------------------------------------------*/
3276 static int
3277 regsCmp(void *p1, void *p2)
3278 {
3279   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3280 }
3281
3282 static bool
3283 inExcludeList (char *s)
3284 {
3285   const char *p = setFirstItem(options.excludeRegsSet);
3286
3287   if (p == NULL || STRCASECMP(p, "none") == 0)
3288     return FALSE;
3289
3290
3291   return isinSetWith(options.excludeRegsSet, s, regsCmp);
3292 }
3293
3294 /*-----------------------------------------------------------------*/
3295 /* genFunction - generated code for function entry                 */
3296 /*-----------------------------------------------------------------*/
3297 static void
3298 genFunction (iCode * ic)
3299 {
3300   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3301   sym_link *ftype;
3302   bool     switchedPSW = FALSE;
3303   int      calleesaves_saved_register = -1;
3304   int      stackAdjust = sym->stack;
3305   int      accIsFree = sym->recvSize < 4;
3306   iCode    *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3307   bool     fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3308
3309   _G.nRegsSaved = 0;
3310   /* create the function header */
3311   emitcode (";", "-----------------------------------------");
3312   emitcode (";", " function %s", sym->name);
3313   emitcode (";", "-----------------------------------------");
3314
3315   emitcode ("", "%s:", sym->rname);
3316   lineCurr->isLabel = 1;
3317   ftype = operandType (IC_LEFT (ic));
3318   _G.currentFunc = sym;
3319
3320   if (IFFUNC_ISNAKED(ftype))
3321   {
3322       emitcode(";", "naked function: no prologue.");
3323       return;
3324   }
3325
3326   /* here we need to generate the equates for the
3327      register bank if required */
3328   if (FUNC_REGBANK (ftype) != rbank)
3329     {
3330       int i;
3331
3332       rbank = FUNC_REGBANK (ftype);
3333       for (i = 0; i < mcs51_nRegs; i++)
3334         {
3335           if (regs8051[i].type != REG_BIT)
3336             {
3337               if (strcmp (regs8051[i].base, "0") == 0)
3338                 emitcode ("", "%s = 0x%02x",
3339                           regs8051[i].dname,
3340                           8 * rbank + regs8051[i].offset);
3341               else
3342                 emitcode ("", "%s = %s + 0x%02x",
3343                           regs8051[i].dname,
3344                           regs8051[i].base,
3345                           8 * rbank + regs8051[i].offset);
3346             }
3347         }
3348     }
3349
3350   /* if this is an interrupt service routine then
3351      save acc, b, dpl, dph  */
3352   if (IFFUNC_ISISR (sym->type))
3353     {
3354       bitVect *rsavebits;
3355
3356       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3357       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3358         {
3359           emitcode ("push", "bits");
3360           BitBankUsed = 1;
3361         }
3362       freeBitVect (rsavebits);
3363
3364       if (!inExcludeList ("acc"))
3365         emitcode ("push", "acc");
3366       if (!inExcludeList ("b"))
3367         emitcode ("push", "b");
3368       if (!inExcludeList ("dpl"))
3369         emitcode ("push", "dpl");
3370       if (!inExcludeList ("dph"))
3371         emitcode ("push", "dph");
3372       /* if this isr has no bank i.e. is going to
3373          run with bank 0 , then we need to save more
3374          registers :-) */
3375       if (!FUNC_REGBANK (sym->type))
3376         {
3377           int i;
3378
3379           /* if this function does not call any other
3380              function then we can be economical and
3381              save only those registers that are used */
3382           if (!IFFUNC_HASFCALL(sym->type))
3383             {
3384               /* if any registers used */
3385               if (sym->regsUsed)
3386                 {
3387                   /* save the registers used */
3388                   for (i = 0; i < sym->regsUsed->size; i++)
3389                     {
3390                       if (bitVectBitValue (sym->regsUsed, i))
3391                         pushReg (i, TRUE);
3392                     }
3393                 }
3394             }
3395           else
3396             {
3397               /* this function has a function call. We cannot
3398                  determine register usage so we will have to push the
3399                  entire bank */
3400                 saveRBank (0, ic, FALSE);
3401                 if (options.parms_in_bank1) {
3402                     for (i=0; i < 8 ; i++ ) {
3403                         emitcode ("push","%s",rb1regs[i]);
3404                     }
3405                 }
3406             }
3407         }
3408         else
3409         {
3410             /* This ISR uses a non-zero bank.
3411              *
3412              * We assume that the bank is available for our
3413              * exclusive use.
3414              *
3415              * However, if this ISR calls a function which uses some
3416              * other bank, we must save that bank entirely.
3417              */
3418             unsigned long banksToSave = 0;
3419
3420             if (IFFUNC_HASFCALL(sym->type))
3421             {
3422
3423 #define MAX_REGISTER_BANKS 4
3424
3425                 iCode *i;
3426                 int ix;
3427
3428                 for (i = ic; i; i = i->next)
3429                 {
3430                     if (i->op == ENDFUNCTION)
3431                     {
3432                         /* we got to the end OK. */
3433                         break;
3434                     }
3435
3436                     if (i->op == CALL)
3437                     {
3438                         sym_link *dtype;
3439
3440                         dtype = operandType (IC_LEFT(i));
3441                         if (dtype
3442                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3443                         {
3444                              /* Mark this bank for saving. */
3445                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3446                              {
3447                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3448                              }
3449                              else
3450                              {
3451                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3452                              }
3453
3454                              /* And note that we don't need to do it in
3455                               * genCall.
3456                               */
3457                              i->bankSaved = 1;
3458                         }
3459                     }
3460                     if (i->op == PCALL)
3461                     {
3462                         /* This is a mess; we have no idea what
3463                          * register bank the called function might
3464                          * use.
3465                          *
3466                          * The only thing I can think of to do is
3467                          * throw a warning and hope.
3468                          */
3469                         werror(W_FUNCPTR_IN_USING_ISR);
3470                     }
3471                 }
3472
3473                 if (banksToSave && options.useXstack)
3474                 {
3475                     /* Since we aren't passing it an ic,
3476                      * saveRBank will assume r0 is available to abuse.
3477                      *
3478                      * So switch to our (trashable) bank now, so
3479                      * the caller's R0 isn't trashed.
3480                      */
3481                     emitcode ("push", "psw");
3482                     emitcode ("mov", "psw,#0x%02x",
3483                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3484                     switchedPSW = TRUE;
3485                 }
3486
3487                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3488                 {
3489                      if (banksToSave & (1 << ix))
3490                      {
3491                          saveRBank(ix, NULL, FALSE);
3492                      }
3493                 }
3494             }
3495             // TODO: this needs a closer look
3496             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3497         }
3498
3499       /* Set the register bank to the desired value if nothing else */
3500       /* has done so yet. */
3501       if (!switchedPSW)
3502         {
3503           emitcode ("push", "psw");
3504           emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3505         }
3506     }
3507   else
3508     {
3509       /* This is a non-ISR function. The caller has already switched register */
3510       /* banks, if necessary, so just handle the callee-saves option. */
3511
3512       /* if callee-save to be used for this function
3513          then save the registers being used in this function */
3514       if (IFFUNC_CALLEESAVES(sym->type))
3515         {
3516           int i;
3517
3518           /* if any registers used */
3519           if (sym->regsUsed)
3520             {
3521               bool bits_pushed = FALSE;
3522               /* save the registers used */
3523               for (i = 0; i < sym->regsUsed->size; i++)
3524                 {
3525                   if (bitVectBitValue (sym->regsUsed, i))
3526                     {
3527                       /* remember one saved register for later usage */
3528                       if (calleesaves_saved_register < 0)
3529                         calleesaves_saved_register = i;
3530                       bits_pushed = pushReg (i, bits_pushed);
3531                       _G.nRegsSaved++;
3532                     }
3533                 }
3534             }
3535         }
3536     }
3537
3538   if (fReentrant)
3539     {
3540       if (options.useXstack)
3541         {
3542           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3543             {
3544               emitcode ("mov", "r0,%s", spname);
3545               emitcode ("inc", "%s", spname);
3546               emitcode ("xch", "a,_bpx");
3547               emitcode ("movx", "@r0,a");
3548               emitcode ("inc", "r0");
3549               emitcode ("mov", "a,r0");
3550               emitcode ("xch", "a,_bpx");
3551             }
3552           if (sym->stack)
3553             {
3554               emitcode ("push", "_bp");     /* save the callers stack  */
3555               emitcode ("mov", "_bp,sp");
3556             }
3557         }
3558       else
3559         {
3560           if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3561             {
3562               /* set up the stack */
3563               emitcode ("push", "_bp");     /* save the callers stack  */
3564               emitcode ("mov", "_bp,sp");
3565             }
3566         }
3567     }
3568
3569   /* For some cases it is worthwhile to perform a RECEIVE iCode */
3570   /* before setting up the stack frame completely. */
3571   if (ric && ric->argreg == 1 && IC_RESULT (ric))
3572     {
3573       symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3574
3575       if (rsym->isitmp)
3576         {
3577           if (rsym && rsym->regType == REG_CND)
3578             rsym = NULL;
3579           if (rsym && (rsym->accuse || rsym->ruonly))
3580             rsym = NULL;
3581           if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3582             rsym = rsym->usl.spillLoc;
3583         }
3584
3585       /* If the RECEIVE operand immediately spills to the first entry on the */
3586       /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3587       /* rather than the usual @r0/r1 machinations. */
3588       if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3589         {
3590           int ofs;
3591
3592           _G.current_iCode = ric;
3593           D(emitcode (";     genReceive",""));
3594           for (ofs=0; ofs < sym->recvSize; ofs++)
3595             {
3596               if (!strcmp (fReturn[ofs], "a"))
3597                 emitcode ("push", "acc");
3598               else
3599                 emitcode ("push", fReturn[ofs]);
3600             }
3601           stackAdjust -= sym->recvSize;
3602           if (stackAdjust<0)
3603             {
3604               assert (stackAdjust>=0);
3605               stackAdjust = 0;
3606             }
3607           _G.current_iCode = ic;
3608           ric->generated = 1;
3609           accIsFree = 1;
3610         }
3611       /* If the RECEIVE operand is 4 registers, we can do the moves now */
3612       /* to free up the accumulator. */
3613       else if (rsym && rsym->nRegs && sym->recvSize == 4)
3614         {
3615           int ofs;
3616
3617           _G.current_iCode = ric;
3618           D(emitcode (";     genReceive",""));
3619           for (ofs=0; ofs < sym->recvSize; ofs++)
3620             {
3621               emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3622             }
3623           _G.current_iCode = ic;
3624           ric->generated = 1;
3625           accIsFree = 1;
3626         }
3627     }
3628
3629   /* adjust the stack for the function */
3630   if (stackAdjust)
3631     {
3632       int i = stackAdjust;
3633       if (i > 256)
3634         werror (W_STACK_OVERFLOW, sym->name);
3635
3636       if (i > 3 && accIsFree)
3637         {
3638           emitcode ("mov", "a,sp");
3639           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3640           emitcode ("mov", "sp,a");
3641         }
3642       else if (i > 5)
3643         {
3644           /* The accumulator is not free, so we will need another register */
3645           /* to clobber. No need to worry about a possible conflict with */
3646           /* the above early RECEIVE optimizations since they would have */
3647           /* freed the accumulator if they were generated. */
3648
3649           if (IFFUNC_CALLEESAVES(sym->type))
3650             {
3651               /* if it's a callee-saves function we need a saved register */
3652               if (calleesaves_saved_register >= 0)
3653                 {
3654                   emitcode ("mov", "%s,a", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3655                   emitcode ("mov", "a,sp");
3656                   emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3657                   emitcode ("mov", "sp,a");
3658                   emitcode ("mov", "a,%s", REG_WITH_INDEX (calleesaves_saved_register)->dname);
3659                 }
3660               else
3661                 /* do it the hard way */
3662                 while (i--)
3663                   emitcode ("inc", "sp");
3664             }
3665           else
3666             {
3667               /* not callee-saves, we can clobber r0 */
3668               emitcode ("mov", "r0,a");
3669               emitcode ("mov", "a,sp");
3670               emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3671               emitcode ("mov", "sp,a");
3672               emitcode ("mov", "a,r0");
3673             }
3674         }
3675       else
3676         while (i--)
3677           emitcode ("inc", "sp");
3678     }
3679
3680   if (sym->xstack)
3681     {
3682       char i = ((char) sym->xstack & 0xff);
3683
3684       if (i > 3 && accIsFree)
3685         {
3686           emitcode ("mov", "a,_spx");
3687           emitcode ("add", "a,#0x%02x", i & 0xff);
3688           emitcode ("mov", "_spx,a");
3689         }
3690       else if (i > 5)
3691         {
3692           emitcode ("push", "acc");
3693           emitcode ("mov", "a,_spx");
3694           emitcode ("add", "a,#0x%02x", i & 0xff);
3695           emitcode ("mov", "_spx,a");
3696           emitcode ("pop", "acc");
3697         }
3698       else
3699         {
3700           while (i--)
3701             emitcode ("inc", "_spx");
3702         }
3703     }
3704
3705   /* if critical function then turn interrupts off */
3706   if (IFFUNC_ISCRITICAL (ftype))
3707     {
3708       symbol *tlbl = newiTempLabel (NULL);
3709       emitcode ("setb", "c");
3710       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3711       emitcode ("clr", "c");
3712       emitLabel (tlbl);
3713       emitcode ("push", "psw"); /* save old ea via c in psw */
3714     }
3715 }
3716
3717 /*-----------------------------------------------------------------*/
3718 /* genEndFunction - generates epilogue for functions               */
3719 /*-----------------------------------------------------------------*/
3720 static void
3721 genEndFunction (iCode * ic)
3722 {
3723   symbol   *sym = OP_SYMBOL (IC_LEFT (ic));
3724   lineNode *lnp = lineCurr;
3725   bitVect  *regsUsed;
3726   bitVect  *regsUsedPrologue;
3727   bitVect  *regsUnneeded;
3728   int      idx;
3729
3730   _G.currentFunc = NULL;
3731   if (IFFUNC_ISNAKED(sym->type))
3732   {
3733       emitcode(";", "naked function: no epilogue.");
3734       if (options.debug && currFunc)
3735         debugFile->writeEndFunction (currFunc, ic, 0);
3736       return;
3737   }
3738
3739   if (IFFUNC_ISCRITICAL (sym->type))
3740     {
3741       if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3742         {
3743           emitcode ("rlc", "a");   /* save c in a */
3744           emitcode ("pop", "psw"); /* restore ea via c in psw */
3745           emitcode ("mov", "ea,c");
3746           emitcode ("rrc", "a");   /* restore c from a */
3747         }
3748       else
3749         {
3750           emitcode ("pop", "psw"); /* restore ea via c in psw */
3751           emitcode ("mov", "ea,c");
3752         }
3753     }
3754
3755   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3756     {
3757       if (options.useXstack)
3758         {
3759           if (sym->stack)
3760             {
3761               emitcode ("mov", "sp,_bp");
3762               emitcode ("pop", "_bp");
3763             }
3764           if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3765             {
3766               emitcode ("xch", "a,_bpx");
3767               emitcode ("mov", "r0,a");
3768               emitcode ("dec", "r0");
3769               emitcode ("movx", "a,@r0");
3770               emitcode ("xch", "a,_bpx");
3771               emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3772             }
3773         }
3774       else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3775         {
3776           if (sym->stack)
3777             emitcode ("mov", "sp,_bp");
3778           emitcode ("pop", "_bp");
3779         }
3780     }
3781
3782   /* restore the register bank  */
3783   if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3784   {
3785     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3786      || !options.useXstack)
3787     {
3788         /* Special case of ISR using non-zero bank with useXstack
3789          * is handled below.
3790          */
3791         emitcode ("pop", "psw");
3792     }
3793   }
3794
3795   if (IFFUNC_ISISR (sym->type))
3796     {
3797       bitVect *rsavebits;
3798
3799       /* now we need to restore the registers */
3800       /* if this isr has no bank i.e. is going to
3801          run with bank 0 , then we need to save more
3802          registers :-) */
3803       if (!FUNC_REGBANK (sym->type))
3804         {
3805           int i;
3806           /* if this function does not call any other
3807              function then we can be economical and
3808              save only those registers that are used */
3809           if (!IFFUNC_HASFCALL(sym->type))
3810             {
3811               /* if any registers used */
3812               if (sym->regsUsed)
3813                 {
3814                   /* save the registers used */
3815                   for (i = sym->regsUsed->size; i >= 0; i--)
3816                     {
3817                       if (bitVectBitValue (sym->regsUsed, i))
3818                         popReg (i, TRUE);
3819                     }
3820                 }
3821             }
3822           else
3823             {
3824               if (options.parms_in_bank1) {
3825                   for (i = 7 ; i >= 0 ; i-- ) {
3826                       emitcode ("pop","%s",rb1regs[i]);
3827                   }
3828               }
3829               /* this function has a function call. We cannot
3830                  determine register usage so we will have to pop the
3831                  entire bank */
3832               unsaveRBank (0, ic, FALSE);
3833             }
3834         }
3835         else
3836         {
3837             /* This ISR uses a non-zero bank.
3838              *
3839              * Restore any register banks saved by genFunction
3840              * in reverse order.
3841              */
3842             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3843             int ix;
3844
3845             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3846             {
3847                 if (savedBanks & (1 << ix))
3848                 {
3849                     unsaveRBank(ix, NULL, FALSE);
3850                 }
3851             }
3852
3853             if (options.useXstack)
3854             {
3855                 /* Restore bank AFTER calling unsaveRBank,
3856                  * since it can trash r0.
3857                  */
3858                 emitcode ("pop", "psw");
3859             }
3860         }
3861
3862       if (!inExcludeList ("dph"))
3863         emitcode ("pop", "dph");
3864       if (!inExcludeList ("dpl"))
3865         emitcode ("pop", "dpl");
3866       if (!inExcludeList ("b"))
3867         emitcode ("pop", "b");
3868       if (!inExcludeList ("acc"))
3869         emitcode ("pop", "acc");
3870
3871       rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), sym->regsUsed);
3872       if (IFFUNC_HASFCALL(sym->type) || !bitVectIsZero (rsavebits))
3873         emitcode ("pop", "bits");
3874       freeBitVect (rsavebits);
3875
3876       /* if debug then send end of function */
3877       if (options.debug && currFunc)
3878         {
3879           debugFile->writeEndFunction (currFunc, ic, 1);
3880         }
3881
3882       emitcode ("reti", "");
3883     }
3884   else
3885     {
3886       if (IFFUNC_CALLEESAVES(sym->type))
3887         {
3888           int i;
3889
3890           /* if any registers used */
3891           if (sym->regsUsed)
3892             {
3893               /* save the registers used */
3894               for (i = sym->regsUsed->size; i >= 0; i--)
3895                 {
3896                   if (bitVectBitValue (sym->regsUsed, i) ||
3897                       (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3898                     emitcode ("pop", "%s", REG_WITH_INDEX (i)->dname);
3899                 }
3900             }
3901           else if (mcs51_ptrRegReq)
3902             {
3903               emitcode ("pop", "%s", REG_WITH_INDEX (R1_IDX)->dname);
3904               emitcode ("pop", "%s", REG_WITH_INDEX (R0_IDX)->dname);
3905             }
3906
3907         }
3908
3909       /* if debug then send end of function */
3910       if (options.debug && currFunc)
3911         {
3912           debugFile->writeEndFunction (currFunc, ic, 1);
3913         }
3914
3915       if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3916         {
3917           emitcode ("ljmp", "__sdcc_banked_ret");
3918         }
3919       else
3920         {
3921           emitcode ("ret", "");
3922         }
3923     }
3924
3925   if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3926     return;
3927
3928   /* If this was an interrupt handler using bank 0 that called another */
3929   /* function, then all registers must be saved; nothing to optimized. */
3930   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3931       && !FUNC_REGBANK(sym->type))
3932     return;
3933
3934   /* There are no push/pops to optimize if not callee-saves or ISR */
3935   if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3936     return;
3937
3938   /* If there were stack parameters, we cannot optimize without also    */
3939   /* fixing all of the stack offsets; this is too dificult to consider. */
3940   if (FUNC_HASSTACKPARM(sym->type))
3941     return;
3942
3943   /* Compute the registers actually used */
3944   regsUsed = newBitVect (mcs51_nRegs);
3945   regsUsedPrologue = newBitVect (mcs51_nRegs);
3946   while (lnp)
3947     {
3948       if (lnp->ic && lnp->ic->op == FUNCTION)
3949         regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3950       else
3951         regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3952
3953       if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3954           && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3955         break;
3956       if (!lnp->prev)
3957         break;
3958       lnp = lnp->prev;
3959     }
3960
3961   if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3962       && !bitVectBitValue (regsUsed, CND_IDX))
3963     {
3964       regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3965       if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3966           && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3967         bitVectUnSetBit (regsUsed, CND_IDX);
3968     }
3969   else
3970     regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3971
3972   /* If this was an interrupt handler that called another function */
3973   /* function, then assume A, B, DPH, & DPL may be modified by it. */
3974   if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3975     {
3976       regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3977       regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3978       regsUsed = bitVectSetBit (regsUsed, B_IDX);
3979       regsUsed = bitVectSetBit (regsUsed, A_IDX);
3980       regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3981     }
3982
3983   /* Remove the unneeded push/pops */
3984   regsUnneeded = newBitVect (mcs51_nRegs);
3985   while (lnp)
3986     {
3987       if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3988         {
3989           if (!strncmp(lnp->line, "push", 4))
3990             {
3991               idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3992               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3993                 {
3994                   connectLine (lnp->prev, lnp->next);
3995                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3996                 }
3997             }
3998           if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3999             {
4000               idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
4001               if (idx>=0 && !bitVectBitValue (regsUsed, idx))
4002                 {
4003                   connectLine (lnp->prev, lnp->next);
4004                   regsUnneeded = bitVectSetBit (regsUnneeded, idx);
4005                 }
4006             }
4007         }
4008       lnp = lnp->next;
4009     }
4010
4011   for (idx = 0; idx < regsUnneeded->size; idx++)
4012     if (bitVectBitValue (regsUnneeded, idx))
4013       emitcode (";", "eliminated unneeded push/pop %s", REG_WITH_INDEX (idx)->dname);
4014
4015   freeBitVect (regsUnneeded);
4016   freeBitVect (regsUsed);
4017   freeBitVect (regsUsedPrologue);
4018 }
4019
4020 /*-----------------------------------------------------------------*/
4021 /* genRet - generate code for return statement                     */
4022 /*-----------------------------------------------------------------*/
4023 static void
4024 genRet (iCode * ic)
4025 {
4026   int size, offset = 0, pushed = 0;
4027
4028   D (emitcode (";", "genRet"));
4029
4030   /* if we have no return value then
4031      just generate the "ret" */
4032   if (!IC_LEFT (ic))
4033     goto jumpret;
4034
4035   /* we have something to return then
4036      move the return value into place */
4037   aopOp (IC_LEFT (ic), ic, FALSE);
4038   size = AOP_SIZE (IC_LEFT (ic));
4039
4040   if (IS_BIT(_G.currentFunc->etype))
4041     {
4042       if (!OP_SYMBOL (IC_LEFT (ic))->ruonly)
4043         toCarry (IC_LEFT (ic));
4044     }
4045   else
4046     {
4047       while (size--)
4048         {
4049           char *l;
4050           if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
4051             {
4052               /* #NOCHANGE */
4053               l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
4054               emitcode ("push", "%s", l);
4055               pushed++;
4056             }
4057           else
4058             {
4059               l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
4060               if (strcmp (fReturn[offset], l))
4061                 emitcode ("mov", "%s,%s", fReturn[offset++], l);
4062             }
4063         }
4064
4065       while (pushed)
4066         {
4067           pushed--;
4068           if (strcmp (fReturn[pushed], "a"))
4069             emitcode ("pop", fReturn[pushed]);
4070           else
4071             emitcode ("pop", "acc");
4072         }
4073     }
4074   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
4075
4076 jumpret:
4077   /* generate a jump to the return label
4078      if the next is not the return statement */
4079   if (!(ic->next && ic->next->op == LABEL &&
4080         IC_LABEL (ic->next) == returnLabel))
4081
4082     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
4083
4084 }
4085
4086 /*-----------------------------------------------------------------*/
4087 /* genLabel - generates a label                                    */
4088 /*-----------------------------------------------------------------*/
4089 static void
4090 genLabel (iCode * ic)
4091 {
4092   /* special case never generate */
4093   if (IC_LABEL (ic) == entryLabel)
4094     return;
4095
4096   emitLabel (IC_LABEL (ic));
4097 }
4098
4099 /*-----------------------------------------------------------------*/
4100 /* genGoto - generates a ljmp                                      */
4101 /*-----------------------------------------------------------------*/
4102 static void
4103 genGoto (iCode * ic)
4104 {
4105   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
4106 }
4107
4108 /*-----------------------------------------------------------------*/
4109 /* findLabelBackwards: walks back through the iCode chain looking  */
4110 /* for the given label. Returns number of iCode instructions     */
4111 /* between that label and given ic.          */
4112 /* Returns zero if label not found.          */
4113 /*-----------------------------------------------------------------*/
4114 static int
4115 findLabelBackwards (iCode * ic, int key)
4116 {
4117   int count = 0;
4118
4119   while (ic->prev)
4120     {
4121       ic = ic->prev;
4122       count++;
4123
4124       /* If we have any pushes or pops, we cannot predict the distance.
4125          I don't like this at all, this should be dealt with in the
4126          back-end */
4127       if (ic->op == IPUSH || ic->op == IPOP) {
4128         return 0;
4129       }
4130
4131       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
4132         {
4133           return count;
4134         }
4135     }
4136
4137   return 0;
4138 }
4139
4140 /*-----------------------------------------------------------------*/
4141 /* genPlusIncr :- does addition with increment if possible         */
4142 /*-----------------------------------------------------------------*/
4143 static bool
4144 genPlusIncr (iCode * ic)
4145 {
4146   unsigned int icount;
4147   unsigned int size = getDataSize (IC_RESULT (ic));
4148
4149   /* will try to generate an increment */
4150   /* if the right side is not a literal
4151      we cannot */
4152   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4153     return FALSE;
4154
4155   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4156
4157   D(emitcode (";","genPlusIncr"));
4158
4159   /* if increment >=16 bits in register or direct space */
4160   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4161         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4162         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4163       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4164       !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4165       (size > 1) &&
4166       (icount == 1))
4167     {
4168       symbol *tlbl;
4169       int emitTlbl;
4170       int labelRange;
4171
4172       /* If the next instruction is a goto and the goto target
4173        * is < 10 instructions previous to this, we can generate
4174        * jumps straight to that target.
4175        */
4176       if (ic->next && ic->next->op == GOTO
4177           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4178           && labelRange <= 10)
4179         {
4180           D (emitcode (";", "tail increment optimized (range %d)", labelRange));
4181           tlbl = IC_LABEL (ic->next);
4182           emitTlbl = 0;
4183         }
4184       else
4185         {
4186           tlbl = newiTempLabel (NULL);
4187           emitTlbl = 1;
4188         }
4189       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4190       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4191           IS_AOP_PREG (IC_RESULT (ic)))
4192         emitcode ("cjne", "%s,#0x00,%05d$",
4193                   aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4194                   tlbl->key + 100);
4195       else
4196         {
4197           emitcode ("clr", "a");
4198           emitcode ("cjne", "a,%s,%05d$",
4199                     aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4200                     tlbl->key + 100);
4201         }
4202
4203       emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4204       if (size > 2)
4205         {
4206           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4207               IS_AOP_PREG (IC_RESULT (ic)))
4208             emitcode ("cjne", "%s,#0x00,%05d$",
4209                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4210                       tlbl->key + 100);
4211           else
4212             emitcode ("cjne", "a,%s,%05d$",
4213                       aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4214                       tlbl->key + 100);
4215
4216           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4217         }
4218       if (size > 3)
4219         {
4220           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4221               IS_AOP_PREG (IC_RESULT (ic)))
4222             emitcode ("cjne", "%s,#0x00,%05d$",
4223                       aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4224                       tlbl->key + 100);
4225           else
4226             {
4227               emitcode ("cjne", "a,%s,%05d$",
4228                         aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4229                         tlbl->key + 100);
4230             }
4231           emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4232         }
4233
4234       if (emitTlbl)
4235         {
4236           emitLabel (tlbl);
4237         }
4238       return TRUE;
4239     }
4240
4241   /* if result is dptr */
4242   if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4243       (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4244       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4245       !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4246     {
4247       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4248         return FALSE;
4249
4250       if (icount > 9)
4251         return FALSE;
4252
4253       if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4254         return FALSE;
4255
4256       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0);
4257       aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1);
4258       while (icount--)
4259         emitcode ("inc", "dptr");
4260
4261       return TRUE;
4262     }
4263
4264   /* if the literal value of the right hand side
4265      is greater than 4 then it is not worth it */
4266   if (icount > 4)
4267     return FALSE;
4268
4269   /* if the sizes are greater than 1 then we cannot */
4270   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4271       AOP_SIZE (IC_LEFT (ic)) > 1)
4272     return FALSE;
4273
4274   /* we can if the aops of the left & result match or
4275      if they are in registers and the registers are the
4276      same */
4277   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4278     {
4279       if (icount > 3)
4280         {
4281           MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4282           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4283           aopPut (IC_RESULT (ic), "a", 0);
4284         }
4285       else
4286         {
4287           while (icount--)
4288             {
4289               emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4290             }
4291         }
4292
4293       return TRUE;
4294     }
4295
4296   if (icount == 1)
4297     {
4298       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4299       emitcode ("inc", "a");
4300       aopPut (IC_RESULT (ic), "a", 0);
4301       return TRUE;
4302     }
4303
4304   return FALSE;
4305 }
4306
4307 /*-----------------------------------------------------------------*/
4308 /* outBitAcc - output a bit in acc                                 */
4309 /*-----------------------------------------------------------------*/
4310 static void
4311 outBitAcc (operand * result)
4312 {
4313   symbol *tlbl = newiTempLabel (NULL);
4314   /* if the result is a bit */
4315   if (AOP_TYPE (result) == AOP_CRY)
4316     {
4317       aopPut (result, "a", 0);
4318     }
4319   else
4320     {
4321       emitcode ("jz", "%05d$", tlbl->key + 100);
4322       emitcode ("mov", "a,%s", one);
4323       emitLabel (tlbl);
4324       outAcc (result);
4325     }
4326 }
4327
4328 /*-----------------------------------------------------------------*/
4329 /* genPlusBits - generates code for addition of two bits           */
4330 /*-----------------------------------------------------------------*/
4331 static void
4332 genPlusBits (iCode * ic)
4333 {
4334   D (emitcode (";", "genPlusBits"));
4335
4336   emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4337   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4338     {
4339       symbol *lbl = newiTempLabel (NULL);
4340       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4341       emitcode ("cpl", "c");
4342       emitLabel (lbl);
4343       outBitC (IC_RESULT (ic));
4344     }
4345   else
4346     {
4347       emitcode ("clr", "a");
4348       emitcode ("rlc", "a");
4349       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4350       emitcode ("addc", "a,%s", zero);
4351       outAcc (IC_RESULT (ic));
4352     }
4353 }
4354
4355 #if 0
4356 /* This is the original version of this code.
4357
4358  * This is being kept around for reference,
4359  * because I am not entirely sure I got it right...
4360  */
4361 static void
4362 adjustArithmeticResult (iCode * ic)
4363 {
4364   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4365       AOP_SIZE (IC_LEFT (ic)) == 3 &&
4366       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4367     aopPut (IC_RESULT (ic),
4368             aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4369             2);
4370
4371   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4372       AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4373       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4374     aopPut (IC_RESULT (ic),
4375             aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4376             2);
4377
4378   if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4379       AOP_SIZE (IC_LEFT (ic)) < 3 &&
4380       AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4381       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4382       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4383     {
4384       char buffer[5];
4385       sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4386       aopPut (IC_RESULT (ic), buffer, 2);
4387     }
4388 }
4389 #else
4390 /* This is the pure and virtuous version of this code.
4391  * I'm pretty certain it's right, but not enough to toss the old
4392  * code just yet...
4393  */
4394 static void
4395 adjustArithmeticResult (iCode * ic)
4396 {
4397   if (opIsGptr (IC_RESULT (ic)) &&
4398       opIsGptr (IC_LEFT (ic)) &&
4399       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4400     {
4401       aopPut (IC_RESULT (ic),
4402               aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4403               GPTRSIZE - 1);
4404     }
4405
4406   if (opIsGptr (IC_RESULT (ic)) &&
4407       opIsGptr (IC_RIGHT (ic)) &&
4408       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4409     {
4410       aopPut (IC_RESULT (ic),
4411               aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4412               GPTRSIZE - 1);
4413     }
4414
4415   if (opIsGptr (IC_RESULT (ic)) &&
4416       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4417       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4418       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4419       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4420     {
4421       char buffer[5];
4422       SNPRINTF (buffer, sizeof(buffer),
4423                 "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4424       aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1);
4425     }
4426 }
4427 #endif
4428
4429 /*-----------------------------------------------------------------*/
4430 /* genPlus - generates code for addition                           */
4431 /*-----------------------------------------------------------------*/
4432 static void
4433 genPlus (iCode * ic)
4434 {
4435   int size, offset = 0;
4436   int skip_bytes = 0;
4437   char *add = "add";
4438   bool swappedLR = FALSE;
4439   operand *leftOp, *rightOp;
4440   operand * op;
4441
4442   D (emitcode (";", "genPlus"));
4443
4444   /* special cases :- */
4445
4446   aopOp (IC_LEFT (ic), ic, FALSE);
4447   aopOp (IC_RIGHT (ic), ic, FALSE);
4448   aopOp (IC_RESULT (ic), ic, TRUE);
4449
4450   /* if literal, literal on the right or
4451      if left requires ACC or right is already
4452      in ACC */
4453   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4454       (AOP_NEEDSACC (IC_LEFT (ic))) ||
4455       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4456     {
4457       operand *t = IC_RIGHT (ic);
4458       IC_RIGHT (ic) = IC_LEFT (ic);
4459       IC_LEFT (ic) = t;
4460       swappedLR = TRUE;
4461     }
4462
4463   /* if both left & right are in bit
4464      space */
4465   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4466       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4467     {
4468       genPlusBits (ic);
4469       goto release;
4470     }
4471
4472   /* if left in bit space & right literal */
4473   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4474       AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4475     {
4476       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4477       /* if result in bit space */
4478       if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4479         {
4480           if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4481             emitcode ("cpl", "c");
4482           outBitC (IC_RESULT (ic));
4483         }
4484       else
4485         {
4486           size = getDataSize (IC_RESULT (ic));
4487           while (size--)
4488             {
4489               MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4490               emitcode ("addc", "a,%s", zero);
4491               aopPut (IC_RESULT (ic), "a", offset++);
4492             }
4493         }
4494       goto release;
4495     }
4496
4497   /* if I can do an increment instead
4498      of add then GOOD for ME */
4499   if (genPlusIncr (ic) == TRUE)
4500     goto release;
4501
4502   size = getDataSize (IC_RESULT (ic));
4503   leftOp = IC_LEFT(ic);
4504   rightOp = IC_RIGHT(ic);
4505   op = IC_LEFT(ic);
4506
4507   /* if this is an add for an array access
4508      at a 256 byte boundary */
4509   if ( 2 == size
4510        && AOP_TYPE (op) == AOP_IMMD
4511        && IS_SYMOP (op)
4512        && IS_SPEC (OP_SYM_ETYPE (op))
4513        && SPEC_ABSA (OP_SYM_ETYPE (op))
4514        && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4515      )
4516     {
4517       D(emitcode (";     genPlus aligned array",""));
4518       aopPut (IC_RESULT (ic),
4519               aopGet (rightOp, 0, FALSE, FALSE),
4520               0);
4521
4522       if( 1 == getDataSize (IC_RIGHT (ic)) )
4523         {
4524           aopPut (IC_RESULT (ic),
4525                   aopGet (leftOp, 1, FALSE, FALSE),
4526                   1);
4527         }
4528       else
4529         {
4530           MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4531           emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4532           aopPut (IC_RESULT (ic), "a", 1);
4533         }
4534       goto release;
4535     }
4536
4537   /* if the lower bytes of a literal are zero skip the addition */
4538   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4539     {
4540        while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4541               (skip_bytes+1 < size))
4542          {
4543            skip_bytes++;
4544          }
4545        if (skip_bytes)
4546          D(emitcode (";     genPlus shortcut",""));
4547     }
4548
4549   while (size--)
4550     {
4551       if( offset >= skip_bytes )
4552         {
4553           if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4554             {
4555               bool pushedB;
4556               MOVA (aopGet (leftOp,  offset, FALSE, TRUE));
4557               pushedB = pushB ();
4558               emitcode("xch", "a,b");
4559               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4560               emitcode (add, "a,b");
4561               popB (pushedB);
4562             }
4563           else if (aopGetUsesAcc (leftOp, offset))
4564             {
4565               MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4566               emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4567             }
4568           else
4569             {
4570               MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4571               emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4572             }
4573           aopPut (IC_RESULT (ic), "a", offset);
4574           add = "addc";  /* further adds must propagate carry */
4575         }
4576       else
4577         {
4578           if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4579               isOperandVolatile (IC_RESULT (ic), FALSE))
4580             {
4581               /* just move */
4582               aopPut (IC_RESULT (ic),
4583                       aopGet (leftOp, offset, FALSE, FALSE),
4584                       offset);
4585             }
4586         }
4587       offset++;
4588     }
4589
4590   adjustArithmeticResult (ic);
4591
4592 release:
4593   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4594   if (!swappedLR)
4595     {
4596       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598     }
4599   else
4600     {
4601       freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602       freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603     }
4604 }
4605
4606 /*-----------------------------------------------------------------*/
4607 /* genMinusDec :- does subtraction with decrement if possible      */
4608 /*-----------------------------------------------------------------*/
4609 static bool
4610 genMinusDec (iCode * ic)
4611 {
4612   unsigned int icount;
4613   unsigned int size = getDataSize (IC_RESULT (ic));
4614
4615   /* will try to generate an increment */
4616   /* if the right side is not a literal
4617      we cannot */
4618   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4619     return FALSE;
4620
4621   /* if the literal value of the right hand side
4622      is greater than 4 then it is not worth it */
4623   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4624     return FALSE;
4625
4626   D (emitcode (";", "genMinusDec"));
4627
4628   /* if decrement >=16 bits in register or direct space */
4629   if (( AOP_TYPE(IC_LEFT(ic)) == AOP_REG || 
4630         AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ||
4631         (IS_AOP_PREG (IC_LEFT(ic)) && !AOP_NEEDSACC (IC_LEFT(ic))) ) &&
4632       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4633       (size > 1) &&
4634       (icount == 1))
4635     {
4636       symbol *tlbl;
4637       int emitTlbl;
4638       int labelRange;
4639
4640       /* If the next instruction is a goto and the goto target
4641        * is <= 10 instructions previous to this, we can generate
4642        * jumps straight to that target.
4643        */
4644       if (ic->next && ic->next->op == GOTO
4645           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4646           && labelRange <= 10)
4647         {
4648           D (emitcode (";", "tail decrement optimized (range %d)", labelRange));
4649           tlbl = IC_LABEL (ic->next);
4650           emitTlbl = 0;
4651         }
4652       else
4653         {
4654           tlbl = newiTempLabel (NULL);
4655           emitTlbl = 1;
4656         }
4657
4658       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4659       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4660           IS_AOP_PREG (IC_RESULT (ic)))
4661         emitcode ("cjne", "%s,#0xff,%05d$"
4662                   ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4663                   ,tlbl->key + 100);
4664       else
4665         {
4666           emitcode ("mov", "a,#0xff");
4667           emitcode ("cjne", "a,%s,%05d$"
4668                     ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4669                     ,tlbl->key + 100);
4670         }
4671       emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4672       if (size > 2)
4673         {
4674           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4675               IS_AOP_PREG (IC_RESULT (ic)))
4676             emitcode ("cjne", "%s,#0xff,%05d$"
4677                       ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4678                       ,tlbl->key + 100);
4679           else
4680             {
4681               emitcode ("cjne", "a,%s,%05d$"
4682                         ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4683                         ,tlbl->key + 100);
4684             }
4685           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4686         }
4687       if (size > 3)
4688         {
4689           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4690               IS_AOP_PREG (IC_RESULT (ic)))
4691             emitcode ("cjne", "%s,#0xff,%05d$"
4692                       ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4693                       ,tlbl->key + 100);
4694           else
4695             {
4696               emitcode ("cjne", "a,%s,%05d$"
4697                         ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4698                         ,tlbl->key + 100);
4699             }
4700           emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4701         }
4702       if (emitTlbl)
4703         {
4704           emitLabel (tlbl);
4705         }
4706       return TRUE;
4707     }
4708
4709   /* if the sizes are greater than 1 then we cannot */
4710   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4711       AOP_SIZE (IC_LEFT (ic)) > 1)
4712     return FALSE;
4713
4714   /* we can if the aops of the left & result match or
4715      if they are in registers and the registers are the
4716      same */
4717   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4718     {
4719       char *l;
4720
4721       if (aopGetUsesAcc (IC_LEFT (ic), 0))
4722         {
4723           MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4724           l = "a";
4725         }
4726       else
4727         {
4728           l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4729         }
4730
4731       while (icount--)
4732         {
4733           emitcode ("dec", "%s", l);
4734         }
4735
4736       if (AOP_NEEDSACC (IC_RESULT (ic)))
4737         aopPut (IC_RESULT (ic), "a", 0);
4738
4739       return TRUE;
4740     }
4741
4742   if (icount == 1)
4743     {
4744       MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4745       emitcode ("dec", "a");
4746       aopPut (IC_RESULT (ic), "a", 0);
4747       return TRUE;
4748     }
4749
4750   return FALSE;
4751 }
4752
4753 /*-----------------------------------------------------------------*/
4754 /* addSign - complete with sign                                    */
4755 /*-----------------------------------------------------------------*/
4756 static void
4757 addSign (operand * result, int offset, int sign)
4758 {
4759   int size = (getDataSize (result) - offset);
4760   if (size > 0)
4761     {
4762       if (sign)
4763         {
4764           emitcode ("rlc", "a");
4765           emitcode ("subb", "a,acc");
4766           while (size--)
4767             {
4768               aopPut (result, "a", offset++);
4769             }
4770         }
4771       else
4772         {
4773           while (size--)
4774             {
4775               aopPut (result, zero, offset++);
4776             }
4777         }
4778     }
4779 }
4780
4781 /*-----------------------------------------------------------------*/
4782 /* genMinusBits - generates code for subtraction  of two bits      */
4783 /*-----------------------------------------------------------------*/
4784 static void
4785 genMinusBits (iCode * ic)
4786 {
4787   symbol *lbl = newiTempLabel (NULL);
4788
4789   D (emitcode (";", "genMinusBits"));
4790
4791   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4792     {
4793       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4794       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4795       emitcode ("cpl", "c");
4796       emitLabel (lbl);
4797       outBitC (IC_RESULT (ic));
4798     }
4799   else
4800     {
4801       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4802       emitcode ("subb", "a,acc");
4803       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4804       emitcode ("inc", "a");
4805       emitLabel (lbl);
4806       aopPut (IC_RESULT (ic), "a", 0);
4807       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4808     }
4809 }
4810
4811 /*-----------------------------------------------------------------*/
4812 /* genMinus - generates code for subtraction                       */
4813 /*-----------------------------------------------------------------*/
4814 static void
4815 genMinus (iCode * ic)
4816 {
4817   int size, offset = 0;
4818
4819   D (emitcode (";", "genMinus"));
4820
4821   aopOp (IC_LEFT (ic), ic, FALSE);
4822   aopOp (IC_RIGHT (ic), ic, FALSE);
4823   aopOp (IC_RESULT (ic), ic, TRUE);
4824
4825   /* special cases :- */
4826   /* if both left & right are in bit space */
4827   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4828       AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4829     {
4830       genMinusBits (ic);
4831       goto release;
4832     }
4833
4834   /* if I can do an decrement instead
4835      of subtract then GOOD for ME */
4836   if (genMinusDec (ic) == TRUE)
4837     goto release;
4838
4839   size = getDataSize (IC_RESULT (ic));
4840
4841   /* if literal, add a,#-lit, else normal subb */
4842   if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4843     {
4844       unsigned long lit = 0L;
4845       bool useCarry = FALSE;
4846
4847       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4848       lit = -(long) lit;
4849
4850       while (size--)
4851         {
4852           if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4853             {
4854               MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4855               if (!offset && !size && lit== (unsigned long) -1)
4856                 {
4857                   emitcode ("dec", "a");
4858                 }
4859               else if (!useCarry)
4860                 {
4861                   /* first add without previous c */
4862                   emitcode ("add", "a,#0x%02x",
4863                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4864                   useCarry = TRUE;
4865                 }
4866               else
4867                 {
4868                   emitcode ("addc", "a,#0x%02x",
4869                             (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4870                 }
4871               aopPut (IC_RESULT (ic), "a", offset++);
4872             }
4873           else
4874             {
4875               /* no need to add zeroes */
4876               if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4877                 {
4878                   aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4879                           offset);
4880                 }
4881               offset++;
4882             }
4883         }
4884     }
4885   else
4886     {
4887       operand *leftOp, *rightOp;
4888
4889       leftOp = IC_LEFT(ic);
4890       rightOp = IC_RIGHT(ic);
4891
4892       while (size--)
4893         {
4894           if (aopGetUsesAcc(rightOp, offset)) {
4895             if (aopGetUsesAcc(leftOp, offset)) {
4896               bool pushedB;
4897
4898               MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4899               pushedB = pushB ();
4900               emitcode ("mov", "b,a");
4901               if (offset == 0)
4902                 CLRC;
4903               MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4904               emitcode ("subb", "a,b");
4905               popB (pushedB);
4906             } else {
4907               /* reverse subtraction with 2's complement */
4908               if (offset == 0)
4909                 emitcode( "setb", "c");
4910               else
4911                 emitcode( "cpl", "c");
4912               wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4913               MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4914               emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4915               emitcode("cpl", "a");
4916               if (size) /* skip if last byte */
4917                 emitcode( "cpl", "c");
4918             }
4919           } else {
4920             MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4921             if (offset == 0)
4922               CLRC;
4923             emitcode ("subb", "a,%s",
4924                       aopGet(rightOp, offset, FALSE, TRUE));
4925           }
4926
4927           aopPut (IC_RESULT (ic), "a", offset++);
4928         }
4929     }
4930
4931   adjustArithmeticResult (ic);
4932
4933 release:
4934   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4935   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937 }
4938
4939
4940 /*-----------------------------------------------------------------*/
4941 /* genMultbits :- multiplication of bits                           */
4942 /*-----------------------------------------------------------------*/
4943 static void
4944 genMultbits (operand * left,
4945              operand * right,
4946              operand * result)
4947 {
4948   D (emitcode (";", "genMultbits"));
4949
4950   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4951   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4952   outBitC (result);
4953 }
4954
4955 /*-----------------------------------------------------------------*/
4956 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4957 /*-----------------------------------------------------------------*/
4958 static void
4959 genMultOneByte (operand * left,
4960                 operand * right,
4961                 operand * result)
4962 {
4963   symbol *lbl;
4964   int size = AOP_SIZE (result);
4965   bool runtimeSign, compiletimeSign;
4966   bool lUnsigned, rUnsigned, pushedB;
4967
4968   D (emitcode (";", "genMultOneByte"));
4969
4970   if (size < 1 || size > 2)
4971     {
4972       /* this should never happen */
4973       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4974                AOP_SIZE(result), __FILE__, lineno);
4975       exit (1);
4976     }
4977
4978   /* (if two literals: the value is computed before) */
4979   /* if one literal, literal on the right */
4980   if (AOP_TYPE (left) == AOP_LIT)
4981     {
4982       operand *t = right;
4983       right = left;
4984       left = t;
4985       /* emitcode (";", "swapped left and right"); */
4986     }
4987   /* if no literal, unsigned on the right: shorter code */
4988   if (   AOP_TYPE (right) != AOP_LIT
4989       && SPEC_USIGN (getSpec (operandType (left))))
4990     {
4991       operand *t = right;
4992       right = left;
4993       left = t;
4994     }
4995
4996   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4997   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4998
4999   pushedB = pushB ();
5000
5001   if (size == 1 /* no, this is not a bug; with a 1 byte result there's
5002                    no need to take care about the signedness! */
5003       || (lUnsigned && rUnsigned))
5004     {
5005       /* just an unsigned 8 * 8 = 8 multiply
5006          or 8u * 8u = 16u */
5007       /* emitcode (";","unsigned"); */
5008       /* TODO: check for accumulator clash between left & right aops? */
5009
5010       if (AOP_TYPE (right) == AOP_LIT)
5011         {
5012           /* moving to accumulator first helps peepholes */
5013           MOVA (aopGet (left, 0, FALSE, FALSE));
5014           MOVB (aopGet (right, 0, FALSE, FALSE));
5015         }
5016       else
5017         {
5018           emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5019           MOVA (aopGet (left, 0, FALSE, FALSE));
5020         }
5021
5022       emitcode ("mul", "ab");
5023       aopPut (result, "a", 0);
5024       if (size == 2)
5025         aopPut (result, "b", 1);
5026
5027       popB (pushedB);
5028       return;
5029     }
5030
5031   /* we have to do a signed multiply */
5032   /* emitcode (";", "signed"); */
5033
5034   /* now sign adjust for both left & right */
5035
5036   /* let's see what's needed: */
5037   /* apply negative sign during runtime */
5038   runtimeSign = FALSE;
5039   /* negative sign from literals */
5040   compiletimeSign = FALSE;
5041
5042   if (!lUnsigned)
5043     {
5044       if (AOP_TYPE(left) == AOP_LIT)
5045         {
5046           /* signed literal */
5047           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5048           if (val < 0)
5049             compiletimeSign = TRUE;
5050         }
5051       else
5052         /* signed but not literal */
5053         runtimeSign = TRUE;
5054     }
5055
5056   if (!rUnsigned)
5057     {
5058       if (AOP_TYPE(right) == AOP_LIT)
5059         {
5060           /* signed literal */
5061           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5062           if (val < 0)
5063             compiletimeSign ^= TRUE;
5064         }
5065       else
5066         /* signed but not literal */
5067         runtimeSign = TRUE;
5068     }
5069
5070   /* initialize F0, which stores the runtime sign */
5071   if (runtimeSign)
5072     {
5073       if (compiletimeSign)
5074         emitcode ("setb", "F0"); /* set sign flag */
5075       else
5076         emitcode ("clr", "F0"); /* reset sign flag */
5077     }
5078
5079   /* save the signs of the operands */
5080   if (AOP_TYPE(right) == AOP_LIT)
5081     {
5082       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5083
5084       if (!rUnsigned && val < 0)
5085         emitcode ("mov", "b,#0x%02x", -val);
5086       else
5087         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5088     }
5089   else /* ! literal */
5090     {
5091       if (rUnsigned)  /* emitcode (";", "signed"); */
5092         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5093       else
5094         {
5095           MOVA (aopGet (right, 0, FALSE, FALSE));
5096           lbl = newiTempLabel (NULL);
5097           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5098           emitcode ("cpl", "F0"); /* complement sign flag */
5099           emitcode ("cpl", "a");  /* 2's complement */
5100           emitcode ("inc", "a");
5101           emitLabel (lbl);
5102           emitcode ("mov", "b,a");
5103         }
5104     }
5105
5106   if (AOP_TYPE(left) == AOP_LIT)
5107     {
5108       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5109
5110       if (!lUnsigned && val < 0)
5111         emitcode ("mov", "a,#0x%02x", -val);
5112       else
5113         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5114     }
5115   else /* ! literal */
5116     {
5117       MOVA (aopGet (left, 0, FALSE, FALSE));
5118
5119       if (!lUnsigned)
5120         {
5121           lbl = newiTempLabel (NULL);
5122           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5123           emitcode ("cpl", "F0"); /* complement sign flag */
5124           emitcode ("cpl", "a"); /* 2's complement */
5125           emitcode ("inc", "a");
5126           emitLabel (lbl);
5127         }
5128     }
5129
5130   /* now the multiplication */
5131   emitcode ("mul", "ab");
5132   if (runtimeSign || compiletimeSign)
5133     {
5134       lbl = newiTempLabel (NULL);
5135       if (runtimeSign)
5136         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5137       emitcode ("cpl", "a"); /* lsb 2's complement */
5138       if (size != 2)
5139         emitcode ("inc", "a"); /* inc doesn't set carry flag */
5140       else
5141         {
5142           emitcode ("add", "a,#1"); /* this sets carry flag */
5143           emitcode ("xch", "a,b");
5144           emitcode ("cpl", "a"); /* msb 2's complement */
5145           emitcode ("addc", "a,#0");
5146           emitcode ("xch", "a,b");
5147         }
5148       emitLabel (lbl);
5149     }
5150   aopPut (result, "a", 0);
5151   if (size == 2)
5152     aopPut (result, "b", 1);
5153
5154   popB (pushedB);
5155 }
5156
5157 /*-----------------------------------------------------------------*/
5158 /* genMult - generates code for multiplication                     */
5159 /*-----------------------------------------------------------------*/
5160 static void
5161 genMult (iCode * ic)
5162 {
5163   operand *left = IC_LEFT (ic);
5164   operand *right = IC_RIGHT (ic);
5165   operand *result = IC_RESULT (ic);
5166
5167   D (emitcode (";", "genMult"));
5168
5169   /* assign the asmops */
5170   aopOp (left, ic, FALSE);
5171   aopOp (right, ic, FALSE);
5172   aopOp (result, ic, TRUE);
5173
5174   /* special cases first */
5175   /* both are bits */
5176   if (AOP_TYPE (left) == AOP_CRY &&
5177       AOP_TYPE (right) == AOP_CRY)
5178     {
5179       genMultbits (left, right, result);
5180       goto release;
5181     }
5182
5183   /* if both are of size == 1 */
5184 #if 0 // one of them can be a sloc shared with the result
5185     if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5186 #else
5187   if (getSize(operandType(left)) == 1 &&
5188       getSize(operandType(right)) == 1)
5189 #endif
5190     {
5191       genMultOneByte (left, right, result);
5192       goto release;
5193     }
5194
5195   /* should have been converted to function call */
5196     fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5197              getSize(OP_SYMBOL(right)->type));
5198   assert (0);
5199
5200 release:
5201   freeAsmop (result, NULL, ic, TRUE);
5202   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5203   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204 }
5205
5206 /*-----------------------------------------------------------------*/
5207 /* genDivbits :- division of bits                                  */
5208 /*-----------------------------------------------------------------*/
5209 static void
5210 genDivbits (operand * left,
5211             operand * right,
5212             operand * result)
5213 {
5214   char *l;
5215   bool pushedB;
5216
5217   D(emitcode (";     genDivbits",""));
5218
5219   pushedB = pushB ();
5220
5221   /* the result must be bit */
5222   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5223   l = aopGet (left, 0, FALSE, FALSE);
5224
5225   MOVA (l);
5226
5227   emitcode ("div", "ab");
5228   emitcode ("rrc", "a");
5229
5230   popB (pushedB);
5231
5232   aopPut (result, "c", 0);
5233 }
5234
5235 /*-----------------------------------------------------------------*/
5236 /* genDivOneByte : 8 bit division                                  */
5237 /*-----------------------------------------------------------------*/
5238 static void
5239 genDivOneByte (operand * left,
5240                operand * right,
5241                operand * result)
5242 {
5243   bool lUnsigned, rUnsigned, pushedB;
5244   bool runtimeSign, compiletimeSign;
5245   bool accuse = FALSE;
5246   bool pushedA = FALSE;
5247   symbol *lbl;
5248   int size, offset;
5249
5250   D(emitcode (";     genDivOneByte",""));
5251
5252   /* Why is it necessary that genDivOneByte() can return an int result?
5253      Have a look at:
5254
5255         volatile unsigned char uc;
5256         volatile signed char sc1, sc2;
5257         volatile int i;
5258
5259         uc  = 255;
5260         sc1 = -1;
5261         i = uc / sc1;
5262
5263      Or:
5264
5265         sc1 = -128;
5266         sc2 = -1;
5267         i = sc1 / sc2;
5268
5269      In all cases a one byte result would overflow, the following cast to int
5270      would return the wrong result.
5271
5272      Two possible solution:
5273         a) cast operands to int, if ((unsigned) / (signed)) or
5274            ((signed) / (signed))
5275         b) return an 16 bit signed int; this is what we're doing here!
5276   */
5277
5278   size = AOP_SIZE (result) - 1;
5279   offset = 1;
5280   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5281   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5282
5283   pushedB = pushB ();
5284
5285   /* signed or unsigned */
5286   if (lUnsigned && rUnsigned)
5287     {
5288       /* unsigned is easy */
5289       MOVB (aopGet (right, 0, FALSE, FALSE));
5290       MOVA (aopGet (left, 0, FALSE, FALSE));
5291       emitcode ("div", "ab");
5292       aopPut (result, "a", 0);
5293       while (size--)
5294         aopPut (result, zero, offset++);
5295
5296       popB (pushedB);
5297       return;
5298     }
5299
5300   /* signed is a little bit more difficult */
5301
5302   /* now sign adjust for both left & right */
5303
5304   /* let's see what's needed: */
5305   /* apply negative sign during runtime */
5306   runtimeSign = FALSE;
5307   /* negative sign from literals */
5308   compiletimeSign = FALSE;
5309
5310   if (!lUnsigned)
5311     {
5312       if (AOP_TYPE(left) == AOP_LIT)
5313         {
5314           /* signed literal */
5315           signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5316           if (val < 0)
5317             compiletimeSign = TRUE;
5318         }
5319       else
5320         /* signed but not literal */
5321         runtimeSign = TRUE;
5322     }
5323
5324   if (!rUnsigned)
5325     {
5326       if (AOP_TYPE(right) == AOP_LIT)
5327         {
5328           /* signed literal */
5329           signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5330           if (val < 0)
5331             compiletimeSign ^= TRUE;
5332         }
5333       else
5334         /* signed but not literal */
5335         runtimeSign = TRUE;
5336     }
5337
5338   /* initialize F0, which stores the runtime sign */
5339   if (runtimeSign)
5340     {
5341       if (compiletimeSign)
5342         emitcode ("setb", "F0"); /* set sign flag */
5343       else
5344         emitcode ("clr", "F0"); /* reset sign flag */
5345     }
5346
5347   /* save the signs of the operands */
5348   if (AOP_TYPE(right) == AOP_LIT)
5349     {
5350       signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5351
5352       if (!rUnsigned && val < 0)
5353         emitcode ("mov", "b,#0x%02x", -val);
5354       else
5355         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5356     }
5357   else /* ! literal */
5358     {
5359       if (rUnsigned)
5360         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5361       else
5362         {
5363           MOVA (aopGet (right, 0, FALSE, FALSE));
5364           lbl = newiTempLabel (NULL);
5365           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5366           emitcode ("cpl", "F0"); /* complement sign flag */
5367           emitcode ("cpl", "a");  /* 2's complement */
5368           emitcode ("inc", "a");
5369           emitLabel (lbl);
5370           emitcode ("mov", "b,a");
5371         }
5372     }
5373
5374   if (AOP_TYPE(left) == AOP_LIT)
5375     {
5376       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5377
5378       if (!lUnsigned && val < 0)
5379         emitcode ("mov", "a,#0x%02x", -val);
5380       else
5381         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5382     }
5383   else /* ! literal */
5384     {
5385       MOVA (aopGet (left, 0, FALSE, FALSE));
5386
5387       if (!lUnsigned)
5388         {
5389           lbl = newiTempLabel (NULL);
5390           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5391           emitcode ("cpl", "F0"); /* complement sign flag */
5392           emitcode ("cpl", "a");  /* 2's complement */
5393           emitcode ("inc", "a");
5394           emitLabel (lbl);
5395         }
5396     }
5397
5398   /* now the division */
5399   emitcode ("div", "ab");
5400
5401   if (runtimeSign || compiletimeSign)
5402     {
5403       lbl = newiTempLabel (NULL);
5404       if (runtimeSign)
5405         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5406       emitcode ("cpl", "a"); /* lsb 2's complement */
5407       emitcode ("inc", "a");
5408       emitLabel (lbl);
5409
5410       accuse = aopPut (result, "a", 0);
5411       if (size > 0)
5412         {
5413           /* msb is 0x00 or 0xff depending on the sign */
5414           if (runtimeSign)
5415             {
5416               if (accuse)
5417                 {
5418                   emitcode ("push", "acc");
5419                   pushedA = TRUE;
5420                 }
5421               emitcode ("mov", "c,F0");
5422               emitcode ("subb", "a,acc");
5423               while (size--)
5424                 aopPut (result, "a", offset++);
5425             }
5426           else /* compiletimeSign */
5427             {
5428               if (aopPutUsesAcc (result, "#0xFF", offset))
5429                 {
5430                   emitcode ("push", "acc");
5431                   pushedA = TRUE;
5432                 }
5433               while (size--)
5434                 aopPut (result, "#0xff", offset++);
5435             }
5436         }
5437     }
5438   else
5439     {
5440       aopPut (result, "a", 0);
5441       while (size--)
5442         aopPut (result, zero, offset++);
5443     }
5444
5445   if (pushedA)
5446     emitcode ("pop", "acc");
5447   popB (pushedB);
5448 }
5449
5450 /*-----------------------------------------------------------------*/
5451 /* genDiv - generates code for division                            */
5452 /*-----------------------------------------------------------------*/
5453 static void
5454 genDiv (iCode * ic)
5455 {
5456   operand *left = IC_LEFT (ic);
5457   operand *right = IC_RIGHT (ic);
5458   operand *result = IC_RESULT (ic);
5459
5460   D (emitcode (";", "genDiv"));
5461
5462   /* assign the amsops */
5463   aopOp (left, ic, FALSE);
5464   aopOp (right, ic, FALSE);
5465   aopOp (result, ic, TRUE);
5466
5467   /* special cases first */
5468   /* both are bits */
5469   if (AOP_TYPE (left) == AOP_CRY &&
5470       AOP_TYPE (right) == AOP_CRY)
5471     {
5472       genDivbits (left, right, result);
5473       goto release;
5474     }
5475
5476   /* if both are of size == 1 */
5477   if (AOP_SIZE (left) == 1 &&
5478       AOP_SIZE (right) == 1)
5479     {
5480       genDivOneByte (left, right, result);
5481       goto release;
5482     }
5483
5484   /* should have been converted to function call */
5485   assert (0);
5486 release:
5487   freeAsmop (result, NULL, ic, TRUE);
5488   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490 }
5491
5492 /*-----------------------------------------------------------------*/
5493 /* genModbits :- modulus of bits                                   */
5494 /*-----------------------------------------------------------------*/
5495 static void
5496 genModbits (operand * left,
5497             operand * right,
5498             operand * result)
5499 {
5500   char *l;
5501   bool pushedB;
5502
5503   D (emitcode (";", "genModbits"));
5504
5505   pushedB = pushB ();
5506
5507   /* the result must be bit */
5508   emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5509   l = aopGet (left, 0, FALSE, FALSE);
5510
5511   MOVA (l);
5512
5513   emitcode ("div", "ab");
5514   emitcode ("mov", "a,b");
5515   emitcode ("rrc", "a");
5516
5517   popB (pushedB);
5518
5519   aopPut (result, "c", 0);
5520 }
5521
5522 /*-----------------------------------------------------------------*/
5523 /* genModOneByte : 8 bit modulus                                   */
5524 /*-----------------------------------------------------------------*/
5525 static void
5526 genModOneByte (operand * left,
5527                operand * right,
5528                operand * result)
5529 {
5530   bool lUnsigned, rUnsigned, pushedB;
5531   bool runtimeSign, compiletimeSign;
5532   symbol *lbl;
5533   int size, offset;
5534
5535   D (emitcode (";", "genModOneByte"));
5536
5537   size = AOP_SIZE (result) - 1;
5538   offset = 1;
5539   lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5540   rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5541
5542   /* if right is a literal, check it for 2^n */
5543   if (AOP_TYPE(right) == AOP_LIT)
5544     {
5545       unsigned char val = abs((int) operandLitValue(right));
5546       symbol *lbl2 = NULL;
5547
5548       switch (val)
5549         {
5550           case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5551           case 2:
5552           case 4:
5553           case 8:
5554           case 16:
5555           case 32:
5556           case 64:
5557           case 128:
5558             if (lUnsigned)
5559               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5560                       "modulus of unsigned char by 2^n literal shouldn't be processed here");
5561               /* because iCode should have been changed to genAnd  */
5562               /* see file "SDCCopt.c", function "convertToFcall()" */
5563
5564             MOVA (aopGet (left, 0, FALSE, FALSE));
5565             emitcode ("mov", "c,acc.7");
5566             emitcode ("anl", "a,#0x%02x", val - 1);
5567             lbl = newiTempLabel (NULL);
5568             emitcode ("jz", "%05d$", (lbl->key + 100));
5569             emitcode ("jnc", "%05d$", (lbl->key + 100));
5570             emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5571             if (size)
5572               {
5573                 int size2 = size;
5574                 int offs2 = offset;
5575
5576                 aopPut (result, "a", 0);
5577                 while (size2--)
5578                   aopPut (result, "#0xff", offs2++);
5579                 lbl2 = newiTempLabel (NULL);
5580                 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5581               }
5582             emitLabel (lbl);
5583             aopPut (result, "a", 0);
5584             while (size--)
5585               aopPut (result, zero, offset++);
5586             if (lbl2)
5587               {
5588                 emitLabel (lbl2);
5589               }
5590             return;
5591
5592           default:
5593             break;
5594         }
5595     }
5596
5597   pushedB = pushB ();
5598
5599   /* signed or unsigned */
5600   if (lUnsigned && rUnsigned)
5601     {
5602       /* unsigned is easy */
5603       MOVB (aopGet (right, 0, FALSE, FALSE));
5604       MOVA (aopGet (left, 0, FALSE, FALSE));
5605       emitcode ("div", "ab");
5606       aopPut (result, "b", 0);
5607       while (size--)
5608         aopPut (result, zero, offset++);
5609
5610       popB (pushedB);
5611       return;
5612     }
5613
5614   /* signed is a little bit more difficult */
5615
5616   /* now sign adjust for both left & right */
5617
5618   /* modulus: sign of the right operand has no influence on the result! */
5619   if (AOP_TYPE(right) == AOP_LIT)
5620     {
5621       signed char val = (char) operandLitValue(right);
5622
5623       if (!rUnsigned && val < 0)
5624         emitcode ("mov", "b,#0x%02x", -val);
5625       else
5626         emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5627     }
5628   else /* not literal */
5629     {
5630       if (rUnsigned)
5631         emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5632       else
5633         {
5634           MOVA (aopGet (right, 0, FALSE, FALSE));
5635           lbl = newiTempLabel (NULL);
5636           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5637           emitcode ("cpl", "a"); /* 2's complement */
5638           emitcode ("inc", "a");
5639           emitLabel (lbl);
5640           emitcode ("mov", "b,a");
5641         }
5642     }
5643
5644   /* let's see what's needed: */
5645   /* apply negative sign during runtime */
5646   runtimeSign = FALSE;
5647   /* negative sign from literals */
5648   compiletimeSign = FALSE;
5649
5650   /* sign adjust left side */
5651   if (AOP_TYPE(left) == AOP_LIT)
5652     {
5653       signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5654
5655       if (!lUnsigned && val < 0)
5656         {
5657           compiletimeSign = TRUE; /* set sign flag */
5658           emitcode ("mov", "a,#0x%02x", -val);
5659         }
5660       else
5661         emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5662     }
5663   else /* ! literal */
5664     {
5665       MOVA (aopGet (left, 0, FALSE, FALSE));
5666
5667       if (!lUnsigned)
5668         {
5669           runtimeSign = TRUE;
5670           emitcode ("clr", "F0"); /* clear sign flag */
5671
5672           lbl = newiTempLabel (NULL);
5673           emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5674           emitcode ("setb", "F0"); /* set sign flag */
5675           emitcode ("cpl", "a");   /* 2's complement */
5676           emitcode ("inc", "a");
5677           emitLabel (lbl);
5678         }
5679     }
5680
5681   /* now the modulus */
5682   emitcode ("div", "ab");
5683
5684   if (runtimeSign || compiletimeSign)
5685     {
5686       emitcode ("mov", "a,b");
5687       lbl = newiTempLabel (NULL);
5688       if (runtimeSign)
5689         emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5690       emitcode ("cpl", "a"); /* 2's complement */
5691       emitcode ("inc", "a");
5692       emitLabel (lbl);
5693
5694       aopPut (result, "a", 0);
5695       if (size > 0)
5696         {
5697           /* msb is 0x00 or 0xff depending on the sign */
5698           if (runtimeSign)
5699             {
5700               emitcode ("mov", "c,F0");
5701               emitcode ("subb", "a,acc");
5702               while (size--)
5703                 aopPut (result, "a", offset++);
5704             }
5705           else /* compiletimeSign */
5706             while (size--)
5707               aopPut (result, "#0xff", offset++);
5708         }
5709     }
5710   else
5711     {
5712       aopPut (result, "b", 0);
5713       while (size--)
5714         aopPut (result, zero, offset++);
5715     }
5716
5717   popB (pushedB);
5718 }
5719
5720 /*-----------------------------------------------------------------*/
5721 /* genMod - generates code for division                            */
5722 /*-----------------------------------------------------------------*/
5723 static void
5724 genMod (iCode * ic)
5725 {
5726   operand *left = IC_LEFT (ic);
5727   operand *right = IC_RIGHT (ic);
5728   operand *result = IC_RESULT (ic);
5729
5730   D (emitcode (";", "genMod"));
5731
5732   /* assign the asmops */
5733   aopOp (left, ic, FALSE);
5734   aopOp (right, ic, FALSE);
5735   aopOp (result, ic, TRUE);
5736
5737   /* special cases first */
5738   /* both are bits */
5739   if (AOP_TYPE (left) == AOP_CRY &&
5740       AOP_TYPE (right) == AOP_CRY)
5741     {
5742       genModbits (left, right, result);
5743       goto release;
5744     }
5745
5746   /* if both are of size == 1 */
5747   if (AOP_SIZE (left) == 1 &&
5748       AOP_SIZE (right) == 1)
5749     {
5750       genModOneByte (left, right, result);
5751       goto release;
5752     }
5753
5754   /* should have been converted to function call */
5755   assert (0);
5756
5757 release:
5758   freeAsmop (result, NULL, ic, TRUE);
5759   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5760   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5761 }
5762
5763 /*-----------------------------------------------------------------*/
5764 /* genIfxJump :- will create a jump depending on the ifx           */
5765 /*-----------------------------------------------------------------*/
5766 static void
5767 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5768 {
5769   symbol *jlbl;
5770   symbol *tlbl = newiTempLabel (NULL);
5771   char *inst;
5772
5773   D (emitcode (";", "genIfxJump"));
5774
5775   /* if true label then we jump if condition
5776      supplied is true */
5777   if (IC_TRUE (ic))
5778     {
5779       jlbl = IC_TRUE (ic);
5780       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5781                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5782     }
5783   else
5784     {
5785       /* false label is present */
5786       jlbl = IC_FALSE (ic);
5787       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5788                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5789     }
5790   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5791     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5792   else
5793     emitcode (inst, "%05d$", tlbl->key + 100);
5794   freeForBranchAsmop (result);
5795   freeForBranchAsmop (right);
5796   freeForBranchAsmop (left);
5797   emitcode ("ljmp", "%05d$", jlbl->key + 100);
5798   emitLabel (tlbl);
5799
5800   /* mark the icode as generated */
5801   ic->generated = 1;
5802 }
5803
5804 /*-----------------------------------------------------------------*/
5805 /* genCmp :- greater or less than comparison                       */
5806 /*-----------------------------------------------------------------*/
5807 static void
5808 genCmp (operand * left, operand * right,
5809         operand * result, iCode * ifx, int sign, iCode *ic)
5810 {
5811   int size, offset = 0;
5812   unsigned long lit = 0L;
5813   bool rightInB;
5814
5815   D (emitcode (";", "genCmp"));
5816
5817   /* if left & right are bit variables */
5818   if (AOP_TYPE (left) == AOP_CRY &&
5819       AOP_TYPE (right) == AOP_CRY)
5820     {
5821       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5822       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5823     }
5824   else
5825     {
5826       /* subtract right from left if at the
5827          end the carry flag is set then we know that
5828          left is greater than right */
5829       size = max (AOP_SIZE (left), AOP_SIZE (right));
5830
5831       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5832       if ((size == 1) && !sign &&
5833           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5834         {
5835           symbol *lbl = newiTempLabel (NULL);
5836           emitcode ("cjne", "%s,%s,%05d$",
5837                     aopGet (left, offset, FALSE, FALSE),
5838                     aopGet (right, offset, FALSE, FALSE),
5839                     lbl->key + 100);
5840           emitLabel (lbl);
5841         }
5842       else
5843         {
5844           if (AOP_TYPE (right) == AOP_LIT)
5845             {
5846               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5847               /* optimize if(x < 0) or if(x >= 0) */
5848               if (lit == 0L)
5849                 {
5850                   if (!sign)
5851                     {
5852                       CLRC;
5853                     }
5854                   else
5855                     {
5856                       MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5857                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5858                         {
5859                           genIfxJump (ifx, "acc.7", left, right, result);
5860                           freeAsmop (right, NULL, ic, TRUE);
5861                           freeAsmop (left, NULL, ic, TRUE);
5862
5863                           return;
5864                         }
5865                       else
5866                         {
5867                           emitcode ("rlc", "a");
5868                         }
5869                     }
5870                   goto release;
5871                 }
5872               else
5873                 {//nonzero literal
5874                   int bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5875                   while (size && (bytelit == 0))
5876                     {
5877                       offset++;
5878                       bytelit = ((lit >> (offset * 8)) & 0x0FFL);
5879                       size--;
5880                     }
5881                   CLRC;
5882                   while (size--)
5883                     {
5884                       MOVA (aopGet (left, offset, FALSE, FALSE));
5885                       if (sign && size == 0)
5886                         {
5887                           emitcode ("xrl", "a,#0x80");
5888                           emitcode ("subb", "a,#0x%02x",
5889                                     0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5890                         }
5891                       else
5892                         {
5893                           emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5894                         }
5895                       offset++;
5896                     }
5897                   goto release;
5898                 }
5899             }
5900           CLRC;
5901           while (size--)
5902             {
5903               bool pushedB = FALSE;
5904               rightInB = aopGetUsesAcc(right, offset);
5905               if (rightInB)
5906                 {
5907                   pushedB = pushB ();
5908                   emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5909                 }
5910               MOVA (aopGet (left, offset, FALSE, FALSE));
5911               if (sign && size == 0)
5912                 {
5913                   emitcode ("xrl", "a,#0x80");
5914                   if (!rightInB)
5915                     {
5916                       pushedB = pushB ();
5917                       rightInB++;
5918                       MOVB (aopGet (right, offset, FALSE, FALSE));
5919                     }
5920                   emitcode ("xrl", "b,#0x80");
5921                   emitcode ("subb", "a,b");
5922                 }
5923               else
5924                 {
5925                   if (rightInB)
5926                     emitcode ("subb", "a,b");
5927                   else
5928                     emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5929                 }
5930               if (rightInB)
5931                 popB (pushedB);
5932               offset++;
5933             }
5934         }
5935     }
5936
5937 release:
5938   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5939   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5940   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5941     {
5942       outBitC (result);
5943     }
5944   else
5945     {
5946       /* if the result is used in the next
5947          ifx conditional branch then generate
5948          code a little differently */
5949       if (ifx)
5950         {
5951           genIfxJump (ifx, "c", NULL, NULL, result);
5952         }
5953       else
5954         {
5955           outBitC (result);
5956         }
5957       /* leave the result in acc */
5958     }
5959 }
5960
5961 /*-----------------------------------------------------------------*/
5962 /* genCmpGt :- greater than comparison                             */
5963 /*-----------------------------------------------------------------*/
5964 static void
5965 genCmpGt (iCode * ic, iCode * ifx)
5966 {
5967   operand *left, *right, *result;
5968   sym_link *letype, *retype;
5969   int sign;
5970
5971   D (emitcode (";", "genCmpGt"));
5972
5973   left = IC_LEFT (ic);
5974   right = IC_RIGHT (ic);
5975   result = IC_RESULT (ic);
5976
5977   letype = getSpec (operandType (left));
5978   retype = getSpec (operandType (right));
5979   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5980            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5981   /* assign the amsops */
5982   aopOp (result, ic, TRUE);
5983   aopOp (left, ic, FALSE);
5984   aopOp (right, ic, FALSE);
5985
5986   genCmp (right, left, result, ifx, sign, ic);
5987
5988   freeAsmop (result, NULL, ic, TRUE);
5989 }
5990
5991 /*-----------------------------------------------------------------*/
5992 /* genCmpLt - less than comparisons                                */
5993 /*-----------------------------------------------------------------*/
5994 static void
5995 genCmpLt (iCode * ic, iCode * ifx)
5996 {
5997   operand *left, *right, *result;
5998   sym_link *letype, *retype;
5999   int sign;
6000
6001   D (emitcode (";", "genCmpLt"));
6002
6003   left = IC_LEFT (ic);
6004   right = IC_RIGHT (ic);
6005   result = IC_RESULT (ic);
6006
6007   letype = getSpec (operandType (left));
6008   retype = getSpec (operandType (right));
6009   sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
6010            (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
6011   /* assign the amsops */
6012   aopOp (result, ic, TRUE);
6013   aopOp (left, ic, FALSE);
6014   aopOp (right, ic, FALSE);
6015
6016   genCmp (left, right, result, ifx, sign, ic);
6017
6018   freeAsmop (result, NULL, ic, TRUE);
6019 }
6020
6021 /*-----------------------------------------------------------------*/
6022 /* gencjneshort - compare and jump if not equal                    */
6023 /*-----------------------------------------------------------------*/
6024 static void
6025 gencjneshort (operand * left, operand * right, symbol * lbl)
6026 {
6027   int size = max (AOP_SIZE (left), AOP_SIZE (right));
6028   int offset = 0;
6029   unsigned long lit = 0L;
6030
6031   D (emitcode (";", "gencjneshort"));
6032
6033   /* if the left side is a literal or
6034      if the right is in a pointer register and left
6035      is not */
6036   if ((AOP_TYPE (left) == AOP_LIT) ||
6037       (AOP_TYPE (left) == AOP_IMMD) ||
6038       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6039     {
6040       operand *t = right;
6041       right = left;
6042       left = t;
6043     }
6044
6045   if (AOP_TYPE (right) == AOP_LIT)
6046     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6047
6048   /* if the right side is a literal then anything goes */
6049   if (AOP_TYPE (right) == AOP_LIT &&
6050       AOP_TYPE (left) != AOP_DIR  &&
6051       AOP_TYPE (left) != AOP_IMMD)
6052     {
6053       while (size--)
6054         {
6055           emitcode ("cjne", "%s,%s,%05d$",
6056                     aopGet (left, offset, FALSE, FALSE),
6057                     aopGet (right, offset, FALSE, FALSE),
6058                     lbl->key + 100);
6059           offset++;
6060         }
6061     }
6062
6063   /* if the right side is in a register or in direct space or
6064      if the left is a pointer register & right is not */
6065   else if (AOP_TYPE (right) == AOP_REG ||
6066            AOP_TYPE (right) == AOP_DIR ||
6067            AOP_TYPE (right) == AOP_LIT ||
6068            AOP_TYPE (right) == AOP_IMMD ||
6069            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
6070            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
6071     {
6072       while (size--)
6073         {
6074           MOVA (aopGet (left, offset, FALSE, FALSE));
6075           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
6076               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
6077             emitcode ("jnz", "%05d$", lbl->key + 100);
6078           else
6079             emitcode ("cjne", "a,%s,%05d$",
6080                       aopGet (right, offset, FALSE, TRUE),
6081                       lbl->key + 100);
6082           offset++;
6083         }
6084     }
6085   else
6086     {
6087       /* right is a pointer reg need both a & b */
6088       while (size--)
6089         {
6090           //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
6091           wassertl(!BINUSE, "B was in use");
6092           MOVB (aopGet (left, offset, FALSE, FALSE));
6093           MOVA (aopGet (right, offset, FALSE, FALSE));
6094           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
6095           offset++;
6096         }
6097     }
6098 }
6099
6100 /*-----------------------------------------------------------------*/
6101 /* gencjne - compare and jump if not equal                         */
6102 /*-----------------------------------------------------------------*/
6103 static void
6104 gencjne (operand * left, operand * right, symbol * lbl)
6105 {
6106   symbol *tlbl = newiTempLabel (NULL);
6107
6108   D (emitcode (";", "gencjne"));
6109
6110   gencjneshort (left, right, lbl);
6111
6112   emitcode ("mov", "a,%s", one);
6113   emitcode ("sjmp", "%05d$", tlbl->key + 100);
6114   emitLabel (lbl);
6115   emitcode ("clr", "a");
6116   emitLabel (tlbl);
6117 }
6118
6119 /*-----------------------------------------------------------------*/
6120 /* genCmpEq - generates code for equal to                          */
6121 /*-----------------------------------------------------------------*/
6122 static void
6123 genCmpEq (iCode * ic, iCode * ifx)
6124 {
6125   bool swappedLR = FALSE;
6126   operand *left, *right, *result;
6127
6128   D (emitcode (";", "genCmpEq"));
6129
6130   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6131   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6132   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6133
6134   /* if literal, literal on the right or
6135      if the right is in a pointer register and left
6136      is not */
6137   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
6138       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
6139     {
6140       operand *t = IC_RIGHT (ic);
6141       IC_RIGHT (ic) = IC_LEFT (ic);
6142       IC_LEFT (ic) = t;
6143       swappedLR = TRUE;
6144     }
6145
6146   if (ifx && !AOP_SIZE (result))
6147     {
6148       symbol *tlbl;
6149       /* if they are both bit variables */
6150       if (AOP_TYPE (left) == AOP_CRY &&
6151           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6152         {
6153           if (AOP_TYPE (right) == AOP_LIT)
6154             {
6155               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6156               if (lit == 0L)
6157                 {
6158                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6159                   emitcode ("cpl", "c");
6160                 }
6161               else if (lit == 1L)
6162                 {
6163                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6164                 }
6165               else
6166                 {
6167                   emitcode ("clr", "c");
6168                 }
6169               /* AOP_TYPE(right) == AOP_CRY */
6170             }
6171           else
6172             {
6173               symbol *lbl = newiTempLabel (NULL);
6174               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6175               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6176               emitcode ("cpl", "c");
6177               emitLabel (lbl);
6178             }
6179           /* if true label then we jump if condition
6180              supplied is true */
6181           tlbl = newiTempLabel (NULL);
6182           if (IC_TRUE (ifx))
6183             {
6184               emitcode ("jnc", "%05d$", tlbl->key + 100);
6185               freeForBranchAsmop (result);
6186               freeForBranchAsmop (right);
6187               freeForBranchAsmop (left);
6188               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6189             }
6190           else
6191             {
6192               emitcode ("jc", "%05d$", tlbl->key + 100);
6193               freeForBranchAsmop (result);
6194               freeForBranchAsmop (right);
6195               freeForBranchAsmop (left);
6196               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6197             }
6198           emitLabel (tlbl);
6199         }
6200       else
6201         {
6202           tlbl = newiTempLabel (NULL);
6203           gencjneshort (left, right, tlbl);
6204           if (IC_TRUE (ifx))
6205             {
6206               freeForBranchAsmop (result);
6207               freeForBranchAsmop (right);
6208               freeForBranchAsmop (left);
6209               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6210               emitLabel (tlbl);
6211             }
6212           else
6213             {
6214               symbol *lbl = newiTempLabel (NULL);
6215               emitcode ("sjmp", "%05d$", lbl->key + 100);
6216               emitLabel (tlbl);
6217               freeForBranchAsmop (result);
6218               freeForBranchAsmop (right);
6219               freeForBranchAsmop (left);
6220               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6221               emitLabel (lbl);
6222             }
6223         }
6224       /* mark the icode as generated */
6225       ifx->generated = 1;
6226       goto release;
6227     }
6228
6229   /* if they are both bit variables */
6230   if (AOP_TYPE (left) == AOP_CRY &&
6231       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6232     {
6233       if (AOP_TYPE (right) == AOP_LIT)
6234         {
6235           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6236           if (lit == 0L)
6237             {
6238               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6239               emitcode ("cpl", "c");
6240             }
6241           else if (lit == 1L)
6242             {
6243               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6244             }
6245           else
6246             {
6247               emitcode ("clr", "c");
6248             }
6249           /* AOP_TYPE(right) == AOP_CRY */
6250         }
6251       else
6252         {
6253           symbol *lbl = newiTempLabel (NULL);
6254           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6255           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6256           emitcode ("cpl", "c");
6257           emitLabel (lbl);
6258         }
6259       /* c = 1 if egal */
6260       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6261         {
6262           outBitC (result);
6263           goto release;
6264         }
6265       if (ifx)
6266         {
6267           genIfxJump (ifx, "c", left, right, result);
6268           goto release;
6269         }
6270       /* if the result is used in an arithmetic operation
6271          then put the result in place */
6272       outBitC (result);
6273     }
6274   else
6275     {
6276       gencjne (left, right, newiTempLabel (NULL));
6277       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6278         {
6279           aopPut (result, "a", 0);
6280           goto release;
6281         }
6282       if (ifx)
6283         {
6284           genIfxJump (ifx, "a", left, right, result);
6285           goto release;
6286         }
6287       /* if the result is used in an arithmetic operation
6288          then put the result in place */
6289       if (AOP_TYPE (result) != AOP_CRY)
6290         outAcc (result);
6291       /* leave the result in acc */
6292     }
6293
6294 release:
6295   freeAsmop (result, NULL, ic, TRUE);
6296   if (!swappedLR)
6297     {
6298       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6299       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6300     }
6301   else
6302     {
6303       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6304       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6305     }
6306 }
6307
6308 /*-----------------------------------------------------------------*/
6309 /* ifxForOp - returns the icode containing the ifx for operand     */
6310 /*-----------------------------------------------------------------*/
6311 static iCode *
6312 ifxForOp (operand * op, iCode * ic)
6313 {
6314   /* if true symbol then needs to be assigned */
6315   if (IS_TRUE_SYMOP (op))
6316     return NULL;
6317
6318   /* if this has register type condition and
6319      the next instruction is ifx with the same operand
6320      and live to of the operand is upto the ifx only then */
6321   if (ic->next &&
6322       ic->next->op == IFX &&
6323       IC_COND (ic->next)->key == op->key &&
6324       OP_SYMBOL (op)->liveTo <= ic->next->seq)
6325     return ic->next;
6326
6327   return NULL;
6328 }
6329
6330 /*-----------------------------------------------------------------*/
6331 /* hasInc - operand is incremented before any other use            */
6332 /*-----------------------------------------------------------------*/
6333 static iCode *
6334 hasInc (operand *op, iCode *ic, int osize)
6335 {
6336   sym_link *type = operandType(op);
6337   sym_link *retype = getSpec (type);
6338   iCode *lic = ic->next;
6339   int isize ;
6340
6341   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6342   if (!IS_SYMOP(op)) return NULL;
6343
6344   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6345   if (IS_AGGREGATE(type->next)) return NULL;
6346   if (osize != (isize = getSize(type->next))) return NULL;
6347
6348   while (lic) {
6349     /* if operand of the form op = op + <sizeof *op> */
6350     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6351         isOperandEqual(IC_RESULT(lic),op) &&
6352         isOperandLiteral(IC_RIGHT(lic)) &&
6353         operandLitValue(IC_RIGHT(lic)) == isize) {
6354       return lic;
6355     }
6356     /* if the operand used or deffed */
6357     if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6358       return NULL;
6359     }
6360     /* if GOTO or IFX */
6361     if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6362     lic = lic->next;
6363   }
6364   return NULL;
6365 }
6366
6367 /*-----------------------------------------------------------------*/
6368 /* genAndOp - for && operation                                     */
6369 /*-----------------------------------------------------------------*/
6370 static void
6371 genAndOp (iCode * ic)
6372 {
6373   operand *left, *right, *result;
6374   symbol *tlbl;
6375
6376   D (emitcode (";", "genAndOp"));
6377
6378   /* note here that && operations that are in an
6379      if statement are taken away by backPatchLabels
6380      only those used in arthmetic operations remain */
6381   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6382   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6383   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6384
6385   /* if both are bit variables */
6386   if (AOP_TYPE (left) == AOP_CRY &&
6387       AOP_TYPE (right) == AOP_CRY)
6388     {
6389       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6390       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6391       outBitC (result);
6392     }
6393   else
6394     {
6395       tlbl = newiTempLabel (NULL);
6396       toBoolean (left);
6397       emitcode ("jz", "%05d$", tlbl->key + 100);
6398       toBoolean (right);
6399       emitLabel (tlbl);
6400       outBitAcc (result);
6401     }
6402
6403   freeAsmop (result, NULL, ic, TRUE);
6404   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6405   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6406 }
6407
6408
6409 /*-----------------------------------------------------------------*/
6410 /* genOrOp - for || operation                                      */
6411 /*-----------------------------------------------------------------*/
6412 static void
6413 genOrOp (iCode * ic)
6414 {
6415   operand *left, *right, *result;
6416   symbol *tlbl;
6417
6418   D (emitcode (";", "genOrOp"));
6419
6420   /* note here that || operations that are in an
6421      if statement are taken away by backPatchLabels
6422      only those used in arthmetic operations remain */
6423   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6424   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6425   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6426
6427   /* if both are bit variables */
6428   if (AOP_TYPE (left) == AOP_CRY &&
6429       AOP_TYPE (right) == AOP_CRY)
6430     {
6431       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6432       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6433       outBitC (result);
6434     }
6435   else
6436     {
6437       tlbl = newiTempLabel (NULL);
6438       toBoolean (left);
6439       emitcode ("jnz", "%05d$", tlbl->key + 100);
6440       toBoolean (right);
6441       emitLabel (tlbl);
6442       outBitAcc (result);
6443     }
6444
6445   freeAsmop (result, NULL, ic, TRUE);
6446   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6447   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6448 }
6449
6450 /*-----------------------------------------------------------------*/
6451 /* isLiteralBit - test if lit == 2^n                               */
6452 /*-----------------------------------------------------------------*/
6453 static int
6454 isLiteralBit (unsigned long lit)
6455 {
6456   unsigned long pw[32] =
6457   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6458    0x100L, 0x200L, 0x400L, 0x800L,
6459    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6460    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6461    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6462    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6463    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6464   int idx;
6465
6466   for (idx = 0; idx < 32; idx++)
6467     if (lit == pw[idx])
6468       return idx + 1;
6469   return 0;
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* continueIfTrue -                                                */
6474 /*-----------------------------------------------------------------*/
6475 static void
6476 continueIfTrue (iCode * ic)
6477 {
6478   if (IC_TRUE (ic))
6479     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6480   ic->generated = 1;
6481 }
6482
6483 /*-----------------------------------------------------------------*/
6484 /* jmpIfTrue -                                                     */
6485 /*-----------------------------------------------------------------*/
6486 static void
6487 jumpIfTrue (iCode * ic)
6488 {
6489   if (!IC_TRUE (ic))
6490     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6491   ic->generated = 1;
6492 }
6493
6494 /*-----------------------------------------------------------------*/
6495 /* jmpTrueOrFalse -                                                */
6496 /*-----------------------------------------------------------------*/
6497 static void
6498 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6499 {
6500   // ugly but optimized by peephole
6501   if (IC_TRUE (ic))
6502     {
6503       symbol *nlbl = newiTempLabel (NULL);
6504       emitcode ("sjmp", "%05d$", nlbl->key + 100);
6505       emitLabel (tlbl);
6506       freeForBranchAsmop (result);
6507       freeForBranchAsmop (right);
6508       freeForBranchAsmop (left);
6509       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6510       emitLabel (nlbl);
6511     }
6512   else
6513     {
6514       freeForBranchAsmop (result);
6515       freeForBranchAsmop (right);
6516       freeForBranchAsmop (left);
6517       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6518       emitLabel (tlbl);
6519     }
6520   ic->generated = 1;
6521 }
6522
6523 /*-----------------------------------------------------------------*/
6524 /* genAnd  - code for and                                          */
6525 /*-----------------------------------------------------------------*/
6526 static void
6527 genAnd (iCode * ic, iCode * ifx)
6528 {
6529   operand *left, *right, *result;
6530   int size, offset = 0;
6531   unsigned long lit = 0L;
6532   int bytelit = 0;
6533   char buffer[10];
6534
6535   D (emitcode (";", "genAnd"));
6536
6537   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6538   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6539   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6540
6541 #ifdef DEBUG_TYPE
6542   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6543             AOP_TYPE (result),
6544             AOP_TYPE (left), AOP_TYPE (right));
6545   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6546             AOP_SIZE (result),
6547             AOP_SIZE (left), AOP_SIZE (right));
6548 #endif
6549
6550   /* if left is a literal & right is not then exchange them */
6551   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6552       AOP_NEEDSACC (left))
6553     {
6554       operand *tmp = right;
6555       right = left;
6556       left = tmp;
6557     }
6558
6559   /* if result = right then exchange left and right */
6560   if (sameRegs (AOP (result), AOP (right)))
6561     {
6562       operand *tmp = right;
6563       right = left;
6564       left = tmp;
6565     }
6566
6567   /* if right is bit then exchange them */
6568   if (AOP_TYPE (right) == AOP_CRY &&
6569       AOP_TYPE (left) != AOP_CRY)
6570     {
6571       operand *tmp = right;
6572       right = left;
6573       left = tmp;
6574     }
6575   if (AOP_TYPE (right) == AOP_LIT)
6576     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6577
6578   size = AOP_SIZE (result);
6579
6580   // if(bit & yy)
6581   // result = bit & yy;
6582   if (AOP_TYPE (left) == AOP_CRY)
6583     {
6584       // c = bit & literal;
6585       if (AOP_TYPE (right) == AOP_LIT)
6586         {
6587           if (lit & 1)
6588             {
6589               if (size && sameRegs (AOP (result), AOP (left)))
6590                 // no change
6591                 goto release;
6592               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6593             }
6594           else
6595             {
6596               // bit(result) = 0;
6597               if (size && (AOP_TYPE (result) == AOP_CRY))
6598                 {
6599                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6600                   goto release;
6601                 }
6602               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6603                 {
6604                   jumpIfTrue (ifx);
6605                   goto release;
6606                 }
6607               emitcode ("clr", "c");
6608             }
6609         }
6610       else
6611         {
6612           if (AOP_TYPE (right) == AOP_CRY)
6613             {
6614               // c = bit & bit;
6615               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6616               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6617             }
6618           else
6619             {
6620               // c = bit & val;
6621               MOVA (aopGet (right, 0, FALSE, FALSE));
6622               // c = lsb
6623               emitcode ("rrc", "a");
6624               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6625             }
6626         }
6627       // bit = c
6628       // val = c
6629       if (size)
6630         outBitC (result);
6631       // if(bit & ...)
6632       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6633         genIfxJump (ifx, "c", left, right, result);
6634       goto release;
6635     }
6636
6637   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6638   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6639   if ((AOP_TYPE (right) == AOP_LIT) &&
6640       (AOP_TYPE (result) == AOP_CRY) &&
6641       (AOP_TYPE (left) != AOP_CRY))
6642     {
6643       int posbit = isLiteralBit (lit);
6644       /* left &  2^n */
6645       if (posbit)
6646         {
6647           posbit--;
6648           MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6649           // bit = left & 2^n
6650           if (size)
6651             {
6652               switch (posbit & 0x07)
6653                 {
6654                   case 0: emitcode ("rrc", "a");
6655                           break;
6656                   case 7: emitcode ("rlc", "a");
6657                           break;
6658                   default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6659                           break;
6660                 }
6661             }
6662           // if(left &  2^n)
6663           else
6664             {
6665               if (ifx)
6666                 {
6667                   SNPRINTF (buffer, sizeof(buffer),
6668                             "acc.%d", posbit & 0x07);
6669                   genIfxJump (ifx, buffer, left, right, result);
6670                 }
6671               else
6672                 {// what is this case? just found it in ds390/gen.c
6673                   emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6674                 }
6675               goto release;
6676             }
6677         }
6678       else
6679         {
6680           symbol *tlbl = newiTempLabel (NULL);
6681           int sizel = AOP_SIZE (left);
6682           if (size)
6683             emitcode ("setb", "c");
6684           while (sizel--)
6685             {
6686               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6687                 {
6688                   MOVA (aopGet (left, offset, FALSE, FALSE));
6689                   // byte ==  2^n ?
6690                   if ((posbit = isLiteralBit (bytelit)) != 0)
6691                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6692                   else
6693                     {
6694                       if (bytelit != 0x0FFL)
6695                         emitcode ("anl", "a,%s",
6696                                   aopGet (right, offset, FALSE, TRUE));
6697                       emitcode ("jnz", "%05d$", tlbl->key + 100);
6698                     }
6699                 }
6700               offset++;
6701             }
6702           // bit = left & literal
6703           if (size)
6704             {
6705               emitcode ("clr", "c");
6706               emitLabel (tlbl);
6707             }
6708           // if(left & literal)
6709           else
6710             {
6711               if (ifx)
6712                 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6713               else
6714                 emitLabel (tlbl);
6715               goto release;
6716             }
6717         }
6718       outBitC (result);
6719       goto release;
6720     }
6721
6722   /* if left is same as result */
6723   if (sameRegs (AOP (result), AOP (left)))
6724     {
6725       for (; size--; offset++)
6726         {
6727           if (AOP_TYPE (right) == AOP_LIT)
6728             {
6729               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6730               if (bytelit == 0x0FF)
6731                 {
6732                   /* dummy read of volatile operand */
6733                   if (isOperandVolatile (left, FALSE))
6734                     MOVA (aopGet (left, offset, FALSE, FALSE));
6735                   else
6736                     continue;
6737                 }
6738               else if (bytelit == 0)
6739                 {
6740                   aopPut (result, zero, offset);
6741                 }
6742               else if (IS_AOP_PREG (result))
6743                 {
6744                   MOVA (aopGet (left, offset, FALSE, TRUE));
6745                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6746                   aopPut (result, "a", offset);
6747                 }
6748               else
6749                 emitcode ("anl", "%s,%s",
6750                           aopGet (left, offset, FALSE, TRUE),
6751                           aopGet (right, offset, FALSE, FALSE));
6752             }
6753           else
6754             {
6755               if (AOP_TYPE (left) == AOP_ACC)
6756                 {
6757                   if (offset)
6758                     emitcode("mov", "a,b");
6759                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6760                 }
6761               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6762                 {
6763                   MOVB (aopGet (left, offset, FALSE, FALSE));
6764                   MOVA (aopGet (right, offset, FALSE, FALSE));
6765                   emitcode ("anl", "a,b");
6766                   aopPut (result, "a", offset);
6767                 }
6768               else if (aopGetUsesAcc (left, offset))
6769                 {
6770                   MOVA (aopGet (left, offset, FALSE, FALSE));
6771                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6772                   aopPut (result, "a", offset);
6773                 }
6774               else
6775                 {
6776                   MOVA (aopGet (right, offset, FALSE, FALSE));
6777                   if (IS_AOP_PREG (result))
6778                     {
6779                       emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6780                       aopPut (result, "a", offset);
6781                     }
6782                   else
6783                     emitcode ("anl", "%s,a", aopGet (left, offset, FALSE, TRUE));
6784                 }
6785             }
6786         }
6787     }
6788   else
6789     {
6790       // left & result in different registers
6791       if (AOP_TYPE (result) == AOP_CRY)
6792         {
6793           // result = bit
6794           // if(size), result in bit
6795           // if(!size && ifx), conditional oper: if(left & right)
6796           symbol *tlbl = newiTempLabel (NULL);
6797           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6798           if (size)
6799             emitcode ("setb", "c");
6800           while (sizer--)
6801             {
6802               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6803                   && AOP_TYPE(left)==AOP_ACC)
6804                 {
6805                   if (offset)
6806                     emitcode("mov", "a,b");
6807                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6808                 }
6809               else if (AOP_TYPE(left)==AOP_ACC)
6810                 {
6811                   if (!offset)
6812                     {
6813                       bool pushedB = pushB ();
6814                       emitcode("mov", "b,a");
6815                       MOVA (aopGet (right, offset, FALSE, FALSE));
6816                       emitcode("anl", "a,b");
6817                       popB (pushedB);
6818                     }
6819                   else
6820                     {
6821                       MOVA (aopGet (right, offset, FALSE, FALSE));
6822                       emitcode("anl", "a,b");
6823                     }
6824                 }
6825               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6826                 {
6827                   MOVB (aopGet (left, offset, FALSE, FALSE));
6828                   MOVA (aopGet (right, offset, FALSE, FALSE));
6829                   emitcode ("anl", "a,b");
6830                 }
6831               else if (aopGetUsesAcc (left, offset))
6832                 {
6833                   MOVA (aopGet (left, offset, FALSE, FALSE));
6834                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6835                     }
6836               else
6837                 {
6838                   MOVA (aopGet (right, offset, FALSE, FALSE));
6839                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6840                 }
6841
6842               emitcode ("jnz", "%05d$", tlbl->key + 100);
6843               offset++;
6844             }
6845           if (size)
6846             {
6847               CLRC;
6848               emitLabel (tlbl);
6849               outBitC (result);
6850             }
6851           else if (ifx)
6852             jmpTrueOrFalse (ifx, tlbl, left, right, result);
6853           else
6854             emitLabel (tlbl);
6855         }
6856       else
6857         {
6858           for (; (size--); offset++)
6859             {
6860               // normal case
6861               // result = left & right
6862               if (AOP_TYPE (right) == AOP_LIT)
6863                 {
6864                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6865                   if (bytelit == 0x0FF)
6866                     {
6867                       aopPut (result,
6868                               aopGet (left, offset, FALSE, FALSE),
6869                               offset);
6870                       continue;
6871                     }
6872                   else if (bytelit == 0)
6873                     {
6874                       /* dummy read of volatile operand */
6875                       if (isOperandVolatile (left, FALSE))
6876                         MOVA (aopGet (left, offset, FALSE, FALSE));
6877                       aopPut (result, zero, offset);
6878                       continue;
6879                     }
6880                   else if (AOP_TYPE (left) == AOP_ACC)
6881                     {
6882                       if (!offset)
6883                         {
6884                           emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6885                           aopPut (result, "a", offset);
6886                           continue;
6887                         }
6888                       else
6889                         {
6890                           emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6891                           aopPut (result, "b", offset);
6892                           continue;
6893                         }
6894                     }
6895                 }
6896               // faster than result <- left, anl result,right
6897               // and better if result is SFR
6898               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6899                   && AOP_TYPE(left)==AOP_ACC)
6900                 {
6901                   if (offset)
6902                     emitcode("mov", "a,b");
6903                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6904                 }
6905               else if (AOP_TYPE(left)==AOP_ACC)
6906                 {
6907                   if (!offset)
6908                     {
6909                       bool pushedB = pushB ();
6910                       emitcode("mov", "b,a");
6911                       MOVA (aopGet (right, offset, FALSE, FALSE));
6912                       emitcode("anl", "a,b");
6913                       popB (pushedB);
6914                     }
6915                   else
6916                     {
6917                       MOVA (aopGet (right, offset, FALSE, FALSE));
6918                       emitcode("anl", "a,b");
6919                     }
6920                 }
6921               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6922                 {
6923                   MOVB (aopGet (left, offset, FALSE, FALSE));
6924                   MOVA (aopGet (right, offset, FALSE, FALSE));
6925                   emitcode ("anl", "a,b");
6926                 }
6927               else if (aopGetUsesAcc (left, offset))
6928                 {
6929                   MOVA (aopGet (left, offset, FALSE, FALSE));
6930                   emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6931                 }
6932               else
6933                 {
6934                   MOVA (aopGet (right, offset, FALSE, FALSE));
6935                   emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6936                 }
6937               aopPut (result, "a", offset);
6938             }
6939         }
6940     }
6941
6942 release:
6943   freeAsmop (result, NULL, ic, TRUE);
6944   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6945   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6946 }
6947
6948 /*-----------------------------------------------------------------*/
6949 /* genOr  - code for or                                            */
6950 /*-----------------------------------------------------------------*/
6951 static void
6952 genOr (iCode * ic, iCode * ifx)
6953 {
6954   operand *left, *right, *result;
6955   int size, offset = 0;
6956   unsigned long lit = 0L;
6957   int bytelit = 0;
6958
6959   D (emitcode (";", "genOr"));
6960
6961   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6962   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6963   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6964
6965 #ifdef DEBUG_TYPE
6966   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6967             AOP_TYPE (result),
6968             AOP_TYPE (left), AOP_TYPE (right));
6969   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6970             AOP_SIZE (result),
6971             AOP_SIZE (left), AOP_SIZE (right));
6972 #endif
6973
6974   /* if left is a literal & right is not then exchange them */
6975   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6976       AOP_NEEDSACC (left))
6977     {
6978       operand *tmp = right;
6979       right = left;
6980       left = tmp;
6981     }
6982
6983   /* if result = right then exchange them */
6984   if (sameRegs (AOP (result), AOP (right)))
6985     {
6986       operand *tmp = right;
6987       right = left;
6988       left = tmp;
6989     }
6990
6991   /* if right is bit then exchange them */
6992   if (AOP_TYPE (right) == AOP_CRY &&
6993       AOP_TYPE (left) != AOP_CRY)
6994     {
6995       operand *tmp = right;
6996       right = left;
6997       left = tmp;
6998     }
6999   if (AOP_TYPE (right) == AOP_LIT)
7000     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7001
7002   size = AOP_SIZE (result);
7003
7004   // if(bit | yy)
7005   // xx = bit | yy;
7006   if (AOP_TYPE (left) == AOP_CRY)
7007     {
7008       if (AOP_TYPE (right) == AOP_LIT)
7009         {
7010           // c = bit | literal;
7011           if (lit)
7012             {
7013               // lit != 0 => result = 1
7014               if (AOP_TYPE (result) == AOP_CRY)
7015                 {
7016                   if (size)
7017                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7018                   else if (ifx)
7019                     continueIfTrue (ifx);
7020                   goto release;
7021                 }
7022               emitcode ("setb", "c");
7023             }
7024           else
7025             {
7026               // lit == 0 => result = left
7027               if (size && sameRegs (AOP (result), AOP (left)))
7028                 goto release;
7029               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7030             }
7031         }
7032       else
7033         {
7034           if (AOP_TYPE (right) == AOP_CRY)
7035             {
7036               // c = bit | bit;
7037               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7038               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
7039             }
7040           else
7041             {
7042               // c = bit | val;
7043               symbol *tlbl = newiTempLabel (NULL);
7044               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
7045                 emitcode ("setb", "c");
7046               emitcode ("jb", "%s,%05d$",
7047                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
7048               toBoolean (right);
7049               emitcode ("jnz", "%05d$", tlbl->key + 100);
7050               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7051                 {
7052                   jmpTrueOrFalse (ifx, tlbl, left, right, result);
7053                   goto release;
7054                 }
7055               else
7056                 {
7057                   CLRC;
7058                   emitLabel (tlbl);
7059                 }
7060             }
7061         }
7062       // bit = c
7063       // val = c
7064       if (size)
7065         outBitC (result);
7066       // if(bit | ...)
7067       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7068         genIfxJump (ifx, "c", left, right, result);
7069       goto release;
7070     }
7071
7072   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7073   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7074   if ((AOP_TYPE (right) == AOP_LIT) &&
7075       (AOP_TYPE (result) == AOP_CRY) &&
7076       (AOP_TYPE (left) != AOP_CRY))
7077     {
7078       if (lit)
7079         {
7080           // result = 1
7081           if (size)
7082             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7083           else
7084             continueIfTrue (ifx);
7085           goto release;
7086         }
7087       else
7088         {
7089           // lit = 0, result = boolean(left)
7090           if (size)
7091             emitcode ("setb", "c");
7092           toBoolean (right);
7093           if (size)
7094             {
7095               symbol *tlbl = newiTempLabel (NULL);
7096               emitcode ("jnz", "%05d$", tlbl->key + 100);
7097               CLRC;
7098               emitLabel (tlbl);
7099             }
7100           else
7101             {
7102               genIfxJump (ifx, "a", left, right, result);
7103               goto release;
7104             }
7105         }
7106       outBitC (result);
7107       goto release;
7108     }
7109
7110   /* if left is same as result */
7111   if (sameRegs (AOP (result), AOP (left)))
7112     {
7113       for (; size--; offset++)
7114         {
7115           if (AOP_TYPE (right) == AOP_LIT)
7116             {
7117               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7118               if (bytelit == 0)
7119                 {
7120                   /* dummy read of volatile operand */
7121                   if (isOperandVolatile (left, FALSE))
7122                     MOVA (aopGet (left, offset, FALSE, FALSE));
7123                   else
7124                     continue;
7125                 }
7126               else if (bytelit == 0x0FF)
7127                 {
7128                   aopPut (result, "#0xFF", offset);
7129                 }
7130               else if (IS_AOP_PREG (left))
7131                 {
7132                   MOVA (aopGet (left, offset, FALSE, TRUE));
7133                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7134                   aopPut (result, "a", offset);
7135                 }
7136               else
7137                 {
7138                   emitcode ("orl", "%s,%s",
7139                             aopGet (left, offset, FALSE, TRUE),
7140                             aopGet (right, offset, FALSE, FALSE));
7141                 }
7142             }
7143           else
7144             {
7145               if (AOP_TYPE (left) == AOP_ACC)
7146                 {
7147                   if (offset)
7148                     emitcode("mov", "a,b");
7149                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7150                 }
7151               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7152                 {
7153                   MOVB (aopGet (left, offset, FALSE, FALSE));
7154                   MOVA (aopGet (right, offset, FALSE, FALSE));
7155                   emitcode ("orl", "a,b");
7156                   aopPut (result, "a", offset);
7157                 }
7158               else if (aopGetUsesAcc (left, offset))
7159                 {
7160                   MOVA (aopGet (left, offset, FALSE, FALSE));
7161                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7162                   aopPut (result, "a", offset);
7163                 }
7164               else
7165                 {
7166                   MOVA (aopGet (right, offset, FALSE, FALSE));
7167                   if (IS_AOP_PREG (left))
7168                     {
7169                       emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7170                       aopPut (result, "a", offset);
7171                     }
7172                   else
7173                     {
7174                       emitcode ("orl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7175                     }
7176                 }
7177             }
7178         }
7179     }
7180   else
7181     {
7182       // left & result in different registers
7183       if (AOP_TYPE (result) == AOP_CRY)
7184         {
7185           // result = bit
7186           // if(size), result in bit
7187           // if(!size && ifx), conditional oper: if(left | right)
7188           symbol *tlbl = newiTempLabel (NULL);
7189           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7190           if (size)
7191             emitcode ("setb", "c");
7192           while (sizer--)
7193             {
7194               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7195                   && AOP_TYPE(left)==AOP_ACC)
7196                 {
7197                   if (offset)
7198                     emitcode("mov", "a,b");
7199                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7200                 }
7201               else if (AOP_TYPE(left)==AOP_ACC)
7202                 {
7203                   if (!offset)
7204                     {
7205                       bool pushedB = pushB ();
7206                       emitcode("mov", "b,a");
7207                       MOVA (aopGet (right, offset, FALSE, FALSE));
7208                       emitcode("orl", "a,b");
7209                       popB (pushedB);
7210                     }
7211                   else
7212                     {
7213                       MOVA (aopGet (right, offset, FALSE, FALSE));
7214                       emitcode("orl", "a,b");
7215                     }
7216                 }
7217               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7218                 {
7219                   MOVB (aopGet (left, offset, FALSE, FALSE));
7220                   MOVA (aopGet (right, offset, FALSE, FALSE));
7221                   emitcode ("orl", "a,b");
7222                 }
7223               else if (aopGetUsesAcc (left, offset))
7224                 {
7225                   MOVA (aopGet (left, offset, FALSE, FALSE));
7226                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7227                 }
7228               else
7229                 {
7230                   MOVA (aopGet (right, offset, FALSE, FALSE));
7231                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7232               }
7233
7234               emitcode ("jnz", "%05d$", tlbl->key + 100);
7235               offset++;
7236             }
7237           if (size)
7238             {
7239               CLRC;
7240               emitLabel (tlbl);
7241               outBitC (result);
7242             }
7243           else if (ifx)
7244             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7245           else
7246             emitLabel (tlbl);
7247         }
7248       else
7249         {
7250           for (; (size--); offset++)
7251             {
7252               // normal case
7253               // result = left | right
7254               if (AOP_TYPE (right) == AOP_LIT)
7255                 {
7256                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7257                   if (bytelit == 0)
7258                     {
7259                       aopPut (result,
7260                               aopGet (left, offset, FALSE, FALSE),
7261                               offset);
7262                       continue;
7263                     }
7264                   else if (bytelit == 0x0FF)
7265                     {
7266                       /* dummy read of volatile operand */
7267                       if (isOperandVolatile (left, FALSE))
7268                         MOVA (aopGet (left, offset, FALSE, FALSE));
7269                       aopPut (result, "#0xFF", offset);
7270                       continue;
7271                     }
7272                 }
7273               // faster than result <- left, orl result,right
7274               // and better if result is SFR
7275               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7276                   && AOP_TYPE(left)==AOP_ACC)
7277                 {
7278                   if (offset)
7279                     emitcode("mov", "a,b");
7280                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7281                 }
7282               else if (AOP_TYPE(left)==AOP_ACC)
7283                 {
7284                   if (!offset)
7285                     {
7286                       bool pushedB = pushB ();
7287                       emitcode("mov", "b,a");
7288                       MOVA (aopGet (right, offset, FALSE, FALSE));
7289                       emitcode("orl", "a,b");
7290                       popB (pushedB);
7291                     }
7292                   else
7293                     {
7294                       MOVA (aopGet (right, offset, FALSE, FALSE));
7295                       emitcode("orl", "a,b");
7296                     }
7297                 }
7298               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7299                 {
7300                   MOVB (aopGet (left, offset, FALSE, FALSE));
7301                   MOVA (aopGet (right, offset, FALSE, FALSE));
7302                   emitcode ("orl", "a,b");
7303                 }
7304               else if (aopGetUsesAcc (left, offset))
7305                 {
7306                   MOVA (aopGet (left, offset, FALSE, FALSE));
7307                   emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7308                 }
7309               else
7310                 {
7311                   MOVA (aopGet (right, offset, FALSE, FALSE));
7312                   emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7313                 }
7314               aopPut (result, "a", offset);
7315             }
7316         }
7317     }
7318
7319 release:
7320   freeAsmop (result, NULL, ic, TRUE);
7321   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7322   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7323 }
7324
7325 /*-----------------------------------------------------------------*/
7326 /* genXor - code for xclusive or                                   */
7327 /*-----------------------------------------------------------------*/
7328 static void
7329 genXor (iCode * ic, iCode * ifx)
7330 {
7331   operand *left, *right, *result;
7332   int size, offset = 0;
7333   unsigned long lit = 0L;
7334   int bytelit = 0;
7335
7336   D (emitcode (";", "genXor"));
7337
7338   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7339   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7340   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7341
7342 #ifdef DEBUG_TYPE
7343   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7344             AOP_TYPE (result),
7345             AOP_TYPE (left), AOP_TYPE (right));
7346   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7347             AOP_SIZE (result),
7348             AOP_SIZE (left), AOP_SIZE (right));
7349 #endif
7350
7351   /* if left is a literal & right is not ||
7352      if left needs acc & right does not */
7353   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7354       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7355     {
7356       operand *tmp = right;
7357       right = left;
7358       left = tmp;
7359     }
7360
7361   /* if result = right then exchange them */
7362   if (sameRegs (AOP (result), AOP (right)))
7363     {
7364       operand *tmp = right;
7365       right = left;
7366       left = tmp;
7367     }
7368
7369   /* if right is bit then exchange them */
7370   if (AOP_TYPE (right) == AOP_CRY &&
7371       AOP_TYPE (left) != AOP_CRY)
7372     {
7373       operand *tmp = right;
7374       right = left;
7375       left = tmp;
7376     }
7377   if (AOP_TYPE (right) == AOP_LIT)
7378     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7379
7380   size = AOP_SIZE (result);
7381
7382   // if(bit ^ yy)
7383   // xx = bit ^ yy;
7384   if (AOP_TYPE (left) == AOP_CRY)
7385     {
7386       if (AOP_TYPE (right) == AOP_LIT)
7387         {
7388           // c = bit & literal;
7389           if (lit >> 1)
7390             {
7391               // lit>>1  != 0 => result = 1
7392               if (AOP_TYPE (result) == AOP_CRY)
7393                 {
7394                   if (size)
7395                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7396                   else if (ifx)
7397                     continueIfTrue (ifx);
7398                   goto release;
7399                 }
7400               emitcode ("setb", "c");
7401             }
7402           else
7403             {
7404               // lit == (0 or 1)
7405               if (lit == 0)
7406                 {
7407                   // lit == 0, result = left
7408                   if (size && sameRegs (AOP (result), AOP (left)))
7409                     goto release;
7410                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7411                 }
7412               else
7413                 {
7414                   // lit == 1, result = not(left)
7415                   if (size && sameRegs (AOP (result), AOP (left)))
7416                     {
7417                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7418                       goto release;
7419                     }
7420                   else
7421                     {
7422                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7423                       emitcode ("cpl", "c");
7424                     }
7425                 }
7426             }
7427         }
7428       else
7429         {
7430           // right != literal
7431           symbol *tlbl = newiTempLabel (NULL);
7432           if (AOP_TYPE (right) == AOP_CRY)
7433             {
7434               // c = bit ^ bit;
7435               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7436             }
7437           else
7438             {
7439               int sizer = AOP_SIZE (right);
7440               // c = bit ^ val
7441               // if val>>1 != 0, result = 1
7442               emitcode ("setb", "c");
7443               while (sizer)
7444                 {
7445                   MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7446                   if (sizer == 1)
7447                     // test the msb of the lsb
7448                     emitcode ("anl", "a,#0xfe");
7449                   emitcode ("jnz", "%05d$", tlbl->key + 100);
7450                   sizer--;
7451                 }
7452               // val = (0,1)
7453               emitcode ("rrc", "a");
7454             }
7455           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7456           emitcode ("cpl", "c");
7457           emitLabel (tlbl);
7458         }
7459       // bit = c
7460       // val = c
7461       if (size)
7462         outBitC (result);
7463       // if(bit ^ ...)
7464       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7465         genIfxJump (ifx, "c", left, right, result);
7466       goto release;
7467     }
7468
7469   /* if left is same as result */
7470   if (sameRegs (AOP (result), AOP (left)))
7471     {
7472       for (; size--; offset++)
7473         {
7474           if (AOP_TYPE (right) == AOP_LIT)
7475             {
7476               bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7477               if (bytelit == 0)
7478                 {
7479                   /* dummy read of volatile operand */
7480                   if (isOperandVolatile (left, FALSE))
7481                     MOVA (aopGet (left, offset, FALSE, FALSE));
7482                   else
7483                     continue;
7484                 }
7485               else if (IS_AOP_PREG (left))
7486                 {
7487                   MOVA (aopGet (left, offset, FALSE, TRUE));
7488                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7489                   aopPut (result, "a", offset);
7490                 }
7491               else
7492                 {
7493                   emitcode ("xrl", "%s,%s",
7494                             aopGet (left, offset, FALSE, TRUE),
7495                             aopGet (right, offset, FALSE, FALSE));
7496                 }
7497             }
7498           else
7499             {
7500               if (AOP_TYPE (left) == AOP_ACC)
7501                 {
7502                   if (offset)
7503                     emitcode("mov", "a,b");
7504                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7505                 }
7506               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7507                 {
7508                   MOVB (aopGet (left, offset, FALSE, FALSE));
7509                   MOVA (aopGet (right, offset, FALSE, FALSE));
7510                   emitcode ("xrl", "a,b");
7511                   aopPut (result, "a", offset);
7512                 }
7513               else if (aopGetUsesAcc (left, offset))
7514                 {
7515                   MOVA (aopGet (left, offset, FALSE, FALSE));
7516                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7517                   aopPut (result, "a", offset);
7518                 }
7519               else
7520                 {
7521                   MOVA (aopGet (right, offset, FALSE, FALSE));
7522                   if (IS_AOP_PREG (left))
7523                     {
7524                       emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7525                       aopPut (result, "a", offset);
7526                     }
7527                   else
7528                     emitcode ("xrl", "%s,a", aopGet (left, offset, FALSE, TRUE));
7529                 }
7530             }
7531         }
7532     }
7533   else
7534     {
7535       // left & result in different registers
7536       if (AOP_TYPE (result) == AOP_CRY)
7537         {
7538           // result = bit
7539           // if(size), result in bit
7540           // if(!size && ifx), conditional oper: if(left ^ right)
7541           symbol *tlbl = newiTempLabel (NULL);
7542           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7543
7544           if (size)
7545             emitcode ("setb", "c");
7546           while (sizer--)
7547             {
7548               if ((AOP_TYPE (right) == AOP_LIT) &&
7549                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7550                 {
7551                   MOVA (aopGet (left, offset, FALSE, FALSE));
7552                 }
7553               else if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7554                   && AOP_TYPE(left)==AOP_ACC)
7555                 {
7556                   if (offset)
7557                     emitcode("mov", "a,b");
7558                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7559                 }
7560               else if (AOP_TYPE(left)==AOP_ACC)
7561                 {
7562                   if (!offset)
7563                     {
7564                       bool pushedB = pushB ();
7565                       emitcode("mov", "b,a");
7566                       MOVA (aopGet (right, offset, FALSE, FALSE));
7567                       emitcode("xrl", "a,b");
7568                       popB (pushedB);
7569                     }
7570                   else
7571                     {
7572                       MOVA (aopGet (right, offset, FALSE, FALSE));
7573                       emitcode("xrl", "a,b");
7574                     }
7575                 }
7576               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7577                 {
7578                   MOVB (aopGet (left, offset, FALSE, FALSE));
7579                   MOVA (aopGet (right, offset, FALSE, FALSE));
7580                   emitcode ("xrl", "a,b");
7581                 }
7582               else if (aopGetUsesAcc (left, offset))
7583                 {
7584                   MOVA (aopGet (left, offset, FALSE, FALSE));
7585                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7586                 }
7587               else
7588                 {
7589                   MOVA (aopGet (right, offset, FALSE, FALSE));
7590                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7591                 }
7592
7593               emitcode ("jnz", "%05d$", tlbl->key + 100);
7594               offset++;
7595             }
7596           if (size)
7597             {
7598               CLRC;
7599               emitLabel (tlbl);
7600               outBitC (result);
7601             }
7602           else if (ifx)
7603             jmpTrueOrFalse (ifx, tlbl, left, right, result);
7604         }
7605       else
7606         {
7607           for (; (size--); offset++)
7608             {
7609               // normal case
7610               // result = left ^ right
7611               if (AOP_TYPE (right) == AOP_LIT)
7612                 {
7613                   bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7614                   if (bytelit == 0)
7615                     {
7616                       aopPut (result,
7617                               aopGet (left, offset, FALSE, FALSE),
7618                               offset);
7619                       continue;
7620                     }
7621                 }
7622               // faster than result <- left, xrl result,right
7623               // and better if result is SFR
7624               if ((AOP_TYPE(right)==AOP_REG  || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
7625                   && AOP_TYPE(left)==AOP_ACC)
7626                 {
7627                   if (offset)
7628                     emitcode("mov", "a,b");
7629                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7630                 }
7631               else if (AOP_TYPE(left)==AOP_ACC)
7632                 {
7633                   if (!offset)
7634                     {
7635                       bool pushedB = pushB ();
7636                       emitcode("mov", "b,a");
7637                       MOVA (aopGet (right, offset, FALSE, FALSE));
7638                       emitcode("xrl", "a,b");
7639                       popB (pushedB);
7640                     }
7641                   else
7642                     {
7643                       MOVA (aopGet (right, offset, FALSE, FALSE));
7644                       emitcode("xrl", "a,b");
7645                     }
7646                 }
7647               else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7648                 {
7649                   MOVB (aopGet (left, offset, FALSE, FALSE));
7650                   MOVA (aopGet (right, offset, FALSE, FALSE));
7651                   emitcode ("xrl", "a,b");
7652                 }
7653               else if (aopGetUsesAcc (left, offset))
7654                 {
7655                   MOVA (aopGet (left, offset, FALSE, FALSE));
7656                   emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7657                 }
7658               else
7659                 {
7660                   MOVA (aopGet (right, offset, FALSE, FALSE));
7661                   emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7662                 }
7663               aopPut (result, "a", offset);
7664             }
7665         }
7666     }
7667
7668 release:
7669   freeAsmop (result, NULL, ic, TRUE);
7670   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7671   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7672 }
7673
7674 /*-----------------------------------------------------------------*/
7675 /* genInline - write the inline code out                           */
7676 /*-----------------------------------------------------------------*/
7677 static void
7678 genInline (iCode * ic)
7679 {
7680   char *buffer, *bp, *bp1;
7681
7682   D (emitcode (";", "genInline"));
7683
7684   _G.inLine += (!options.asmpeep);
7685
7686   buffer = bp = bp1 = Safe_strdup(IC_INLINE(ic));
7687
7688   /* emit each line as a code */
7689   while (*bp)
7690     {
7691       if (*bp == '\n')
7692         {
7693           *bp++ = '\0';
7694           emitcode (bp1, "");
7695           bp1 = bp;
7696         }
7697       else
7698         {
7699           /* Add \n for labels, not dirs such as c:\mydir */
7700           if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7701             {
7702               bp++;
7703               *bp = '\0';
7704               bp++;
7705               emitcode (bp1, "");
7706               bp1 = bp;
7707             }
7708           else
7709             bp++;
7710         }
7711     }
7712   if (bp1 != bp)
7713     emitcode (bp1, "");
7714   /*     emitcode("",buffer); */
7715   _G.inLine -= (!options.asmpeep);
7716 }
7717
7718 /*-----------------------------------------------------------------*/
7719 /* genRRC - rotate right with carry                                */
7720 /*-----------------------------------------------------------------*/
7721 static void
7722 genRRC (iCode * ic)
7723 {
7724   operand *left, *result;
7725   int size, offset;
7726   char *l;
7727
7728   D (emitcode (";", "genRRC"));
7729
7730   /* rotate right with carry */
7731   left = IC_LEFT (ic);
7732   result = IC_RESULT (ic);
7733   aopOp (left, ic, FALSE);
7734   aopOp (result, ic, FALSE);
7735
7736   /* move it to the result */
7737   size = AOP_SIZE (result);
7738   offset = size - 1;
7739   if (size == 1) { /* special case for 1 byte */
7740       l = aopGet (left, offset, FALSE, FALSE);
7741       MOVA (l);
7742       emitcode ("rr", "a");
7743       goto release;
7744   }
7745   /* no need to clear carry, bit7 will be written later */
7746   while (size--)
7747     {
7748       l = aopGet (left, offset, FALSE, FALSE);
7749       MOVA (l);
7750       emitcode ("rrc", "a");
7751       if (AOP_SIZE (result) > 1)
7752         aopPut (result, "a", offset--);
7753     }
7754   /* now we need to put the carry into the
7755      highest order byte of the result */
7756   if (AOP_SIZE (result) > 1)
7757     {
7758       l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7759       MOVA (l);
7760     }
7761   emitcode ("mov", "acc.7,c");
7762  release:
7763   aopPut (result, "a", AOP_SIZE (result) - 1);
7764   freeAsmop (result, NULL, ic, TRUE);
7765   freeAsmop (left, NULL, ic, TRUE);
7766 }
7767
7768 /*-----------------------------------------------------------------*/
7769 /* genRLC - generate code for rotate left with carry               */
7770 /*-----------------------------------------------------------------*/
7771 static void
7772 genRLC (iCode * ic)
7773 {
7774   operand *left, *result;
7775   int size, offset;
7776   char *l;
7777
7778   D (emitcode (";", "genRLC"));
7779
7780   /* rotate right with carry */
7781   left = IC_LEFT (ic);
7782   result = IC_RESULT (ic);
7783   aopOp (left, ic, FALSE);
7784   aopOp (result, ic, FALSE);
7785
7786   /* move it to the result */
7787   size = AOP_SIZE (result);
7788   offset = 0;
7789   if (size--)
7790     {
7791       l = aopGet (left, offset, FALSE, FALSE);
7792       MOVA (l);
7793       if (size == 0) { /* special case for 1 byte */
7794               emitcode("rl","a");
7795               goto release;
7796       }
7797       emitcode("rlc","a"); /* bit0 will be written later */
7798       if (AOP_SIZE (result) > 1)
7799         {
7800           aopPut (result, "a", offset++);
7801         }
7802
7803       while (size--)
7804         {
7805           l = aopGet (left, offset, FALSE, FALSE);
7806           MOVA (l);
7807           emitcode ("rlc", "a");
7808           if (AOP_SIZE (result) > 1)
7809             aopPut (result, "a", offset++);
7810         }
7811     }
7812   /* now we need to put the carry into the
7813      highest order byte of the result */
7814   if (AOP_SIZE (result) > 1)
7815     {
7816       l = aopGet (result, 0, FALSE, FALSE);
7817       MOVA (l);
7818     }
7819   emitcode ("mov", "acc.0,c");
7820  release:
7821   aopPut (result, "a", 0);
7822   freeAsmop (result, NULL, ic, TRUE);
7823   freeAsmop (left, NULL, ic, TRUE);
7824 }
7825
7826 /*-----------------------------------------------------------------*/
7827 /* genGetHbit - generates code get highest order bit               */
7828 /*-----------------------------------------------------------------*/
7829 static void
7830 genGetHbit (iCode * ic)
7831 {
7832   operand *left, *result;
7833
7834   D (emitcode (";", "genGetHbit"));
7835
7836   left = IC_LEFT (ic);
7837   result = IC_RESULT (ic);
7838   aopOp (left, ic, FALSE);
7839   aopOp (result, ic, FALSE);
7840
7841   /* get the highest order byte into a */
7842   MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7843   if (AOP_TYPE (result) == AOP_CRY)
7844     {
7845       emitcode ("rlc", "a");
7846       outBitC (result);
7847     }
7848   else
7849     {
7850       emitcode ("rl", "a");
7851       emitcode ("anl", "a,#0x01");
7852       outAcc (result);
7853     }
7854
7855   freeAsmop (result, NULL, ic, TRUE);
7856   freeAsmop (left, NULL, ic, TRUE);
7857 }
7858
7859 /*-----------------------------------------------------------------*/
7860 /* genGetAbit - generates code get a single bit                    */
7861 /*-----------------------------------------------------------------*/
7862 static void
7863 genGetAbit (iCode * ic)
7864 {
7865   operand *left, *right, *result;
7866   int shCount;
7867
7868   D (emitcode (";", "genGetAbit"));
7869
7870   left = IC_LEFT (ic);
7871   right = IC_RIGHT (ic);
7872   result = IC_RESULT (ic);
7873   aopOp (left, ic, FALSE);
7874   aopOp (right, ic, FALSE);
7875   aopOp (result, ic, FALSE);
7876
7877   shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7878
7879   /* get the needed byte into a */
7880   MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7881   shCount %= 8;
7882   if (AOP_TYPE (result) == AOP_CRY)
7883     {
7884       if ((shCount) == 7)
7885           emitcode ("rlc", "a");
7886       else if ((shCount) == 0)
7887           emitcode ("rrc", "a");
7888       else
7889           emitcode ("mov", "c,acc[%d]", shCount);
7890       outBitC (result);
7891     }
7892   else
7893     {
7894       switch (shCount)
7895         {
7896         case 2:
7897           emitcode ("rr", "a");
7898           //fallthrough
7899         case 1:
7900           emitcode ("rr", "a");
7901           //fallthrough
7902         case 0:
7903           emitcode ("anl", "a,#0x01");
7904           break;
7905         case 3:
7906         case 5:
7907           emitcode ("mov", "c,acc[%d]", shCount);
7908           emitcode ("clr", "a");
7909           emitcode ("rlc", "a");
7910           break;
7911         case 4:
7912           emitcode ("swap", "a");
7913           emitcode ("anl", "a,#0x01");
7914           break;
7915         case 6:
7916           emitcode ("rl", "a");
7917           //fallthrough
7918         case 7:
7919           emitcode ("rl", "a");
7920           emitcode ("anl", "a,#0x01");
7921           break;
7922         }
7923       outAcc (result);
7924     }
7925
7926   freeAsmop (result, NULL, ic, TRUE);
7927   freeAsmop (right, NULL, ic, TRUE);
7928   freeAsmop (left, NULL, ic, TRUE);
7929 }
7930
7931 /*-----------------------------------------------------------------*/
7932 /* genGetByte - generates code get a single byte                   */
7933 /*-----------------------------------------------------------------*/
7934 static void
7935 genGetByte (iCode * ic)
7936 {
7937   operand *left, *right, *result;
7938   int offset;
7939
7940   D (emitcode (";", "genGetByte"));
7941
7942   left = IC_LEFT (ic);
7943   right = IC_RIGHT (ic);
7944   result = IC_RESULT (ic);
7945   aopOp (left, ic, FALSE);
7946   aopOp (right, ic, FALSE);
7947   aopOp (result, ic, FALSE);
7948
7949   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7950   aopPut (result,
7951           aopGet (left, offset, FALSE, FALSE),
7952           0);
7953
7954   freeAsmop (result, NULL, ic, TRUE);
7955   freeAsmop (right, NULL, ic, TRUE);
7956   freeAsmop (left, NULL, ic, TRUE);
7957 }
7958
7959 /*-----------------------------------------------------------------*/
7960 /* genGetWord - generates code get two bytes                       */
7961 /*-----------------------------------------------------------------*/
7962 static void
7963 genGetWord (iCode * ic)
7964 {
7965   operand *left, *right, *result;
7966   int offset;
7967
7968   D (emitcode (";", "genGetWord"));
7969
7970   left = IC_LEFT (ic);
7971   right = IC_RIGHT (ic);
7972   result = IC_RESULT (ic);
7973   aopOp (left, ic, FALSE);
7974   aopOp (right, ic, FALSE);
7975   aopOp (result, ic, FALSE);
7976
7977   offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7978   aopPut (result,
7979           aopGet (left, offset, FALSE, FALSE),
7980           0);
7981   aopPut (result,
7982           aopGet (left, offset+1, FALSE, FALSE),
7983           1);
7984
7985   freeAsmop (result, NULL, ic, TRUE);
7986   freeAsmop (right, NULL, ic, TRUE);
7987   freeAsmop (left, NULL, ic, TRUE);
7988 }
7989
7990 /*-----------------------------------------------------------------*/
7991 /* genSwap - generates code to swap nibbles or bytes               */
7992 /*-----------------------------------------------------------------*/
7993 static void
7994 genSwap (iCode * ic)
7995 {
7996   operand *left, *result;
7997
7998   D(emitcode (";     genSwap",""));
7999
8000   left = IC_LEFT (ic);
8001   result = IC_RESULT (ic);
8002   aopOp (left, ic, FALSE);
8003   aopOp (result, ic, FALSE);
8004
8005   switch (AOP_SIZE (left))
8006     {
8007     case 1: /* swap nibbles in byte */
8008       MOVA (aopGet (left, 0, FALSE, FALSE));
8009       emitcode ("swap", "a");
8010       aopPut (result, "a", 0);
8011       break;
8012     case 2: /* swap bytes in word */
8013       if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
8014         {
8015           MOVA (aopGet (left, 0, FALSE, FALSE));
8016           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8017           aopPut (result, "a", 1);
8018         }
8019       else if (operandsEqu (left, result))
8020         {
8021           char * reg = "a";
8022           bool pushedB = FALSE, leftInB = FALSE;
8023
8024           MOVA (aopGet (left, 0, FALSE, FALSE));
8025           if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
8026             {
8027               pushedB = pushB ();
8028               emitcode ("mov", "b,a");
8029               reg = "b";
8030               leftInB = TRUE;
8031             }
8032           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8033           aopPut (result, reg, 1);
8034
8035           if (leftInB)
8036             popB (pushedB);
8037         }
8038       else
8039         {
8040           aopPut (result, aopGet (left, 1, FALSE, FALSE), 0);
8041           aopPut (result, aopGet (left, 0, FALSE, FALSE), 1);
8042         }
8043       break;
8044     default:
8045       wassertl(FALSE, "unsupported SWAP operand size");
8046     }
8047
8048   freeAsmop (result, NULL, ic, TRUE);
8049   freeAsmop (left, NULL, ic, TRUE);
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* AccRol - rotate left accumulator by known count                 */
8054 /*-----------------------------------------------------------------*/
8055 static void
8056 AccRol (int shCount)
8057 {
8058   shCount &= 0x0007;            // shCount : 0..7
8059
8060   switch (shCount)
8061     {
8062     case 0:
8063       break;
8064     case 1:
8065       emitcode ("rl", "a");
8066       break;
8067     case 2:
8068       emitcode ("rl", "a");
8069       emitcode ("rl", "a");
8070       break;
8071     case 3:
8072       emitcode ("swap", "a");
8073       emitcode ("rr", "a");
8074       break;
8075     case 4:
8076       emitcode ("swap", "a");
8077       break;
8078     case 5:
8079       emitcode ("swap", "a");
8080       emitcode ("rl", "a");
8081       break;
8082     case 6:
8083       emitcode ("rr", "a");
8084       emitcode ("rr", "a");
8085       break;
8086     case 7:
8087       emitcode ("rr", "a");
8088       break;
8089     }
8090 }
8091
8092 /*-----------------------------------------------------------------*/
8093 /* AccLsh - left shift accumulator by known count                  */
8094 /*-----------------------------------------------------------------*/
8095 static void
8096 AccLsh (int shCount)
8097 {
8098   if (shCount != 0)
8099     {
8100       if (shCount == 1)
8101         emitcode ("add", "a,acc");
8102       else if (shCount == 2)
8103         {
8104           emitcode ("add", "a,acc");
8105           emitcode ("add", "a,acc");
8106         }
8107       else
8108         {
8109           /* rotate left accumulator */
8110           AccRol (shCount);
8111           /* and kill the lower order bits */
8112           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
8113         }
8114     }
8115 }
8116
8117 /*-----------------------------------------------------------------*/
8118 /* AccRsh - right shift accumulator by known count                 */
8119 /*-----------------------------------------------------------------*/
8120 static void
8121 AccRsh (int shCount)
8122 {
8123   if (shCount != 0)
8124     {
8125       if (shCount == 1)
8126         {
8127           CLRC;
8128           emitcode ("rrc", "a");
8129         }
8130       else
8131         {
8132           /* rotate right accumulator */
8133           AccRol (8 - shCount);
8134           /* and kill the higher order bits */
8135           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8136         }
8137     }
8138 }
8139
8140 /*-----------------------------------------------------------------*/
8141 /* AccSRsh - signed right shift accumulator by known count                 */
8142 /*-----------------------------------------------------------------*/
8143 static void
8144 AccSRsh (int shCount)
8145 {
8146   symbol *tlbl;
8147   if (shCount != 0)
8148     {
8149       if (shCount == 1)
8150         {
8151           emitcode ("mov", "c,acc.7");
8152           emitcode ("rrc", "a");
8153         }
8154       else if (shCount == 2)
8155         {
8156           emitcode ("mov", "c,acc.7");
8157           emitcode ("rrc", "a");
8158           emitcode ("mov", "c,acc.7");
8159           emitcode ("rrc", "a");
8160         }
8161       else
8162         {
8163           tlbl = newiTempLabel (NULL);
8164           /* rotate right accumulator */
8165           AccRol (8 - shCount);
8166           /* and kill the higher order bits */
8167           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
8168           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8169           emitcode ("orl", "a,#0x%02x",
8170                     (unsigned char) ~SRMask[shCount]);
8171           emitLabel (tlbl);
8172         }
8173     }
8174 }
8175
8176 /*-----------------------------------------------------------------*/
8177 /* shiftR1Left2Result - shift right one byte from left to result   */
8178 /*-----------------------------------------------------------------*/
8179 static void
8180 shiftR1Left2Result (operand * left, int offl,
8181                     operand * result, int offr,
8182                     int shCount, int sign)
8183 {
8184   MOVA (aopGet (left, offl, FALSE, FALSE));
8185   /* shift right accumulator */
8186   if (sign)
8187     AccSRsh (shCount);
8188   else
8189     AccRsh (shCount);
8190   aopPut (result, "a", offr);
8191 }
8192
8193 /*-----------------------------------------------------------------*/
8194 /* shiftL1Left2Result - shift left one byte from left to result    */
8195 /*-----------------------------------------------------------------*/
8196 static void
8197 shiftL1Left2Result (operand * left, int offl,
8198                     operand * result, int offr, int shCount)
8199 {
8200   char *l;
8201   l = aopGet (left, offl, FALSE, FALSE);
8202   MOVA (l);
8203   /* shift left accumulator */
8204   AccLsh (shCount);
8205   aopPut (result, "a", offr);
8206 }
8207
8208 /*-----------------------------------------------------------------*/
8209 /* movLeft2Result - move byte from left to result                  */
8210 /*-----------------------------------------------------------------*/
8211 static void
8212 movLeft2Result (operand * left, int offl,
8213                 operand * result, int offr, int sign)
8214 {
8215   char *l;
8216   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
8217     {
8218       l = aopGet (left, offl, FALSE, FALSE);
8219
8220       if (*l == '@' && (IS_AOP_PREG (result)))
8221         {
8222           emitcode ("mov", "a,%s", l);
8223           aopPut (result, "a", offr);
8224         }
8225       else
8226         {
8227           if (!sign)
8228             {
8229               aopPut (result, l, offr);
8230             }
8231           else
8232             {
8233               /* MSB sign in acc.7 ! */
8234               if (getDataSize (left) == offl + 1)
8235                 {
8236                   MOVA (l);
8237                   aopPut (result, "a", offr);
8238                 }
8239             }
8240         }
8241     }
8242 }
8243
8244 /*-----------------------------------------------------------------*/
8245 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
8246 /*-----------------------------------------------------------------*/
8247 static void
8248 AccAXRrl1 (char *x)
8249 {
8250   emitcode ("rrc", "a");
8251   emitcode ("xch", "a,%s", x);
8252   emitcode ("rrc", "a");
8253   emitcode ("xch", "a,%s", x);
8254 }
8255
8256 /*-----------------------------------------------------------------*/
8257 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
8258 /*-----------------------------------------------------------------*/
8259 static void
8260 AccAXLrl1 (char *x)
8261 {
8262   emitcode ("xch", "a,%s", x);
8263   emitcode ("rlc", "a");
8264   emitcode ("xch", "a,%s", x);
8265   emitcode ("rlc", "a");
8266 }
8267
8268 /*-----------------------------------------------------------------*/
8269 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
8270 /*-----------------------------------------------------------------*/
8271 static void
8272 AccAXLsh1 (char *x)
8273 {
8274   emitcode ("xch", "a,%s", x);
8275   emitcode ("add", "a,acc");
8276   emitcode ("xch", "a,%s", x);
8277   emitcode ("rlc", "a");
8278 }
8279
8280 /*-----------------------------------------------------------------*/
8281 /* AccAXLsh - left shift a:x by known count (0..7)                 */
8282 /*-----------------------------------------------------------------*/
8283 static void
8284 AccAXLsh (char *x, int shCount)
8285 {
8286   switch (shCount)
8287     {
8288     case 0:
8289       break;
8290     case 1:
8291       AccAXLsh1 (x);
8292       break;
8293     case 2:
8294       AccAXLsh1 (x);
8295       AccAXLsh1 (x);
8296       break;
8297     case 3:
8298     case 4:
8299     case 5:                     // AAAAABBB:CCCCCDDD
8300
8301       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
8302
8303       emitcode ("anl", "a,#0x%02x",
8304                 SLMask[shCount]);       // BBB00000:CCCCCDDD
8305
8306       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
8307
8308       AccRol (shCount);         // DDDCCCCC:BBB00000
8309
8310       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
8311
8312       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
8313
8314       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
8315
8316       emitcode ("anl", "a,#0x%02x",
8317                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
8318
8319       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
8320
8321       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
8322
8323       break;
8324     case 6:                     // AAAAAABB:CCCCCCDD
8325       emitcode ("anl", "a,#0x%02x",
8326                 SRMask[shCount]);       // 000000BB:CCCCCCDD
8327       emitcode ("mov", "c,acc.0");      // c = B
8328       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
8329 #if 0 // REMOVE ME
8330       AccAXRrl1 (x);            // BCCCCCCD:D000000B
8331       AccAXRrl1 (x);            // BBCCCCCC:DD000000
8332 #else
8333       emitcode("rrc","a");
8334       emitcode("xch","a,%s", x);
8335       emitcode("rrc","a");
8336       emitcode("mov","c,acc.0"); //<< get correct bit
8337       emitcode("xch","a,%s", x);
8338
8339       emitcode("rrc","a");
8340       emitcode("xch","a,%s", x);
8341       emitcode("rrc","a");
8342       emitcode("xch","a,%s", x);
8343 #endif
8344       break;
8345     case 7:                     // a:x <<= 7
8346
8347       emitcode ("anl", "a,#0x%02x",
8348                 SRMask[shCount]);       // 0000000B:CCCCCCCD
8349
8350       emitcode ("mov", "c,acc.0");      // c = B
8351
8352       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
8353
8354       AccAXRrl1 (x);            // BCCCCCCC:D0000000
8355
8356       break;
8357     default:
8358       break;
8359     }
8360 }
8361
8362 /*-----------------------------------------------------------------*/
8363 /* AccAXRsh - right shift a:x known count (0..7)                   */
8364 /*-----------------------------------------------------------------*/
8365 static void
8366 AccAXRsh (char *x, int shCount)
8367 {
8368   switch (shCount)
8369     {
8370     case 0:
8371       break;
8372     case 1:
8373       CLRC;
8374       AccAXRrl1 (x);            // 0->a:x
8375
8376       break;
8377     case 2:
8378       CLRC;
8379       AccAXRrl1 (x);            // 0->a:x
8380
8381       CLRC;
8382       AccAXRrl1 (x);            // 0->a:x
8383
8384       break;
8385     case 3:
8386     case 4:
8387     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8388
8389       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
8390
8391       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8392
8393       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8394
8395       emitcode ("anl", "a,#0x%02x",
8396                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8397
8398       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8399
8400       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8401
8402       emitcode ("anl", "a,#0x%02x",
8403                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8404
8405       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8406
8407       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8408
8409       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
8410
8411       break;
8412     case 6:                     // AABBBBBB:CCDDDDDD
8413
8414       emitcode ("mov", "c,acc.7");
8415       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8416
8417       emitcode ("mov", "c,acc.7");
8418       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8419
8420       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8421
8422       emitcode ("anl", "a,#0x%02x",
8423                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8424
8425       break;
8426     case 7:                     // ABBBBBBB:CDDDDDDD
8427
8428       emitcode ("mov", "c,acc.7");      // c = A
8429
8430       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8431
8432       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8433
8434       emitcode ("anl", "a,#0x%02x",
8435                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8436
8437       break;
8438     default:
8439       break;
8440     }
8441 }
8442
8443 /*-----------------------------------------------------------------*/
8444 /* AccAXRshS - right shift signed a:x known count (0..7)           */
8445 /*-----------------------------------------------------------------*/
8446 static void
8447 AccAXRshS (char *x, int shCount)
8448 {
8449   symbol *tlbl;
8450   switch (shCount)
8451     {
8452     case 0:
8453       break;
8454     case 1:
8455       emitcode ("mov", "c,acc.7");
8456       AccAXRrl1 (x);            // s->a:x
8457
8458       break;
8459     case 2:
8460       emitcode ("mov", "c,acc.7");
8461       AccAXRrl1 (x);            // s->a:x
8462
8463       emitcode ("mov", "c,acc.7");
8464       AccAXRrl1 (x);            // s->a:x
8465
8466       break;
8467     case 3:
8468     case 4:
8469     case 5:                     // AAAAABBB:CCCCCDDD = a:x
8470
8471       tlbl = newiTempLabel (NULL);
8472       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
8473
8474       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
8475
8476       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
8477
8478       emitcode ("anl", "a,#0x%02x",
8479                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
8480
8481       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
8482
8483       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
8484
8485       emitcode ("anl", "a,#0x%02x",
8486                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
8487
8488       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
8489
8490       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
8491
8492       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
8493
8494       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8495       emitcode ("orl", "a,#0x%02x",
8496                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
8497
8498       emitLabel (tlbl);
8499       break;                    // SSSSAAAA:BBBCCCCC
8500
8501     case 6:                     // AABBBBBB:CCDDDDDD
8502
8503       tlbl = newiTempLabel (NULL);
8504       emitcode ("mov", "c,acc.7");
8505       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
8506
8507       emitcode ("mov", "c,acc.7");
8508       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
8509
8510       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
8511
8512       emitcode ("anl", "a,#0x%02x",
8513                 SRMask[shCount]);       // 000000AA:BBBBBBCC
8514
8515       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8516       emitcode ("orl", "a,#0x%02x",
8517                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
8518
8519       emitLabel (tlbl);
8520       break;
8521     case 7:                     // ABBBBBBB:CDDDDDDD
8522
8523       tlbl = newiTempLabel (NULL);
8524       emitcode ("mov", "c,acc.7");      // c = A
8525
8526       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
8527
8528       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
8529
8530       emitcode ("anl", "a,#0x%02x",
8531                 SRMask[shCount]);       // 0000000A:BBBBBBBC
8532
8533       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8534       emitcode ("orl", "a,#0x%02x",
8535                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
8536
8537       emitLabel (tlbl);
8538       break;
8539     default:
8540       break;
8541     }
8542 }
8543
8544 /*-----------------------------------------------------------------*/
8545 /* shiftL2Left2Result - shift left two bytes from left to result   */
8546 /*-----------------------------------------------------------------*/
8547 static void
8548 shiftL2Left2Result (operand * left, int offl,
8549                     operand * result, int offr, int shCount)
8550 {
8551   char * x;
8552   bool pushedB = FALSE;
8553   bool usedB = FALSE;
8554
8555   if (sameRegs (AOP (result), AOP (left)) &&
8556       ((offl + MSB16) == offr))
8557     {
8558       /* don't crash result[offr] */
8559       MOVA (aopGet (left, offl, FALSE, FALSE));
8560       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8561       usedB = !strncmp(x, "b", 1);
8562     }
8563   else if (aopGetUsesAcc (result, offr))
8564     {
8565       movLeft2Result (left, offl, result, offr, 0);
8566       pushedB = pushB ();
8567       usedB = TRUE;
8568       emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8569       MOVA (aopGet (result, offr, FALSE, FALSE));
8570       emitcode ("xch", "a,b");
8571       x = "b";
8572     }
8573   else
8574     {
8575       movLeft2Result (left, offl, result, offr, 0);
8576       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8577       x = aopGet (result, offr, FALSE, FALSE);
8578     }
8579   /* ax << shCount (x = lsb(result)) */
8580   AccAXLsh (x, shCount);
8581   if (usedB)
8582     {
8583       emitcode ("xch", "a,b");
8584       aopPut (result, "a", offr);
8585       aopPut (result, "b", offr + MSB16);
8586       popB (pushedB);
8587     }
8588   else
8589     {
8590       aopPut (result, "a", offr + MSB16);
8591     }
8592 }
8593
8594
8595 /*-----------------------------------------------------------------*/
8596 /* shiftR2Left2Result - shift right two bytes from left to result  */
8597 /*-----------------------------------------------------------------*/
8598 static void
8599 shiftR2Left2Result (operand * left, int offl,
8600                     operand * result, int offr,
8601                     int shCount, int sign)
8602 {
8603   char * x;
8604   bool pushedB = FALSE;
8605   bool usedB = FALSE;
8606
8607   if (sameRegs (AOP (result), AOP (left)) &&
8608       ((offl + MSB16) == offr))
8609     {
8610       /* don't crash result[offr] */
8611       MOVA (aopGet (left, offl, FALSE, FALSE));
8612       x = xch_a_aopGet (left, offl + MSB16, FALSE, FALSE);
8613       usedB = !strncmp(x, "b", 1);
8614     }
8615   else if (aopGetUsesAcc (result, offr))
8616     {
8617       movLeft2Result (left, offl, result, offr, 0);
8618       pushedB = pushB ();
8619       usedB = TRUE;
8620       emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8621       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8622       x = "b";
8623     }
8624   else
8625     {
8626       movLeft2Result (left, offl, result, offr, 0);
8627       MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8628       x = aopGet (result, offr, FALSE, FALSE);
8629     }
8630   /* a:x >> shCount (x = lsb(result)) */
8631   if (sign)
8632     AccAXRshS (x, shCount);
8633   else
8634     AccAXRsh (x, shCount);
8635   if (usedB)
8636     {
8637       emitcode ("xch", "a,b");
8638       aopPut (result, "a", offr);
8639       emitcode ("xch", "a,b");
8640       popB (pushedB);
8641     }
8642   if (getDataSize (result) > 1)
8643     aopPut (result, "a", offr + MSB16);
8644 }
8645
8646 /*-----------------------------------------------------------------*/
8647 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8648 /*-----------------------------------------------------------------*/
8649 static void
8650 shiftLLeftOrResult (operand * left, int offl,
8651                     operand * result, int offr, int shCount)
8652 {
8653   MOVA (aopGet (left, offl, FALSE, FALSE));
8654   /* shift left accumulator */
8655   AccLsh (shCount);
8656   /* or with result */
8657   if (aopGetUsesAcc (result, offr))
8658     {
8659       emitcode ("xch", "a,b");
8660       MOVA (aopGet (result, offr, FALSE, FALSE));
8661       emitcode ("orl", "a,b");
8662     }
8663   else
8664     {
8665       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8666     }
8667   /* back to result */
8668   aopPut (result, "a", offr);
8669 }
8670
8671 /*-----------------------------------------------------------------*/
8672 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8673 /*-----------------------------------------------------------------*/
8674 static void
8675 shiftRLeftOrResult (operand * left, int offl,
8676                     operand * result, int offr, int shCount)
8677 {
8678   MOVA (aopGet (left, offl, FALSE, FALSE));
8679   /* shift right accumulator */
8680   AccRsh (shCount);
8681   /* or with result */
8682   if (aopGetUsesAcc(result, offr))
8683     {
8684       emitcode ("xch", "a,b");
8685       MOVA (aopGet (result, offr, FALSE, FALSE));
8686       emitcode ("orl", "a,b");
8687     }
8688   else
8689     {
8690       emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8691     }
8692   /* back to result */
8693   aopPut (result, "a", offr);
8694 }
8695
8696 /*-----------------------------------------------------------------*/
8697 /* genlshOne - left shift a one byte quantity by known count       */
8698 /*-----------------------------------------------------------------*/
8699 static void
8700 genlshOne (operand * result, operand * left, int shCount)
8701 {
8702   D (emitcode (";", "genlshOne"));
8703
8704   shiftL1Left2Result (left, LSB, result, LSB, shCount);
8705 }
8706
8707 /*-----------------------------------------------------------------*/
8708 /* genlshTwo - left shift two bytes by known amount != 0           */
8709 /*-----------------------------------------------------------------*/
8710 static void
8711 genlshTwo (operand * result, operand * left, int shCount)
8712 {
8713   int size;
8714
8715   D (emitcode (";", "genlshTwo"));
8716
8717   size = getDataSize (result);
8718
8719   /* if shCount >= 8 */
8720   if (shCount >= 8)
8721     {
8722       shCount -= 8;
8723
8724       if (size > 1)
8725         {
8726           if (shCount)
8727             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8728           else
8729             movLeft2Result (left, LSB, result, MSB16, 0);
8730         }
8731       aopPut (result, zero, LSB);
8732     }
8733
8734   /*  1 <= shCount <= 7 */
8735   else
8736     {
8737       if (size == 1)
8738         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8739       else
8740         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8741     }
8742 }
8743
8744 /*-----------------------------------------------------------------*/
8745 /* shiftLLong - shift left one long from left to result            */
8746 /* offl = LSB or MSB16                                             */
8747 /*-----------------------------------------------------------------*/
8748 static void
8749 shiftLLong (operand * left, operand * result, int offr)
8750 {
8751   char *l;
8752   int size = AOP_SIZE (result);
8753
8754   if (size >= LSB + offr)
8755     {
8756       l = aopGet (left, LSB, FALSE, FALSE);
8757       MOVA (l);
8758       emitcode ("add", "a,acc");
8759       if (sameRegs (AOP (left), AOP (result)) &&
8760           size >= MSB16 + offr && offr != LSB)
8761         xch_a_aopGet (left, LSB + offr, FALSE, FALSE);
8762       else
8763         aopPut (result, "a", LSB + offr);
8764     }
8765
8766   if (size >= MSB16 + offr)
8767     {
8768       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8769         {
8770           l = aopGet (left, MSB16, FALSE, FALSE);
8771           MOVA (l);
8772         }
8773       emitcode ("rlc", "a");
8774       if (sameRegs (AOP (left), AOP (result)) &&
8775           size >= MSB24 + offr && offr != LSB)
8776         xch_a_aopGet (left, MSB16 + offr, FALSE, FALSE);
8777       else
8778         aopPut (result, "a", MSB16 + offr);
8779     }
8780
8781   if (size >= MSB24 + offr)
8782     {
8783       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8784         {
8785           l = aopGet (left, MSB24, FALSE, FALSE);
8786           MOVA (l);
8787         }
8788       emitcode ("rlc", "a");
8789       if (sameRegs (AOP (left), AOP (result)) &&
8790           size >= MSB32 + offr && offr != LSB)
8791         xch_a_aopGet (left, MSB24 + offr, FALSE, FALSE);
8792       else
8793         aopPut (result, "a", MSB24 + offr);
8794     }
8795
8796   if (size > MSB32 + offr)
8797     {
8798       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8799         {
8800           l = aopGet (left, MSB32, FALSE, FALSE);
8801           MOVA (l);
8802         }
8803       emitcode ("rlc", "a");
8804       aopPut (result, "a", MSB32 + offr);
8805     }
8806   if (offr != LSB)
8807     aopPut (result, zero, LSB);
8808 }
8809
8810 /*-----------------------------------------------------------------*/
8811 /* genlshFour - shift four byte by a known amount != 0             */
8812 /*-----------------------------------------------------------------*/
8813 static void
8814 genlshFour (operand * result, operand * left, int shCount)
8815 {
8816   int size;
8817
8818   D (emitcode (";", "genlshFour"));
8819
8820   size = AOP_SIZE (result);
8821
8822   /* if shifting more that 3 bytes */
8823   if (shCount >= 24)
8824     {
8825       shCount -= 24;
8826       if (shCount)
8827         /* lowest order of left goes to the highest
8828            order of the destination */
8829         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8830       else
8831         movLeft2Result (left, LSB, result, MSB32, 0);
8832       aopPut (result, zero, LSB);
8833       aopPut (result, zero, MSB16);
8834       aopPut (result, zero, MSB24);
8835       return;
8836     }
8837
8838   /* more than two bytes */
8839   else if (shCount >= 16)
8840     {
8841       /* lower order two bytes goes to higher order two bytes */
8842       shCount -= 16;
8843       /* if some more remaining */
8844       if (shCount)
8845         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8846       else
8847         {
8848           movLeft2Result (left, MSB16, result, MSB32, 0);
8849           movLeft2Result (left, LSB, result, MSB24, 0);
8850         }
8851       aopPut (result, zero, MSB16);
8852       aopPut (result, zero, LSB);
8853       return;
8854     }
8855
8856   /* if more than 1 byte */
8857   else if (shCount >= 8)
8858     {
8859       /* lower order three bytes goes to higher order  three bytes */
8860       shCount -= 8;
8861       if (size == 2)
8862         {
8863           if (shCount)
8864             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8865           else
8866             movLeft2Result (left, LSB, result, MSB16, 0);
8867         }
8868       else
8869         {                       /* size = 4 */
8870           if (shCount == 0)
8871             {
8872               movLeft2Result (left, MSB24, result, MSB32, 0);
8873               movLeft2Result (left, MSB16, result, MSB24, 0);
8874               movLeft2Result (left, LSB, result, MSB16, 0);
8875               aopPut (result, zero, LSB);
8876             }
8877           else if (shCount == 1)
8878             shiftLLong (left, result, MSB16);
8879           else
8880             {
8881               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8882               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8883               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8884               aopPut (result, zero, LSB);
8885             }
8886         }
8887     }
8888
8889   /* 1 <= shCount <= 7 */
8890   else if (shCount <= 2)
8891     {
8892       shiftLLong (left, result, LSB);
8893       if (shCount == 2)
8894         shiftLLong (result, result, LSB);
8895     }
8896   /* 3 <= shCount <= 7, optimize */
8897   else
8898     {
8899       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8900       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8901       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8902     }
8903 }
8904
8905 /*-----------------------------------------------------------------*/
8906 /* genLeftShiftLiteral - left shifting by known count              */
8907 /*-----------------------------------------------------------------*/
8908 static void
8909 genLeftShiftLiteral (operand * left,
8910                      operand * right,
8911                      operand * result,
8912                      iCode * ic)
8913 {
8914   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8915   int size;
8916
8917   D (emitcode (";", "genLeftShiftLiteral"));
8918
8919   freeAsmop (right, NULL, ic, TRUE);
8920
8921   aopOp (left, ic, FALSE);
8922   aopOp (result, ic, FALSE);
8923
8924   size = getSize (operandType (result));
8925
8926 #if VIEW_SIZE
8927   emitcode ("; shift left ", "result %d, left %d", size,
8928             AOP_SIZE (left));
8929 #endif
8930
8931   /* I suppose that the left size >= result size */
8932   if (shCount == 0)
8933     {
8934       while (size--)
8935         {
8936           movLeft2Result (left, size, result, size, 0);
8937         }
8938     }
8939   else if (shCount >= (size * 8))
8940     {
8941       while (size--)
8942         {
8943           aopPut (result, zero, size);
8944         }
8945     }
8946   else
8947     {
8948       switch (size)
8949         {
8950         case 1:
8951           genlshOne (result, left, shCount);
8952           break;
8953
8954         case 2:
8955           genlshTwo (result, left, shCount);
8956           break;
8957
8958         case 4:
8959           genlshFour (result, left, shCount);
8960           break;
8961         default:
8962           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8963                   "*** ack! mystery literal shift!\n");
8964           break;
8965         }
8966     }
8967   freeAsmop (result, NULL, ic, TRUE);
8968   freeAsmop (left, NULL, ic, TRUE);
8969 }
8970
8971 /*-----------------------------------------------------------------*/
8972 /* genLeftShift - generates code for left shifting                 */
8973 /*-----------------------------------------------------------------*/
8974 static void
8975 genLeftShift (iCode * ic)
8976 {
8977   operand *left, *right, *result;
8978   int size, offset;
8979   char *l;
8980   symbol *tlbl, *tlbl1;
8981   bool pushedB;
8982
8983   D (emitcode (";", "genLeftShift"));
8984
8985   right = IC_RIGHT (ic);
8986   left = IC_LEFT (ic);
8987   result = IC_RESULT (ic);
8988
8989   aopOp (right, ic, FALSE);
8990
8991   /* if the shift count is known then do it
8992      as efficiently as possible */
8993   if (AOP_TYPE (right) == AOP_LIT)
8994     {
8995       genLeftShiftLiteral (left, right, result, ic);
8996       return;
8997     }
8998
8999   /* shift count is unknown then we have to form
9000      a loop get the loop count in B : Note: we take
9001      only the lower order byte since shifting
9002      more that 32 bits make no sense anyway, ( the
9003      largest size of an object can be only 32 bits ) */
9004
9005   pushedB = pushB ();
9006   MOVB (aopGet (right, 0, FALSE, FALSE));
9007   emitcode ("inc", "b");
9008   freeAsmop (right, NULL, ic, TRUE);
9009   aopOp (left, ic, FALSE);
9010   aopOp (result, ic, FALSE);
9011
9012   /* now move the left to the result if they are not the same */
9013   if (!sameRegs (AOP (left), AOP (result)) &&
9014       AOP_SIZE (result) > 1)
9015     {
9016
9017       size = AOP_SIZE (result);
9018       offset = 0;
9019       while (size--)
9020         {
9021           l = aopGet (left, offset, FALSE, TRUE);
9022           if (*l == '@' && (IS_AOP_PREG (result)))
9023             {
9024
9025               emitcode ("mov", "a,%s", l);
9026               aopPut (result, "a", offset);
9027             }
9028           else
9029             aopPut (result, l, offset);
9030           offset++;
9031         }
9032     }
9033
9034   tlbl = newiTempLabel (NULL);
9035   size = AOP_SIZE (result);
9036   offset = 0;
9037   tlbl1 = newiTempLabel (NULL);
9038
9039   /* if it is only one byte then */
9040   if (size == 1)
9041     {
9042       symbol *tlbl1 = newiTempLabel (NULL);
9043
9044       l = aopGet (left, 0, FALSE, FALSE);
9045       MOVA (l);
9046       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9047       emitLabel (tlbl);
9048       emitcode ("add", "a,acc");
9049       emitLabel (tlbl1);
9050       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9051       popB (pushedB);
9052       aopPut (result, "a", 0);
9053       goto release;
9054     }
9055
9056   reAdjustPreg (AOP (result));
9057
9058   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9059   emitLabel (tlbl);
9060   l = aopGet (result, offset, FALSE, FALSE);
9061   MOVA (l);
9062   emitcode ("add", "a,acc");
9063   aopPut (result, "a", offset++);
9064   while (--size)
9065     {
9066       l = aopGet (result, offset, FALSE, FALSE);
9067       MOVA (l);
9068       emitcode ("rlc", "a");
9069       aopPut (result, "a", offset++);
9070     }
9071   reAdjustPreg (AOP (result));
9072
9073   emitLabel (tlbl1);
9074   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9075   popB (pushedB);
9076 release:
9077   freeAsmop (result, NULL, ic, TRUE);
9078   freeAsmop (left, NULL, ic, TRUE);
9079 }
9080
9081 /*-----------------------------------------------------------------*/
9082 /* genrshOne - right shift a one byte quantity by known count      */
9083 /*-----------------------------------------------------------------*/
9084 static void
9085 genrshOne (operand * result, operand * left,
9086            int shCount, int sign)
9087 {
9088   D (emitcode (";", "genrshOne"));
9089
9090   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
9091 }
9092
9093 /*-----------------------------------------------------------------*/
9094 /* genrshTwo - right shift two bytes by known amount != 0          */
9095 /*-----------------------------------------------------------------*/
9096 static void
9097 genrshTwo (operand * result, operand * left,
9098            int shCount, int sign)
9099 {
9100   D (emitcode (";", "genrshTwo"));
9101
9102   /* if shCount >= 8 */
9103   if (shCount >= 8)
9104     {
9105       shCount -= 8;
9106       if (shCount)
9107         shiftR1Left2Result (left, MSB16, result, LSB, shCount, sign);
9108       else
9109         movLeft2Result (left, MSB16, result, LSB, sign);
9110       addSign (result, MSB16, sign);
9111     }
9112
9113   /*  1 <= shCount <= 7 */
9114   else
9115     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
9116 }
9117
9118 /*-----------------------------------------------------------------*/
9119 /* shiftRLong - shift right one long from left to result           */
9120 /* offl = LSB or MSB16                                             */
9121 /*-----------------------------------------------------------------*/
9122 static void
9123 shiftRLong (operand * left, int offl,
9124             operand * result, int sign)
9125 {
9126   bool overlapping = regsInCommon (left, result) || operandsEqu(left, result);
9127
9128   if (overlapping && offl>1)
9129     {
9130       // we are in big trouble, but this shouldn't happen
9131       werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
9132     }
9133
9134   MOVA (aopGet (left, MSB32, FALSE, FALSE));
9135
9136   if (offl==MSB16)
9137     {
9138       // shift is > 8
9139       if (sign)
9140         {
9141           emitcode ("rlc", "a");
9142           emitcode ("subb", "a,acc");
9143           if (overlapping && sameByte (AOP (left), MSB32, AOP (result), MSB32))
9144             {
9145               xch_a_aopGet (left, MSB32, FALSE, FALSE);
9146             }
9147           else
9148             {
9149               aopPut (result, "a", MSB32);
9150               MOVA (aopGet (left, MSB32, FALSE, FALSE));
9151             }
9152         }
9153       else
9154         {
9155           if (aopPutUsesAcc (result, zero, MSB32))
9156             {
9157               emitcode("xch", "a,b");
9158               aopPut (result, zero, MSB32);
9159               emitcode("xch", "a,b");
9160             }
9161           else
9162             {
9163               aopPut (result, zero, MSB32);
9164             }
9165         }
9166     }
9167
9168   if (!sign)
9169     {
9170       emitcode ("clr", "c");
9171     }
9172   else
9173     {
9174       emitcode ("mov", "c,acc.7");
9175     }
9176
9177   emitcode ("rrc", "a");
9178
9179   if (overlapping && offl==MSB16 &&
9180       sameByte (AOP (left), MSB24, AOP (result), MSB32-offl))
9181     {
9182       xch_a_aopGet (left, MSB24, FALSE, FALSE);
9183     }
9184   else
9185     {
9186       aopPut (result, "a", MSB32 - offl);
9187       MOVA (aopGet (left, MSB24, FALSE, FALSE));
9188     }
9189
9190   emitcode ("rrc", "a");
9191   if (overlapping && offl==MSB16 &&
9192       sameByte (AOP (left), MSB16, AOP (result), MSB24-offl))
9193     {
9194       xch_a_aopGet (left, MSB16, FALSE, FALSE);
9195     }
9196   else
9197     {
9198       aopPut (result, "a", MSB24 - offl);
9199       MOVA (aopGet (left, MSB16, FALSE, FALSE));
9200     }
9201
9202   emitcode ("rrc", "a");
9203   if (offl != LSB)
9204     {
9205       aopPut (result, "a", MSB16 - offl);
9206     }
9207   else
9208     {
9209       if (overlapping &&
9210           sameByte (AOP (left), LSB, AOP (result), MSB16-offl))
9211         {
9212           xch_a_aopGet (left, LSB, FALSE, FALSE);
9213         }
9214       else
9215         {
9216           aopPut (result, "a", MSB16 - offl);
9217           MOVA (aopGet (left, LSB, FALSE, FALSE));
9218         }
9219       emitcode ("rrc", "a");
9220       aopPut (result, "a", LSB);
9221     }
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genrshFour - shift four byte by a known amount != 0             */
9226 /*-----------------------------------------------------------------*/
9227 static void
9228 genrshFour (operand * result, operand * left,
9229             int shCount, int sign)
9230 {
9231   D (emitcode (";", "genrshFour"));
9232
9233   /* if shifting more that 3 bytes */
9234   if (shCount >= 24)
9235     {
9236       shCount -= 24;
9237       if (shCount)
9238         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
9239       else
9240         movLeft2Result (left, MSB32, result, LSB, sign);
9241       addSign (result, MSB16, sign);
9242     }
9243   else if (shCount >= 16)
9244     {
9245       shCount -= 16;
9246       if (shCount)
9247         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
9248       else
9249         {
9250           movLeft2Result (left, MSB24, result, LSB, 0);
9251           movLeft2Result (left, MSB32, result, MSB16, sign);
9252         }
9253       addSign (result, MSB24, sign);
9254     }
9255   else if (shCount >= 8)
9256     {
9257       shCount -= 8;
9258       if (shCount == 1)
9259         {
9260           shiftRLong (left, MSB16, result, sign);
9261         }
9262       else if (shCount == 0)
9263         {
9264           movLeft2Result (left, MSB16, result, LSB, 0);
9265           movLeft2Result (left, MSB24, result, MSB16, 0);
9266           movLeft2Result (left, MSB32, result, MSB24, sign);
9267           addSign (result, MSB32, sign);
9268         }
9269       else
9270         {
9271           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
9272           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
9273           /* the last shift is signed */
9274           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
9275           addSign (result, MSB32, sign);
9276         }
9277     }
9278   else
9279     {
9280       /* 1 <= shCount <= 7 */
9281       if (shCount <= 2)
9282         {
9283           shiftRLong (left, LSB, result, sign);
9284           if (shCount == 2)
9285             shiftRLong (result, LSB, result, sign);
9286         }
9287       else
9288         {
9289           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
9290           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
9291           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
9292         }
9293     }
9294 }
9295
9296 /*-----------------------------------------------------------------*/
9297 /* genRightShiftLiteral - right shifting by known count            */
9298 /*-----------------------------------------------------------------*/
9299 static void
9300 genRightShiftLiteral (operand * left,
9301                       operand * right,
9302                       operand * result,
9303                       iCode * ic,
9304                       int sign)
9305 {
9306   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9307   int size;
9308
9309   D (emitcode (";", "genRightShiftLiteral"));
9310
9311   freeAsmop (right, NULL, ic, TRUE);
9312
9313   aopOp (left, ic, FALSE);
9314   aopOp (result, ic, FALSE);
9315
9316 #if VIEW_SIZE
9317   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
9318             AOP_SIZE (left));
9319 #endif
9320
9321   size = getDataSize (left);
9322   /* test the LEFT size !!! */
9323
9324   /* I suppose that the left size >= result size */
9325   if (shCount == 0)
9326     {
9327       size = getDataSize (result);
9328       while (size--)
9329         movLeft2Result (left, size, result, size, 0);
9330     }
9331
9332   else if (shCount >= (size * 8))
9333     {
9334       if (sign)
9335         {
9336           /* get sign in acc.7 */
9337           MOVA (aopGet (left, size - 1, FALSE, FALSE));
9338         }
9339       addSign (result, LSB, sign);
9340     }
9341   else
9342     {
9343       switch (size)
9344         {
9345         case 1:
9346           genrshOne (result, left, shCount, sign);
9347           break;
9348
9349         case 2:
9350           genrshTwo (result, left, shCount, sign);
9351           break;
9352
9353         case 4:
9354           genrshFour (result, left, shCount, sign);
9355           break;
9356         default:
9357           break;
9358         }
9359     }
9360   freeAsmop (result, NULL, ic, TRUE);
9361   freeAsmop (left, NULL, ic, TRUE);
9362 }
9363
9364 /*-----------------------------------------------------------------*/
9365 /* genSignedRightShift - right shift of signed number              */
9366 /*-----------------------------------------------------------------*/
9367 static void
9368 genSignedRightShift (iCode * ic)
9369 {
9370   operand *right, *left, *result;
9371   int size, offset;
9372   char *l;
9373   symbol *tlbl, *tlbl1;
9374   bool pushedB;
9375
9376   D (emitcode (";", "genSignedRightShift"));
9377
9378   /* we do it the hard way put the shift count in b
9379      and loop thru preserving the sign */
9380
9381   right = IC_RIGHT (ic);
9382   left = IC_LEFT (ic);
9383   result = IC_RESULT (ic);
9384
9385   aopOp (right, ic, FALSE);
9386
9387
9388   if (AOP_TYPE (right) == AOP_LIT)
9389     {
9390       genRightShiftLiteral (left, right, result, ic, 1);
9391       return;
9392     }
9393   /* shift count is unknown then we have to form
9394      a loop get the loop count in B : Note: we take
9395      only the lower order byte since shifting
9396      more that 32 bits make no sense anyway, ( the
9397      largest size of an object can be only 32 bits ) */
9398
9399   pushedB = pushB ();
9400   MOVB (aopGet (right, 0, FALSE, FALSE));
9401   emitcode ("inc", "b");
9402   freeAsmop (right, NULL, ic, TRUE);
9403   aopOp (left, ic, FALSE);
9404   aopOp (result, ic, FALSE);
9405
9406   /* now move the left to the result if they are not the
9407      same */
9408   if (!sameRegs (AOP (left), AOP (result)) &&
9409       AOP_SIZE (result) > 1)
9410     {
9411
9412       size = AOP_SIZE (result);
9413       offset = 0;
9414       while (size--)
9415         {
9416           l = aopGet (left, offset, FALSE, TRUE);
9417           if (*l == '@' && IS_AOP_PREG (result))
9418             {
9419
9420               emitcode ("mov", "a,%s", l);
9421               aopPut (result, "a", offset);
9422             }
9423           else
9424             aopPut (result, l, offset);
9425           offset++;
9426         }
9427     }
9428
9429   /* mov the highest order bit to OVR */
9430   tlbl = newiTempLabel (NULL);
9431   tlbl1 = newiTempLabel (NULL);
9432
9433   size = AOP_SIZE (result);
9434   offset = size - 1;
9435   MOVA (aopGet (left, offset, FALSE, FALSE));
9436   emitcode ("rlc", "a");
9437   emitcode ("mov", "ov,c");
9438   /* if it is only one byte then */
9439   if (size == 1)
9440     {
9441       l = aopGet (left, 0, FALSE, FALSE);
9442       MOVA (l);
9443       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9444       emitLabel (tlbl);
9445       emitcode ("mov", "c,ov");
9446       emitcode ("rrc", "a");
9447       emitLabel (tlbl1);
9448       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9449       popB (pushedB);
9450       aopPut (result, "a", 0);
9451       goto release;
9452     }
9453
9454   reAdjustPreg (AOP (result));
9455   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9456   emitLabel (tlbl);
9457   emitcode ("mov", "c,ov");
9458   while (size--)
9459     {
9460       l = aopGet (result, offset, FALSE, FALSE);
9461       MOVA (l);
9462       emitcode ("rrc", "a");
9463       aopPut (result, "a", offset--);
9464     }
9465   reAdjustPreg (AOP (result));
9466   emitLabel (tlbl1);
9467   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9468   popB (pushedB);
9469
9470 release:
9471   freeAsmop (result, NULL, ic, TRUE);
9472   freeAsmop (left, NULL, ic, TRUE);
9473 }
9474
9475 /*-----------------------------------------------------------------*/
9476 /* genRightShift - generate code for right shifting                */
9477 /*-----------------------------------------------------------------*/
9478 static void
9479 genRightShift (iCode * ic)
9480 {
9481   operand *right, *left, *result;
9482   sym_link *letype;
9483   int size, offset;
9484   char *l;
9485   symbol *tlbl, *tlbl1;
9486   bool pushedB;
9487
9488   D (emitcode (";", "genRightShift"));
9489
9490   /* if signed then we do it the hard way preserve the
9491      sign bit moving it inwards */
9492   letype = getSpec (operandType (IC_LEFT (ic)));
9493
9494   if (!SPEC_USIGN (letype))
9495     {
9496       genSignedRightShift (ic);
9497       return;
9498     }
9499
9500   /* signed & unsigned types are treated the same : i.e. the
9501      signed is NOT propagated inwards : quoting from the
9502      ANSI - standard : "for E1 >> E2, is equivalent to division
9503      by 2**E2 if unsigned or if it has a non-negative value,
9504      otherwise the result is implementation defined ", MY definition
9505      is that the sign does not get propagated */
9506
9507   right = IC_RIGHT (ic);
9508   left = IC_LEFT (ic);
9509   result = IC_RESULT (ic);
9510
9511   aopOp (right, ic, FALSE);
9512
9513   /* if the shift count is known then do it
9514      as efficiently as possible */
9515   if (AOP_TYPE (right) == AOP_LIT)
9516     {
9517       genRightShiftLiteral (left, right, result, ic, 0);
9518       return;
9519     }
9520
9521   /* shift count is unknown then we have to form
9522      a loop get the loop count in B : Note: we take
9523      only the lower order byte since shifting
9524      more that 32 bits make no sense anyway, ( the
9525      largest size of an object can be only 32 bits ) */
9526
9527   pushedB = pushB ();
9528   MOVB (aopGet (right, 0, FALSE, FALSE));
9529   emitcode ("inc", "b");
9530   freeAsmop (right, NULL, ic, TRUE);
9531   aopOp (left, ic, FALSE);
9532   aopOp (result, ic, FALSE);
9533
9534   /* now move the left to the result if they are not the
9535      same */
9536   if (!sameRegs (AOP (left), AOP (result)) &&
9537       AOP_SIZE (result) > 1)
9538     {
9539       size = AOP_SIZE (result);
9540       offset = 0;
9541       while (size--)
9542         {
9543           l = aopGet (left, offset, FALSE, TRUE);
9544           if (*l == '@' && IS_AOP_PREG (result))
9545             {
9546
9547               emitcode ("mov", "a,%s", l);
9548               aopPut (result, "a", offset);
9549             }
9550           else
9551             aopPut (result, l, offset);
9552           offset++;
9553         }
9554     }
9555
9556   tlbl = newiTempLabel (NULL);
9557   tlbl1 = newiTempLabel (NULL);
9558   size = AOP_SIZE (result);
9559   offset = size - 1;
9560
9561   /* if it is only one byte then */
9562   if (size == 1)
9563     {
9564       l = aopGet (left, 0, FALSE, FALSE);
9565       MOVA (l);
9566       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9567       emitLabel (tlbl);
9568       CLRC;
9569       emitcode ("rrc", "a");
9570       emitLabel (tlbl1);
9571       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9572       popB (pushedB);
9573       aopPut (result, "a", 0);
9574       goto release;
9575     }
9576
9577   reAdjustPreg (AOP (result));
9578   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9579   emitLabel (tlbl);
9580   CLRC;
9581   while (size--)
9582     {
9583       l = aopGet (result, offset, FALSE, FALSE);
9584       MOVA (l);
9585       emitcode ("rrc", "a");
9586       aopPut (result, "a", offset--);
9587     }
9588   reAdjustPreg (AOP (result));
9589
9590   emitLabel (tlbl1);
9591   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9592   popB (pushedB);
9593
9594 release:
9595   freeAsmop (result, NULL, ic, TRUE);
9596   freeAsmop (left, NULL, ic, TRUE);
9597 }
9598
9599 /*-----------------------------------------------------------------*/
9600 /* emitPtrByteGet - emits code to get a byte into A through a      */
9601 /*                  pointer register (R0, R1, or DPTR). The        */
9602 /*                  original value of A can be preserved in B.     */
9603 /*-----------------------------------------------------------------*/
9604 static void
9605 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9606 {
9607   switch (p_type)
9608     {
9609     case IPOINTER:
9610     case POINTER:
9611       if (preserveAinB)
9612         emitcode ("mov", "b,a");
9613       emitcode ("mov", "a,@%s", rname);
9614       break;
9615
9616     case PPOINTER:
9617       if (preserveAinB)
9618         emitcode ("mov", "b,a");
9619       emitcode ("movx", "a,@%s", rname);
9620       break;
9621
9622     case FPOINTER:
9623       if (preserveAinB)
9624         emitcode ("mov", "b,a");
9625       emitcode ("movx", "a,@dptr");
9626       break;
9627
9628     case CPOINTER:
9629       if (preserveAinB)
9630         emitcode ("mov", "b,a");
9631       emitcode ("clr", "a");
9632       emitcode ("movc", "a,@a+dptr");
9633       break;
9634
9635     case GPOINTER:
9636       if (preserveAinB)
9637         {
9638           emitcode ("push", "b");
9639           emitcode ("push", "acc");
9640         }
9641       emitcode ("lcall", "__gptrget");
9642       if (preserveAinB)
9643         emitcode ("pop", "b");
9644       break;
9645     }
9646 }
9647
9648 /*-----------------------------------------------------------------*/
9649 /* emitPtrByteSet - emits code to set a byte from src through a    */
9650 /*                  pointer register (R0, R1, or DPTR).            */
9651 /*-----------------------------------------------------------------*/
9652 static void
9653 emitPtrByteSet (char *rname, int p_type, char *src)
9654 {
9655   switch (p_type)
9656     {
9657     case IPOINTER:
9658     case POINTER:
9659       if (*src=='@')
9660         {
9661           MOVA (src);
9662           emitcode ("mov", "@%s,a", rname);
9663         }
9664       else
9665         emitcode ("mov", "@%s,%s", rname, src);
9666       break;
9667
9668     case PPOINTER:
9669       MOVA (src);
9670       emitcode ("movx", "@%s,a", rname);
9671       break;
9672
9673     case FPOINTER:
9674       MOVA (src);
9675       emitcode ("movx", "@dptr,a");
9676       break;
9677
9678     case GPOINTER:
9679       MOVA (src);
9680       emitcode ("lcall", "__gptrput");
9681       break;
9682     }
9683 }
9684
9685 /*-----------------------------------------------------------------*/
9686 /* genUnpackBits - generates code for unpacking bits               */
9687 /*-----------------------------------------------------------------*/
9688 static void
9689 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9690 {
9691   int offset = 0;       /* result byte offset */
9692   int rsize;            /* result size */
9693   int rlen = 0;         /* remaining bitfield length */
9694   sym_link *etype;      /* bitfield type information */
9695   int blen;             /* bitfield length */
9696   int bstr;             /* bitfield starting bit within byte */
9697   char buffer[10];
9698
9699   D(emitcode (";     genUnpackBits",""));
9700
9701   etype = getSpec (operandType (result));
9702   rsize = getSize (operandType (result));
9703   blen = SPEC_BLEN (etype);
9704   bstr = SPEC_BSTR (etype);
9705
9706   if (ifx && blen <= 8)
9707     {
9708       emitPtrByteGet (rname, ptype, FALSE);
9709       if (blen == 1)
9710         {
9711           SNPRINTF (buffer, sizeof(buffer),
9712                     "acc.%d", bstr);
9713           genIfxJump (ifx, buffer, NULL, NULL, NULL);
9714         }
9715       else
9716         {
9717           if (blen < 8)
9718             emitcode ("anl", "a,#0x%02x",
9719                       (((unsigned char) -1) >> (8 - blen)) << bstr);
9720           genIfxJump (ifx, "a", NULL, NULL, NULL);
9721         }
9722       return;
9723     }
9724   wassert (!ifx);
9725
9726   /* If the bitfield length is less than a byte */
9727   if (blen < 8)
9728     {
9729       emitPtrByteGet (rname, ptype, FALSE);
9730       AccRol (8 - bstr);
9731       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9732       if (!SPEC_USIGN (etype))
9733         {
9734           /* signed bitfield */
9735           symbol *tlbl = newiTempLabel (NULL);
9736
9737           emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9738           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9739           emitLabel (tlbl);
9740         }
9741       aopPut (result, "a", offset++);
9742       goto finish;
9743     }
9744
9745   /* Bit field did not fit in a byte. Copy all
9746      but the partial byte at the end.  */
9747   for (rlen=blen;rlen>=8;rlen-=8)
9748     {
9749       emitPtrByteGet (rname, ptype, FALSE);
9750       aopPut (result, "a", offset++);
9751       if (rlen>8)
9752         emitcode ("inc", "%s", rname);
9753     }
9754
9755   /* Handle the partial byte at the end */
9756   if (rlen)
9757     {
9758       emitPtrByteGet (rname, ptype, FALSE);
9759       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9760       if (!SPEC_USIGN (etype))
9761         {
9762           /* signed bitfield */
9763           symbol *tlbl = newiTempLabel (NULL);
9764
9765           emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9766           emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9767           emitLabel (tlbl);
9768         }
9769       aopPut (result, "a", offset++);
9770     }
9771
9772 finish:
9773   if (offset < rsize)
9774     {
9775       char *source;
9776
9777       if (SPEC_USIGN (etype))
9778         source = zero;
9779       else
9780         {
9781           /* signed bitfield: sign extension with 0x00 or 0xff */
9782           emitcode ("rlc", "a");
9783           emitcode ("subb", "a,acc");
9784
9785           source = "a";
9786         }
9787       rsize -= offset;
9788       while (rsize--)
9789         aopPut (result, source, offset++);
9790     }
9791 }
9792
9793
9794 /*-----------------------------------------------------------------*/
9795 /* genDataPointerGet - generates code when ptr offset is known     */
9796 /*-----------------------------------------------------------------*/
9797 static void
9798 genDataPointerGet (operand * left,
9799                    operand * result,
9800                    iCode * ic)
9801 {
9802   char *l;
9803   char buffer[256];
9804   int size, offset = 0;
9805
9806   D (emitcode (";", "genDataPointerGet"));
9807
9808   aopOp (result, ic, TRUE);
9809
9810   /* get the string representation of the name */
9811   l = aopGet (left, 0, FALSE, TRUE);
9812   l++; // remove #
9813   size = AOP_SIZE (result);
9814   while (size--)
9815     {
9816       if (offset)
9817         {
9818           SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
9819         }
9820       else
9821         {
9822           SNPRINTF (buffer, sizeof(buffer), "%s", l);
9823         }
9824       aopPut (result, buffer, offset++);
9825     }
9826
9827   freeAsmop (result, NULL, ic, TRUE);
9828   freeAsmop (left, NULL, ic, TRUE);
9829 }
9830
9831 /*-----------------------------------------------------------------*/
9832 /* genNearPointerGet - emitcode for near pointer fetch             */
9833 /*-----------------------------------------------------------------*/
9834 static void
9835 genNearPointerGet (operand * left,
9836                    operand * result,
9837                    iCode * ic,
9838                    iCode * pi,
9839                    iCode * ifx)
9840 {
9841   asmop *aop = NULL;
9842   regs *preg = NULL;
9843   char *rname;
9844   sym_link *rtype, *retype;
9845   sym_link *ltype = operandType (left);
9846   char buffer[80];
9847
9848   D (emitcode (";", "genNearPointerGet"));
9849
9850   rtype = operandType (result);
9851   retype = getSpec (rtype);
9852
9853   aopOp (left, ic, FALSE);
9854
9855   /* if left is rematerialisable and
9856      result is not bitfield variable type and
9857      the left is pointer to data space i.e
9858      lower 128 bytes of space */
9859   if (AOP_TYPE (left) == AOP_IMMD &&
9860       !IS_BITFIELD (retype) &&
9861       DCL_TYPE (ltype) == POINTER)
9862     {
9863       genDataPointerGet (left, result, ic);
9864       return;
9865     }
9866
9867  /* if the value is already in a pointer register
9868      then don't need anything more */
9869   if (!AOP_INPREG (AOP (left)))
9870     {
9871       if (IS_AOP_PREG (left))
9872         {
9873           // Aha, it is a pointer, just in disguise.
9874           rname = aopGet (left, 0, FALSE, FALSE);
9875           if (*rname != '@')
9876             {
9877               fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9878                       __FILE__, __LINE__);
9879             }
9880           else
9881             {
9882               // Expected case.
9883               emitcode ("mov", "a%s,%s", rname + 1, rname);
9884               rname++;  // skip the '@'.
9885             }
9886         }
9887       else
9888         {
9889           /* otherwise get a free pointer register */
9890           aop = newAsmop (0);
9891           preg = getFreePtr (ic, &aop, FALSE);
9892           emitcode ("mov", "%s,%s",
9893                     preg->name,
9894                     aopGet (left, 0, FALSE, TRUE));
9895           rname = preg->name;
9896         }
9897     }
9898   else
9899     rname = aopGet (left, 0, FALSE, FALSE);
9900
9901   //aopOp (result, ic, FALSE);
9902   aopOp (result, ic, result?TRUE:FALSE);
9903
9904   /* if bitfield then unpack the bits */
9905   if (IS_BITFIELD (retype))
9906     genUnpackBits (result, rname, POINTER, ifx);
9907   else
9908     {
9909       /* we have can just get the values */
9910       int size = AOP_SIZE (result);
9911       int offset = 0;
9912
9913       while (size--)
9914         {
9915           if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9916             {
9917
9918               emitcode ("mov", "a,@%s", rname);
9919               if (!ifx)
9920                 aopPut (result, "a", offset);
9921             }
9922           else
9923             {
9924               SNPRINTF (buffer, sizeof(buffer), "@%s", rname);
9925               aopPut (result, buffer, offset);
9926             }
9927           offset++;
9928           if (size || pi)
9929             emitcode ("inc", "%s", rname);
9930         }
9931     }
9932
9933   /* now some housekeeping stuff */
9934   if (aop)       /* we had to allocate for this iCode */
9935     {
9936       if (pi) { /* post increment present */
9937         aopPut (left, rname, 0);
9938       }
9939       freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9940     }
9941   else
9942     {
9943       /* we did not allocate which means left
9944          already in a pointer register, then
9945          if size > 0 && this could be used again
9946          we have to point it back to where it
9947          belongs */
9948       if ((AOP_SIZE (result) > 1 &&
9949            !OP_SYMBOL (left)->remat &&
9950            (OP_SYMBOL (left)->liveTo > ic->seq ||
9951             ic->depth)) &&
9952           !pi)
9953         {
9954           int size = AOP_SIZE (result) - 1;
9955           while (size--)
9956             emitcode ("dec", "%s", rname);
9957         }
9958     }
9959
9960   if (ifx && !ifx->generated)
9961     {
9962       genIfxJump (ifx, "a", left, NULL, result);
9963     }
9964
9965   /* done */
9966   freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9967   freeAsmop (left, NULL, ic, TRUE);
9968   if (pi) pi->generated = 1;
9969 }
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9973 /*-----------------------------------------------------------------*/
9974 static void
9975 genPagedPointerGet (operand * left,
9976                     operand * result,
9977                     iCode * ic,
9978                     iCode *pi,
9979                     iCode *ifx)
9980 {
9981   asmop *aop = NULL;
9982   regs *preg = NULL;
9983   char *rname;
9984   sym_link *rtype, *retype;
9985
9986   D (emitcode (";", "genPagedPointerGet"));
9987
9988   rtype = operandType (result);
9989   retype = getSpec (rtype);
9990
9991   aopOp (left, ic, FALSE);
9992
9993   /* if the value is already in a pointer register
9994      then don't need anything more */
9995   if (!AOP_INPREG (AOP (left)))
9996     {
9997       /* otherwise get a free pointer register */
9998       aop = newAsmop (0);
9999       preg = getFreePtr (ic, &aop, FALSE);
10000       emitcode ("mov", "%s,%s",
10001                 preg->name,
10002                 aopGet (left, 0, FALSE, TRUE));
10003       rname = preg->name;
10004     }
10005   else
10006     rname = aopGet (left, 0, FALSE, FALSE);
10007
10008   aopOp (result, ic, FALSE);
10009
10010   /* if bitfield then unpack the bits */
10011   if (IS_BITFIELD (retype))
10012     genUnpackBits (result, rname, PPOINTER, ifx);
10013   else
10014     {
10015       /* we have can just get the values */
10016       int size = AOP_SIZE (result);
10017       int offset = 0;
10018
10019       while (size--)
10020         {
10021
10022           emitcode ("movx", "a,@%s", rname);
10023           if (!ifx)
10024             aopPut (result, "a", offset);
10025
10026           offset++;
10027
10028           if (size || pi)
10029             emitcode ("inc", "%s", rname);
10030         }
10031     }
10032
10033   /* now some housekeeping stuff */
10034   if (aop) /* we had to allocate for this iCode */
10035     {
10036       if (pi)
10037         aopPut (left, rname, 0);
10038       freeAsmop (NULL, aop, ic, TRUE);
10039     }
10040   else
10041     {
10042       /* we did not allocate which means left
10043          already in a pointer register, then
10044          if size > 0 && this could be used again
10045          we have to point it back to where it
10046          belongs */
10047       if ((AOP_SIZE (result) > 1 &&
10048            !OP_SYMBOL (left)->remat &&
10049            (OP_SYMBOL (left)->liveTo > ic->seq ||
10050             ic->depth)) &&
10051           !pi)
10052         {
10053           int size = AOP_SIZE (result) - 1;
10054           while (size--)
10055             emitcode ("dec", "%s", rname);
10056         }
10057     }
10058
10059   if (ifx && !ifx->generated)
10060     {
10061       genIfxJump (ifx, "a", left, NULL, result);
10062     }
10063
10064   /* done */
10065   freeAsmop (result, NULL, ic, TRUE);
10066   freeAsmop (left, NULL, ic, TRUE);
10067   if (pi) pi->generated = 1;
10068 }
10069
10070 /*--------------------------------------------------------------------*/
10071 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
10072 /*--------------------------------------------------------------------*/
10073 static void
10074 loadDptrFromOperand (operand *op, bool loadBToo)
10075 {
10076   if (AOP_TYPE (op) != AOP_STR)
10077     {
10078       /* if this is rematerializable */
10079       if (AOP_TYPE (op) == AOP_IMMD)
10080         {
10081           emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
10082           if (loadBToo)
10083             {
10084               if (AOP(op)->aopu.aop_immd.from_cast_remat)
10085                 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
10086               else
10087                 {
10088                   wassertl(FALSE, "need pointerCode");
10089                   emitcode ("", "; mov b,???");
10090                   /* genPointerGet and genPointerSet originally did different
10091                   ** things for this case. Both seem wrong.
10092                   ** from genPointerGet:
10093                   **  emitcode ("mov", "b,#%d", pointerCode (retype));
10094                   ** from genPointerSet:
10095                   **  emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
10096                   */
10097                 }
10098             }
10099         }
10100       else if (AOP_TYPE (op) == AOP_DPTR)
10101         {
10102           if (loadBToo)
10103             {
10104               MOVA (aopGet (op, 0, FALSE, FALSE));
10105               emitcode ("push", "acc");
10106               MOVA (aopGet (op, 1, FALSE, FALSE));
10107               emitcode ("push", "acc");
10108               emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10109               emitcode ("pop", "dph");
10110               emitcode ("pop", "dpl");
10111             }
10112           else
10113             {
10114               MOVA (aopGet (op, 0, FALSE, FALSE));
10115               emitcode ("push", "acc");
10116               emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10117               emitcode ("pop", "dpl");
10118             }
10119         }
10120       else
10121         {                       /* we need to get it byte by byte */
10122           emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
10123           emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
10124           if (loadBToo)
10125             emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
10126         }
10127     }
10128 }
10129
10130 /*-----------------------------------------------------------------*/
10131 /* genFarPointerGet - get value from far space                     */
10132 /*-----------------------------------------------------------------*/
10133 static void
10134 genFarPointerGet (operand * left,
10135                   operand * result, iCode * ic, iCode * pi, iCode * ifx)
10136 {
10137   int size, offset;
10138   sym_link *retype = getSpec (operandType (result));
10139
10140   D (emitcode (";", "genFarPointerGet"));
10141
10142   aopOp (left, ic, FALSE);
10143   loadDptrFromOperand (left, FALSE);
10144
10145   /* so dptr now contains the address */
10146   aopOp (result, ic, FALSE);
10147
10148   /* if bit then unpack */
10149   if (IS_BITFIELD (retype))
10150     genUnpackBits (result, "dptr", FPOINTER, ifx);
10151   else
10152     {
10153       size = AOP_SIZE (result);
10154       offset = 0;
10155
10156       while (size--)
10157         {
10158           emitcode ("movx", "a,@dptr");
10159           if (!ifx)
10160             aopPut (result, "a", offset++);
10161           if (size || pi)
10162             emitcode ("inc", "dptr");
10163         }
10164     }
10165
10166   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10167     {
10168       aopPut (left, "dpl", 0);
10169       aopPut (left, "dph", 1);
10170       pi->generated = 1;
10171     }
10172
10173   if (ifx && !ifx->generated)
10174     {
10175       genIfxJump (ifx, "a", left, NULL, result);
10176     }
10177
10178   freeAsmop (result, NULL, ic, TRUE);
10179   freeAsmop (left, NULL, ic, TRUE);
10180 }
10181
10182 /*-----------------------------------------------------------------*/
10183 /* genCodePointerGet - get value from code space                   */
10184 /*-----------------------------------------------------------------*/
10185 static void
10186 genCodePointerGet (operand * left,
10187                     operand * result, iCode * ic, iCode *pi, iCode *ifx)
10188 {
10189   int size, offset;
10190   sym_link *retype = getSpec (operandType (result));
10191
10192   D (emitcode (";", "genCodePointerGet"));
10193
10194   aopOp (left, ic, FALSE);
10195   loadDptrFromOperand (left, FALSE);
10196
10197   /* so dptr now contains the address */
10198   aopOp (result, ic, FALSE);
10199
10200   /* if bit then unpack */
10201   if (IS_BITFIELD (retype))
10202     genUnpackBits (result, "dptr", CPOINTER, ifx);
10203   else
10204     {
10205       size = AOP_SIZE (result);
10206       offset = 0;
10207
10208       while (size--)
10209         {
10210           emitcode ("clr", "a");
10211           emitcode ("movc", "a,@a+dptr");
10212           if (!ifx)
10213             aopPut (result, "a", offset++);
10214           if (size || pi)
10215             emitcode ("inc", "dptr");
10216         }
10217     }
10218
10219   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10220     {
10221       aopPut (left, "dpl", 0);
10222       aopPut (left, "dph", 1);
10223       pi->generated = 1;
10224     }
10225
10226   if (ifx && !ifx->generated)
10227     {
10228       genIfxJump (ifx, "a", left, NULL, result);
10229     }
10230
10231   freeAsmop (result, NULL, ic, TRUE);
10232   freeAsmop (left, NULL, ic, TRUE);
10233 }
10234
10235 /*-----------------------------------------------------------------*/
10236 /* genGenPointerGet - get value from generic pointer space         */
10237 /*-----------------------------------------------------------------*/
10238 static void
10239 genGenPointerGet (operand * left,
10240                   operand * result, iCode * ic, iCode *pi, iCode *ifx)
10241 {
10242   int size, offset;
10243   sym_link *retype = getSpec (operandType (result));
10244
10245   D (emitcode (";", "genGenPointerGet"));
10246
10247   aopOp (left, ic, FALSE);
10248   loadDptrFromOperand (left, TRUE);
10249
10250   /* so dptr now contains the address */
10251   aopOp (result, ic, FALSE);
10252
10253   /* if bit then unpack */
10254   if (IS_BITFIELD (retype))
10255     {
10256       genUnpackBits (result, "dptr", GPOINTER, ifx);
10257     }
10258   else
10259     {
10260       size = AOP_SIZE (result);
10261       offset = 0;
10262
10263       while (size--)
10264         {
10265           emitcode ("lcall", "__gptrget");
10266           if (!ifx)
10267             aopPut (result, "a", offset++);
10268           if (size || pi)
10269             emitcode ("inc", "dptr");
10270         }
10271     }
10272
10273   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
10274     {
10275       aopPut (left, "dpl", 0);
10276       aopPut (left, "dph", 1);
10277       pi->generated = 1;
10278     }
10279
10280   if (ifx && !ifx->generated)
10281     {
10282       genIfxJump (ifx, "a", left, NULL, result);
10283     }
10284
10285   freeAsmop (result, NULL, ic, TRUE);
10286   freeAsmop (left, NULL, ic, TRUE);
10287 }
10288
10289 /*-----------------------------------------------------------------*/
10290 /* genPointerGet - generate code for pointer get                   */
10291 /*-----------------------------------------------------------------*/
10292 static void
10293 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
10294 {
10295   operand *left, *result;
10296   sym_link *type, *etype;
10297   int p_type;
10298
10299   D (emitcode (";", "genPointerGet"));
10300
10301   left = IC_LEFT (ic);
10302   result = IC_RESULT (ic);
10303
10304   if (getSize (operandType (result))>1)
10305     ifx = NULL;
10306
10307   /* depending on the type of pointer we need to
10308      move it to the correct pointer register */
10309   type = operandType (left);
10310   etype = getSpec (type);
10311   /* if left is of type of pointer then it is simple */
10312   if (IS_PTR (type) && !IS_FUNC (type->next))
10313     p_type = DCL_TYPE (type);
10314   else
10315     {
10316       /* we have to go by the storage class */
10317       p_type = PTR_TYPE (SPEC_OCLS (etype));
10318     }
10319
10320   /* special case when cast remat */
10321   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
10322       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode))
10323     {
10324       left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
10325       type = operandType (left);
10326       p_type = DCL_TYPE (type);
10327     }
10328   /* now that we have the pointer type we assign
10329      the pointer values */
10330   switch (p_type)
10331     {
10332
10333     case POINTER:
10334     case IPOINTER:
10335       genNearPointerGet (left, result, ic, pi, ifx);
10336       break;
10337
10338     case PPOINTER:
10339       genPagedPointerGet (left, result, ic, pi, ifx);
10340       break;
10341
10342     case FPOINTER:
10343       genFarPointerGet (left, result, ic, pi, ifx);
10344       break;
10345
10346     case CPOINTER:
10347       genCodePointerGet (left, result, ic, pi, ifx);
10348       break;
10349
10350     case GPOINTER:
10351       genGenPointerGet (left, result, ic, pi, ifx);
10352       break;
10353     }
10354 }
10355
10356
10357 /*-----------------------------------------------------------------*/
10358 /* genPackBits - generates code for packed bit storage             */
10359 /*-----------------------------------------------------------------*/
10360 static void
10361 genPackBits (sym_link * etype,
10362              operand * right,
10363              char *rname, int p_type)
10364 {
10365   int offset = 0;       /* source byte offset */
10366   int rlen = 0;         /* remaining bitfield length */
10367   int blen;             /* bitfield length */
10368   int bstr;             /* bitfield starting bit within byte */
10369   int litval;           /* source literal value (if AOP_LIT) */
10370   unsigned char mask;   /* bitmask within current byte */
10371
10372   D(emitcode (";     genPackBits",""));
10373
10374   blen = SPEC_BLEN (etype);
10375   bstr = SPEC_BSTR (etype);
10376
10377   /* If the bitfield length is less than a byte */
10378   if (blen < 8)
10379     {
10380       mask = ((unsigned char) (0xFF << (blen + bstr)) |
10381               (unsigned char) (0xFF >> (8 - bstr)));
10382
10383       if (AOP_TYPE (right) == AOP_LIT)
10384         {
10385           /* Case with a bitfield length <8 and literal source
10386           */
10387           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10388           litval <<= bstr;
10389           litval &= (~mask) & 0xff;
10390           emitPtrByteGet (rname, p_type, FALSE);
10391           if ((mask|litval)!=0xff)
10392             emitcode ("anl","a,#0x%02x", mask);
10393           if (litval)
10394             emitcode ("orl","a,#0x%02x", litval);
10395         }
10396       else
10397         {
10398           if ((blen==1) && (p_type!=GPOINTER))
10399             {
10400               /* Case with a bitfield length == 1 and no generic pointer
10401               */
10402               if (AOP_TYPE (right) == AOP_CRY)
10403                 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10404               else
10405                 {
10406                   MOVA (aopGet (right, 0, FALSE, FALSE));
10407                   emitcode ("rrc","a");
10408                 }
10409               emitPtrByteGet (rname, p_type, FALSE);
10410               emitcode ("mov","acc.%d,c",bstr);
10411             }
10412           else
10413             {
10414               bool pushedB;
10415               /* Case with a bitfield length < 8 and arbitrary source
10416               */
10417               MOVA (aopGet (right, 0, FALSE, FALSE));
10418               /* shift and mask source value */
10419               AccLsh (bstr);
10420               emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10421
10422               pushedB = pushB ();
10423               /* transfer A to B and get next byte */
10424               emitPtrByteGet (rname, p_type, TRUE);
10425
10426               emitcode ("anl", "a,#0x%02x", mask);
10427               emitcode ("orl", "a,b");
10428               if (p_type == GPOINTER)
10429                 emitcode ("pop", "b");
10430
10431               popB (pushedB);
10432            }
10433         }
10434
10435       emitPtrByteSet (rname, p_type, "a");
10436       return;
10437     }
10438
10439   /* Bit length is greater than 7 bits. In this case, copy  */
10440   /* all except the partial byte at the end                 */
10441   for (rlen=blen;rlen>=8;rlen-=8)
10442     {
10443       emitPtrByteSet (rname, p_type,
10444                       aopGet (right, offset++, FALSE, TRUE) );
10445       if (rlen>8)
10446         emitcode ("inc", "%s", rname);
10447     }
10448
10449   /* If there was a partial byte at the end */
10450   if (rlen)
10451     {
10452       mask = (((unsigned char) -1 << rlen) & 0xff);
10453
10454       if (AOP_TYPE (right) == AOP_LIT)
10455         {
10456           /* Case with partial byte and literal source
10457           */
10458           litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10459           litval >>= (blen-rlen);
10460           litval &= (~mask) & 0xff;
10461           emitPtrByteGet (rname, p_type, FALSE);
10462           if ((mask|litval)!=0xff)
10463             emitcode ("anl","a,#0x%02x", mask);
10464           if (litval)
10465             emitcode ("orl","a,#0x%02x", litval);
10466         }
10467       else
10468         {
10469           bool pushedB;
10470           /* Case with partial byte and arbitrary source
10471           */
10472           MOVA (aopGet (right, offset++, FALSE, FALSE));
10473           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10474
10475           pushedB = pushB ();
10476           /* transfer A to B and get next byte */
10477           emitPtrByteGet (rname, p_type, TRUE);
10478
10479           emitcode ("anl", "a,#0x%02x", mask);
10480           emitcode ("orl", "a,b");
10481           if (p_type == GPOINTER)
10482             emitcode ("pop", "b");
10483
10484           popB (pushedB);
10485         }
10486       emitPtrByteSet (rname, p_type, "a");
10487     }
10488 }
10489
10490
10491 /*-----------------------------------------------------------------*/
10492 /* genDataPointerSet - remat pointer to data space                 */
10493 /*-----------------------------------------------------------------*/
10494 static void
10495 genDataPointerSet (operand * right,
10496                    operand * result,
10497                    iCode * ic)
10498 {
10499   int size, offset = 0;
10500   char *l, buffer[256];
10501
10502   D (emitcode (";", "genDataPointerSet"));
10503
10504   aopOp (right, ic, FALSE);
10505
10506   l = aopGet (result, 0, FALSE, TRUE);
10507   l++; //remove #
10508   size = AOP_SIZE (right);
10509   while (size--)
10510     {
10511       if (offset)
10512         SNPRINTF (buffer, sizeof(buffer), "(%s + %d)", l, offset);
10513       else
10514         SNPRINTF (buffer, sizeof(buffer), "%s", l);
10515       emitcode ("mov", "%s,%s", buffer,
10516                 aopGet (right, offset++, FALSE, FALSE));
10517     }
10518
10519   freeAsmop (result, NULL, ic, TRUE);
10520   freeAsmop (right, NULL, ic, TRUE);
10521 }
10522
10523 /*-----------------------------------------------------------------*/
10524 /* genNearPointerSet - emitcode for near pointer put                */
10525 /*-----------------------------------------------------------------*/
10526 static void
10527 genNearPointerSet (operand * right,
10528                    operand * result,
10529                    iCode * ic,
10530                    iCode * pi)
10531 {
10532   asmop *aop = NULL;
10533   regs *preg = NULL;
10534   char *rname, *l;
10535   sym_link *retype, *letype;
10536   sym_link *ptype = operandType (result);
10537
10538   D (emitcode (";", "genNearPointerSet"));
10539
10540   retype = getSpec (operandType (right));
10541   letype = getSpec (ptype);
10542
10543   aopOp (result, ic, FALSE);
10544
10545   /* if the result is rematerializable &
10546      in data space & not a bit variable */
10547   if (AOP_TYPE (result) == AOP_IMMD &&
10548       DCL_TYPE (ptype) == POINTER &&
10549       !IS_BITVAR (retype) &&
10550       !IS_BITVAR (letype))
10551     {
10552       genDataPointerSet (right, result, ic);
10553       return;
10554     }
10555
10556   /* if the value is already in a pointer register
10557      then don't need anything more */
10558   if (!AOP_INPREG (AOP (result)))
10559     {
10560         if (
10561             //AOP_TYPE (result) == AOP_STK
10562             IS_AOP_PREG(result)
10563             )
10564         {
10565             // Aha, it is a pointer, just in disguise.
10566             rname = aopGet (result, 0, FALSE, FALSE);
10567             if (*rname != '@')
10568             {
10569                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10570                         __FILE__, __LINE__);
10571             }
10572             else
10573             {
10574                 // Expected case.
10575                 emitcode ("mov", "a%s,%s", rname + 1, rname);
10576                 rname++;  // skip the '@'.
10577             }
10578         }
10579         else
10580         {
10581             /* otherwise get a free pointer register */
10582             aop = newAsmop (0);
10583             preg = getFreePtr (ic, &aop, FALSE);
10584             emitcode ("mov", "%s,%s",
10585                       preg->name,
10586                       aopGet (result, 0, FALSE, TRUE));
10587             rname = preg->name;
10588         }
10589     }
10590     else
10591     {
10592         rname = aopGet (result, 0, FALSE, FALSE);
10593     }
10594
10595   aopOp (right, ic, FALSE);
10596
10597   /* if bitfield then unpack the bits */
10598   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10599     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10600   else
10601     {
10602       /* we can just get the values */
10603       int size = AOP_SIZE (right);
10604       int offset = 0;
10605
10606       while (size--)
10607         {
10608           l = aopGet (right, offset, FALSE, TRUE);
10609           if ((*l == '@') || (strcmp (l, "acc") == 0))
10610             {
10611               MOVA (l);
10612               emitcode ("mov", "@%s,a", rname);
10613             }
10614           else
10615             emitcode ("mov", "@%s,%s", rname, l);
10616           if (size || pi)
10617             emitcode ("inc", "%s", rname);
10618           offset++;
10619         }
10620     }
10621
10622   /* now some housekeeping stuff */
10623   if (aop) /* we had to allocate for this iCode */
10624     {
10625       if (pi)
10626         aopPut (result, rname, 0);
10627       freeAsmop (NULL, aop, ic, TRUE);
10628     }
10629   else
10630     {
10631       /* we did not allocate which means left
10632          already in a pointer register, then
10633          if size > 0 && this could be used again
10634          we have to point it back to where it
10635          belongs */
10636       if ((AOP_SIZE (right) > 1 &&
10637            !OP_SYMBOL (result)->remat &&
10638            (OP_SYMBOL (result)->liveTo > ic->seq ||
10639             ic->depth)) &&
10640           !pi)
10641         {
10642           int size = AOP_SIZE (right) - 1;
10643           while (size--)
10644             emitcode ("dec", "%s", rname);
10645         }
10646     }
10647
10648   /* done */
10649   if (pi) pi->generated = 1;
10650   freeAsmop (result, NULL, ic, TRUE);
10651   freeAsmop (right, NULL, ic, TRUE);
10652 }
10653
10654 /*-----------------------------------------------------------------*/
10655 /* genPagedPointerSet - emitcode for Paged pointer put             */
10656 /*-----------------------------------------------------------------*/
10657 static void
10658 genPagedPointerSet (operand * right,
10659                     operand * result,
10660                     iCode * ic,
10661                     iCode * pi)
10662 {
10663   asmop *aop = NULL;
10664   regs *preg = NULL;
10665   char *rname, *l;
10666   sym_link *retype, *letype;
10667
10668   D (emitcode (";", "genPagedPointerSet"));
10669
10670   retype = getSpec (operandType (right));
10671   letype = getSpec (operandType (result));
10672
10673   aopOp (result, ic, FALSE);
10674
10675   /* if the value is already in a pointer register
10676      then don't need anything more */
10677   if (!AOP_INPREG (AOP (result)))
10678     {
10679       /* otherwise get a free pointer register */
10680       aop = newAsmop (0);
10681       preg = getFreePtr (ic, &aop, FALSE);
10682       emitcode ("mov", "%s,%s",
10683                 preg->name,
10684                 aopGet (result, 0, FALSE, TRUE));
10685       rname = preg->name;
10686     }
10687   else
10688     rname = aopGet (result, 0, FALSE, FALSE);
10689
10690   aopOp (right, ic, FALSE);
10691
10692   /* if bitfield then unpack the bits */
10693   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10694     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10695   else
10696     {
10697       /* we have can just get the values */
10698       int size = AOP_SIZE (right);
10699       int offset = 0;
10700
10701       while (size--)
10702         {
10703           l = aopGet (right, offset, FALSE, TRUE);
10704           MOVA (l);
10705           emitcode ("movx", "@%s,a", rname);
10706
10707           if (size || pi)
10708             emitcode ("inc", "%s", rname);
10709
10710           offset++;
10711         }
10712     }
10713
10714   /* now some housekeeping stuff */
10715   if (aop) /* we had to allocate for this iCode */
10716     {
10717       if (pi)
10718         aopPut (result, rname, 0);
10719       freeAsmop (NULL, aop, ic, TRUE);
10720     }
10721   else
10722     {
10723       /* we did not allocate which means left
10724          already in a pointer register, then
10725          if size > 0 && this could be used again
10726          we have to point it back to where it
10727          belongs */
10728       if (AOP_SIZE (right) > 1 &&
10729           !OP_SYMBOL (result)->remat &&
10730           (OP_SYMBOL (result)->liveTo > ic->seq ||
10731            ic->depth))
10732         {
10733           int size = AOP_SIZE (right) - 1;
10734           while (size--)
10735             emitcode ("dec", "%s", rname);
10736         }
10737     }
10738
10739   /* done */
10740   if (pi) pi->generated = 1;
10741   freeAsmop (result, NULL, ic, TRUE);
10742   freeAsmop (right, NULL, ic, TRUE);
10743 }
10744
10745 /*-----------------------------------------------------------------*/
10746 /* genFarPointerSet - set value from far space                     */
10747 /*-----------------------------------------------------------------*/
10748 static void
10749 genFarPointerSet (operand * right,
10750                   operand * result, iCode * ic, iCode * pi)
10751 {
10752   int size, offset;
10753   sym_link *retype = getSpec (operandType (right));
10754   sym_link *letype = getSpec (operandType (result));
10755
10756   D(emitcode (";     genFarPointerSet",""));
10757
10758   aopOp (result, ic, FALSE);
10759   loadDptrFromOperand (result, FALSE);
10760
10761   /* so dptr now contains the address */
10762   aopOp (right, ic, FALSE);
10763
10764   /* if bit then unpack */
10765   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10766     genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10767   else
10768     {
10769       size = AOP_SIZE (right);
10770       offset = 0;
10771
10772       while (size--)
10773         {
10774           char *l = aopGet (right, offset++, FALSE, FALSE);
10775           MOVA (l);
10776           emitcode ("movx", "@dptr,a");
10777           if (size || pi)
10778             emitcode ("inc", "dptr");
10779         }
10780     }
10781   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10782     aopPut (result, "dpl", 0);
10783     aopPut (result, "dph", 1);
10784     pi->generated=1;
10785   }
10786   freeAsmop (result, NULL, ic, TRUE);
10787   freeAsmop (right, NULL, ic, TRUE);
10788 }
10789
10790 /*-----------------------------------------------------------------*/
10791 /* genGenPointerSet - set value from generic pointer space         */
10792 /*-----------------------------------------------------------------*/
10793 static void
10794 genGenPointerSet (operand * right,
10795                   operand * result, iCode * ic, iCode * pi)
10796 {
10797   int size, offset;
10798   sym_link *retype = getSpec (operandType (right));
10799   sym_link *letype = getSpec (operandType (result));
10800
10801   D (emitcode (";", "genGenPointerSet"));
10802
10803   aopOp (result, ic, FALSE);
10804   loadDptrFromOperand (result, TRUE);
10805
10806   /* so dptr now contains the address */
10807   aopOp (right, ic, FALSE);
10808
10809   /* if bit then unpack */
10810   if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10811     {
10812       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10813     }
10814   else
10815     {
10816       size = AOP_SIZE (right);
10817       offset = 0;
10818
10819       while (size--)
10820         {
10821           char *l = aopGet (right, offset++, FALSE, FALSE);
10822           MOVA (l);
10823           emitcode ("lcall", "__gptrput");
10824           if (size || pi)
10825             emitcode ("inc", "dptr");
10826         }
10827     }
10828
10829   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10830     aopPut (result, "dpl", 0);
10831     aopPut (result, "dph", 1);
10832     pi->generated=1;
10833   }
10834   freeAsmop (result, NULL, ic, TRUE);
10835   freeAsmop (right, NULL, ic, TRUE);
10836 }
10837
10838 /*-----------------------------------------------------------------*/
10839 /* genPointerSet - stores the value into a pointer location        */
10840 /*-----------------------------------------------------------------*/
10841 static void
10842 genPointerSet (iCode * ic, iCode *pi)
10843 {
10844   operand *right, *result;
10845   sym_link *type, *etype;
10846   int p_type;
10847
10848   D (emitcode (";", "genPointerSet"));
10849
10850   right = IC_RIGHT (ic);
10851   result = IC_RESULT (ic);
10852
10853   /* depending on the type of pointer we need to
10854      move it to the correct pointer register */
10855   type = operandType (result);
10856   etype = getSpec (type);
10857   /* if left is of type of pointer then it is simple */
10858   if (IS_PTR (type) && !IS_FUNC (type->next))
10859     {
10860       p_type = DCL_TYPE (type);
10861     }
10862   else
10863     {
10864       /* we have to go by the storage class */
10865       p_type = PTR_TYPE (SPEC_OCLS (etype));
10866     }
10867
10868   /* special case when cast remat */
10869   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10870       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10871           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10872           type = operandType (result);
10873           p_type = DCL_TYPE (type);
10874   }
10875
10876   /* now that we have the pointer type we assign
10877      the pointer values */
10878   switch (p_type)
10879     {
10880
10881     case POINTER:
10882     case IPOINTER:
10883       genNearPointerSet (right, result, ic, pi);
10884       break;
10885
10886     case PPOINTER:
10887       genPagedPointerSet (right, result, ic, pi);
10888       break;
10889
10890     case FPOINTER:
10891       genFarPointerSet (right, result, ic, pi);
10892       break;
10893
10894     case GPOINTER:
10895       genGenPointerSet (right, result, ic, pi);
10896       break;
10897
10898     default:
10899       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10900               "genPointerSet: illegal pointer type");
10901     }
10902 }
10903
10904 /*-----------------------------------------------------------------*/
10905 /* genIfx - generate code for Ifx statement                        */
10906 /*-----------------------------------------------------------------*/
10907 static void
10908 genIfx (iCode * ic, iCode * popIc)
10909 {
10910   operand *cond = IC_COND (ic);
10911   int isbit = 0;
10912   char *dup = NULL;
10913
10914   D (emitcode (";", "genIfx"));
10915
10916   aopOp (cond, ic, FALSE);
10917
10918   /* get the value into acc */
10919   if (AOP_TYPE (cond) != AOP_CRY)
10920     {
10921       toBoolean (cond);
10922     }
10923   else
10924     {
10925       isbit = 1;
10926       if (AOP(cond)->aopu.aop_dir)
10927         dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10928     }
10929
10930   /* the result is now in the accumulator or a directly addressable bit */
10931   freeAsmop (cond, NULL, ic, TRUE);
10932
10933   /* if there was something to be popped then do it */
10934   if (popIc)
10935     genIpop (popIc);
10936
10937   /* if the condition is a bit variable */
10938   if (isbit && dup)
10939     genIfxJump(ic, dup, NULL, NULL, NULL);
10940   else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10941     genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10942   else if (isbit && !IS_ITEMP (cond))
10943     genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10944   else
10945     genIfxJump (ic, "a", NULL, NULL, NULL);
10946
10947   ic->generated = 1;
10948 }
10949
10950 /*-----------------------------------------------------------------*/
10951 /* genAddrOf - generates code for address of                       */
10952 /*-----------------------------------------------------------------*/
10953 static void
10954 genAddrOf (iCode * ic)
10955 {
10956   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10957   int size, offset;
10958
10959   D (emitcode (";", "genAddrOf"));
10960
10961   aopOp (IC_RESULT (ic), ic, FALSE);
10962
10963   /* if the operand is on the stack then we
10964      need to get the stack offset of this
10965      variable */
10966   if (sym->onStack)
10967     {
10968       /* if it has an offset then we need to compute it */
10969       if (sym->stack)
10970         {
10971           int stack_offset = ((sym->stack < 0) ?
10972                               ((char) (sym->stack - _G.nRegsSaved)) :
10973                               ((char) sym->stack)) & 0xff;
10974           if ((abs(stack_offset) == 1) &&
10975               !AOP_NEEDSACC(IC_RESULT (ic)) &&
10976               !isOperandVolatile (IC_RESULT (ic), FALSE))
10977             {
10978               aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10979               if (stack_offset > 0)
10980                 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10981               else
10982                 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
10983             }
10984           else
10985             {
10986               emitcode ("mov", "a,%s", SYM_BP (sym));
10987               emitcode ("add", "a,#0x%02x", stack_offset & 0xff);
10988               aopPut (IC_RESULT (ic), "a", 0);
10989             }
10990         }
10991       else
10992         {
10993           /* we can just move _bp */
10994           aopPut (IC_RESULT (ic), SYM_BP (sym), 0);
10995         }
10996       /* fill the result with zero */
10997       size = AOP_SIZE (IC_RESULT (ic)) - 1;
10998
10999       offset = 1;
11000       while (size--)
11001         {
11002           aopPut (IC_RESULT (ic), zero, offset++);
11003         }
11004       goto release;
11005     }
11006
11007   /* object not on stack then we need the name */
11008   size = AOP_SIZE (IC_RESULT (ic));
11009   offset = 0;
11010
11011   while (size--)
11012     {
11013       char s[SDCC_NAME_MAX];
11014       if (offset)
11015         sprintf (s, "#(%s >> %d)",
11016                  sym->rname,
11017                  offset * 8);
11018       else
11019         SNPRINTF (s, sizeof(s), "#%s", sym->rname);
11020       aopPut (IC_RESULT (ic), s, offset++);
11021     }
11022
11023 release:
11024   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11025
11026 }
11027
11028 /*-----------------------------------------------------------------*/
11029 /* genFarFarAssign - assignment when both are in far space         */
11030 /*-----------------------------------------------------------------*/
11031 static void
11032 genFarFarAssign (operand * result, operand * right, iCode * ic)
11033 {
11034   int size = AOP_SIZE (right);
11035   int offset = 0;
11036   char *l;
11037
11038   D (emitcode (";", "genFarFarAssign"));
11039
11040   /* first push the right side on to the stack */
11041   while (size--)
11042     {
11043       l = aopGet (right, offset++, FALSE, FALSE);
11044       MOVA (l);
11045       emitcode ("push", "acc");
11046     }
11047
11048   freeAsmop (right, NULL, ic, FALSE);
11049   /* now assign DPTR to result */
11050   aopOp (result, ic, FALSE);
11051   size = AOP_SIZE (result);
11052   while (size--)
11053     {
11054       emitcode ("pop", "acc");
11055       aopPut (result, "a", --offset);
11056     }
11057   freeAsmop (result, NULL, ic, FALSE);
11058 }
11059
11060 /*-----------------------------------------------------------------*/
11061 /* genAssign - generate code for assignment                        */
11062 /*-----------------------------------------------------------------*/
11063 static void
11064 genAssign (iCode * ic)
11065 {
11066   operand *result, *right;
11067   int size, offset;
11068   unsigned long lit = 0L;
11069
11070   D (emitcode (";", "genAssign"));
11071
11072   result = IC_RESULT (ic);
11073   right = IC_RIGHT (ic);
11074
11075   /* if they are the same */
11076   if (operandsEqu (result, right) &&
11077       !isOperandVolatile (result, FALSE) &&
11078       !isOperandVolatile (right, FALSE))
11079     return;
11080
11081   aopOp (right, ic, FALSE);
11082
11083   /* special case both in far space */
11084   if (AOP_TYPE (right) == AOP_DPTR &&
11085       IS_TRUE_SYMOP (result) &&
11086       isOperandInFarSpace (result))
11087     {
11088       genFarFarAssign (result, right, ic);
11089       return;
11090     }
11091
11092   aopOp (result, ic, TRUE);
11093
11094   /* if they are the same registers */
11095   if (sameRegs (AOP (right), AOP (result)) &&
11096       !isOperandVolatile (result, FALSE) &&
11097       !isOperandVolatile (right, FALSE))
11098     goto release;
11099
11100   /* if the result is a bit */
11101   if (AOP_TYPE (result) == AOP_CRY)
11102     {
11103       assignBit (result, right);
11104       goto release;
11105     }
11106
11107   /* bit variables done */
11108   /* general case */
11109   size = AOP_SIZE (result);
11110   offset = 0;
11111   if (AOP_TYPE (right) == AOP_LIT)
11112     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
11113
11114   if ((size > 1) &&
11115       (AOP_TYPE (result) != AOP_REG) &&
11116       (AOP_TYPE (right) == AOP_LIT) &&
11117       !IS_FLOAT (operandType (right)) &&
11118       (lit < 256L))
11119     {
11120       while ((size) && (lit))
11121         {
11122           aopPut (result,
11123                   aopGet (right, offset, FALSE, FALSE),
11124                   offset);
11125           lit >>= 8;
11126           offset++;
11127           size--;
11128         }
11129       /* And now fill the rest with zeros. */
11130       if (size)
11131         {
11132           emitcode ("clr", "a");
11133         }
11134       while (size--)
11135         {
11136           aopPut (result, "a", offset);
11137           offset++;
11138         }
11139     }
11140   else
11141     {
11142       while (size--)
11143         {
11144           aopPut (result,
11145                   aopGet (right, offset, FALSE, FALSE),
11146                   offset);
11147           offset++;
11148         }
11149     }
11150
11151 release:
11152   freeAsmop (result, NULL, ic, TRUE);
11153   freeAsmop (right, NULL, ic, TRUE);
11154 }
11155
11156 /*-----------------------------------------------------------------*/
11157 /* genJumpTab - generates code for jump table                      */
11158 /*-----------------------------------------------------------------*/
11159 static void
11160 genJumpTab (iCode * ic)
11161 {
11162   symbol *jtab,*jtablo,*jtabhi;
11163   char *l;
11164   unsigned int count;
11165
11166   D (emitcode (";", "genJumpTab"));
11167
11168   count = elementsInSet( IC_JTLABELS (ic) );
11169
11170   if( count <= 16 )
11171     {
11172       /* this algorithm needs 9 cycles and 7 + 3*n bytes
11173          if the switch argument is in a register.
11174          (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
11175       /* Peephole may not convert ljmp to sjmp or ret
11176          labelIsReturnOnly & labelInRange must check
11177          currPl->ic->op != JUMPTABLE */
11178       aopOp (IC_JTCOND (ic), ic, FALSE);
11179       /* get the condition into accumulator */
11180       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11181       MOVA (l);
11182       /* multiply by three */
11183       if (aopGetUsesAcc (IC_JTCOND (ic), 0))
11184         {
11185           emitcode ("mov", "b,#3");
11186           emitcode ("mul", "ab");
11187         }
11188       else
11189         {
11190           emitcode ("add", "a,acc");
11191           emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
11192         }
11193       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11194
11195       jtab = newiTempLabel (NULL);
11196       emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
11197       emitcode ("jmp", "@a+dptr");
11198       emitLabel (jtab);
11199       /* now generate the jump labels */
11200       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11201            jtab = setNextItem (IC_JTLABELS (ic)))
11202         emitcode ("ljmp", "%05d$", jtab->key + 100);
11203     }
11204   else
11205     {
11206       /* this algorithm needs 14 cycles and 13 + 2*n bytes
11207          if the switch argument is in a register.
11208          For n>6 this algorithm may be more compact */
11209       jtablo = newiTempLabel (NULL);
11210       jtabhi = newiTempLabel (NULL);
11211
11212       /* get the condition into accumulator.
11213          Using b as temporary storage, if register push/pop is needed */
11214       aopOp (IC_JTCOND (ic), ic, FALSE);
11215       l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
11216       if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
11217           (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
11218         {
11219           // (MB) what if B is in use???
11220           wassertl(!BINUSE, "B was in use");
11221           emitcode ("mov", "b,%s", l);
11222           l = "b";
11223         }
11224       freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11225       MOVA (l);
11226       if( count <= 112 )
11227         {
11228           emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
11229           emitcode ("movc", "a,@a+pc");
11230           emitcode ("push", "acc");
11231
11232           MOVA (l);
11233           emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
11234           emitcode ("movc", "a,@a+pc");
11235           emitcode ("push", "acc");
11236         }
11237       else
11238         {
11239           /* this scales up to n<=255, but needs two more bytes
11240              and changes dptr */
11241           emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
11242           emitcode ("movc", "a,@a+dptr");
11243           emitcode ("push", "acc");
11244
11245           MOVA (l);
11246           emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
11247           emitcode ("movc", "a,@a+dptr");
11248           emitcode ("push", "acc");
11249         }
11250
11251       emitcode ("ret", "");
11252
11253       /* now generate jump table, LSB */
11254       emitLabel (jtablo);
11255       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11256            jtab = setNextItem (IC_JTLABELS (ic)))
11257         emitcode (".db", "%05d$", jtab->key + 100);
11258
11259       /* now generate jump table, MSB */
11260       emitLabel (jtabhi);
11261       for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11262            jtab = setNextItem (IC_JTLABELS (ic)))
11263          emitcode (".db", "%05d$>>8", jtab->key + 100);
11264     }
11265 }
11266
11267 /*-----------------------------------------------------------------*/
11268 /* genCast - gen code for casting                                  */
11269 /*-----------------------------------------------------------------*/
11270 static void
11271 genCast (iCode * ic)
11272 {
11273   operand *result = IC_RESULT (ic);
11274   sym_link *ctype = operandType (IC_LEFT (ic));
11275   sym_link *rtype = operandType (IC_RIGHT (ic));
11276   operand *right = IC_RIGHT (ic);
11277   int size, offset;
11278
11279   D (emitcode (";", "genCast"));
11280
11281   /* if they are equivalent then do nothing */
11282   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11283     return;
11284
11285   aopOp (right, ic, FALSE);
11286   aopOp (result, ic, FALSE);
11287
11288   /* if the result is a bit (and not a bitfield) */
11289   if (IS_BIT (OP_SYMBOL (result)->type))
11290     {
11291       assignBit (result, right);
11292       goto release;
11293     }
11294
11295   /* if they are the same size : or less */
11296   if (AOP_SIZE (result) <= AOP_SIZE (right))
11297     {
11298
11299       /* if they are in the same place */
11300       if (sameRegs (AOP (right), AOP (result)))
11301         goto release;
11302
11303       /* if they in different places then copy */
11304       size = AOP_SIZE (result);
11305       offset = 0;
11306       while (size--)
11307         {
11308           aopPut (result,
11309                   aopGet (right, offset, FALSE, FALSE),
11310                   offset);
11311           offset++;
11312         }
11313       goto release;
11314     }
11315
11316   /* if the result is of type pointer */
11317   if (IS_PTR (ctype))
11318     {
11319
11320       int p_type;
11321       sym_link *type = operandType (right);
11322       sym_link *etype = getSpec (type);
11323
11324       /* pointer to generic pointer */
11325       if (IS_GENPTR (ctype))
11326         {
11327           if (IS_PTR (type))
11328             {
11329               p_type = DCL_TYPE (type);
11330             }
11331           else
11332             {
11333               if (SPEC_SCLS(etype)==S_REGISTER) {
11334                 // let's assume it is a generic pointer
11335                 p_type=GPOINTER;
11336               } else {
11337                 /* we have to go by the storage class */
11338                 p_type = PTR_TYPE (SPEC_OCLS (etype));
11339               }
11340             }
11341
11342           /* the first two bytes are known */
11343           size = GPTRSIZE - 1;
11344           offset = 0;
11345           while (size--)
11346             {
11347               aopPut (result,
11348                       aopGet (right, offset, FALSE, FALSE),
11349                       offset);
11350               offset++;
11351             }
11352           /* the last byte depending on type */
11353             {
11354                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11355                 char gpValStr[10];
11356
11357                 if (gpVal == -1)
11358                 {
11359                     // pointerTypeToGPByte will have bitched.
11360                     exit(1);
11361                 }
11362
11363                 sprintf(gpValStr, "#0x%x", gpVal);
11364                 aopPut (result, gpValStr, GPTRSIZE - 1);
11365             }
11366           goto release;
11367         }
11368
11369       /* just copy the pointers */
11370       size = AOP_SIZE (result);
11371       offset = 0;
11372       while (size--)
11373         {
11374           aopPut (result,
11375                   aopGet (right, offset, FALSE, FALSE),
11376                   offset);
11377           offset++;
11378         }
11379       goto release;
11380     }
11381
11382   /* so we now know that the size of destination is greater
11383      than the size of the source */
11384   /* we move to result for the size of source */
11385   size = AOP_SIZE (right);
11386   offset = 0;
11387   while (size--)
11388     {
11389       aopPut (result,
11390               aopGet (right, offset, FALSE, FALSE),
11391               offset);
11392       offset++;
11393     }
11394
11395   /* now depending on the sign of the source && destination */
11396   size = AOP_SIZE (result) - AOP_SIZE (right);
11397   /* if unsigned or not an integral type */
11398   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11399     {
11400       while (size--)
11401         aopPut (result, zero, offset++);
11402     }
11403   else
11404     {
11405       /* we need to extend the sign :{ */
11406       char *l = aopGet (right, AOP_SIZE (right) - 1,
11407                         FALSE, FALSE);
11408       MOVA (l);
11409       emitcode ("rlc", "a");
11410       emitcode ("subb", "a,acc");
11411       while (size--)
11412         aopPut (result, "a", offset++);
11413     }
11414
11415   /* we are done hurray !!!! */
11416
11417 release:
11418   freeAsmop (result, NULL, ic, TRUE);
11419   freeAsmop (right, NULL, ic, TRUE);
11420 }
11421
11422 /*-----------------------------------------------------------------*/
11423 /* genDjnz - generate decrement & jump if not zero instrucion      */
11424 /*-----------------------------------------------------------------*/
11425 static int
11426 genDjnz (iCode * ic, iCode * ifx)
11427 {
11428   symbol *lbl, *lbl1;
11429   if (!ifx)
11430     return 0;
11431
11432   /* if the if condition has a false label
11433      then we cannot save */
11434   if (IC_FALSE (ifx))
11435     return 0;
11436
11437   /* if the minus is not of the form a = a - 1 */
11438   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11439       !IS_OP_LITERAL (IC_RIGHT (ic)))
11440     return 0;
11441
11442   if (operandLitValue (IC_RIGHT (ic)) != 1)
11443     return 0;
11444
11445   /* if the size of this greater than one then no
11446      saving */
11447   if (getSize (operandType (IC_RESULT (ic))) > 1)
11448     return 0;
11449
11450   /* otherwise we can save BIG */
11451
11452   D (emitcode (";", "genDjnz"));
11453
11454   lbl = newiTempLabel (NULL);
11455   lbl1 = newiTempLabel (NULL);
11456
11457   aopOp (IC_RESULT (ic), ic, FALSE);
11458
11459   if (AOP_NEEDSACC(IC_RESULT(ic)))
11460   {
11461       /* If the result is accessed indirectly via
11462        * the accumulator, we must explicitly write
11463        * it back after the decrement.
11464        */
11465       char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11466
11467       if (strcmp(rByte, "a"))
11468       {
11469            /* Something is hopelessly wrong */
11470            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11471                    __FILE__, __LINE__);
11472            /* We can just give up; the generated code will be inefficient,
11473             * but what the hey.
11474             */
11475            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11476            return 0;
11477       }
11478       emitcode ("dec", "%s", rByte);
11479       aopPut (IC_RESULT (ic), rByte, 0);
11480       emitcode ("jnz", "%05d$", lbl->key + 100);
11481   }
11482   else if (IS_AOP_PREG (IC_RESULT (ic)))
11483     {
11484       emitcode ("dec", "%s",
11485                 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11486       MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11487       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11488       ifx->generated = 1;
11489       emitcode ("jnz", "%05d$", lbl->key + 100);
11490     }
11491   else
11492     {
11493       emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11494                 lbl->key + 100);
11495     }
11496   emitcode ("sjmp", "%05d$", lbl1->key + 100);
11497   emitLabel (lbl);
11498   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11499   emitLabel (lbl1);
11500
11501   if (!ifx->generated)
11502       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11503   ifx->generated = 1;
11504   return 1;
11505 }
11506
11507 /*-----------------------------------------------------------------*/
11508 /* genReceive - generate code for a receive iCode                  */
11509 /*-----------------------------------------------------------------*/
11510 static void
11511 genReceive (iCode * ic)
11512 {
11513   int size = getSize (operandType (IC_RESULT (ic)));
11514   int offset = 0;
11515
11516   D (emitcode (";", "genReceive"));
11517
11518   if (ic->argreg == 1)
11519     { /* first parameter */
11520       if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11521            isOperandInPagedSpace (IC_RESULT (ic))) &&
11522           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11523            IS_TRUE_SYMOP (IC_RESULT (ic))))
11524         {
11525           regs *tempRegs[4];
11526           int receivingA = 0;
11527           int roffset = 0;
11528
11529           for (offset = 0; offset<size; offset++)
11530             if (!strcmp (fReturn[offset], "a"))
11531               receivingA = 1;
11532
11533           if (!receivingA)
11534             {
11535               if (size==1 || getTempRegs(tempRegs, size-1, ic))
11536                 {
11537                   for (offset = size-1; offset>0; offset--)
11538                     emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11539                   emitcode("mov","a,%s", fReturn[0]);
11540                   _G.accInUse++;
11541                   aopOp (IC_RESULT (ic), ic, FALSE);
11542                   _G.accInUse--;
11543                   aopPut (IC_RESULT (ic), "a", offset);
11544                   for (offset = 1; offset<size; offset++)
11545                     aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset);
11546                   goto release;
11547                 }
11548             }
11549           else
11550             {
11551               if (getTempRegs(tempRegs, size, ic))
11552                 {
11553                   for (offset = 0; offset<size; offset++)
11554                     emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11555                   aopOp (IC_RESULT (ic), ic, FALSE);
11556                   for (offset = 0; offset<size; offset++)
11557                     aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset);
11558                   goto release;
11559                 }
11560             }
11561
11562           offset = fReturnSizeMCS51 - size;
11563           while (size--)
11564             {
11565               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11566                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11567               offset++;
11568             }
11569           aopOp (IC_RESULT (ic), ic, FALSE);
11570           size = AOP_SIZE (IC_RESULT (ic));
11571           offset = 0;
11572           while (size--)
11573             {
11574               emitcode ("pop", "acc");
11575               aopPut (IC_RESULT (ic), "a", offset++);
11576             }
11577         }
11578       else
11579         {
11580           _G.accInUse++;
11581           aopOp (IC_RESULT (ic), ic, FALSE);
11582           _G.accInUse--;
11583           assignResultValue (IC_RESULT (ic), NULL);
11584         }
11585     }
11586   else if (ic->argreg > 12)
11587     { /* bit parameters */
11588       if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11589         {
11590           aopOp (IC_RESULT (ic), ic, FALSE);
11591           emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11592           outBitC(IC_RESULT (ic));
11593         }
11594     }
11595   else
11596     { /* other parameters */
11597       int rb1off ;
11598       aopOp (IC_RESULT (ic), ic, FALSE);
11599       rb1off = ic->argreg;
11600       while (size--)
11601         {
11602           aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++);
11603         }
11604     }
11605
11606 release:
11607   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11608 }
11609
11610 /*-----------------------------------------------------------------*/
11611 /* genDummyRead - generate code for dummy read of volatiles        */
11612 /*-----------------------------------------------------------------*/
11613 static void
11614 genDummyRead (iCode * ic)
11615 {
11616   operand *op;
11617   int size, offset;
11618
11619   D (emitcode(";", "genDummyRead"));
11620
11621   op = IC_RIGHT (ic);
11622   if (op && IS_SYMOP (op))
11623     {
11624       aopOp (op, ic, FALSE);
11625
11626       /* if the result is a bit */
11627       if (AOP_TYPE (op) == AOP_CRY)
11628         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11629       else
11630         {
11631           /* bit variables done */
11632           /* general case */
11633           size = AOP_SIZE (op);
11634           offset = 0;
11635           while (size--)
11636           {
11637             MOVA (aopGet (op, offset, FALSE, FALSE));
11638             offset++;
11639           }
11640         }
11641
11642       freeAsmop (op, NULL, ic, TRUE);
11643     }
11644
11645   op = IC_LEFT (ic);
11646   if (op && IS_SYMOP (op))
11647     {
11648       aopOp (op, ic, FALSE);
11649
11650       /* if the result is a bit */
11651       if (AOP_TYPE (op) == AOP_CRY)
11652         emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11653       else
11654         {
11655           /* bit variables done */
11656           /* general case */
11657           size = AOP_SIZE (op);
11658           offset = 0;
11659           while (size--)
11660           {
11661             MOVA (aopGet (op, offset, FALSE, FALSE));
11662             offset++;
11663           }
11664         }
11665
11666       freeAsmop (op, NULL, ic, TRUE);
11667     }
11668 }
11669
11670 /*-----------------------------------------------------------------*/
11671 /* genCritical - generate code for start of a critical sequence    */
11672 /*-----------------------------------------------------------------*/
11673 static void
11674 genCritical (iCode *ic)
11675 {
11676   symbol *tlbl = newiTempLabel (NULL);
11677
11678   D (emitcode(";", "genCritical"));
11679
11680   if (IC_RESULT (ic))
11681     {
11682       aopOp (IC_RESULT (ic), ic, TRUE);
11683       aopPut (IC_RESULT (ic), one, 0); /* save old ea in an operand */
11684       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11685       aopPut (IC_RESULT (ic), zero, 0);
11686       emitLabel (tlbl);
11687       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11688     }
11689   else
11690     {
11691       emitcode ("setb", "c");
11692       emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11693       emitcode ("clr", "c");
11694       emitLabel (tlbl);
11695       emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11696     }
11697 }
11698
11699 /*-----------------------------------------------------------------*/
11700 /* genEndCritical - generate code for end of a critical sequence   */
11701 /*-----------------------------------------------------------------*/
11702 static void
11703 genEndCritical (iCode *ic)
11704 {
11705   D(emitcode(";     genEndCritical",""));
11706
11707   if (IC_RIGHT (ic))
11708     {
11709       aopOp (IC_RIGHT (ic), ic, FALSE);
11710       if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11711         {
11712           emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11713           emitcode ("mov", "ea,c");
11714         }
11715       else
11716         {
11717           if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11718             MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11719           emitcode ("rrc", "a");
11720           emitcode ("mov", "ea,c");
11721         }
11722       freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11723     }
11724   else
11725     {
11726       emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11727       emitcode ("mov", "ea,c");
11728     }
11729 }
11730
11731 /*-----------------------------------------------------------------*/
11732 /* gen51Code - generate code for 8051 based controllers            */
11733 /*-----------------------------------------------------------------*/
11734 void
11735 gen51Code (iCode * lic)
11736 {
11737   iCode *ic;
11738   int cln = 0;
11739   /* int cseq = 0; */
11740
11741   _G.currentFunc = NULL;
11742   lineHead = lineCurr = NULL;
11743
11744   /* print the allocation information */
11745   if (allocInfo && currFunc)
11746     printAllocInfo (currFunc, codeOutBuf);
11747   /* if debug information required */
11748   if (options.debug && currFunc)
11749     {
11750       debugFile->writeFunction (currFunc, lic);
11751     }
11752   /* stack pointer name */
11753   if (options.useXstack)
11754     spname = "_spx";
11755   else
11756     spname = "sp";
11757
11758
11759   for (ic = lic; ic; ic = ic->next)
11760     {
11761       _G.current_iCode = ic;
11762
11763       if (ic->lineno && cln != ic->lineno)
11764         {
11765           if (options.debug)
11766             {
11767               debugFile->writeCLine (ic);
11768             }
11769           if (!options.noCcodeInAsm) {
11770             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
11771                       printCLine(ic->filename, ic->lineno));
11772           }
11773           cln = ic->lineno;
11774         }
11775       #if 0
11776       if (ic->seqPoint && ic->seqPoint != cseq)
11777         {
11778           emitcode ("", "; sequence point %d", ic->seqPoint);
11779           cseq = ic->seqPoint;
11780         }
11781       #endif
11782       if (options.iCodeInAsm) {
11783         char regsInUse[80];
11784         int i;
11785         char *iLine;
11786
11787         #if 0
11788         for (i=0; i<8; i++) {
11789           sprintf (&regsInUse[i],
11790                    "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11791         regsInUse[i]=0;
11792         #else
11793         strcpy (regsInUse, "--------");
11794         for (i=0; i < 8; i++) {
11795           if (bitVectBitValue (ic->rMask, i))
11796             {
11797               int offset = regs8051[i].offset;
11798               regsInUse[offset] = offset + '0'; /* show rMask */
11799             }
11800         #endif
11801         }
11802         iLine = printILine(ic);
11803         emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11804         dbuf_free(iLine);
11805       }
11806       /* if the result is marked as
11807          spilt and rematerializable or code for
11808          this has already been generated then
11809          do nothing */
11810       if (resultRemat (ic) || ic->generated)
11811         continue;
11812
11813       /* depending on the operation */
11814       switch (ic->op)
11815         {
11816         case '!':
11817           genNot (ic);
11818           break;
11819
11820         case '~':
11821           genCpl (ic);
11822           break;
11823
11824         case UNARYMINUS:
11825           genUminus (ic);
11826           break;
11827
11828         case IPUSH:
11829           genIpush (ic);
11830           break;
11831
11832         case IPOP:
11833           /* IPOP happens only when trying to restore a
11834              spilt live range, if there is an ifx statement
11835              following this pop then the if statement might
11836              be using some of the registers being popped which
11837              would destory the contents of the register so
11838              we need to check for this condition and handle it */
11839           if (ic->next &&
11840               ic->next->op == IFX &&
11841               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11842             genIfx (ic->next, ic);
11843           else
11844             genIpop (ic);
11845           break;
11846
11847         case CALL:
11848           genCall (ic);
11849           break;
11850
11851         case PCALL:
11852           genPcall (ic);
11853           break;
11854
11855         case FUNCTION:
11856           genFunction (ic);
11857           break;
11858
11859         case ENDFUNCTION:
11860           genEndFunction (ic);
11861           break;
11862
11863         case RETURN:
11864           genRet (ic);
11865           break;
11866
11867         case LABEL:
11868           genLabel (ic);
11869           break;
11870
11871         case GOTO:
11872           genGoto (ic);
11873           break;
11874
11875         case '+':
11876           genPlus (ic);
11877           break;
11878
11879         case '-':
11880           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11881             genMinus (ic);
11882           break;
11883
11884         case '*':
11885           genMult (ic);
11886           break;
11887
11888         case '/':
11889           genDiv (ic);
11890           break;
11891
11892         case '%':
11893           genMod (ic);
11894           break;
11895
11896         case '>':
11897           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11898           break;
11899
11900         case '<':
11901           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11902           break;
11903
11904         case LE_OP:
11905         case GE_OP:
11906         case NE_OP:
11907
11908           /* note these two are xlated by algebraic equivalence
11909              in decorateType() in SDCCast.c */
11910           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11911                   "got '>=' or '<=' shouldn't have come here");
11912           break;
11913
11914         case EQ_OP:
11915           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11916           break;
11917
11918         case AND_OP:
11919           genAndOp (ic);
11920           break;
11921
11922         case OR_OP:
11923           genOrOp (ic);
11924           break;
11925
11926         case '^':
11927           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11928           break;
11929
11930         case '|':
11931           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11932           break;
11933
11934         case BITWISEAND:
11935           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11936           break;
11937
11938         case INLINEASM:
11939           genInline (ic);
11940           break;
11941
11942         case RRC:
11943           genRRC (ic);
11944           break;
11945
11946         case RLC:
11947           genRLC (ic);
11948           break;
11949
11950         case GETHBIT:
11951           genGetHbit (ic);
11952           break;
11953
11954         case GETABIT:
11955           genGetAbit (ic);
11956           break;
11957
11958         case GETBYTE:
11959           genGetByte (ic);
11960           break;
11961
11962         case GETWORD:
11963           genGetWord (ic);
11964           break;
11965
11966         case LEFT_OP:
11967           genLeftShift (ic);
11968           break;
11969
11970         case RIGHT_OP:
11971           genRightShift (ic);
11972           break;
11973
11974         case GET_VALUE_AT_ADDRESS:
11975           genPointerGet (ic,
11976                          hasInc (IC_LEFT (ic), ic,
11977                                  getSize (operandType (IC_RESULT (ic)))),
11978                          ifxForOp (IC_RESULT (ic), ic) );
11979           break;
11980
11981         case '=':
11982           if (POINTER_SET (ic))
11983             genPointerSet (ic,
11984                            hasInc (IC_RESULT (ic), ic,
11985                                    getSize (operandType (IC_RIGHT (ic)))));
11986           else
11987             genAssign (ic);
11988           break;
11989
11990         case IFX:
11991           genIfx (ic, NULL);
11992           break;
11993
11994         case ADDRESS_OF:
11995           genAddrOf (ic);
11996           break;
11997
11998         case JUMPTABLE:
11999           genJumpTab (ic);
12000           break;
12001
12002         case CAST:
12003           genCast (ic);
12004           break;
12005
12006         case RECEIVE:
12007           genReceive (ic);
12008           break;
12009
12010         case SEND:
12011           addSet (&_G.sendSet, ic);
12012           break;
12013
12014         case DUMMY_READ_VOLATILE:
12015           genDummyRead (ic);
12016           break;
12017
12018         case CRITICAL:
12019           genCritical (ic);
12020           break;
12021
12022         case ENDCRITICAL:
12023           genEndCritical (ic);
12024           break;
12025
12026         case SWAP:
12027           genSwap (ic);
12028           break;
12029
12030         default:
12031           ic = ic;
12032         }
12033     }
12034
12035   _G.current_iCode = NULL;
12036
12037   /* now we are ready to call the
12038      peep hole optimizer */
12039   if (!options.nopeep)
12040     peepHole (&lineHead);
12041
12042   /* now do the actual printing */
12043   printLine (lineHead, codeOutBuf);
12044   return;
12045 }