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