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