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