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