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