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