630e1192a7bc88ffb423eea45be1efc431080c78
[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   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4212   if (!IS_SYMOP(op)) return NULL;
4213
4214   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4215   isize = getSize(type->next);
4216   while (lic) {
4217     /* if operand of the form op = op + <sizeof *op> */
4218     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4219         isOperandEqual(IC_RESULT(lic),op) && 
4220         isOperandLiteral(IC_RIGHT(lic)) &&
4221         operandLitValue(IC_RIGHT(lic)) == isize) {
4222       return lic;
4223     }
4224     /* if the operand used or deffed */
4225     if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4226       return NULL;
4227     }
4228     lic = lic->next;
4229   }
4230   return NULL;
4231 }
4232
4233 /*-----------------------------------------------------------------*/
4234 /* genAndOp - for && operation                                     */
4235 /*-----------------------------------------------------------------*/
4236 static void
4237 genAndOp (iCode * ic)
4238 {
4239   operand *left, *right, *result;
4240   symbol *tlbl;
4241
4242   /* note here that && operations that are in an
4243      if statement are taken away by backPatchLabels
4244      only those used in arthmetic operations remain */
4245   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4246   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4247   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4248
4249   /* if both are bit variables */
4250   if (AOP_TYPE (left) == AOP_CRY &&
4251       AOP_TYPE (right) == AOP_CRY)
4252     {
4253       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4254       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4255       outBitC (result);
4256     }
4257   else
4258     {
4259       tlbl = newiTempLabel (NULL);
4260       toBoolean (left);
4261       emitcode ("jz", "%05d$", tlbl->key + 100);
4262       toBoolean (right);
4263       emitcode ("", "%05d$:", tlbl->key + 100);
4264       outBitAcc (result);
4265     }
4266
4267   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269   freeAsmop (result, NULL, ic, TRUE);
4270 }
4271
4272
4273 /*-----------------------------------------------------------------*/
4274 /* genOrOp - for || operation                                      */
4275 /*-----------------------------------------------------------------*/
4276 static void
4277 genOrOp (iCode * ic)
4278 {
4279   operand *left, *right, *result;
4280   symbol *tlbl;
4281
4282   /* note here that || operations that are in an
4283      if statement are taken away by backPatchLabels
4284      only those used in arthmetic operations remain */
4285   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4286   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4287   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4288
4289   /* if both are bit variables */
4290   if (AOP_TYPE (left) == AOP_CRY &&
4291       AOP_TYPE (right) == AOP_CRY)
4292     {
4293       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4294       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4295       outBitC (result);
4296     }
4297   else
4298     {
4299       tlbl = newiTempLabel (NULL);
4300       toBoolean (left);
4301       emitcode ("jnz", "%05d$", tlbl->key + 100);
4302       toBoolean (right);
4303       emitcode ("", "%05d$:", tlbl->key + 100);
4304       outBitAcc (result);
4305     }
4306
4307   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4308   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4309   freeAsmop (result, NULL, ic, TRUE);
4310 }
4311
4312 /*-----------------------------------------------------------------*/
4313 /* isLiteralBit - test if lit == 2^n                               */
4314 /*-----------------------------------------------------------------*/
4315 static int
4316 isLiteralBit (unsigned long lit)
4317 {
4318   unsigned long pw[32] =
4319   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4320    0x100L, 0x200L, 0x400L, 0x800L,
4321    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4322    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4323    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4324    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4325    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4326   int idx;
4327
4328   for (idx = 0; idx < 32; idx++)
4329     if (lit == pw[idx])
4330       return idx + 1;
4331   return 0;
4332 }
4333
4334 /*-----------------------------------------------------------------*/
4335 /* continueIfTrue -                                                */
4336 /*-----------------------------------------------------------------*/
4337 static void
4338 continueIfTrue (iCode * ic)
4339 {
4340   if (IC_TRUE (ic))
4341     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4342   ic->generated = 1;
4343 }
4344
4345 /*-----------------------------------------------------------------*/
4346 /* jmpIfTrue -                                                     */
4347 /*-----------------------------------------------------------------*/
4348 static void
4349 jumpIfTrue (iCode * ic)
4350 {
4351   if (!IC_TRUE (ic))
4352     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4353   ic->generated = 1;
4354 }
4355
4356 /*-----------------------------------------------------------------*/
4357 /* jmpTrueOrFalse -                                                */
4358 /*-----------------------------------------------------------------*/
4359 static void
4360 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4361 {
4362   // ugly but optimized by peephole
4363   if (IC_TRUE (ic))
4364     {
4365       symbol *nlbl = newiTempLabel (NULL);
4366       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4367       emitcode ("", "%05d$:", tlbl->key + 100);
4368       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4369       emitcode ("", "%05d$:", nlbl->key + 100);
4370     }
4371   else
4372     {
4373       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4374       emitcode ("", "%05d$:", tlbl->key + 100);
4375     }
4376   ic->generated = 1;
4377 }
4378
4379 /*-----------------------------------------------------------------*/
4380 /* genAnd  - code for and                                          */
4381 /*-----------------------------------------------------------------*/
4382 static void
4383 genAnd (iCode * ic, iCode * ifx)
4384 {
4385   operand *left, *right, *result;
4386   int size, offset = 0;
4387   unsigned long lit = 0L;
4388   int bytelit = 0;
4389   char buffer[10];
4390
4391   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4392   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4393   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4394
4395 #ifdef DEBUG_TYPE
4396   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4397             AOP_TYPE (result),
4398             AOP_TYPE (left), AOP_TYPE (right));
4399   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4400             AOP_SIZE (result),
4401             AOP_SIZE (left), AOP_SIZE (right));
4402 #endif
4403
4404   /* if left is a literal & right is not then exchange them */
4405   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4406       AOP_NEEDSACC (left))
4407     {
4408       operand *tmp = right;
4409       right = left;
4410       left = tmp;
4411     }
4412
4413   /* if result = right then exchange them */
4414   if (sameRegs (AOP (result), AOP (right)))
4415     {
4416       operand *tmp = right;
4417       right = left;
4418       left = tmp;
4419     }
4420
4421   /* if right is bit then exchange them */
4422   if (AOP_TYPE (right) == AOP_CRY &&
4423       AOP_TYPE (left) != AOP_CRY)
4424     {
4425       operand *tmp = right;
4426       right = left;
4427       left = tmp;
4428     }
4429   if (AOP_TYPE (right) == AOP_LIT)
4430     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4431
4432   size = AOP_SIZE (result);
4433
4434   // if(bit & yy)
4435   // result = bit & yy;
4436   if (AOP_TYPE (left) == AOP_CRY)
4437     {
4438       // c = bit & literal;
4439       if (AOP_TYPE (right) == AOP_LIT)
4440         {
4441           if (lit & 1)
4442             {
4443               if (size && sameRegs (AOP (result), AOP (left)))
4444                 // no change
4445                 goto release;
4446               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4447             }
4448           else
4449             {
4450               // bit(result) = 0;
4451               if (size && (AOP_TYPE (result) == AOP_CRY))
4452                 {
4453                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4454                   goto release;
4455                 }
4456               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4457                 {
4458                   jumpIfTrue (ifx);
4459                   goto release;
4460                 }
4461               emitcode ("clr", "c");
4462             }
4463         }
4464       else
4465         {
4466           if (AOP_TYPE (right) == AOP_CRY)
4467             {
4468               // c = bit & bit;
4469               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4470               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4471             }
4472           else
4473             {
4474               // c = bit & val;
4475               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4476               // c = lsb
4477               emitcode ("rrc", "a");
4478               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4479             }
4480         }
4481       // bit = c
4482       // val = c
4483       if (size)
4484         outBitC (result);
4485       // if(bit & ...)
4486       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4487         genIfxJump (ifx, "c");
4488       goto release;
4489     }
4490
4491   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4492   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4493   if ((AOP_TYPE (right) == AOP_LIT) &&
4494       (AOP_TYPE (result) == AOP_CRY) &&
4495       (AOP_TYPE (left) != AOP_CRY))
4496     {
4497       int posbit = isLiteralBit (lit);
4498       /* left &  2^n */
4499       if (posbit)
4500         {
4501           posbit--;
4502           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4503           // bit = left & 2^n
4504           if (size)
4505             emitcode ("mov", "c,acc.%d", posbit & 0x07);
4506           // if(left &  2^n)
4507           else
4508             {
4509               if (ifx)
4510                 {
4511                   sprintf (buffer, "acc.%d", posbit & 0x07);
4512                   genIfxJump (ifx, buffer);
4513                 }
4514               goto release;
4515             }
4516         }
4517       else
4518         {
4519           symbol *tlbl = newiTempLabel (NULL);
4520           int sizel = AOP_SIZE (left);
4521           if (size)
4522             emitcode ("setb", "c");
4523           while (sizel--)
4524             {
4525               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4526                 {
4527                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4528                   // byte ==  2^n ?
4529                   if ((posbit = isLiteralBit (bytelit)) != 0)
4530                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4531                   else
4532                     {
4533                       if (bytelit != 0x0FFL)
4534                         emitcode ("anl", "a,%s",
4535                                   aopGet (AOP (right), offset, FALSE, TRUE));
4536                       emitcode ("jnz", "%05d$", tlbl->key + 100);
4537                     }
4538                 }
4539               offset++;
4540             }
4541           // bit = left & literal
4542           if (size)
4543             {
4544               emitcode ("clr", "c");
4545               emitcode ("", "%05d$:", tlbl->key + 100);
4546             }
4547           // if(left & literal)
4548           else
4549             {
4550               if (ifx)
4551                 jmpTrueOrFalse (ifx, tlbl);
4552               goto release;
4553             }
4554         }
4555       outBitC (result);
4556       goto release;
4557     }
4558
4559   /* if left is same as result */
4560   if (sameRegs (AOP (result), AOP (left)))
4561     {
4562       for (; size--; offset++)
4563         {
4564           if (AOP_TYPE (right) == AOP_LIT)
4565             {
4566               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4567                 continue;
4568               else if (bytelit == 0)
4569                 aopPut (AOP (result), zero, offset);
4570               else if (IS_AOP_PREG (result))
4571                 {
4572                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4573                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4574                   aopPut (AOP (result), "a", offset);
4575                 }
4576               else
4577                 emitcode ("anl", "%s,%s",
4578                           aopGet (AOP (left), offset, FALSE, TRUE),
4579                           aopGet (AOP (right), offset, FALSE, FALSE));
4580             }
4581           else
4582             {
4583               if (AOP_TYPE (left) == AOP_ACC)
4584                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4585               else
4586                 {
4587                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4588                   if (IS_AOP_PREG (result))
4589                     {
4590                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4591                       aopPut (AOP (result), "a", offset);
4592
4593                     }
4594                   else
4595                     emitcode ("anl", "%s,a",
4596                               aopGet (AOP (left), offset, FALSE, TRUE));
4597                 }
4598             }
4599         }
4600     }
4601   else
4602     {
4603       // left & result in different registers
4604       if (AOP_TYPE (result) == AOP_CRY)
4605         {
4606           // result = bit
4607           // if(size), result in bit
4608           // if(!size && ifx), conditional oper: if(left & right)
4609           symbol *tlbl = newiTempLabel (NULL);
4610           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4611           if (size)
4612             emitcode ("setb", "c");
4613           while (sizer--)
4614             {
4615               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4616                 emitcode ("anl", "a,%s",
4617                           aopGet (AOP (right), offset, FALSE, FALSE));
4618               } else {
4619                 if (AOP_TYPE(left)==AOP_ACC) {
4620                   emitcode("mov", "b,a");
4621                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4622                   emitcode("anl", "a,b");
4623                 }else {
4624                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4625                   emitcode ("anl", "a,%s",
4626                             aopGet (AOP (left), offset, FALSE, FALSE));
4627                 }
4628               }
4629               emitcode ("jnz", "%05d$", tlbl->key + 100);
4630               offset++;
4631             }
4632           if (size)
4633             {
4634               CLRC;
4635               emitcode ("", "%05d$:", tlbl->key + 100);
4636               outBitC (result);
4637             }
4638           else if (ifx)
4639             jmpTrueOrFalse (ifx, tlbl);
4640         }
4641       else
4642         {
4643           for (; (size--); offset++)
4644             {
4645               // normal case
4646               // result = left & right
4647               if (AOP_TYPE (right) == AOP_LIT)
4648                 {
4649                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4650                     {
4651                       aopPut (AOP (result),
4652                               aopGet (AOP (left), offset, FALSE, FALSE),
4653                               offset);
4654                       continue;
4655                     }
4656                   else if (bytelit == 0)
4657                     {
4658                       aopPut (AOP (result), zero, offset);
4659                       continue;
4660                     }
4661                 }
4662               // faster than result <- left, anl result,right
4663               // and better if result is SFR
4664               if (AOP_TYPE (left) == AOP_ACC)
4665                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4666               else
4667                 {
4668                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4669                   emitcode ("anl", "a,%s",
4670                             aopGet (AOP (left), offset, FALSE, FALSE));
4671                 }
4672               aopPut (AOP (result), "a", offset);
4673             }
4674         }
4675     }
4676
4677 release:
4678   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680   freeAsmop (result, NULL, ic, TRUE);
4681 }
4682
4683 /*-----------------------------------------------------------------*/
4684 /* genOr  - code for or                                            */
4685 /*-----------------------------------------------------------------*/
4686 static void
4687 genOr (iCode * ic, iCode * ifx)
4688 {
4689   operand *left, *right, *result;
4690   int size, offset = 0;
4691   unsigned long lit = 0L;
4692
4693   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4694   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4695   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4696
4697 #ifdef DEBUG_TYPE
4698   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4699             AOP_TYPE (result),
4700             AOP_TYPE (left), AOP_TYPE (right));
4701   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4702             AOP_SIZE (result),
4703             AOP_SIZE (left), AOP_SIZE (right));
4704 #endif
4705
4706   /* if left is a literal & right is not then exchange them */
4707   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4708       AOP_NEEDSACC (left))
4709     {
4710       operand *tmp = right;
4711       right = left;
4712       left = tmp;
4713     }
4714
4715   /* if result = right then exchange them */
4716   if (sameRegs (AOP (result), AOP (right)))
4717     {
4718       operand *tmp = right;
4719       right = left;
4720       left = tmp;
4721     }
4722
4723   /* if right is bit then exchange them */
4724   if (AOP_TYPE (right) == AOP_CRY &&
4725       AOP_TYPE (left) != AOP_CRY)
4726     {
4727       operand *tmp = right;
4728       right = left;
4729       left = tmp;
4730     }
4731   if (AOP_TYPE (right) == AOP_LIT)
4732     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4733
4734   size = AOP_SIZE (result);
4735
4736   // if(bit | yy)
4737   // xx = bit | yy;
4738   if (AOP_TYPE (left) == AOP_CRY)
4739     {
4740       if (AOP_TYPE (right) == AOP_LIT)
4741         {
4742           // c = bit & literal;
4743           if (lit)
4744             {
4745               // lit != 0 => result = 1
4746               if (AOP_TYPE (result) == AOP_CRY)
4747                 {
4748                   if (size)
4749                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4750                   else if (ifx)
4751                     continueIfTrue (ifx);
4752                   goto release;
4753                 }
4754               emitcode ("setb", "c");
4755             }
4756           else
4757             {
4758               // lit == 0 => result = left
4759               if (size && sameRegs (AOP (result), AOP (left)))
4760                 goto release;
4761               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4762             }
4763         }
4764       else
4765         {
4766           if (AOP_TYPE (right) == AOP_CRY)
4767             {
4768               // c = bit | bit;
4769               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4770               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4771             }
4772           else
4773             {
4774               // c = bit | val;
4775               symbol *tlbl = newiTempLabel (NULL);
4776               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4777                 emitcode ("setb", "c");
4778               emitcode ("jb", "%s,%05d$",
4779                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
4780               toBoolean (right);
4781               emitcode ("jnz", "%05d$", tlbl->key + 100);
4782               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4783                 {
4784                   jmpTrueOrFalse (ifx, tlbl);
4785                   goto release;
4786                 }
4787               else
4788                 {
4789                   CLRC;
4790                   emitcode ("", "%05d$:", tlbl->key + 100);
4791                 }
4792             }
4793         }
4794       // bit = c
4795       // val = c
4796       if (size)
4797         outBitC (result);
4798       // if(bit | ...)
4799       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4800         genIfxJump (ifx, "c");
4801       goto release;
4802     }
4803
4804   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4805   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4806   if ((AOP_TYPE (right) == AOP_LIT) &&
4807       (AOP_TYPE (result) == AOP_CRY) &&
4808       (AOP_TYPE (left) != AOP_CRY))
4809     {
4810       if (lit)
4811         {
4812           // result = 1
4813           if (size)
4814             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4815           else
4816             continueIfTrue (ifx);
4817           goto release;
4818         }
4819       else
4820         {
4821           // lit = 0, result = boolean(left)
4822           if (size)
4823             emitcode ("setb", "c");
4824           toBoolean (right);
4825           if (size)
4826             {
4827               symbol *tlbl = newiTempLabel (NULL);
4828               emitcode ("jnz", "%05d$", tlbl->key + 100);
4829               CLRC;
4830               emitcode ("", "%05d$:", tlbl->key + 100);
4831             }
4832           else
4833             {
4834               genIfxJump (ifx, "a");
4835               goto release;
4836             }
4837         }
4838       outBitC (result);
4839       goto release;
4840     }
4841
4842   /* if left is same as result */
4843   if (sameRegs (AOP (result), AOP (left)))
4844     {
4845       for (; size--; offset++)
4846         {
4847           if (AOP_TYPE (right) == AOP_LIT)
4848             {
4849               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4850                 continue;
4851               else if (IS_AOP_PREG (left))
4852                 {
4853                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4854                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4855                   aopPut (AOP (result), "a", offset);
4856                 }
4857               else
4858                 emitcode ("orl", "%s,%s",
4859                           aopGet (AOP (left), offset, FALSE, TRUE),
4860                           aopGet (AOP (right), offset, FALSE, FALSE));
4861             }
4862           else
4863             {
4864               if (AOP_TYPE (left) == AOP_ACC)
4865                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4866               else
4867                 {
4868                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4869                   if (IS_AOP_PREG (left))
4870                     {
4871                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4872                       aopPut (AOP (result), "a", offset);
4873                     }
4874                   else
4875                     emitcode ("orl", "%s,a",
4876                               aopGet (AOP (left), offset, FALSE, TRUE));
4877                 }
4878             }
4879         }
4880     }
4881   else
4882     {
4883       // left & result in different registers
4884       if (AOP_TYPE (result) == AOP_CRY)
4885         {
4886           // result = bit
4887           // if(size), result in bit
4888           // if(!size && ifx), conditional oper: if(left | right)
4889           symbol *tlbl = newiTempLabel (NULL);
4890           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4891           if (size)
4892             emitcode ("setb", "c");
4893           while (sizer--)
4894             {
4895               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4896                 emitcode ("orl", "a,%s",
4897                           aopGet (AOP (right), offset, FALSE, FALSE));
4898               } else {
4899                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4900                 emitcode ("orl", "a,%s",
4901                           aopGet (AOP (left), offset, FALSE, FALSE));
4902               }
4903               emitcode ("jnz", "%05d$", tlbl->key + 100);
4904               offset++;
4905             }
4906           if (size)
4907             {
4908               CLRC;
4909               emitcode ("", "%05d$:", tlbl->key + 100);
4910               outBitC (result);
4911             }
4912           else if (ifx)
4913             jmpTrueOrFalse (ifx, tlbl);
4914         }
4915       else
4916         for (; (size--); offset++)
4917           {
4918             // normal case
4919             // result = left & right
4920             if (AOP_TYPE (right) == AOP_LIT)
4921               {
4922                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4923                   {
4924                     aopPut (AOP (result),
4925                             aopGet (AOP (left), offset, FALSE, FALSE),
4926                             offset);
4927                     continue;
4928                   }
4929               }
4930             // faster than result <- left, anl result,right
4931             // and better if result is SFR
4932             if (AOP_TYPE (left) == AOP_ACC)
4933               emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4934             else
4935               {
4936                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4937                 emitcode ("orl", "a,%s",
4938                           aopGet (AOP (left), offset, FALSE, FALSE));
4939               }
4940             aopPut (AOP (result), "a", offset);
4941           }
4942     }
4943
4944 release:
4945   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4946   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4947   freeAsmop (result, NULL, ic, TRUE);
4948 }
4949
4950 /*-----------------------------------------------------------------*/
4951 /* genXor - code for xclusive or                                   */
4952 /*-----------------------------------------------------------------*/
4953 static void
4954 genXor (iCode * ic, iCode * ifx)
4955 {
4956   operand *left, *right, *result;
4957   int size, offset = 0;
4958   unsigned long lit = 0L;
4959
4960   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4961   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4962   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4963
4964 #ifdef DEBUG_TYPE
4965   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4966             AOP_TYPE (result),
4967             AOP_TYPE (left), AOP_TYPE (right));
4968   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4969             AOP_SIZE (result),
4970             AOP_SIZE (left), AOP_SIZE (right));
4971 #endif
4972
4973   /* if left is a literal & right is not ||
4974      if left needs acc & right does not */
4975   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4976       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4977     {
4978       operand *tmp = right;
4979       right = left;
4980       left = tmp;
4981     }
4982
4983   /* if result = right then exchange them */
4984   if (sameRegs (AOP (result), AOP (right)))
4985     {
4986       operand *tmp = right;
4987       right = left;
4988       left = tmp;
4989     }
4990
4991   /* if right is bit then exchange them */
4992   if (AOP_TYPE (right) == AOP_CRY &&
4993       AOP_TYPE (left) != AOP_CRY)
4994     {
4995       operand *tmp = right;
4996       right = left;
4997       left = tmp;
4998     }
4999   if (AOP_TYPE (right) == AOP_LIT)
5000     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5001
5002   size = AOP_SIZE (result);
5003
5004   // if(bit ^ yy)
5005   // xx = bit ^ yy;
5006   if (AOP_TYPE (left) == AOP_CRY)
5007     {
5008       if (AOP_TYPE (right) == AOP_LIT)
5009         {
5010           // c = bit & literal;
5011           if (lit >> 1)
5012             {
5013               // lit>>1  != 0 => result = 1
5014               if (AOP_TYPE (result) == AOP_CRY)
5015                 {
5016                   if (size)
5017                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5018                   else if (ifx)
5019                     continueIfTrue (ifx);
5020                   goto release;
5021                 }
5022               emitcode ("setb", "c");
5023             }
5024           else
5025             {
5026               // lit == (0 or 1)
5027               if (lit == 0)
5028                 {
5029                   // lit == 0, result = left
5030                   if (size && sameRegs (AOP (result), AOP (left)))
5031                     goto release;
5032                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5033                 }
5034               else
5035                 {
5036                   // lit == 1, result = not(left)
5037                   if (size && sameRegs (AOP (result), AOP (left)))
5038                     {
5039                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5040                       goto release;
5041                     }
5042                   else
5043                     {
5044                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5045                       emitcode ("cpl", "c");
5046                     }
5047                 }
5048             }
5049
5050         }
5051       else
5052         {
5053           // right != literal
5054           symbol *tlbl = newiTempLabel (NULL);
5055           if (AOP_TYPE (right) == AOP_CRY)
5056             {
5057               // c = bit ^ bit;
5058               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5059             }
5060           else
5061             {
5062               int sizer = AOP_SIZE (right);
5063               // c = bit ^ val
5064               // if val>>1 != 0, result = 1
5065               emitcode ("setb", "c");
5066               while (sizer)
5067                 {
5068                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5069                   if (sizer == 1)
5070                     // test the msb of the lsb
5071                     emitcode ("anl", "a,#0xfe");
5072                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5073                   sizer--;
5074                 }
5075               // val = (0,1)
5076               emitcode ("rrc", "a");
5077             }
5078           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5079           emitcode ("cpl", "c");
5080           emitcode ("", "%05d$:", (tlbl->key + 100));
5081         }
5082       // bit = c
5083       // val = c
5084       if (size)
5085         outBitC (result);
5086       // if(bit | ...)
5087       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5088         genIfxJump (ifx, "c");
5089       goto release;
5090     }
5091
5092   if (sameRegs (AOP (result), AOP (left)))
5093     {
5094       /* if left is same as result */
5095       for (; size--; offset++)
5096         {
5097           if (AOP_TYPE (right) == AOP_LIT)
5098             {
5099               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5100                 continue;
5101               else if (IS_AOP_PREG (left))
5102                 {
5103                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5104                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5105                   aopPut (AOP (result), "a", offset);
5106                 }
5107               else
5108                 emitcode ("xrl", "%s,%s",
5109                           aopGet (AOP (left), offset, FALSE, TRUE),
5110                           aopGet (AOP (right), offset, FALSE, FALSE));
5111             }
5112           else
5113             {
5114               if (AOP_TYPE (left) == AOP_ACC)
5115                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5116               else
5117                 {
5118                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5119                   if (IS_AOP_PREG (left))
5120                     {
5121                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5122                       aopPut (AOP (result), "a", offset);
5123                     }
5124                   else
5125                     emitcode ("xrl", "%s,a",
5126                               aopGet (AOP (left), offset, FALSE, TRUE));
5127                 }
5128             }
5129         }
5130     }
5131   else
5132     {
5133       // left & result in different registers
5134       if (AOP_TYPE (result) == AOP_CRY)
5135         {
5136           // result = bit
5137           // if(size), result in bit
5138           // if(!size && ifx), conditional oper: if(left ^ right)
5139           symbol *tlbl = newiTempLabel (NULL);
5140           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5141           if (size)
5142             emitcode ("setb", "c");
5143           while (sizer--)
5144             {
5145               if ((AOP_TYPE (right) == AOP_LIT) &&
5146                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5147                 {
5148                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5149                 }
5150               else
5151                 {
5152                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5153                     emitcode ("xrl", "a,%s",
5154                               aopGet (AOP (right), offset, FALSE, FALSE));
5155                   } else {
5156                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5157                     emitcode ("xrl", "a,%s",
5158                               aopGet (AOP (left), offset, FALSE, FALSE));
5159                   }
5160                 }
5161               emitcode ("jnz", "%05d$", tlbl->key + 100);
5162               offset++;
5163             }
5164           if (size)
5165             {
5166               CLRC;
5167               emitcode ("", "%05d$:", tlbl->key + 100);
5168               outBitC (result);
5169             }
5170           else if (ifx)
5171             jmpTrueOrFalse (ifx, tlbl);
5172         }
5173       else
5174         for (; (size--); offset++)
5175           {
5176             // normal case
5177             // result = left & right
5178             if (AOP_TYPE (right) == AOP_LIT)
5179               {
5180                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5181                   {
5182                     aopPut (AOP (result),
5183                             aopGet (AOP (left), offset, FALSE, FALSE),
5184                             offset);
5185                     continue;
5186                   }
5187               }
5188             // faster than result <- left, anl result,right
5189             // and better if result is SFR
5190             if (AOP_TYPE (left) == AOP_ACC)
5191               emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5192             else
5193               {
5194                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5195                 emitcode ("xrl", "a,%s",
5196                           aopGet (AOP (left), offset, FALSE, TRUE));
5197               }
5198             aopPut (AOP (result), "a", offset);
5199           }
5200     }
5201
5202 release:
5203   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5204   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5205   freeAsmop (result, NULL, ic, TRUE);
5206 }
5207
5208 /*-----------------------------------------------------------------*/
5209 /* genInline - write the inline code out                           */
5210 /*-----------------------------------------------------------------*/
5211 static void
5212 genInline (iCode * ic)
5213 {
5214   char *buffer, *bp, *bp1;
5215
5216   _G.inLine += (!options.asmpeep);
5217
5218   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5219   strcpy (buffer, IC_INLINE (ic));
5220
5221   /* emit each line as a code */
5222   while (*bp)
5223     {
5224       if (*bp == '\n')
5225         {
5226           *bp++ = '\0';
5227           emitcode (bp1, "");
5228           bp1 = bp;
5229         }
5230       else
5231         {
5232           if (*bp == ':')
5233             {
5234               bp++;
5235               *bp = '\0';
5236               bp++;
5237               emitcode (bp1, "");
5238               bp1 = bp;
5239             }
5240           else
5241             bp++;
5242         }
5243     }
5244   if (bp1 != bp)
5245     emitcode (bp1, "");
5246   /*     emitcode("",buffer); */
5247   _G.inLine -= (!options.asmpeep);
5248 }
5249
5250 /*-----------------------------------------------------------------*/
5251 /* genRRC - rotate right with carry                                */
5252 /*-----------------------------------------------------------------*/
5253 static void
5254 genRRC (iCode * ic)
5255 {
5256   operand *left, *result;
5257   int size, offset = 0;
5258   char *l;
5259
5260   /* rotate right with carry */
5261   left = IC_LEFT (ic);
5262   result = IC_RESULT (ic);
5263   aopOp (left, ic, FALSE);
5264   aopOp (result, ic, FALSE);
5265
5266   /* move it to the result */
5267   size = AOP_SIZE (result);
5268   offset = size - 1;
5269   if (size == 1) { /* special case for 1 byte */
5270       l = aopGet (AOP (left), offset, FALSE, FALSE);
5271       MOVA (l);
5272       emitcode ("rr", "a");
5273       goto release;
5274   }
5275   CLRC;
5276   while (size--)
5277     {
5278       l = aopGet (AOP (left), offset, FALSE, FALSE);
5279       MOVA (l);
5280       emitcode ("rrc", "a");
5281       if (AOP_SIZE (result) > 1)
5282         aopPut (AOP (result), "a", offset--);
5283     }
5284   /* now we need to put the carry into the
5285      highest order byte of the result */
5286   if (AOP_SIZE (result) > 1)
5287     {
5288       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5289       MOVA (l);
5290     }
5291   emitcode ("mov", "acc.7,c");
5292  release:
5293   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5294   freeAsmop (left, NULL, ic, TRUE);
5295   freeAsmop (result, NULL, ic, TRUE);
5296 }
5297
5298 /*-----------------------------------------------------------------*/
5299 /* genRLC - generate code for rotate left with carry               */
5300 /*-----------------------------------------------------------------*/
5301 static void
5302 genRLC (iCode * ic)
5303 {
5304   operand *left, *result;
5305   int size, offset = 0;
5306   char *l;
5307
5308   /* rotate right with carry */
5309   left = IC_LEFT (ic);
5310   result = IC_RESULT (ic);
5311   aopOp (left, ic, FALSE);
5312   aopOp (result, ic, FALSE);
5313
5314   /* move it to the result */
5315   size = AOP_SIZE (result);
5316   offset = 0;
5317   if (size--)
5318     {
5319       l = aopGet (AOP (left), offset, FALSE, FALSE);
5320       MOVA (l);
5321       if (size == 0) { /* special case for 1 byte */
5322               emitcode("rl","a");
5323               goto release;
5324       }
5325       emitcode ("add", "a,acc");
5326       if (AOP_SIZE (result) > 1)
5327         aopPut (AOP (result), "a", offset++);
5328       while (size--)
5329         {
5330           l = aopGet (AOP (left), offset, FALSE, FALSE);
5331           MOVA (l);
5332           emitcode ("rlc", "a");
5333           if (AOP_SIZE (result) > 1)
5334             aopPut (AOP (result), "a", offset++);
5335         }
5336     }
5337   /* now we need to put the carry into the
5338      highest order byte of the result */
5339   if (AOP_SIZE (result) > 1)
5340     {
5341       l = aopGet (AOP (result), 0, FALSE, FALSE);
5342       MOVA (l);
5343     }
5344   emitcode ("mov", "acc.0,c");
5345  release:
5346   aopPut (AOP (result), "a", 0);
5347   freeAsmop (left, NULL, ic, TRUE);
5348   freeAsmop (result, NULL, ic, TRUE);
5349 }
5350
5351 /*-----------------------------------------------------------------*/
5352 /* genGetHbit - generates code get highest order bit               */
5353 /*-----------------------------------------------------------------*/
5354 static void
5355 genGetHbit (iCode * ic)
5356 {
5357   operand *left, *result;
5358   left = IC_LEFT (ic);
5359   result = IC_RESULT (ic);
5360   aopOp (left, ic, FALSE);
5361   aopOp (result, ic, FALSE);
5362
5363   /* get the highest order byte into a */
5364   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5365   if (AOP_TYPE (result) == AOP_CRY)
5366     {
5367       emitcode ("rlc", "a");
5368       outBitC (result);
5369     }
5370   else
5371     {
5372       emitcode ("rl", "a");
5373       emitcode ("anl", "a,#0x01");
5374       outAcc (result);
5375     }
5376
5377
5378   freeAsmop (left, NULL, ic, TRUE);
5379   freeAsmop (result, NULL, ic, TRUE);
5380 }
5381
5382 /*-----------------------------------------------------------------*/
5383 /* AccRol - rotate left accumulator by known count                 */
5384 /*-----------------------------------------------------------------*/
5385 static void
5386 AccRol (int shCount)
5387 {
5388   shCount &= 0x0007;            // shCount : 0..7
5389
5390   switch (shCount)
5391     {
5392     case 0:
5393       break;
5394     case 1:
5395       emitcode ("rl", "a");
5396       break;
5397     case 2:
5398       emitcode ("rl", "a");
5399       emitcode ("rl", "a");
5400       break;
5401     case 3:
5402       emitcode ("swap", "a");
5403       emitcode ("rr", "a");
5404       break;
5405     case 4:
5406       emitcode ("swap", "a");
5407       break;
5408     case 5:
5409       emitcode ("swap", "a");
5410       emitcode ("rl", "a");
5411       break;
5412     case 6:
5413       emitcode ("rr", "a");
5414       emitcode ("rr", "a");
5415       break;
5416     case 7:
5417       emitcode ("rr", "a");
5418       break;
5419     }
5420 }
5421
5422 /*-----------------------------------------------------------------*/
5423 /* AccLsh - left shift accumulator by known count                  */
5424 /*-----------------------------------------------------------------*/
5425 static void
5426 AccLsh (int shCount)
5427 {
5428   if (shCount != 0)
5429     {
5430       if (shCount == 1)
5431         emitcode ("add", "a,acc");
5432       else if (shCount == 2)
5433         {
5434           emitcode ("add", "a,acc");
5435           emitcode ("add", "a,acc");
5436         }
5437       else
5438         {
5439           /* rotate left accumulator */
5440           AccRol (shCount);
5441           /* and kill the lower order bits */
5442           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5443         }
5444     }
5445 }
5446
5447 /*-----------------------------------------------------------------*/
5448 /* AccRsh - right shift accumulator by known count                 */
5449 /*-----------------------------------------------------------------*/
5450 static void
5451 AccRsh (int shCount)
5452 {
5453   if (shCount != 0)
5454     {
5455       if (shCount == 1)
5456         {
5457           CLRC;
5458           emitcode ("rrc", "a");
5459         }
5460       else
5461         {
5462           /* rotate right accumulator */
5463           AccRol (8 - shCount);
5464           /* and kill the higher order bits */
5465           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5466         }
5467     }
5468 }
5469
5470 /*-----------------------------------------------------------------*/
5471 /* AccSRsh - signed right shift accumulator by known count                 */
5472 /*-----------------------------------------------------------------*/
5473 static void
5474 AccSRsh (int shCount)
5475 {
5476   symbol *tlbl;
5477   if (shCount != 0)
5478     {
5479       if (shCount == 1)
5480         {
5481           emitcode ("mov", "c,acc.7");
5482           emitcode ("rrc", "a");
5483         }
5484       else if (shCount == 2)
5485         {
5486           emitcode ("mov", "c,acc.7");
5487           emitcode ("rrc", "a");
5488           emitcode ("mov", "c,acc.7");
5489           emitcode ("rrc", "a");
5490         }
5491       else
5492         {
5493           tlbl = newiTempLabel (NULL);
5494           /* rotate right accumulator */
5495           AccRol (8 - shCount);
5496           /* and kill the higher order bits */
5497           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5498           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5499           emitcode ("orl", "a,#0x%02x",
5500                     (unsigned char) ~SRMask[shCount]);
5501           emitcode ("", "%05d$:", tlbl->key + 100);
5502         }
5503     }
5504 }
5505
5506 /*-----------------------------------------------------------------*/
5507 /* shiftR1Left2Result - shift right one byte from left to result   */
5508 /*-----------------------------------------------------------------*/
5509 static void
5510 shiftR1Left2Result (operand * left, int offl,
5511                     operand * result, int offr,
5512                     int shCount, int sign)
5513 {
5514   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5515   /* shift right accumulator */
5516   if (sign)
5517     AccSRsh (shCount);
5518   else
5519     AccRsh (shCount);
5520   aopPut (AOP (result), "a", offr);
5521 }
5522
5523 /*-----------------------------------------------------------------*/
5524 /* shiftL1Left2Result - shift left one byte from left to result    */
5525 /*-----------------------------------------------------------------*/
5526 static void
5527 shiftL1Left2Result (operand * left, int offl,
5528                     operand * result, int offr, int shCount)
5529 {
5530   char *l;
5531   l = aopGet (AOP (left), offl, FALSE, FALSE);
5532   MOVA (l);
5533   /* shift left accumulator */
5534   AccLsh (shCount);
5535   aopPut (AOP (result), "a", offr);
5536 }
5537
5538 /*-----------------------------------------------------------------*/
5539 /* movLeft2Result - move byte from left to result                  */
5540 /*-----------------------------------------------------------------*/
5541 static void
5542 movLeft2Result (operand * left, int offl,
5543                 operand * result, int offr, int sign)
5544 {
5545   char *l;
5546   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5547     {
5548       l = aopGet (AOP (left), offl, FALSE, FALSE);
5549
5550       if (*l == '@' && (IS_AOP_PREG (result)))
5551         {
5552           emitcode ("mov", "a,%s", l);
5553           aopPut (AOP (result), "a", offr);
5554         }
5555       else
5556         {
5557           if (!sign)
5558             aopPut (AOP (result), l, offr);
5559           else
5560             {
5561               /* MSB sign in acc.7 ! */
5562               if (getDataSize (left) == offl + 1)
5563                 {
5564                   emitcode ("mov", "a,%s", l);
5565                   aopPut (AOP (result), "a", offr);
5566                 }
5567             }
5568         }
5569     }
5570 }
5571
5572 /*-----------------------------------------------------------------*/
5573 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5574 /*-----------------------------------------------------------------*/
5575 static void
5576 AccAXRrl1 (char *x)
5577 {
5578   emitcode ("rrc", "a");
5579   emitcode ("xch", "a,%s", x);
5580   emitcode ("rrc", "a");
5581   emitcode ("xch", "a,%s", x);
5582 }
5583
5584 /*-----------------------------------------------------------------*/
5585 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5586 /*-----------------------------------------------------------------*/
5587 static void
5588 AccAXLrl1 (char *x)
5589 {
5590   emitcode ("xch", "a,%s", x);
5591   emitcode ("rlc", "a");
5592   emitcode ("xch", "a,%s", x);
5593   emitcode ("rlc", "a");
5594 }
5595
5596 /*-----------------------------------------------------------------*/
5597 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5598 /*-----------------------------------------------------------------*/
5599 static void
5600 AccAXLsh1 (char *x)
5601 {
5602   emitcode ("xch", "a,%s", x);
5603   emitcode ("add", "a,acc");
5604   emitcode ("xch", "a,%s", x);
5605   emitcode ("rlc", "a");
5606 }
5607
5608 /*-----------------------------------------------------------------*/
5609 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5610 /*-----------------------------------------------------------------*/
5611 static void
5612 AccAXLsh (char *x, int shCount)
5613 {
5614   switch (shCount)
5615     {
5616     case 0:
5617       break;
5618     case 1:
5619       AccAXLsh1 (x);
5620       break;
5621     case 2:
5622       AccAXLsh1 (x);
5623       AccAXLsh1 (x);
5624       break;
5625     case 3:
5626     case 4:
5627     case 5:                     // AAAAABBB:CCCCCDDD
5628
5629       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
5630
5631       emitcode ("anl", "a,#0x%02x",
5632                 SLMask[shCount]);       // BBB00000:CCCCCDDD
5633
5634       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
5635
5636       AccRol (shCount);         // DDDCCCCC:BBB00000
5637
5638       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
5639
5640       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
5641
5642       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
5643
5644       emitcode ("anl", "a,#0x%02x",
5645                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
5646
5647       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
5648
5649       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
5650
5651       break;
5652     case 6:                     // AAAAAABB:CCCCCCDD
5653       emitcode ("anl", "a,#0x%02x",
5654                 SRMask[shCount]);       // 000000BB:CCCCCCDD
5655       emitcode ("mov", "c,acc.0");      // c = B
5656       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
5657 #if 0 // REMOVE ME
5658       AccAXRrl1 (x);            // BCCCCCCD:D000000B
5659       AccAXRrl1 (x);            // BBCCCCCC:DD000000
5660 #else
5661       emitcode("rrc","a"); 
5662       emitcode("xch","a,%s", x); 
5663       emitcode("rrc","a"); 
5664       emitcode("mov","c,acc.0"); //<< get correct bit 
5665       emitcode("xch","a,%s", x); 
5666
5667       emitcode("rrc","a"); 
5668       emitcode("xch","a,%s", x); 
5669       emitcode("rrc","a"); 
5670       emitcode("xch","a,%s", x); 
5671 #endif
5672       break;
5673     case 7:                     // a:x <<= 7
5674
5675       emitcode ("anl", "a,#0x%02x",
5676                 SRMask[shCount]);       // 0000000B:CCCCCCCD
5677
5678       emitcode ("mov", "c,acc.0");      // c = B
5679
5680       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
5681
5682       AccAXRrl1 (x);            // BCCCCCCC:D0000000
5683
5684       break;
5685     default:
5686       break;
5687     }
5688 }
5689
5690 /*-----------------------------------------------------------------*/
5691 /* AccAXRsh - right shift a:x known count (0..7)                   */
5692 /*-----------------------------------------------------------------*/
5693 static void
5694 AccAXRsh (char *x, int shCount)
5695 {
5696   switch (shCount)
5697     {
5698     case 0:
5699       break;
5700     case 1:
5701       CLRC;
5702       AccAXRrl1 (x);            // 0->a:x
5703
5704       break;
5705     case 2:
5706       CLRC;
5707       AccAXRrl1 (x);            // 0->a:x
5708
5709       CLRC;
5710       AccAXRrl1 (x);            // 0->a:x
5711
5712       break;
5713     case 3:
5714     case 4:
5715     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5716
5717       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
5718
5719       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5720
5721       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5722
5723       emitcode ("anl", "a,#0x%02x",
5724                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5725
5726       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5727
5728       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5729
5730       emitcode ("anl", "a,#0x%02x",
5731                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5732
5733       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5734
5735       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5736
5737       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
5738
5739       break;
5740     case 6:                     // AABBBBBB:CCDDDDDD
5741
5742       emitcode ("mov", "c,acc.7");
5743       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5744
5745       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5746
5747       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5748
5749       emitcode ("anl", "a,#0x%02x",
5750                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5751
5752       break;
5753     case 7:                     // ABBBBBBB:CDDDDDDD
5754
5755       emitcode ("mov", "c,acc.7");      // c = A
5756
5757       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5758
5759       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5760
5761       emitcode ("anl", "a,#0x%02x",
5762                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5763
5764       break;
5765     default:
5766       break;
5767     }
5768 }
5769
5770 /*-----------------------------------------------------------------*/
5771 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5772 /*-----------------------------------------------------------------*/
5773 static void
5774 AccAXRshS (char *x, int shCount)
5775 {
5776   symbol *tlbl;
5777   switch (shCount)
5778     {
5779     case 0:
5780       break;
5781     case 1:
5782       emitcode ("mov", "c,acc.7");
5783       AccAXRrl1 (x);            // s->a:x
5784
5785       break;
5786     case 2:
5787       emitcode ("mov", "c,acc.7");
5788       AccAXRrl1 (x);            // s->a:x
5789
5790       emitcode ("mov", "c,acc.7");
5791       AccAXRrl1 (x);            // s->a:x
5792
5793       break;
5794     case 3:
5795     case 4:
5796     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5797
5798       tlbl = newiTempLabel (NULL);
5799       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
5800
5801       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5802
5803       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5804
5805       emitcode ("anl", "a,#0x%02x",
5806                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5807
5808       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5809
5810       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5811
5812       emitcode ("anl", "a,#0x%02x",
5813                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5814
5815       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5816
5817       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5818
5819       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
5820
5821       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5822       emitcode ("orl", "a,#0x%02x",
5823                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
5824
5825       emitcode ("", "%05d$:", tlbl->key + 100);
5826       break;                    // SSSSAAAA:BBBCCCCC
5827
5828     case 6:                     // AABBBBBB:CCDDDDDD
5829
5830       tlbl = newiTempLabel (NULL);
5831       emitcode ("mov", "c,acc.7");
5832       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5833
5834       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5835
5836       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5837
5838       emitcode ("anl", "a,#0x%02x",
5839                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5840
5841       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5842       emitcode ("orl", "a,#0x%02x",
5843                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
5844
5845       emitcode ("", "%05d$:", tlbl->key + 100);
5846       break;
5847     case 7:                     // ABBBBBBB:CDDDDDDD
5848
5849       tlbl = newiTempLabel (NULL);
5850       emitcode ("mov", "c,acc.7");      // c = A
5851
5852       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5853
5854       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5855
5856       emitcode ("anl", "a,#0x%02x",
5857                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5858
5859       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5860       emitcode ("orl", "a,#0x%02x",
5861                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
5862
5863       emitcode ("", "%05d$:", tlbl->key + 100);
5864       break;
5865     default:
5866       break;
5867     }
5868 }
5869
5870 /*-----------------------------------------------------------------*/
5871 /* shiftL2Left2Result - shift left two bytes from left to result   */
5872 /*-----------------------------------------------------------------*/
5873 static void
5874 shiftL2Left2Result (operand * left, int offl,
5875                     operand * result, int offr, int shCount)
5876 {
5877   if (sameRegs (AOP (result), AOP (left)) &&
5878       ((offl + MSB16) == offr))
5879     {
5880       /* don't crash result[offr] */
5881       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5882       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5883     }
5884   else
5885     {
5886       movLeft2Result (left, offl, result, offr, 0);
5887       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5888     }
5889   /* ax << shCount (x = lsb(result)) */
5890   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5891   aopPut (AOP (result), "a", offr + MSB16);
5892 }
5893
5894
5895 /*-----------------------------------------------------------------*/
5896 /* shiftR2Left2Result - shift right two bytes from left to result  */
5897 /*-----------------------------------------------------------------*/
5898 static void
5899 shiftR2Left2Result (operand * left, int offl,
5900                     operand * result, int offr,
5901                     int shCount, int sign)
5902 {
5903   if (sameRegs (AOP (result), AOP (left)) &&
5904       ((offl + MSB16) == offr))
5905     {
5906       /* don't crash result[offr] */
5907       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5908       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5909     }
5910   else
5911     {
5912       movLeft2Result (left, offl, result, offr, 0);
5913       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5914     }
5915   /* a:x >> shCount (x = lsb(result)) */
5916   if (sign)
5917     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5918   else
5919     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5920   if (getDataSize (result) > 1)
5921     aopPut (AOP (result), "a", offr + MSB16);
5922 }
5923
5924 /*-----------------------------------------------------------------*/
5925 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5926 /*-----------------------------------------------------------------*/
5927 static void
5928 shiftLLeftOrResult (operand * left, int offl,
5929                     operand * result, int offr, int shCount)
5930 {
5931   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5932   /* shift left accumulator */
5933   AccLsh (shCount);
5934   /* or with result */
5935   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5936   /* back to result */
5937   aopPut (AOP (result), "a", offr);
5938 }
5939
5940 /*-----------------------------------------------------------------*/
5941 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5942 /*-----------------------------------------------------------------*/
5943 static void
5944 shiftRLeftOrResult (operand * left, int offl,
5945                     operand * result, int offr, int shCount)
5946 {
5947   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5948   /* shift right accumulator */
5949   AccRsh (shCount);
5950   /* or with result */
5951   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5952   /* back to result */
5953   aopPut (AOP (result), "a", offr);
5954 }
5955
5956 /*-----------------------------------------------------------------*/
5957 /* genlshOne - left shift a one byte quantity by known count       */
5958 /*-----------------------------------------------------------------*/
5959 static void
5960 genlshOne (operand * result, operand * left, int shCount)
5961 {
5962   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5963 }
5964
5965 /*-----------------------------------------------------------------*/
5966 /* genlshTwo - left shift two bytes by known amount != 0           */
5967 /*-----------------------------------------------------------------*/
5968 static void
5969 genlshTwo (operand * result, operand * left, int shCount)
5970 {
5971   int size;
5972
5973   size = getDataSize (result);
5974
5975   /* if shCount >= 8 */
5976   if (shCount >= 8)
5977     {
5978       shCount -= 8;
5979
5980       if (size > 1)
5981         {
5982           if (shCount)
5983             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5984           else
5985             movLeft2Result (left, LSB, result, MSB16, 0);
5986         }
5987       aopPut (AOP (result), zero, LSB);
5988     }
5989
5990   /*  1 <= shCount <= 7 */
5991   else
5992     {
5993       if (size == 1)
5994         shiftL1Left2Result (left, LSB, result, LSB, shCount);
5995       else
5996         shiftL2Left2Result (left, LSB, result, LSB, shCount);
5997     }
5998 }
5999
6000 /*-----------------------------------------------------------------*/
6001 /* shiftLLong - shift left one long from left to result            */
6002 /* offl = LSB or MSB16                                             */
6003 /*-----------------------------------------------------------------*/
6004 static void
6005 shiftLLong (operand * left, operand * result, int offr)
6006 {
6007   char *l;
6008   int size = AOP_SIZE (result);
6009
6010   if (size >= LSB + offr)
6011     {
6012       l = aopGet (AOP (left), LSB, FALSE, FALSE);
6013       MOVA (l);
6014       emitcode ("add", "a,acc");
6015       if (sameRegs (AOP (left), AOP (result)) &&
6016           size >= MSB16 + offr && offr != LSB)
6017         emitcode ("xch", "a,%s",
6018                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6019       else
6020         aopPut (AOP (result), "a", LSB + offr);
6021     }
6022
6023   if (size >= MSB16 + offr)
6024     {
6025       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6026         {
6027           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6028           MOVA (l);
6029         }
6030       emitcode ("rlc", "a");
6031       if (sameRegs (AOP (left), AOP (result)) &&
6032           size >= MSB24 + offr && offr != LSB)
6033         emitcode ("xch", "a,%s",
6034                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6035       else
6036         aopPut (AOP (result), "a", MSB16 + offr);
6037     }
6038
6039   if (size >= MSB24 + offr)
6040     {
6041       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6042         {
6043           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6044           MOVA (l);
6045         }
6046       emitcode ("rlc", "a");
6047       if (sameRegs (AOP (left), AOP (result)) &&
6048           size >= MSB32 + offr && offr != LSB)
6049         emitcode ("xch", "a,%s",
6050                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6051       else
6052         aopPut (AOP (result), "a", MSB24 + offr);
6053     }
6054
6055   if (size > MSB32 + offr)
6056     {
6057       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6058         {
6059           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6060           MOVA (l);
6061         }
6062       emitcode ("rlc", "a");
6063       aopPut (AOP (result), "a", MSB32 + offr);
6064     }
6065   if (offr != LSB)
6066     aopPut (AOP (result), zero, LSB);
6067 }
6068
6069 /*-----------------------------------------------------------------*/
6070 /* genlshFour - shift four byte by a known amount != 0             */
6071 /*-----------------------------------------------------------------*/
6072 static void
6073 genlshFour (operand * result, operand * left, int shCount)
6074 {
6075   int size;
6076
6077   size = AOP_SIZE (result);
6078
6079   /* if shifting more that 3 bytes */
6080   if (shCount >= 24)
6081     {
6082       shCount -= 24;
6083       if (shCount)
6084         /* lowest order of left goes to the highest
6085            order of the destination */
6086         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6087       else
6088         movLeft2Result (left, LSB, result, MSB32, 0);
6089       aopPut (AOP (result), zero, LSB);
6090       aopPut (AOP (result), zero, MSB16);
6091       aopPut (AOP (result), zero, MSB24);
6092       return;
6093     }
6094
6095   /* more than two bytes */
6096   else if (shCount >= 16)
6097     {
6098       /* lower order two bytes goes to higher order two bytes */
6099       shCount -= 16;
6100       /* if some more remaining */
6101       if (shCount)
6102         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6103       else
6104         {
6105           movLeft2Result (left, MSB16, result, MSB32, 0);
6106           movLeft2Result (left, LSB, result, MSB24, 0);
6107         }
6108       aopPut (AOP (result), zero, MSB16);
6109       aopPut (AOP (result), zero, LSB);
6110       return;
6111     }
6112
6113   /* if more than 1 byte */
6114   else if (shCount >= 8)
6115     {
6116       /* lower order three bytes goes to higher order  three bytes */
6117       shCount -= 8;
6118       if (size == 2)
6119         {
6120           if (shCount)
6121             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6122           else
6123             movLeft2Result (left, LSB, result, MSB16, 0);
6124         }
6125       else
6126         {                       /* size = 4 */
6127           if (shCount == 0)
6128             {
6129               movLeft2Result (left, MSB24, result, MSB32, 0);
6130               movLeft2Result (left, MSB16, result, MSB24, 0);
6131               movLeft2Result (left, LSB, result, MSB16, 0);
6132               aopPut (AOP (result), zero, LSB);
6133             }
6134           else if (shCount == 1)
6135             shiftLLong (left, result, MSB16);
6136           else
6137             {
6138               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6139               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6140               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6141               aopPut (AOP (result), zero, LSB);
6142             }
6143         }
6144     }
6145
6146   /* 1 <= shCount <= 7 */
6147   else if (shCount <= 2)
6148     {
6149       shiftLLong (left, result, LSB);
6150       if (shCount == 2)
6151         shiftLLong (result, result, LSB);
6152     }
6153   /* 3 <= shCount <= 7, optimize */
6154   else
6155     {
6156       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6157       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6158       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6159     }
6160 }
6161
6162 /*-----------------------------------------------------------------*/
6163 /* genLeftShiftLiteral - left shifting by known count              */
6164 /*-----------------------------------------------------------------*/
6165 static void
6166 genLeftShiftLiteral (operand * left,
6167                      operand * right,
6168                      operand * result,
6169                      iCode * ic)
6170 {
6171   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6172   int size;
6173
6174   freeAsmop (right, NULL, ic, TRUE);
6175
6176   aopOp (left, ic, FALSE);
6177   aopOp (result, ic, FALSE);
6178
6179   size = getSize (operandType (result));
6180
6181 #if VIEW_SIZE
6182   emitcode ("; shift left ", "result %d, left %d", size,
6183             AOP_SIZE (left));
6184 #endif
6185
6186   /* I suppose that the left size >= result size */
6187   if (shCount == 0)
6188     {
6189       while (size--)
6190         {
6191           movLeft2Result (left, size, result, size, 0);
6192         }
6193     }
6194
6195   else if (shCount >= (size * 8))
6196     while (size--)
6197       aopPut (AOP (result), zero, size);
6198   else
6199     {
6200       switch (size)
6201         {
6202         case 1:
6203           genlshOne (result, left, shCount);
6204           break;
6205
6206         case 2:
6207           genlshTwo (result, left, shCount);
6208           break;
6209
6210         case 4:
6211           genlshFour (result, left, shCount);
6212           break;
6213         default:
6214           fprintf(stderr, "*** ack! mystery literal shift!\n");
6215           break;
6216         }
6217     }
6218   freeAsmop (left, NULL, ic, TRUE);
6219   freeAsmop (result, NULL, ic, TRUE);
6220 }
6221
6222 /*-----------------------------------------------------------------*/
6223 /* genLeftShift - generates code for left shifting                 */
6224 /*-----------------------------------------------------------------*/
6225 static void
6226 genLeftShift (iCode * ic)
6227 {
6228   operand *left, *right, *result;
6229   int size, offset;
6230   char *l;
6231   symbol *tlbl, *tlbl1;
6232
6233   right = IC_RIGHT (ic);
6234   left = IC_LEFT (ic);
6235   result = IC_RESULT (ic);
6236
6237   aopOp (right, ic, FALSE);
6238
6239   /* if the shift count is known then do it
6240      as efficiently as possible */
6241   if (AOP_TYPE (right) == AOP_LIT)
6242     {
6243       genLeftShiftLiteral (left, right, result, ic);
6244       return;
6245     }
6246
6247   /* shift count is unknown then we have to form
6248      a loop get the loop count in B : Note: we take
6249      only the lower order byte since shifting
6250      more that 32 bits make no sense anyway, ( the
6251      largest size of an object can be only 32 bits ) */
6252
6253   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6254   emitcode ("inc", "b");
6255   freeAsmop (right, NULL, ic, TRUE);
6256   aopOp (left, ic, FALSE);
6257   aopOp (result, ic, FALSE);
6258
6259   /* now move the left to the result if they are not the
6260      same */
6261   if (!sameRegs (AOP (left), AOP (result)) &&
6262       AOP_SIZE (result) > 1)
6263     {
6264
6265       size = AOP_SIZE (result);
6266       offset = 0;
6267       while (size--)
6268         {
6269           l = aopGet (AOP (left), offset, FALSE, TRUE);
6270           if (*l == '@' && (IS_AOP_PREG (result)))
6271             {
6272
6273               emitcode ("mov", "a,%s", l);
6274               aopPut (AOP (result), "a", offset);
6275             }
6276           else
6277             aopPut (AOP (result), l, offset);
6278           offset++;
6279         }
6280     }
6281
6282   tlbl = newiTempLabel (NULL);
6283   size = AOP_SIZE (result);
6284   offset = 0;
6285   tlbl1 = newiTempLabel (NULL);
6286
6287   /* if it is only one byte then */
6288   if (size == 1)
6289     {
6290       symbol *tlbl1 = newiTempLabel (NULL);
6291
6292       l = aopGet (AOP (left), 0, FALSE, FALSE);
6293       MOVA (l);
6294       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6295       emitcode ("", "%05d$:", tlbl->key + 100);
6296       emitcode ("add", "a,acc");
6297       emitcode ("", "%05d$:", tlbl1->key + 100);
6298       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6299       aopPut (AOP (result), "a", 0);
6300       goto release;
6301     }
6302
6303   reAdjustPreg (AOP (result));
6304
6305   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6306   emitcode ("", "%05d$:", tlbl->key + 100);
6307   l = aopGet (AOP (result), offset, FALSE, FALSE);
6308   MOVA (l);
6309   emitcode ("add", "a,acc");
6310   aopPut (AOP (result), "a", offset++);
6311   while (--size)
6312     {
6313       l = aopGet (AOP (result), offset, FALSE, FALSE);
6314       MOVA (l);
6315       emitcode ("rlc", "a");
6316       aopPut (AOP (result), "a", offset++);
6317     }
6318   reAdjustPreg (AOP (result));
6319
6320   emitcode ("", "%05d$:", tlbl1->key + 100);
6321   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6322 release:
6323   freeAsmop (left, NULL, ic, TRUE);
6324   freeAsmop (result, NULL, ic, TRUE);
6325 }
6326
6327 /*-----------------------------------------------------------------*/
6328 /* genrshOne - right shift a one byte quantity by known count      */
6329 /*-----------------------------------------------------------------*/
6330 static void
6331 genrshOne (operand * result, operand * left,
6332            int shCount, int sign)
6333 {
6334   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6335 }
6336
6337 /*-----------------------------------------------------------------*/
6338 /* genrshTwo - right shift two bytes by known amount != 0          */
6339 /*-----------------------------------------------------------------*/
6340 static void
6341 genrshTwo (operand * result, operand * left,
6342            int shCount, int sign)
6343 {
6344   /* if shCount >= 8 */
6345   if (shCount >= 8)
6346     {
6347       shCount -= 8;
6348       if (shCount)
6349         shiftR1Left2Result (left, MSB16, result, LSB,
6350                             shCount, sign);
6351       else
6352         movLeft2Result (left, MSB16, result, LSB, sign);
6353       addSign (result, MSB16, sign);
6354     }
6355
6356   /*  1 <= shCount <= 7 */
6357   else
6358     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6359 }
6360
6361 /*-----------------------------------------------------------------*/
6362 /* shiftRLong - shift right one long from left to result           */
6363 /* offl = LSB or MSB16                                             */
6364 /*-----------------------------------------------------------------*/
6365 static void
6366 shiftRLong (operand * left, int offl,
6367             operand * result, int sign)
6368 {
6369   int isSameRegs=sameRegs(AOP(left),AOP(result));
6370
6371   if (isSameRegs && offl>1) {
6372     // we are in big trouble, but this shouldn't happen
6373     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6374   }
6375
6376   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6377   
6378   if (offl==MSB16) {
6379     // shift is > 8
6380     if (sign) {
6381       emitcode ("rlc", "a");
6382       emitcode ("subb", "a,acc");
6383       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6384     } else {
6385       aopPut (AOP(result), zero, MSB32);
6386     }
6387   }
6388
6389   if (!sign) {
6390     emitcode ("clr", "c");
6391   } else {
6392     emitcode ("mov", "c,acc.7");
6393   }
6394
6395   emitcode ("rrc", "a");
6396
6397   if (isSameRegs && offl==MSB16) {
6398     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6399   } else {
6400     aopPut (AOP (result), "a", MSB32);
6401     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6402   }
6403
6404   emitcode ("rrc", "a");
6405   if (isSameRegs && offl==1) {
6406     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6407   } else {
6408     aopPut (AOP (result), "a", MSB24);
6409     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6410   }
6411   emitcode ("rrc", "a");
6412   aopPut (AOP (result), "a", MSB16 - offl);
6413
6414   if (offl == LSB)
6415     {
6416       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6417       emitcode ("rrc", "a");
6418       aopPut (AOP (result), "a", LSB);
6419     }
6420 }
6421
6422 /*-----------------------------------------------------------------*/
6423 /* genrshFour - shift four byte by a known amount != 0             */
6424 /*-----------------------------------------------------------------*/
6425 static void
6426 genrshFour (operand * result, operand * left,
6427             int shCount, int sign)
6428 {
6429   /* if shifting more that 3 bytes */
6430   if (shCount >= 24)
6431     {
6432       shCount -= 24;
6433       if (shCount)
6434         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6435       else
6436         movLeft2Result (left, MSB32, result, LSB, sign);
6437       addSign (result, MSB16, sign);
6438     }
6439   else if (shCount >= 16)
6440     {
6441       shCount -= 16;
6442       if (shCount)
6443         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6444       else
6445         {
6446           movLeft2Result (left, MSB24, result, LSB, 0);
6447           movLeft2Result (left, MSB32, result, MSB16, sign);
6448         }
6449       addSign (result, MSB24, sign);
6450     }
6451   else if (shCount >= 8)
6452     {
6453       shCount -= 8;
6454       if (shCount == 1)
6455         shiftRLong (left, MSB16, result, sign);
6456       else if (shCount == 0)
6457         {
6458           movLeft2Result (left, MSB16, result, LSB, 0);
6459           movLeft2Result (left, MSB24, result, MSB16, 0);
6460           movLeft2Result (left, MSB32, result, MSB24, sign);
6461           addSign (result, MSB32, sign);
6462         }
6463       else
6464         {
6465           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6466           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6467           /* the last shift is signed */
6468           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6469           addSign (result, MSB32, sign);
6470         }
6471     }
6472   else
6473     {                           /* 1 <= shCount <= 7 */
6474       if (shCount <= 2)
6475         {
6476           shiftRLong (left, LSB, result, sign);
6477           if (shCount == 2)
6478             shiftRLong (result, LSB, result, sign);
6479         }
6480       else
6481         {
6482           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6483           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6484           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6485         }
6486     }
6487 }
6488
6489 /*-----------------------------------------------------------------*/
6490 /* genRightShiftLiteral - right shifting by known count            */
6491 /*-----------------------------------------------------------------*/
6492 static void
6493 genRightShiftLiteral (operand * left,
6494                       operand * right,
6495                       operand * result,
6496                       iCode * ic,
6497                       int sign)
6498 {
6499   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6500   int size;
6501
6502   freeAsmop (right, NULL, ic, TRUE);
6503
6504   aopOp (left, ic, FALSE);
6505   aopOp (result, ic, FALSE);
6506
6507 #if VIEW_SIZE
6508   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6509             AOP_SIZE (left));
6510 #endif
6511
6512   size = getDataSize (left);
6513   /* test the LEFT size !!! */
6514
6515   /* I suppose that the left size >= result size */
6516   if (shCount == 0)
6517     {
6518       size = getDataSize (result);
6519       while (size--)
6520         movLeft2Result (left, size, result, size, 0);
6521     }
6522
6523   else if (shCount >= (size * 8))
6524     {
6525       if (sign)
6526         /* get sign in acc.7 */
6527         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6528       addSign (result, LSB, sign);
6529     }
6530   else
6531     {
6532       switch (size)
6533         {
6534         case 1:
6535           genrshOne (result, left, shCount, sign);
6536           break;
6537
6538         case 2:
6539           genrshTwo (result, left, shCount, sign);
6540           break;
6541
6542         case 4:
6543           genrshFour (result, left, shCount, sign);
6544           break;
6545         default:
6546           break;
6547         }
6548
6549       freeAsmop (left, NULL, ic, TRUE);
6550       freeAsmop (result, NULL, ic, TRUE);
6551     }
6552 }
6553
6554 /*-----------------------------------------------------------------*/
6555 /* genSignedRightShift - right shift of signed number              */
6556 /*-----------------------------------------------------------------*/
6557 static void
6558 genSignedRightShift (iCode * ic)
6559 {
6560   operand *right, *left, *result;
6561   int size, offset;
6562   char *l;
6563   symbol *tlbl, *tlbl1;
6564
6565   /* we do it the hard way put the shift count in b
6566      and loop thru preserving the sign */
6567
6568   right = IC_RIGHT (ic);
6569   left = IC_LEFT (ic);
6570   result = IC_RESULT (ic);
6571
6572   aopOp (right, ic, FALSE);
6573
6574
6575   if (AOP_TYPE (right) == AOP_LIT)
6576     {
6577       genRightShiftLiteral (left, right, result, ic, 1);
6578       return;
6579     }
6580   /* shift count is unknown then we have to form
6581      a loop get the loop count in B : Note: we take
6582      only the lower order byte since shifting
6583      more that 32 bits make no sense anyway, ( the
6584      largest size of an object can be only 32 bits ) */
6585
6586   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6587   emitcode ("inc", "b");
6588   freeAsmop (right, NULL, ic, TRUE);
6589   aopOp (left, ic, FALSE);
6590   aopOp (result, ic, FALSE);
6591
6592   /* now move the left to the result if they are not the
6593      same */
6594   if (!sameRegs (AOP (left), AOP (result)) &&
6595       AOP_SIZE (result) > 1)
6596     {
6597
6598       size = AOP_SIZE (result);
6599       offset = 0;
6600       while (size--)
6601         {
6602           l = aopGet (AOP (left), offset, FALSE, TRUE);
6603           if (*l == '@' && IS_AOP_PREG (result))
6604             {
6605
6606               emitcode ("mov", "a,%s", l);
6607               aopPut (AOP (result), "a", offset);
6608             }
6609           else
6610             aopPut (AOP (result), l, offset);
6611           offset++;
6612         }
6613     }
6614
6615   /* mov the highest order bit to OVR */
6616   tlbl = newiTempLabel (NULL);
6617   tlbl1 = newiTempLabel (NULL);
6618
6619   size = AOP_SIZE (result);
6620   offset = size - 1;
6621   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6622   emitcode ("rlc", "a");
6623   emitcode ("mov", "ov,c");
6624   /* if it is only one byte then */
6625   if (size == 1)
6626     {
6627       l = aopGet (AOP (left), 0, FALSE, FALSE);
6628       MOVA (l);
6629       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6630       emitcode ("", "%05d$:", tlbl->key + 100);
6631       emitcode ("mov", "c,ov");
6632       emitcode ("rrc", "a");
6633       emitcode ("", "%05d$:", tlbl1->key + 100);
6634       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6635       aopPut (AOP (result), "a", 0);
6636       goto release;
6637     }
6638
6639   reAdjustPreg (AOP (result));
6640   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6641   emitcode ("", "%05d$:", tlbl->key + 100);
6642   emitcode ("mov", "c,ov");
6643   while (size--)
6644     {
6645       l = aopGet (AOP (result), offset, FALSE, FALSE);
6646       MOVA (l);
6647       emitcode ("rrc", "a");
6648       aopPut (AOP (result), "a", offset--);
6649     }
6650   reAdjustPreg (AOP (result));
6651   emitcode ("", "%05d$:", tlbl1->key + 100);
6652   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6653
6654 release:
6655   freeAsmop (left, NULL, ic, TRUE);
6656   freeAsmop (result, NULL, ic, TRUE);
6657 }
6658
6659 /*-----------------------------------------------------------------*/
6660 /* genRightShift - generate code for right shifting                */
6661 /*-----------------------------------------------------------------*/
6662 static void
6663 genRightShift (iCode * ic)
6664 {
6665   operand *right, *left, *result;
6666   sym_link *retype;
6667   int size, offset;
6668   char *l;
6669   symbol *tlbl, *tlbl1;
6670
6671   /* if signed then we do it the hard way preserve the
6672      sign bit moving it inwards */
6673   retype = getSpec (operandType (IC_RESULT (ic)));
6674
6675   if (!SPEC_USIGN (retype))
6676     {
6677       genSignedRightShift (ic);
6678       return;
6679     }
6680
6681   /* signed & unsigned types are treated the same : i.e. the
6682      signed is NOT propagated inwards : quoting from the
6683      ANSI - standard : "for E1 >> E2, is equivalent to division
6684      by 2**E2 if unsigned or if it has a non-negative value,
6685      otherwise the result is implementation defined ", MY definition
6686      is that the sign does not get propagated */
6687
6688   right = IC_RIGHT (ic);
6689   left = IC_LEFT (ic);
6690   result = IC_RESULT (ic);
6691
6692   aopOp (right, ic, FALSE);
6693
6694   /* if the shift count is known then do it
6695      as efficiently as possible */
6696   if (AOP_TYPE (right) == AOP_LIT)
6697     {
6698       genRightShiftLiteral (left, right, result, ic, 0);
6699       return;
6700     }
6701
6702   /* shift count is unknown then we have to form
6703      a loop get the loop count in B : Note: we take
6704      only the lower order byte since shifting
6705      more that 32 bits make no sense anyway, ( the
6706      largest size of an object can be only 32 bits ) */
6707
6708   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6709   emitcode ("inc", "b");
6710   freeAsmop (right, NULL, ic, TRUE);
6711   aopOp (left, ic, FALSE);
6712   aopOp (result, ic, FALSE);
6713
6714   /* now move the left to the result if they are not the
6715      same */
6716   if (!sameRegs (AOP (left), AOP (result)) &&
6717       AOP_SIZE (result) > 1)
6718     {
6719
6720       size = AOP_SIZE (result);
6721       offset = 0;
6722       while (size--)
6723         {
6724           l = aopGet (AOP (left), offset, FALSE, TRUE);
6725           if (*l == '@' && IS_AOP_PREG (result))
6726             {
6727
6728               emitcode ("mov", "a,%s", l);
6729               aopPut (AOP (result), "a", offset);
6730             }
6731           else
6732             aopPut (AOP (result), l, offset);
6733           offset++;
6734         }
6735     }
6736
6737   tlbl = newiTempLabel (NULL);
6738   tlbl1 = newiTempLabel (NULL);
6739   size = AOP_SIZE (result);
6740   offset = size - 1;
6741
6742   /* if it is only one byte then */
6743   if (size == 1)
6744     {
6745       l = aopGet (AOP (left), 0, FALSE, FALSE);
6746       MOVA (l);
6747       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6748       emitcode ("", "%05d$:", tlbl->key + 100);
6749       CLRC;
6750       emitcode ("rrc", "a");
6751       emitcode ("", "%05d$:", tlbl1->key + 100);
6752       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6753       aopPut (AOP (result), "a", 0);
6754       goto release;
6755     }
6756
6757   reAdjustPreg (AOP (result));
6758   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6759   emitcode ("", "%05d$:", tlbl->key + 100);
6760   CLRC;
6761   while (size--)
6762     {
6763       l = aopGet (AOP (result), offset, FALSE, FALSE);
6764       MOVA (l);
6765       emitcode ("rrc", "a");
6766       aopPut (AOP (result), "a", offset--);
6767     }
6768   reAdjustPreg (AOP (result));
6769
6770   emitcode ("", "%05d$:", tlbl1->key + 100);
6771   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6772
6773 release:
6774   freeAsmop (left, NULL, ic, TRUE);
6775   freeAsmop (result, NULL, ic, TRUE);
6776 }
6777
6778 /*-----------------------------------------------------------------*/
6779 /* genUnpackBits - generates code for unpacking bits               */
6780 /*-----------------------------------------------------------------*/
6781 static void
6782 genUnpackBits (operand * result, char *rname, int ptype)
6783 {
6784   int shCnt;
6785   int rlen = 0;
6786   sym_link *etype;
6787   int offset = 0;
6788   int rsize;
6789
6790   etype = getSpec (operandType (result));
6791   rsize = getSize (operandType (result));
6792   /* read the first byte  */
6793   switch (ptype)
6794     {
6795
6796     case POINTER:
6797     case IPOINTER:
6798       emitcode ("mov", "a,@%s", rname);
6799       break;
6800
6801     case PPOINTER:
6802       emitcode ("movx", "a,@%s", rname);
6803       break;
6804
6805     case FPOINTER:
6806       emitcode ("movx", "a,@dptr");
6807       break;
6808
6809     case CPOINTER:
6810       emitcode ("clr", "a");
6811       emitcode ("movc", "a,@a+dptr");
6812       break;
6813
6814     case GPOINTER:
6815       emitcode ("lcall", "__gptrget");
6816       break;
6817     }
6818
6819   rlen = SPEC_BLEN (etype);
6820
6821   /* if we have bitdisplacement then it fits   */
6822   /* into this byte completely or if length is */
6823   /* less than a byte                          */
6824   if ((shCnt = SPEC_BSTR (etype)) ||
6825       (SPEC_BLEN (etype) <= 8))
6826     {
6827
6828       /* shift right acc */
6829       AccRsh (shCnt);
6830
6831       emitcode ("anl", "a,#0x%02x",
6832                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6833       aopPut (AOP (result), "a", offset++);
6834       goto finish;
6835     }
6836
6837   /* bit field did not fit in a byte  */
6838   aopPut (AOP (result), "a", offset++);
6839
6840   while (1)
6841     {
6842
6843       switch (ptype)
6844         {
6845         case POINTER:
6846         case IPOINTER:
6847           emitcode ("inc", "%s", rname);
6848           emitcode ("mov", "a,@%s", rname);
6849           break;
6850
6851         case PPOINTER:
6852           emitcode ("inc", "%s", rname);
6853           emitcode ("movx", "a,@%s", rname);
6854           break;
6855
6856         case FPOINTER:
6857           emitcode ("inc", "dptr");
6858           emitcode ("movx", "a,@dptr");
6859           break;
6860
6861         case CPOINTER:
6862           emitcode ("clr", "a");
6863           emitcode ("inc", "dptr");
6864           emitcode ("movc", "a,@a+dptr");
6865           break;
6866
6867         case GPOINTER:
6868           emitcode ("inc", "dptr");
6869           emitcode ("lcall", "__gptrget");
6870           break;
6871         }
6872
6873       rlen -= 8;
6874       /* if we are done */
6875       if (rlen < 8)
6876         break;
6877
6878       aopPut (AOP (result), "a", offset++);
6879
6880     }
6881
6882   if (rlen)
6883     {
6884       //  emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6885       AccLsh (8 - rlen);
6886       aopPut (AOP (result), "a", offset++);
6887     }
6888
6889 finish:
6890   if (offset < rsize)
6891     {
6892       rsize -= offset;
6893       while (rsize--)
6894         aopPut (AOP (result), zero, offset++);
6895     }
6896   return;
6897 }
6898
6899
6900 /*-----------------------------------------------------------------*/
6901 /* genDataPointerGet - generates code when ptr offset is known     */
6902 /*-----------------------------------------------------------------*/
6903 static void
6904 genDataPointerGet (operand * left,
6905                    operand * result,
6906                    iCode * ic)
6907 {
6908   char *l;
6909   char buffer[256];
6910   int size, offset = 0;
6911   aopOp (result, ic, TRUE);
6912
6913   /* get the string representation of the name */
6914   l = aopGet (AOP (left), 0, FALSE, TRUE);
6915   size = AOP_SIZE (result);
6916   while (size--)
6917     {
6918       if (offset)
6919         sprintf (buffer, "(%s + %d)", l + 1, offset);
6920       else
6921         sprintf (buffer, "%s", l + 1);
6922       aopPut (AOP (result), buffer, offset++);
6923     }
6924
6925   freeAsmop (left, NULL, ic, TRUE);
6926   freeAsmop (result, NULL, ic, TRUE);
6927 }
6928
6929 /*-----------------------------------------------------------------*/
6930 /* genNearPointerGet - emitcode for near pointer fetch             */
6931 /*-----------------------------------------------------------------*/
6932 static void
6933 genNearPointerGet (operand * left,
6934                    operand * result,
6935                    iCode * ic,
6936                    iCode * pi)
6937 {
6938   asmop *aop = NULL;
6939   regs *preg = NULL;
6940   char *rname;
6941   sym_link *rtype, *retype;
6942   sym_link *ltype = operandType (left);
6943   char buffer[80];
6944
6945   rtype = operandType (result);
6946   retype = getSpec (rtype);
6947
6948   aopOp (left, ic, FALSE);
6949
6950   /* if left is rematerialisable and
6951      result is not bit variable type and
6952      the left is pointer to data space i.e
6953      lower 128 bytes of space */
6954   if (AOP_TYPE (left) == AOP_IMMD &&
6955       !IS_BITVAR (retype) &&
6956       DCL_TYPE (ltype) == POINTER)
6957     {
6958       genDataPointerGet (left, result, ic);
6959       return;
6960     }
6961
6962   /* if the value is already in a pointer register
6963      then don't need anything more */
6964   if (!AOP_INPREG (AOP (left)))
6965     {
6966       /* otherwise get a free pointer register */
6967       aop = newAsmop (0);
6968       preg = getFreePtr (ic, &aop, FALSE);
6969       emitcode ("mov", "%s,%s",
6970                 preg->name,
6971                 aopGet (AOP (left), 0, FALSE, TRUE));
6972       rname = preg->name;
6973     }
6974   else
6975     rname = aopGet (AOP (left), 0, FALSE, FALSE);
6976   
6977   //aopOp (result, ic, FALSE);
6978   aopOp (result, ic, result?TRUE:FALSE);
6979
6980   /* if bitfield then unpack the bits */
6981   if (IS_BITVAR (retype))
6982     genUnpackBits (result, rname, POINTER);
6983   else
6984     {
6985       /* we have can just get the values */
6986       int size = AOP_SIZE (result);
6987       int offset = 0;
6988
6989       while (size--)
6990         {
6991           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6992             {
6993
6994               emitcode ("mov", "a,@%s", rname);
6995               aopPut (AOP (result), "a", offset);
6996             }
6997           else
6998             {
6999               sprintf (buffer, "@%s", rname);
7000               aopPut (AOP (result), buffer, offset);
7001             }
7002           offset++;
7003           if (size || pi)
7004             emitcode ("inc", "%s", rname);
7005         }
7006     }
7007
7008   /* now some housekeeping stuff */
7009   if (aop)       /* we had to allocate for this iCode */
7010     {
7011       if (pi) { /* post increment present */
7012         aopPut(AOP ( left ),rname,0);
7013       }
7014       freeAsmop (NULL, aop, ic, TRUE);
7015     }
7016   else
7017     {
7018       /* we did not allocate which means left
7019          already in a pointer register, then
7020          if size > 0 && this could be used again
7021          we have to point it back to where it
7022          belongs */
7023       if ((AOP_SIZE (result) > 1 &&
7024            !OP_SYMBOL (left)->remat &&
7025            (OP_SYMBOL (left)->liveTo > ic->seq ||
7026             ic->depth)) &&
7027           !pi)
7028         {
7029           int size = AOP_SIZE (result) - 1;
7030           while (size--)
7031             emitcode ("dec", "%s", rname);
7032         }
7033     }
7034
7035   /* done */
7036   freeAsmop (left, NULL, ic, TRUE);
7037   freeAsmop (result, NULL, ic, TRUE);
7038   if (pi) pi->generated = 1;
7039 }
7040
7041 /*-----------------------------------------------------------------*/
7042 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7043 /*-----------------------------------------------------------------*/
7044 static void
7045 genPagedPointerGet (operand * left,
7046                     operand * result,
7047                     iCode * ic,
7048                     iCode *pi)
7049 {
7050   asmop *aop = NULL;
7051   regs *preg = NULL;
7052   char *rname;
7053   sym_link *rtype, *retype;
7054
7055   rtype = operandType (result);
7056   retype = getSpec (rtype);
7057
7058   aopOp (left, ic, FALSE);
7059
7060   /* if the value is already in a pointer register
7061      then don't need anything more */
7062   if (!AOP_INPREG (AOP (left)))
7063     {
7064       /* otherwise get a free pointer register */
7065       aop = newAsmop (0);
7066       preg = getFreePtr (ic, &aop, FALSE);
7067       emitcode ("mov", "%s,%s",
7068                 preg->name,
7069                 aopGet (AOP (left), 0, FALSE, TRUE));
7070       rname = preg->name;
7071     }
7072   else
7073     rname = aopGet (AOP (left), 0, FALSE, FALSE);
7074
7075   aopOp (result, ic, FALSE);
7076
7077   /* if bitfield then unpack the bits */
7078   if (IS_BITVAR (retype))
7079     genUnpackBits (result, rname, PPOINTER);
7080   else
7081     {
7082       /* we have can just get the values */
7083       int size = AOP_SIZE (result);
7084       int offset = 0;
7085
7086       while (size--)
7087         {
7088
7089           emitcode ("movx", "a,@%s", rname);
7090           aopPut (AOP (result), "a", offset);
7091
7092           offset++;
7093
7094           if (size || pi)
7095             emitcode ("inc", "%s", rname);
7096         }
7097     }
7098
7099   /* now some housekeeping stuff */
7100   if (aop) /* we had to allocate for this iCode */
7101     {
7102       if (pi) aopPut ( AOP (left), rname, 0);
7103       freeAsmop (NULL, aop, ic, TRUE);
7104     }
7105   else
7106     {
7107       /* we did not allocate which means left
7108          already in a pointer register, then
7109          if size > 0 && this could be used again
7110          we have to point it back to where it
7111          belongs */
7112       if ((AOP_SIZE (result) > 1 &&
7113            !OP_SYMBOL (left)->remat &&
7114            (OP_SYMBOL (left)->liveTo > ic->seq ||
7115             ic->depth)) &&
7116           !pi)
7117         {
7118           int size = AOP_SIZE (result) - 1;
7119           while (size--)
7120             emitcode ("dec", "%s", rname);
7121         }
7122     }
7123
7124   /* done */
7125   freeAsmop (left, NULL, ic, TRUE);
7126   freeAsmop (result, NULL, ic, TRUE);
7127   if (pi) pi->generated = 1;
7128
7129 }
7130
7131 /*-----------------------------------------------------------------*/
7132 /* genFarPointerGet - gget value from far space                    */
7133 /*-----------------------------------------------------------------*/
7134 static void
7135 genFarPointerGet (operand * left,
7136                   operand * result, iCode * ic, iCode * pi)
7137 {
7138   int size, offset;
7139   sym_link *retype = getSpec (operandType (result));
7140
7141   aopOp (left, ic, FALSE);
7142
7143   /* if the operand is already in dptr
7144      then we do nothing else we move the value to dptr */
7145   if (AOP_TYPE (left) != AOP_STR)
7146     {
7147       /* if this is remateriazable */
7148       if (AOP_TYPE (left) == AOP_IMMD)
7149         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7150       else
7151         {                       /* we need to get it byte by byte */
7152           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7153           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7154         }
7155     }
7156   /* so dptr know contains the address */
7157   aopOp (result, ic, FALSE);
7158
7159   /* if bit then unpack */
7160   if (IS_BITVAR (retype))
7161     genUnpackBits (result, "dptr", FPOINTER);
7162   else
7163     {
7164       size = AOP_SIZE (result);
7165       offset = 0;
7166
7167       while (size--)
7168         {
7169           emitcode ("movx", "a,@dptr");
7170           aopPut (AOP (result), "a", offset++);
7171           if (size || pi)
7172             emitcode ("inc", "dptr");
7173         }
7174     }
7175   
7176   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7177     aopPut ( AOP (left), "dpl", 0);
7178     aopPut ( AOP (left), "dph", 1);
7179     pi->generated = 1;
7180   }
7181   freeAsmop (left, NULL, ic, TRUE);
7182   freeAsmop (result, NULL, ic, TRUE);
7183 }
7184
7185 /*-----------------------------------------------------------------*/
7186 /* genCodePointerGet - gget value from code space                  */
7187 /*-----------------------------------------------------------------*/
7188 static void
7189 genCodePointerGet (operand * left,
7190                     operand * result, iCode * ic, iCode *pi)
7191 {
7192   int size, offset;
7193   sym_link *retype = getSpec (operandType (result));
7194
7195   aopOp (left, ic, FALSE);
7196
7197   /* if the operand is already in dptr
7198      then we do nothing else we move the value to dptr */
7199   if (AOP_TYPE (left) != AOP_STR)
7200     {
7201       /* if this is remateriazable */
7202       if (AOP_TYPE (left) == AOP_IMMD)
7203         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7204       else
7205         {                       /* we need to get it byte by byte */
7206           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7207           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7208         }
7209     }
7210   /* so dptr know contains the address */
7211   aopOp (result, ic, FALSE);
7212
7213   /* if bit then unpack */
7214   if (IS_BITVAR (retype))
7215     genUnpackBits (result, "dptr", CPOINTER);
7216   else
7217     {
7218       size = AOP_SIZE (result);
7219       offset = 0;
7220
7221       while (size--)
7222         {
7223           emitcode ("clr", "a");
7224           emitcode ("movc", "a,@a+dptr");
7225           aopPut (AOP (result), "a", offset++);
7226           if (size || pi)
7227             emitcode ("inc", "dptr");
7228         }
7229     }
7230
7231   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7232     aopPut ( AOP (left), "dpl", 0);
7233     aopPut ( AOP (left), "dph", 1);
7234     pi->generated = 1;
7235   }
7236   freeAsmop (left, NULL, ic, TRUE);
7237   freeAsmop (result, NULL, ic, TRUE);
7238 }
7239
7240 /*-----------------------------------------------------------------*/
7241 /* genGenPointerGet - gget value from generic pointer space        */
7242 /*-----------------------------------------------------------------*/
7243 static void
7244 genGenPointerGet (operand * left,
7245                   operand * result, iCode * ic, iCode *pi)
7246 {
7247   int size, offset;
7248   sym_link *retype = getSpec (operandType (result));
7249
7250   aopOp (left, ic, FALSE);
7251
7252   /* if the operand is already in dptr
7253      then we do nothing else we move the value to dptr */
7254   if (AOP_TYPE (left) != AOP_STR)
7255     {
7256       /* if this is remateriazable */
7257       if (AOP_TYPE (left) == AOP_IMMD)
7258         {
7259           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7260           emitcode ("mov", "b,#%d", pointerCode (retype));
7261         }
7262       else
7263         {                       /* we need to get it byte by byte */
7264           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7265           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7266           emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7267         }
7268     }
7269   /* so dptr know contains the address */
7270   aopOp (result, ic, FALSE);
7271
7272   /* if bit then unpack */
7273   if (IS_BITVAR (retype))
7274     genUnpackBits (result, "dptr", GPOINTER);
7275   else
7276     {
7277       size = AOP_SIZE (result);
7278       offset = 0;
7279
7280       while (size--)
7281         {
7282           emitcode ("lcall", "__gptrget");
7283           aopPut (AOP (result), "a", offset++);
7284           if (size || pi)
7285             emitcode ("inc", "dptr");
7286         }
7287     }
7288
7289   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7290     aopPut ( AOP (left), "dpl", 0);
7291     aopPut ( AOP (left), "dph", 1);
7292     pi->generated = 1;
7293   }
7294   freeAsmop (left, NULL, ic, TRUE);
7295   freeAsmop (result, NULL, ic, TRUE);
7296 }
7297
7298 /*-----------------------------------------------------------------*/
7299 /* genPointerGet - generate code for pointer get                   */
7300 /*-----------------------------------------------------------------*/
7301 static void
7302 genPointerGet (iCode * ic, iCode *pi)
7303 {
7304   operand *left, *result;
7305   sym_link *type, *etype;
7306   int p_type;
7307
7308   left = IC_LEFT (ic);
7309   result = IC_RESULT (ic);
7310
7311   /* depending on the type of pointer we need to
7312      move it to the correct pointer register */
7313   type = operandType (left);
7314   etype = getSpec (type);
7315   /* if left is of type of pointer then it is simple */
7316   if (IS_PTR (type) && !IS_FUNC (type->next))
7317     p_type = DCL_TYPE (type);
7318   else
7319     {
7320       /* we have to go by the storage class */
7321       p_type = PTR_TYPE (SPEC_OCLS (etype));
7322     }
7323
7324   /* now that we have the pointer type we assign
7325      the pointer values */
7326   switch (p_type)
7327     {
7328
7329     case POINTER:
7330     case IPOINTER:
7331       genNearPointerGet (left, result, ic, pi);
7332       break;
7333
7334     case PPOINTER:
7335       genPagedPointerGet (left, result, ic, pi);
7336       break;
7337
7338     case FPOINTER:
7339       genFarPointerGet (left, result, ic, pi);
7340       break;
7341
7342     case CPOINTER:
7343       genCodePointerGet (left, result, ic, pi);
7344       break;
7345
7346     case GPOINTER:
7347       genGenPointerGet (left, result, ic, pi);
7348       break;
7349     }
7350
7351 }
7352
7353 /*-----------------------------------------------------------------*/
7354 /* genPackBits - generates code for packed bit storage             */
7355 /*-----------------------------------------------------------------*/
7356 static void
7357 genPackBits (sym_link * etype,
7358              operand * right,
7359              char *rname, int p_type)
7360 {
7361   int shCount = 0;
7362   int offset = 0;
7363   int rLen = 0;
7364   int blen, bstr;
7365   char *l;
7366
7367   blen = SPEC_BLEN (etype);
7368   bstr = SPEC_BSTR (etype);
7369
7370   l = aopGet (AOP (right), offset++, FALSE, FALSE);
7371   MOVA (l);
7372
7373   /* if the bit lenth is less than or    */
7374   /* it exactly fits a byte then         */
7375   if (SPEC_BLEN (etype) <= 8)
7376     {
7377       shCount = SPEC_BSTR (etype);
7378
7379       /* shift left acc */
7380       AccLsh (shCount);
7381
7382       if (SPEC_BLEN (etype) < 8)
7383         {                       /* if smaller than a byte */
7384
7385
7386           switch (p_type)
7387             {
7388             case POINTER:
7389               emitcode ("mov", "b,a");
7390               emitcode ("mov", "a,@%s", rname);
7391               break;
7392
7393             case FPOINTER:
7394               emitcode ("mov", "b,a");
7395               emitcode ("movx", "a,@dptr");
7396               break;
7397
7398             case GPOINTER:
7399               emitcode ("push", "b");
7400               emitcode ("push", "acc");
7401               emitcode ("lcall", "__gptrget");
7402               emitcode ("pop", "b");
7403               break;
7404             }
7405
7406           emitcode ("anl", "a,#0x%02x", (unsigned char)
7407                     ((unsigned char) (0xFF << (blen + bstr)) |
7408                      (unsigned char) (0xFF >> (8 - bstr))));
7409           emitcode ("orl", "a,b");
7410           if (p_type == GPOINTER)
7411             emitcode ("pop", "b");
7412         }
7413     }
7414
7415   switch (p_type)
7416     {
7417     case POINTER:
7418       emitcode ("mov", "@%s,a", rname);
7419       break;
7420
7421     case FPOINTER:
7422       emitcode ("movx", "@dptr,a");
7423       break;
7424
7425     case GPOINTER:
7426       emitcode ("lcall", "__gptrput");
7427       break;
7428     }
7429
7430   /* if we r done */
7431   if (SPEC_BLEN (etype) <= 8)
7432     return;
7433
7434   emitcode ("inc", "%s", rname);
7435   rLen = SPEC_BLEN (etype);
7436
7437   /* now generate for lengths greater than one byte */
7438   while (1)
7439     {
7440
7441       l = aopGet (AOP (right), offset++, FALSE, TRUE);
7442
7443       rLen -= 8;
7444       if (rLen < 8)
7445         break;
7446
7447       switch (p_type)
7448         {
7449         case POINTER:
7450           if (*l == '@')
7451             {
7452               MOVA (l);
7453               emitcode ("mov", "@%s,a", rname);
7454             }
7455           else
7456             emitcode ("mov", "@%s,%s", rname, l);
7457           break;
7458
7459         case FPOINTER:
7460           MOVA (l);
7461           emitcode ("movx", "@dptr,a");
7462           break;
7463
7464         case GPOINTER:
7465           MOVA (l);
7466           emitcode ("lcall", "__gptrput");
7467           break;
7468         }
7469       emitcode ("inc", "%s", rname);
7470     }
7471
7472   MOVA (l);
7473
7474   /* last last was not complete */
7475   if (rLen)
7476     {
7477       /* save the byte & read byte */
7478       switch (p_type)
7479         {
7480         case POINTER:
7481           emitcode ("mov", "b,a");
7482           emitcode ("mov", "a,@%s", rname);
7483           break;
7484
7485         case FPOINTER:
7486           emitcode ("mov", "b,a");
7487           emitcode ("movx", "a,@dptr");
7488           break;
7489
7490         case GPOINTER:
7491           emitcode ("push", "b");
7492           emitcode ("push", "acc");
7493           emitcode ("lcall", "__gptrget");
7494           emitcode ("pop", "b");
7495           break;
7496         }
7497
7498       emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7499       emitcode ("orl", "a,b");
7500     }
7501
7502   if (p_type == GPOINTER)
7503     emitcode ("pop", "b");
7504
7505   switch (p_type)
7506     {
7507
7508     case POINTER:
7509       emitcode ("mov", "@%s,a", rname);
7510       break;
7511
7512     case FPOINTER:
7513       emitcode ("movx", "@dptr,a");
7514       break;
7515
7516     case GPOINTER:
7517       emitcode ("lcall", "__gptrput");
7518       break;
7519     }
7520 }
7521 /*-----------------------------------------------------------------*/
7522 /* genDataPointerSet - remat pointer to data space                 */
7523 /*-----------------------------------------------------------------*/
7524 static void
7525 genDataPointerSet (operand * right,
7526                    operand * result,
7527                    iCode * ic)
7528 {
7529   int size, offset = 0;
7530   char *l, buffer[256];
7531
7532   aopOp (right, ic, FALSE);
7533
7534   l = aopGet (AOP (result), 0, FALSE, TRUE);
7535   size = AOP_SIZE (right);
7536   while (size--)
7537     {
7538       if (offset)
7539         sprintf (buffer, "(%s + %d)", l + 1, offset);
7540       else
7541         sprintf (buffer, "%s", l + 1);
7542       emitcode ("mov", "%s,%s", buffer,
7543                 aopGet (AOP (right), offset++, FALSE, FALSE));
7544     }
7545
7546   freeAsmop (right, NULL, ic, TRUE);
7547   freeAsmop (result, NULL, ic, TRUE);
7548 }
7549
7550 /*-----------------------------------------------------------------*/
7551 /* genNearPointerSet - emitcode for near pointer put                */
7552 /*-----------------------------------------------------------------*/
7553 static void
7554 genNearPointerSet (operand * right,
7555                    operand * result,
7556                    iCode * ic,
7557                    iCode * pi)
7558 {
7559   asmop *aop = NULL;
7560   regs *preg = NULL;
7561   char *rname, *l;
7562   sym_link *retype, *letype;
7563   sym_link *ptype = operandType (result);
7564
7565   retype = getSpec (operandType (right));
7566   letype = getSpec (ptype);
7567   aopOp (result, ic, FALSE);
7568
7569   /* if the result is rematerializable &
7570      in data space & not a bit variable */
7571   if (AOP_TYPE (result) == AOP_IMMD &&
7572       DCL_TYPE (ptype) == POINTER &&
7573       !IS_BITVAR (retype) &&
7574       !IS_BITVAR (letype))
7575     {
7576       genDataPointerSet (right, result, ic);
7577       return;
7578     }
7579   
7580   /* if the value is already in a pointer register
7581      then don't need anything more */
7582   if (!AOP_INPREG (AOP (result)))
7583     {
7584       /* otherwise get a free pointer register */
7585       aop = newAsmop (0);
7586       preg = getFreePtr (ic, &aop, FALSE);
7587       emitcode ("mov", "%s,%s",
7588                 preg->name,
7589                 aopGet (AOP (result), 0, FALSE, TRUE));
7590       rname = preg->name;
7591     }
7592   else
7593     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7594
7595   aopOp (right, ic, FALSE);
7596
7597   /* if bitfield then unpack the bits */
7598   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7599     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7600   else
7601     {
7602       /* we have can just get the values */
7603       int size = AOP_SIZE (right);
7604       int offset = 0;
7605
7606       while (size--)
7607         {
7608           l = aopGet (AOP (right), offset, FALSE, TRUE);
7609           if (*l == '@')
7610             {
7611               MOVA (l);
7612               emitcode ("mov", "@%s,a", rname);
7613             }
7614           else
7615             emitcode ("mov", "@%s,%s", rname, l);
7616           if (size || pi)
7617             emitcode ("inc", "%s", rname);
7618           offset++;
7619         }
7620     }
7621
7622   /* now some housekeeping stuff */
7623   if (aop) /* we had to allocate for this iCode */
7624     {
7625       if (pi) aopPut (AOP (result),rname,0);
7626       freeAsmop (NULL, aop, ic, TRUE);
7627     }
7628   else
7629     {
7630       /* we did not allocate which means left
7631          already in a pointer register, then
7632          if size > 0 && this could be used again
7633          we have to point it back to where it
7634          belongs */
7635       if ((AOP_SIZE (right) > 1 &&
7636            !OP_SYMBOL (result)->remat &&
7637            (OP_SYMBOL (result)->liveTo > ic->seq ||
7638             ic->depth)) &&
7639           !pi)
7640         {
7641           int size = AOP_SIZE (right) - 1;
7642           while (size--)
7643             emitcode ("dec", "%s", rname);
7644         }
7645     }
7646
7647   /* done */
7648   if (pi) pi->generated = 1;
7649   freeAsmop (result, NULL, ic, TRUE);
7650   freeAsmop (right, NULL, ic, TRUE);
7651 }
7652
7653 /*-----------------------------------------------------------------*/
7654 /* genPagedPointerSet - emitcode for Paged pointer put             */
7655 /*-----------------------------------------------------------------*/
7656 static void
7657 genPagedPointerSet (operand * right,
7658                     operand * result,
7659                     iCode * ic,
7660                     iCode * pi)
7661 {
7662   asmop *aop = NULL;
7663   regs *preg = NULL;
7664   char *rname, *l;
7665   sym_link *retype, *letype;
7666
7667   retype = getSpec (operandType (right));
7668   letype = getSpec (operandType (result));
7669
7670   aopOp (result, ic, FALSE);
7671
7672   /* if the value is already in a pointer register
7673      then don't need anything more */
7674   if (!AOP_INPREG (AOP (result)))
7675     {
7676       /* otherwise get a free pointer register */
7677       aop = newAsmop (0);
7678       preg = getFreePtr (ic, &aop, FALSE);
7679       emitcode ("mov", "%s,%s",
7680                 preg->name,
7681                 aopGet (AOP (result), 0, FALSE, TRUE));
7682       rname = preg->name;
7683     }
7684   else
7685     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7686
7687   aopOp (right, ic, FALSE);
7688
7689   /* if bitfield then unpack the bits */
7690   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7691     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7692   else
7693     {
7694       /* we have can just get the values */
7695       int size = AOP_SIZE (right);
7696       int offset = 0;
7697
7698       while (size--)
7699         {
7700           l = aopGet (AOP (right), offset, FALSE, TRUE);
7701
7702           MOVA (l);
7703           emitcode ("movx", "@%s,a", rname);
7704
7705           if (size || pi)
7706             emitcode ("inc", "%s", rname);
7707
7708           offset++;
7709         }
7710     }
7711
7712   /* now some housekeeping stuff */
7713   if (aop) /* we had to allocate for this iCode */
7714     {
7715       if (pi) aopPut (AOP (result),rname,0);
7716       freeAsmop (NULL, aop, ic, TRUE);
7717     }
7718   else
7719     {
7720       /* we did not allocate which means left
7721          already in a pointer register, then
7722          if size > 0 && this could be used again
7723          we have to point it back to where it
7724          belongs */
7725       if (AOP_SIZE (right) > 1 &&
7726           !OP_SYMBOL (result)->remat &&
7727           (OP_SYMBOL (result)->liveTo > ic->seq ||
7728            ic->depth))
7729         {
7730           int size = AOP_SIZE (right) - 1;
7731           while (size--)
7732             emitcode ("dec", "%s", rname);
7733         }
7734     }
7735
7736   /* done */
7737   if (pi) pi->generated = 1;
7738   freeAsmop (result, NULL, ic, TRUE);
7739   freeAsmop (right, NULL, ic, TRUE);
7740
7741
7742 }
7743
7744 /*-----------------------------------------------------------------*/
7745 /* genFarPointerSet - set value from far space                     */
7746 /*-----------------------------------------------------------------*/
7747 static void
7748 genFarPointerSet (operand * right,
7749                   operand * result, iCode * ic, iCode * pi)
7750 {
7751   int size, offset;
7752   sym_link *retype = getSpec (operandType (right));
7753   sym_link *letype = getSpec (operandType (result));
7754   aopOp (result, ic, FALSE);
7755
7756   /* if the operand is already in dptr
7757      then we do nothing else we move the value to dptr */
7758   if (AOP_TYPE (result) != AOP_STR)
7759     {
7760       /* if this is remateriazable */
7761       if (AOP_TYPE (result) == AOP_IMMD)
7762         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7763       else
7764         {                       /* we need to get it byte by byte */
7765           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7766           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7767         }
7768     }
7769   /* so dptr know contains the address */
7770   aopOp (right, ic, FALSE);
7771
7772   /* if bit then unpack */
7773   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7774     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7775   else
7776     {
7777       size = AOP_SIZE (right);
7778       offset = 0;
7779
7780       while (size--)
7781         {
7782           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7783           MOVA (l);
7784           emitcode ("movx", "@dptr,a");
7785           if (size || pi)
7786             emitcode ("inc", "dptr");
7787         }
7788     }
7789   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7790     aopPut (AOP(result),"dpl",0);
7791     aopPut (AOP(result),"dph",1);
7792     pi->generated=1;
7793   }
7794   freeAsmop (result, NULL, ic, TRUE);
7795   freeAsmop (right, NULL, ic, TRUE);
7796 }
7797
7798 /*-----------------------------------------------------------------*/
7799 /* genGenPointerSet - set value from generic pointer space         */
7800 /*-----------------------------------------------------------------*/
7801 static void
7802 genGenPointerSet (operand * right,
7803                   operand * result, iCode * ic, iCode * pi)
7804 {
7805   int size, offset;
7806   sym_link *retype = getSpec (operandType (right));
7807   sym_link *letype = getSpec (operandType (result));
7808
7809   aopOp (result, ic, FALSE);
7810
7811   /* if the operand is already in dptr
7812      then we do nothing else we move the value to dptr */
7813   if (AOP_TYPE (result) != AOP_STR)
7814     {
7815       /* if this is remateriazable */
7816       if (AOP_TYPE (result) == AOP_IMMD)
7817         {
7818           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7819           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7820         }
7821       else
7822         {                       /* we need to get it byte by byte */
7823           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7824           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7825           emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7826         }
7827     }
7828   /* so dptr know contains the address */
7829   aopOp (right, ic, FALSE);
7830
7831   /* if bit then unpack */
7832   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7833     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7834   else
7835     {
7836       size = AOP_SIZE (right);
7837       offset = 0;
7838
7839       while (size--)
7840         {
7841           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7842           MOVA (l);
7843           emitcode ("lcall", "__gptrput");
7844           if (size || pi)
7845             emitcode ("inc", "dptr");
7846         }
7847     }
7848
7849   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7850     aopPut (AOP(result),"dpl",0);
7851     aopPut (AOP(result),"dph",1);
7852     pi->generated=1;
7853   }
7854   freeAsmop (result, NULL, ic, TRUE);
7855   freeAsmop (right, NULL, ic, TRUE);
7856 }
7857
7858 /*-----------------------------------------------------------------*/
7859 /* genPointerSet - stores the value into a pointer location        */
7860 /*-----------------------------------------------------------------*/
7861 static void
7862 genPointerSet (iCode * ic, iCode *pi)
7863 {
7864   operand *right, *result;
7865   sym_link *type, *etype;
7866   int p_type;
7867
7868   right = IC_RIGHT (ic);
7869   result = IC_RESULT (ic);
7870
7871   /* depending on the type of pointer we need to
7872      move it to the correct pointer register */
7873   type = operandType (result);
7874   etype = getSpec (type);
7875   /* if left is of type of pointer then it is simple */
7876   if (IS_PTR (type) && !IS_FUNC (type->next))
7877     {
7878       p_type = DCL_TYPE (type);
7879     }
7880   else
7881     {
7882       /* we have to go by the storage class */
7883       p_type = PTR_TYPE (SPEC_OCLS (etype));
7884     }
7885
7886   /* now that we have the pointer type we assign
7887      the pointer values */
7888   switch (p_type)
7889     {
7890
7891     case POINTER:
7892     case IPOINTER:
7893       genNearPointerSet (right, result, ic, pi);
7894       break;
7895
7896     case PPOINTER:
7897       genPagedPointerSet (right, result, ic, pi);
7898       break;
7899
7900     case FPOINTER:
7901       genFarPointerSet (right, result, ic, pi);
7902       break;
7903
7904     case GPOINTER:
7905       genGenPointerSet (right, result, ic, pi);
7906       break;
7907     }
7908
7909 }
7910
7911 /*-----------------------------------------------------------------*/
7912 /* genIfx - generate code for Ifx statement                        */
7913 /*-----------------------------------------------------------------*/
7914 static void
7915 genIfx (iCode * ic, iCode * popIc)
7916 {
7917   operand *cond = IC_COND (ic);
7918   int isbit = 0;
7919
7920   aopOp (cond, ic, FALSE);
7921
7922   /* get the value into acc */
7923   if (AOP_TYPE (cond) != AOP_CRY)
7924     toBoolean (cond);
7925   else
7926     isbit = 1;
7927   /* the result is now in the accumulator */
7928   freeAsmop (cond, NULL, ic, TRUE);
7929
7930   /* if there was something to be popped then do it */
7931   if (popIc)
7932     genIpop (popIc);
7933
7934   /* if the condition is  a bit variable */
7935   if (isbit && IS_ITEMP (cond) &&
7936       SPIL_LOC (cond))
7937     genIfxJump (ic, SPIL_LOC (cond)->rname);
7938   else if (isbit && !IS_ITEMP (cond))
7939     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7940   else
7941     genIfxJump (ic, "a");
7942
7943   ic->generated = 1;
7944 }
7945
7946 /*-----------------------------------------------------------------*/
7947 /* genAddrOf - generates code for address of                       */
7948 /*-----------------------------------------------------------------*/
7949 static void
7950 genAddrOf (iCode * ic)
7951 {
7952   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7953   int size, offset;
7954
7955   aopOp (IC_RESULT (ic), ic, FALSE);
7956
7957   /* if the operand is on the stack then we
7958      need to get the stack offset of this
7959      variable */
7960   if (sym->onStack)
7961     {
7962       /* if it has an offset then we need to compute
7963          it */
7964       if (sym->stack)
7965         {
7966           emitcode ("mov", "a,_bp");
7967           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7968           aopPut (AOP (IC_RESULT (ic)), "a", 0);
7969         }
7970       else
7971         {
7972           /* we can just move _bp */
7973           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7974         }
7975       /* fill the result with zero */
7976       size = AOP_SIZE (IC_RESULT (ic)) - 1;
7977
7978       offset = 1;
7979       while (size--)
7980         {
7981           aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7982         }
7983
7984       goto release;
7985     }
7986
7987   /* object not on stack then we need the name */
7988   size = AOP_SIZE (IC_RESULT (ic));
7989   offset = 0;
7990
7991   while (size--)
7992     {
7993       char s[SDCC_NAME_MAX];
7994       if (offset)
7995         sprintf (s, "#(%s >> %d)",
7996                  sym->rname,
7997                  offset * 8);
7998       else
7999         sprintf (s, "#%s", sym->rname);
8000       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8001     }
8002
8003 release:
8004   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8005
8006 }
8007
8008 /*-----------------------------------------------------------------*/
8009 /* genFarFarAssign - assignment when both are in far space         */
8010 /*-----------------------------------------------------------------*/
8011 static void
8012 genFarFarAssign (operand * result, operand * right, iCode * ic)
8013 {
8014   int size = AOP_SIZE (right);
8015   int offset = 0;
8016   char *l;
8017   /* first push the right side on to the stack */
8018   while (size--)
8019     {
8020       l = aopGet (AOP (right), offset++, FALSE, FALSE);
8021       MOVA (l);
8022       emitcode ("push", "acc");
8023     }
8024
8025   freeAsmop (right, NULL, ic, FALSE);
8026   /* now assign DPTR to result */
8027   aopOp (result, ic, FALSE);
8028   size = AOP_SIZE (result);
8029   while (size--)
8030     {
8031       emitcode ("pop", "acc");
8032       aopPut (AOP (result), "a", --offset);
8033     }
8034   freeAsmop (result, NULL, ic, FALSE);
8035
8036 }
8037
8038 /*-----------------------------------------------------------------*/
8039 /* genAssign - generate code for assignment                        */
8040 /*-----------------------------------------------------------------*/
8041 static void
8042 genAssign (iCode * ic)
8043 {
8044   operand *result, *right;
8045   int size, offset;
8046   unsigned long lit = 0L;
8047
8048   D(emitcode(";","genAssign"));
8049
8050   result = IC_RESULT (ic);
8051   right = IC_RIGHT (ic);
8052
8053   /* if they are the same */
8054   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8055     return;
8056
8057   aopOp (right, ic, FALSE);
8058
8059   /* special case both in far space */
8060   if (AOP_TYPE (right) == AOP_DPTR &&
8061       IS_TRUE_SYMOP (result) &&
8062       isOperandInFarSpace (result))
8063     {
8064
8065       genFarFarAssign (result, right, ic);
8066       return;
8067     }
8068
8069   aopOp (result, ic, TRUE);
8070
8071   /* if they are the same registers */
8072   if (sameRegs (AOP (right), AOP (result)))
8073     goto release;
8074
8075   /* if the result is a bit */
8076   if (AOP_TYPE (result) == AOP_CRY)
8077     {
8078
8079       /* if the right size is a literal then
8080          we know what the value is */
8081       if (AOP_TYPE (right) == AOP_LIT)
8082         {
8083           if (((int) operandLitValue (right)))
8084             aopPut (AOP (result), one, 0);
8085           else
8086             aopPut (AOP (result), zero, 0);
8087           goto release;
8088         }
8089
8090       /* the right is also a bit variable */
8091       if (AOP_TYPE (right) == AOP_CRY)
8092         {
8093           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8094           aopPut (AOP (result), "c", 0);
8095           goto release;
8096         }
8097
8098       /* we need to or */
8099       toBoolean (right);
8100       aopPut (AOP (result), "a", 0);
8101       goto release;
8102     }
8103
8104   /* bit variables done */
8105   /* general case */
8106   size = AOP_SIZE (result);
8107   offset = 0;
8108   if (AOP_TYPE (right) == AOP_LIT)
8109     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8110   if ((size > 1) &&
8111       (AOP_TYPE (result) != AOP_REG) &&
8112       (AOP_TYPE (right) == AOP_LIT) &&
8113       !IS_FLOAT (operandType (right)) &&
8114       (lit < 256L))
8115     {
8116       emitcode ("clr", "a");
8117       while (size--)
8118         {
8119           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8120             aopPut (AOP (result), "a", size);
8121           else
8122             aopPut (AOP (result),
8123                     aopGet (AOP (right), size, FALSE, FALSE),
8124                     size);
8125         }
8126     }
8127   else
8128     {
8129       while (size--)
8130         {
8131           aopPut (AOP (result),
8132                   aopGet (AOP (right), offset, FALSE, FALSE),
8133                   offset);
8134           offset++;
8135         }
8136     }
8137
8138 release:
8139   freeAsmop (right, NULL, ic, TRUE);
8140   freeAsmop (result, NULL, ic, TRUE);
8141 }
8142
8143 /*-----------------------------------------------------------------*/
8144 /* genJumpTab - genrates code for jump table                       */
8145 /*-----------------------------------------------------------------*/
8146 static void
8147 genJumpTab (iCode * ic)
8148 {
8149   symbol *jtab;
8150   char *l;
8151
8152   aopOp (IC_JTCOND (ic), ic, FALSE);
8153   /* get the condition into accumulator */
8154   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8155   MOVA (l);
8156   /* multiply by three */
8157   emitcode ("add", "a,acc");
8158   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8159   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8160
8161   jtab = newiTempLabel (NULL);
8162   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8163   emitcode ("jmp", "@a+dptr");
8164   emitcode ("", "%05d$:", jtab->key + 100);
8165   /* now generate the jump labels */
8166   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8167        jtab = setNextItem (IC_JTLABELS (ic)))
8168     emitcode ("ljmp", "%05d$", jtab->key + 100);
8169
8170 }
8171
8172 /*-----------------------------------------------------------------*/
8173 /* genCast - gen code for casting                                  */
8174 /*-----------------------------------------------------------------*/
8175 static void
8176 genCast (iCode * ic)
8177 {
8178   operand *result = IC_RESULT (ic);
8179   sym_link *ctype = operandType (IC_LEFT (ic));
8180   sym_link *rtype = operandType (IC_RIGHT (ic));
8181   operand *right = IC_RIGHT (ic);
8182   int size, offset;
8183
8184   D(emitcode(";", "genCast"));
8185
8186   /* if they are equivalent then do nothing */
8187   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8188     return;
8189
8190   aopOp (right, ic, FALSE);
8191   aopOp (result, ic, FALSE);
8192
8193   /* if the result is a bit */
8194   // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8195   if (IS_BITVAR(OP_SYMBOL(result)->type))
8196     {
8197       /* if the right size is a literal then
8198          we know what the value is */
8199       if (AOP_TYPE (right) == AOP_LIT)
8200         {
8201           if (((int) operandLitValue (right)))
8202             aopPut (AOP (result), one, 0);
8203           else
8204             aopPut (AOP (result), zero, 0);
8205
8206           goto release;
8207         }
8208
8209       /* the right is also a bit variable */
8210       if (AOP_TYPE (right) == AOP_CRY)
8211         {
8212           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8213           aopPut (AOP (result), "c", 0);
8214           goto release;
8215         }
8216
8217       /* we need to or */
8218       toBoolean (right);
8219       aopPut (AOP (result), "a", 0);
8220       goto release;
8221     }
8222
8223   /* if they are the same size : or less */
8224   if (AOP_SIZE (result) <= AOP_SIZE (right))
8225     {
8226
8227       /* if they are in the same place */
8228       if (sameRegs (AOP (right), AOP (result)))
8229         goto release;
8230
8231       /* if they in different places then copy */
8232       size = AOP_SIZE (result);
8233       offset = 0;
8234       while (size--)
8235         {
8236           aopPut (AOP (result),
8237                   aopGet (AOP (right), offset, FALSE, FALSE),
8238                   offset);
8239           offset++;
8240         }
8241       goto release;
8242     }
8243
8244
8245   /* if the result is of type pointer */
8246   if (IS_PTR (ctype))
8247     {
8248
8249       int p_type;
8250       sym_link *type = operandType (right);
8251       sym_link *etype = getSpec (type);
8252
8253       /* pointer to generic pointer */
8254       if (IS_GENPTR (ctype))
8255         {
8256           char *l = zero;
8257
8258           if (IS_PTR (type))
8259             p_type = DCL_TYPE (type);
8260           else
8261             {
8262               if (SPEC_SCLS(etype)==S_REGISTER) {
8263                 // let's assume it is a generic pointer
8264                 p_type=GPOINTER;
8265               } else {
8266                 /* we have to go by the storage class */
8267                 p_type = PTR_TYPE (SPEC_OCLS (etype));
8268               }
8269             }
8270
8271           /* the first two bytes are known */
8272           size = GPTRSIZE - 1;
8273           offset = 0;
8274           while (size--)
8275             {
8276               aopPut (AOP (result),
8277                       aopGet (AOP (right), offset, FALSE, FALSE),
8278                       offset);
8279               offset++;
8280             }
8281           /* the last byte depending on type */
8282           switch (p_type)
8283             {
8284             case IPOINTER:
8285             case POINTER:
8286               l = zero;
8287               break;
8288             case FPOINTER:
8289               l = one;
8290               break;
8291             case CPOINTER:
8292               l = "#0x02";
8293               break;
8294             case GPOINTER:
8295               l = "0x03";
8296               break;
8297             case PPOINTER: // what the fck is this?
8298               l = "#0x03";
8299               break;
8300
8301             default:
8302               /* this should never happen */
8303               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8304                       "got unknown pointer type");
8305               exit (1);
8306             }
8307           aopPut (AOP (result), l, GPTRSIZE - 1);
8308           goto release;
8309         }
8310
8311       /* just copy the pointers */
8312       size = AOP_SIZE (result);
8313       offset = 0;
8314       while (size--)
8315         {
8316           aopPut (AOP (result),
8317                   aopGet (AOP (right), offset, FALSE, FALSE),
8318                   offset);
8319           offset++;
8320         }
8321       goto release;
8322     }
8323
8324   /* so we now know that the size of destination is greater
8325      than the size of the source */
8326   /* we move to result for the size of source */
8327   size = AOP_SIZE (right);
8328   offset = 0;
8329   while (size--)
8330     {
8331       aopPut (AOP (result),
8332               aopGet (AOP (right), offset, FALSE, FALSE),
8333               offset);
8334       offset++;
8335     }
8336
8337   /* now depending on the sign of the source && destination */
8338   size = AOP_SIZE (result) - AOP_SIZE (right);
8339   /* if unsigned or not an integral type */
8340   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8341     {
8342       while (size--)
8343         aopPut (AOP (result), zero, offset++);
8344     }
8345   else
8346     {
8347       /* we need to extend the sign :{ */
8348       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8349                         FALSE, FALSE);
8350       MOVA (l);
8351       emitcode ("rlc", "a");
8352       emitcode ("subb", "a,acc");
8353       while (size--)
8354         aopPut (AOP (result), "a", offset++);
8355     }
8356
8357   /* we are done hurray !!!! */
8358
8359 release:
8360   freeAsmop (right, NULL, ic, TRUE);
8361   freeAsmop (result, NULL, ic, TRUE);
8362
8363 }
8364
8365 /*-----------------------------------------------------------------*/
8366 /* genDjnz - generate decrement & jump if not zero instrucion      */
8367 /*-----------------------------------------------------------------*/
8368 static int
8369 genDjnz (iCode * ic, iCode * ifx)
8370 {
8371   symbol *lbl, *lbl1;
8372   if (!ifx)
8373     return 0;
8374
8375   /* if the if condition has a false label
8376      then we cannot save */
8377   if (IC_FALSE (ifx))
8378     return 0;
8379
8380   /* if the minus is not of the form
8381      a = a - 1 */
8382   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8383       !IS_OP_LITERAL (IC_RIGHT (ic)))
8384     return 0;
8385
8386   if (operandLitValue (IC_RIGHT (ic)) != 1)
8387     return 0;
8388
8389   /* if the size of this greater than one then no
8390      saving */
8391   if (getSize (operandType (IC_RESULT (ic))) > 1)
8392     return 0;
8393
8394   /* otherwise we can save BIG */
8395   lbl = newiTempLabel (NULL);
8396   lbl1 = newiTempLabel (NULL);
8397
8398   aopOp (IC_RESULT (ic), ic, FALSE);
8399
8400   if (AOP_NEEDSACC(IC_RESULT(ic)))
8401   {
8402       /* If the result is accessed indirectly via
8403        * the accumulator, we must explicitly write
8404        * it back after the decrement.
8405        */
8406       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8407       
8408       if (strcmp(rByte, "a"))
8409       {
8410            /* Something is hopelessly wrong */
8411            fprintf(stderr, "*** warning: internal error at %s:%d\n",
8412                    __FILE__, __LINE__);
8413            /* We can just give up; the generated code will be inefficient,
8414             * but what the hey.
8415             */
8416            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8417            return 0;
8418       }
8419       emitcode ("dec", "%s", rByte);
8420       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8421       emitcode ("jnz", "%05d$", lbl->key + 100);
8422   }
8423   else if (IS_AOP_PREG (IC_RESULT (ic)))
8424     {
8425       emitcode ("dec", "%s",
8426                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8427       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8428       emitcode ("jnz", "%05d$", lbl->key + 100);
8429     }
8430   else
8431     {
8432       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8433                 lbl->key + 100);
8434     }
8435   emitcode ("sjmp", "%05d$", lbl1->key + 100);
8436   emitcode ("", "%05d$:", lbl->key + 100);
8437   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8438   emitcode ("", "%05d$:", lbl1->key + 100);
8439
8440   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8441   ifx->generated = 1;
8442   return 1;
8443 }
8444
8445 /*-----------------------------------------------------------------*/
8446 /* genReceive - generate code for a receive iCode                  */
8447 /*-----------------------------------------------------------------*/
8448 static void
8449 genReceive (iCode * ic)
8450 {
8451   if (isOperandInFarSpace (IC_RESULT (ic)) &&
8452       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8453        IS_TRUE_SYMOP (IC_RESULT (ic))))
8454     {
8455
8456       int size = getSize (operandType (IC_RESULT (ic)));
8457       int offset = fReturnSizeMCS51 - size;
8458       while (size--)
8459         {
8460           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8461                                 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8462           offset++;
8463         }
8464       aopOp (IC_RESULT (ic), ic, FALSE);
8465       size = AOP_SIZE (IC_RESULT (ic));
8466       offset = 0;
8467       while (size--)
8468         {
8469           emitcode ("pop", "acc");
8470           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8471         }
8472
8473     }
8474   else
8475     {
8476       _G.accInUse++;
8477       aopOp (IC_RESULT (ic), ic, FALSE);
8478       _G.accInUse--;
8479       assignResultValue (IC_RESULT (ic));
8480     }
8481
8482   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8483 }
8484
8485 /*-----------------------------------------------------------------*/
8486 /* gen51AggregateAssign - copy complete array's or structures            */
8487 /*-----------------------------------------------------------------*/
8488 void gen51AggregateAssign(iCode *ic) {
8489   operand *left=IC_LEFT(ic);
8490   operand *right=IC_RIGHT(ic);
8491   char *fromName=OP_SYMBOL(right)->rname;
8492   char *toName=OP_SYMBOL(left)->rname;
8493   int fromSize=getSize(OP_SYMBOL(right)->type);
8494   int toSize=getSize(OP_SYMBOL(left)->type);
8495   int count=toSize;
8496
8497   if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8498       SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8499     // well, this code isn't used yet from anywhere else as for initialising
8500     fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8501     exit (457);
8502   }
8503
8504   if (fromSize!=toSize) {
8505     fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8506              ic->filename, ic->lineno);
8507     exit (821);
8508   }
8509
8510 #if 1
8511   // use the generic memcpy() for now
8512   emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8513   emitcode ("mov", "dptr,#_memcpy_PARM_2");
8514   emitcode ("mov", "a,#%s", fromName);
8515   emitcode ("movx", "@dptr,a");
8516   emitcode ("inc", "dptr");
8517   emitcode ("mov", "a,#(%s>>8)", fromName);
8518   emitcode ("movx", "@dptr,a");
8519   emitcode ("inc", "dptr");
8520   emitcode ("mov", "a,#%02x;    only from cseg for now", 2);
8521   emitcode ("movx", "@dptr,a");
8522   emitcode ("mov", "dptr,#_memcpy_PARM_3");
8523   emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8524   emitcode ("movx", "@dptr,a");
8525   emitcode ("inc", "dptr");
8526   emitcode ("mov", "a,#(%d>>8)", count);
8527   emitcode ("movx", "@dptr,a");
8528   emitcode ("mov", "dptr,#%s", toName);
8529   emitcode ("mov", "b,#%02x;    only to xseg for now", 1);
8530   emitcode ("lcall", "_memcpy");
8531 #else
8532   // more efficient, but will require the native_memcpy_cs2xs
8533   emitcode ("mov", "r0,#%s", fromName);
8534   emitcode ("mov", "r1,#(%s>>8)", fromName);
8535   emitcode ("mov", "r2,#%s", toName);
8536   emitcode ("mov", "r3,#(%s>>8)", toName);
8537   emitcode ("mov", "r4,#%d", count);
8538   emitcode ("mov", "r5,#(%d>>8)", count);
8539   emitcode ("lcall", "_native_memcpy_cs2xs");
8540 #endif
8541 }
8542
8543 /*-----------------------------------------------------------------*/
8544 /* gen51Code - generate code for 8051 based controllers            */
8545 /*-----------------------------------------------------------------*/
8546 void
8547 gen51Code (iCode * lic)
8548 {
8549   iCode *ic;
8550   int cln = 0;
8551
8552   lineHead = lineCurr = NULL;
8553
8554   /* print the allocation information */
8555   if (allocInfo)
8556     printAllocInfo (currFunc, codeOutFile);
8557   /* if debug information required */
8558   /*     if (options.debug && currFunc) { */
8559   if (options.debug && currFunc)
8560     {
8561       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8562       _G.debugLine = 1;
8563       if (IS_STATIC (currFunc->etype))
8564         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8565       else
8566         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8567       _G.debugLine = 0;
8568     }
8569   /* stack pointer name */
8570   if (options.useXstack)
8571     spname = "_spx";
8572   else
8573     spname = "sp";
8574
8575
8576   for (ic = lic; ic; ic = ic->next)
8577     {
8578
8579       if (cln != ic->lineno)
8580         {
8581           if (options.debug)
8582             {
8583               _G.debugLine = 1;
8584               emitcode ("", "C$%s$%d$%d$%d ==.",
8585                         FileBaseName (ic->filename), ic->lineno,
8586                         ic->level, ic->block);
8587               _G.debugLine = 0;
8588             }
8589           emitcode (";", "%s %d", ic->filename, ic->lineno);
8590           cln = ic->lineno;
8591         }
8592       /* if the result is marked as
8593          spilt and rematerializable or code for
8594          this has already been generated then
8595          do nothing */
8596       if (resultRemat (ic) || ic->generated)
8597         continue;
8598
8599       /* depending on the operation */
8600       switch (ic->op)
8601         {
8602         case '!':
8603           genNot (ic);
8604           break;
8605
8606         case '~':
8607           genCpl (ic);
8608           break;
8609
8610         case UNARYMINUS:
8611           genUminus (ic);
8612           break;
8613
8614         case IPUSH:
8615           genIpush (ic);
8616           break;
8617
8618         case IPOP:
8619           /* IPOP happens only when trying to restore a
8620              spilt live range, if there is an ifx statement
8621              following this pop then the if statement might
8622              be using some of the registers being popped which
8623              would destory the contents of the register so
8624              we need to check for this condition and handle it */
8625           if (ic->next &&
8626               ic->next->op == IFX &&
8627               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8628             genIfx (ic->next, ic);
8629           else
8630             genIpop (ic);
8631           break;
8632
8633         case CALL:
8634           genCall (ic);
8635           break;
8636
8637         case PCALL:
8638           genPcall (ic);
8639           break;
8640
8641         case FUNCTION:
8642           genFunction (ic);
8643           break;
8644
8645         case ENDFUNCTION:
8646           genEndFunction (ic);
8647           break;
8648
8649         case RETURN:
8650           genRet (ic);
8651           break;
8652
8653         case LABEL:
8654           genLabel (ic);
8655           break;
8656
8657         case GOTO:
8658           genGoto (ic);
8659           break;
8660
8661         case '+':
8662           genPlus (ic);
8663           break;
8664
8665         case '-':
8666           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8667             genMinus (ic);
8668           break;
8669
8670         case '*':
8671           genMult (ic);
8672           break;
8673
8674         case '/':
8675           genDiv (ic);
8676           break;
8677
8678         case '%':
8679           genMod (ic);
8680           break;
8681
8682         case '>':
8683           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8684           break;
8685
8686         case '<':
8687           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8688           break;
8689
8690         case LE_OP:
8691         case GE_OP:
8692         case NE_OP:
8693
8694           /* note these two are xlated by algebraic equivalence
8695              during parsing SDCC.y */
8696           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8697                   "got '>=' or '<=' shouldn't have come here");
8698           break;
8699
8700         case EQ_OP:
8701           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8702           break;
8703
8704         case AND_OP:
8705           genAndOp (ic);
8706           break;
8707
8708         case OR_OP:
8709           genOrOp (ic);
8710           break;
8711
8712         case '^':
8713           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8714           break;
8715
8716         case '|':
8717           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8718           break;
8719
8720         case BITWISEAND:
8721           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8722           break;
8723
8724         case INLINEASM:
8725           genInline (ic);
8726           break;
8727
8728         case RRC:
8729           genRRC (ic);
8730           break;
8731
8732         case RLC:
8733           genRLC (ic);
8734           break;
8735
8736         case GETHBIT:
8737           genGetHbit (ic);
8738           break;
8739
8740         case LEFT_OP:
8741           genLeftShift (ic);
8742           break;
8743
8744         case RIGHT_OP:
8745           genRightShift (ic);
8746           break;
8747
8748         case GET_VALUE_AT_ADDRESS:
8749           genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8750           break;
8751
8752         case '=':
8753           if (POINTER_SET (ic))
8754             genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8755           else
8756             genAssign (ic);
8757           break;
8758
8759         case IFX:
8760           genIfx (ic, NULL);
8761           break;
8762
8763         case ADDRESS_OF:
8764           genAddrOf (ic);
8765           break;
8766
8767         case JUMPTABLE:
8768           genJumpTab (ic);
8769           break;
8770
8771         case CAST:
8772           genCast (ic);
8773           break;
8774
8775         case RECEIVE:
8776           genReceive (ic);
8777           break;
8778
8779         case SEND:
8780           addSet (&_G.sendSet, ic);
8781           break;
8782
8783         case ARRAYINIT:
8784           gen51AggregateAssign(ic);
8785           break;
8786
8787         default:
8788           ic = ic;
8789         }
8790     }
8791
8792
8793   /* now we are ready to call the
8794      peep hole optimizer */
8795   if (!options.nopeep)
8796     peepHole (&lineHead);
8797
8798   /* now do the actual printing */
8799   printLine (lineHead, codeOutFile);
8800   return;
8801 }