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