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