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