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