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