Improved genFarFarAssign
[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 ;jwk saveRegisters", ds390_regWithIdx (i)->dname);
1796       }
1797
1798   detype = getSpec (operandType (IC_LEFT (ic)));
1799   if (detype &&
1800       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
1801       IS_ISR (currFunc->etype) &&
1802       !ic->bankSaved)
1803
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 ;jwk unsaveRegisters", 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 ;jwk genIpush: !parm", 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 ;jwk genIpush", 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 ;jwk genIpop", 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
2153   D (emitcode (";", "genCall ");
2154     );
2155
2156   /* if caller saves & we have not saved then */
2157   if (!ic->regsSaved)
2158     saveRegisters (ic);
2159
2160   /* if we are calling a function that is not using
2161      the same register bank then we need to save the
2162      destination registers on the stack */
2163   detype = getSpec (operandType (IC_LEFT (ic)));
2164   if (detype &&
2165       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
2166       IS_ISR (currFunc->etype) &&
2167       !ic->bankSaved)
2168
2169     saverbank (SPEC_BANK (detype), ic, TRUE);
2170
2171   /* if send set is not empty the assign */
2172   if (_G.sendSet)
2173     {
2174       iCode *sic;
2175
2176       for (sic = setFirstItem (_G.sendSet); sic;
2177            sic = setNextItem (_G.sendSet))
2178         {
2179           int size, offset = 0;
2180
2181           aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2182           size = AOP_SIZE (IC_LEFT (sic));
2183
2184           _startLazyDPSEvaluation ();
2185           while (size--)
2186             {
2187               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2188                                 FALSE, FALSE, TRUE);
2189               if (strcmp (l, fReturn[offset])) {
2190                 genSetDPTR(0);
2191                 _flushLazyDPS();
2192                 emitcode ("mov", "%s,%s ;jwk lazy genCall",
2193                           fReturn[offset],
2194                           l);
2195               }
2196               offset++;
2197             }
2198           _endLazyDPSEvaluation ();
2199           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2200         }
2201       _G.sendSet = NULL;
2202     }
2203   /* make the call */
2204   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2205                             OP_SYMBOL (IC_LEFT (ic))->rname :
2206                             OP_SYMBOL (IC_LEFT (ic))->name));
2207
2208   /* if we need assign a result value */
2209   if ((IS_ITEMP (IC_RESULT (ic)) &&
2210        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2211         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2212       IS_TRUE_SYMOP (IC_RESULT (ic)))
2213     {
2214       if (isOperandInFarSpace (IC_RESULT (ic))
2215           && getSize (operandType (IC_RESULT (ic))) <= 2)
2216         {
2217           int size = getSize (operandType (IC_RESULT (ic)));
2218
2219           /* Special case for 1 or 2 byte return in far space. */
2220           MOVA (fReturn[0]);
2221           if (size > 1)
2222             {
2223               emitcode ("mov", "b,%s", fReturn[1]);
2224             }
2225
2226           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2227           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2228
2229           if (size > 1)
2230             {
2231               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2232             }
2233           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2234         }
2235       else
2236         {
2237           _G.accInUse++;
2238           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2239           _G.accInUse--;
2240
2241           assignResultValue (IC_RESULT (ic));
2242
2243           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2244         }
2245     }
2246
2247   /* adjust the stack for parameters if
2248      required */
2249   if (ic->parmBytes)
2250     {
2251       int i;
2252       if (ic->parmBytes > 3)
2253         {
2254           emitcode ("mov", "a,%s", spname);
2255           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2256           emitcode ("mov", "%s,a", spname);
2257         }
2258       else
2259         for (i = 0; i < ic->parmBytes; i++)
2260           emitcode ("dec", "%s", spname);
2261
2262     }
2263
2264   /* if register bank was saved then pop them */
2265   if (ic->bankSaved)
2266     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2267
2268   /* if we hade saved some registers then unsave them */
2269   if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
2270     unsaveRegisters (ic);
2271
2272
2273 }
2274
2275 /*-----------------------------------------------------------------*/
2276 /* genPcall - generates a call by pointer statement                */
2277 /*-----------------------------------------------------------------*/
2278 static void
2279 genPcall (iCode * ic)
2280 {
2281   sym_link *detype;
2282   symbol *rlbl = newiTempLabel (NULL);
2283
2284   D (emitcode (";", "genPcall ");
2285     );
2286
2287
2288   /* if caller saves & we have not saved then */
2289   if (!ic->regsSaved)
2290     saveRegisters (ic);
2291
2292   /* if we are calling a function that is not using
2293      the same register bank then we need to save the
2294      destination registers on the stack */
2295   detype = getSpec (operandType (IC_LEFT (ic)));
2296   if (detype &&
2297       IS_ISR (currFunc->etype) &&
2298       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
2299     saverbank (SPEC_BANK (detype), ic, TRUE);
2300
2301
2302   /* push the return address on to the stack */
2303   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2304   emitcode ("push", "acc");
2305   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2306   emitcode ("push", "acc");
2307
2308   if (options.model == MODEL_FLAT24)
2309     {
2310       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2311       emitcode ("push", "acc");
2312     }
2313
2314   /* now push the calling address */
2315   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2316
2317   pushSide (IC_LEFT (ic), FPTRSIZE);
2318
2319   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2320
2321   /* if send set is not empty the assign */
2322   if (_G.sendSet)
2323     {
2324       iCode *sic;
2325
2326       for (sic = setFirstItem (_G.sendSet); sic;
2327            sic = setNextItem (_G.sendSet))
2328         {
2329           int size, offset = 0;
2330
2331           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2332           size = AOP_SIZE (IC_LEFT (sic));
2333           _startLazyDPSEvaluation ();
2334           while (size--)
2335             {
2336               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2337                                 FALSE, FALSE, TRUE);
2338               if (strcmp (l, fReturn[offset]))
2339                 {
2340                   emitcode ("mov", "%s,%s",
2341                             fReturn[offset],
2342                             l);
2343                 }
2344               offset++;
2345             }
2346           _endLazyDPSEvaluation ();
2347           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2348         }
2349       _G.sendSet = NULL;
2350     }
2351
2352   emitcode ("ret", "");
2353   emitcode ("", "%05d$:", (rlbl->key + 100));
2354
2355
2356   /* if we need assign a result value */
2357   if ((IS_ITEMP (IC_RESULT (ic)) &&
2358        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2359         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2360       IS_TRUE_SYMOP (IC_RESULT (ic)))
2361     {
2362
2363       _G.accInUse++;
2364       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2365       _G.accInUse--;
2366
2367       assignResultValue (IC_RESULT (ic));
2368
2369       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2370     }
2371
2372   /* adjust the stack for parameters if
2373      required */
2374   if (ic->parmBytes)
2375     {
2376       int i;
2377       if (ic->parmBytes > 3)
2378         {
2379           emitcode ("mov", "a,%s", spname);
2380           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2381           emitcode ("mov", "%s,a", spname);
2382         }
2383       else
2384         for (i = 0; i < ic->parmBytes; i++)
2385           emitcode ("dec", "%s", spname);
2386
2387     }
2388
2389   /* if register bank was saved then unsave them */
2390   if (detype &&
2391       (SPEC_BANK (currFunc->etype) !=
2392        SPEC_BANK (detype)))
2393     unsaverbank (SPEC_BANK (detype), ic, TRUE);
2394
2395   /* if we hade saved some registers then
2396      unsave them */
2397   if (ic->regsSaved)
2398     unsaveRegisters (ic);
2399
2400 }
2401
2402 /*-----------------------------------------------------------------*/
2403 /* resultRemat - result  is rematerializable                       */
2404 /*-----------------------------------------------------------------*/
2405 static int
2406 resultRemat (iCode * ic)
2407 {
2408   if (SKIP_IC (ic) || ic->op == IFX)
2409     return 0;
2410
2411   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2412     {
2413       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2414       if (sym->remat && !POINTER_SET (ic))
2415         return 1;
2416     }
2417
2418   return 0;
2419 }
2420
2421 #if defined(__BORLANDC__) || defined(_MSC_VER)
2422 #define STRCASECMP stricmp
2423 #else
2424 #define STRCASECMP strcasecmp
2425 #endif
2426
2427 /*-----------------------------------------------------------------*/
2428 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2429 /*-----------------------------------------------------------------*/
2430 static bool
2431 inExcludeList (char *s)
2432 {
2433   int i = 0;
2434
2435   if (options.excludeRegs[i] &&
2436       STRCASECMP (options.excludeRegs[i], "none") == 0)
2437     return FALSE;
2438
2439   for (i = 0; options.excludeRegs[i]; i++)
2440     {
2441       if (options.excludeRegs[i] &&
2442           STRCASECMP (s, options.excludeRegs[i]) == 0)
2443         return TRUE;
2444     }
2445   return FALSE;
2446 }
2447
2448 /*-----------------------------------------------------------------*/
2449 /* genFunction - generated code for function entry                 */
2450 /*-----------------------------------------------------------------*/
2451 static void
2452 genFunction (iCode * ic)
2453 {
2454   symbol *sym;
2455   sym_link *fetype;
2456
2457   D (emitcode (";", "genFunction ");
2458     );
2459
2460   _G.nRegsSaved = 0;
2461   /* create the function header */
2462   emitcode (";", "-----------------------------------------");
2463   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2464   emitcode (";", "-----------------------------------------");
2465
2466   emitcode ("", "%s:", sym->rname);
2467   fetype = getSpec (operandType (IC_LEFT (ic)));
2468
2469   /* if critical function then turn interrupts off */
2470   if (SPEC_CRTCL (fetype))
2471     emitcode ("clr", "ea");
2472
2473   /* here we need to generate the equates for the
2474      register bank if required */
2475   if (SPEC_BANK (fetype) != rbank)
2476     {
2477       int i;
2478
2479       rbank = SPEC_BANK (fetype);
2480       for (i = 0; i < ds390_nRegs; i++)
2481         {
2482           if (strcmp (regs390[i].base, "0") == 0)
2483             emitcode ("", "%s = 0x%02x",
2484                       regs390[i].dname,
2485                       8 * rbank + regs390[i].offset);
2486           else
2487             emitcode ("", "%s = %s + 0x%02x",
2488                       regs390[i].dname,
2489                       regs390[i].base,
2490                       8 * rbank + regs390[i].offset);
2491         }
2492     }
2493
2494   /* if this is an interrupt service routine then
2495      save acc, b, dpl, dph  */
2496   if (IS_ISR (sym->etype))
2497     {
2498
2499       if (!inExcludeList ("acc"))
2500         emitcode ("push", "acc");
2501       if (!inExcludeList ("b"))
2502         emitcode ("push", "b");
2503       if (!inExcludeList ("dpl"))
2504         emitcode ("push", "dpl");
2505       if (!inExcludeList ("dph"))
2506         emitcode ("push", "dph");
2507       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2508         {
2509           emitcode ("push", "dpx");
2510           /* Make sure we're using standard DPTR */
2511           emitcode ("push", "dps");
2512           emitcode ("mov", "dps, #0x00");
2513           if (options.stack10bit)
2514             {
2515               /* This ISR could conceivably use DPTR2. Better save it. */
2516               emitcode ("push", "dpl1");
2517               emitcode ("push", "dph1");
2518               emitcode ("push", "dpx1");
2519               emitcode ("push",  DP2_RESULT_REG);
2520             }
2521         }
2522       /* if this isr has no bank i.e. is going to
2523          run with bank 0 , then we need to save more
2524          registers :-) */
2525       if (!SPEC_BANK (sym->etype))
2526         {
2527
2528           /* if this function does not call any other
2529              function then we can be economical and
2530              save only those registers that are used */
2531           if (!sym->hasFcall)
2532             {
2533               int i;
2534
2535               /* if any registers used */
2536               if (sym->regsUsed)
2537                 {
2538                   /* save the registers used */
2539                   for (i = 0; i < sym->regsUsed->size; i++)
2540                     {
2541                       if (bitVectBitValue (sym->regsUsed, i) ||
2542                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2543                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2544                     }
2545                 }
2546
2547             }
2548           else
2549             {
2550               /* this function has  a function call cannot
2551                  determines register usage so we will have the
2552                  entire bank */
2553               saverbank (0, ic, FALSE);
2554             }
2555         }
2556     }
2557   else
2558     {
2559       /* if callee-save to be used for this function
2560          then save the registers being used in this function */
2561       if (sym->calleeSave)
2562         {
2563           int i;
2564
2565           /* if any registers used */
2566           if (sym->regsUsed)
2567             {
2568               /* save the registers used */
2569               for (i = 0; i < sym->regsUsed->size; i++)
2570                 {
2571                   if (bitVectBitValue (sym->regsUsed, i) ||
2572                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2573                     {
2574                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2575                       _G.nRegsSaved++;
2576                     }
2577                 }
2578             }
2579         }
2580     }
2581
2582   /* set the register bank to the desired value */
2583   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2584     {
2585       emitcode ("push", "psw");
2586       emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
2587     }
2588
2589   if (IS_RENT (sym->etype) || options.stackAuto)
2590     {
2591
2592       if (options.useXstack)
2593         {
2594           emitcode ("mov", "r0,%s", spname);
2595           emitcode ("mov", "a,_bp");
2596           emitcode ("movx", "@r0,a");
2597           emitcode ("inc", "%s", spname);
2598         }
2599       else
2600         {
2601           /* set up the stack */
2602           emitcode ("push", "_bp");     /* save the callers stack  */
2603         }
2604       emitcode ("mov", "_bp,%s", spname);
2605     }
2606
2607   /* adjust the stack for the function */
2608   if (sym->stack)
2609     {
2610
2611       int i = sym->stack;
2612       if (i > 256)
2613         werror (W_STACK_OVERFLOW, sym->name);
2614
2615       if (i > 3 && sym->recvSize < 4)
2616         {
2617
2618           emitcode ("mov", "a,sp");
2619           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2620           emitcode ("mov", "sp,a");
2621
2622         }
2623       else
2624         while (i--)
2625           emitcode ("inc", "sp");
2626     }
2627
2628   if (sym->xstack)
2629     {
2630
2631       emitcode ("mov", "a,_spx");
2632       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2633       emitcode ("mov", "_spx,a");
2634     }
2635
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genEndFunction - generates epilogue for functions               */
2640 /*-----------------------------------------------------------------*/
2641 static void
2642 genEndFunction (iCode * ic)
2643 {
2644   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2645
2646   D (emitcode (";", "genEndFunction ");
2647     );
2648
2649   if (IS_RENT (sym->etype) || options.stackAuto)
2650     {
2651       emitcode ("mov", "%s,_bp", spname);
2652     }
2653
2654   /* if use external stack but some variables were
2655      added to the local stack then decrement the
2656      local stack */
2657   if (options.useXstack && sym->stack)
2658     {
2659       emitcode ("mov", "a,sp");
2660       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2661       emitcode ("mov", "sp,a");
2662     }
2663
2664
2665   if ((IS_RENT (sym->etype) || options.stackAuto))
2666     {
2667       if (options.useXstack)
2668         {
2669           emitcode ("mov", "r0,%s", spname);
2670           emitcode ("movx", "a,@r0");
2671           emitcode ("mov", "_bp,a");
2672           emitcode ("dec", "%s", spname);
2673         }
2674       else
2675         {
2676           emitcode ("pop", "_bp");
2677         }
2678     }
2679
2680   /* restore the register bank  */
2681   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
2682     emitcode ("pop", "psw");
2683
2684   if (IS_ISR (sym->etype))
2685     {
2686
2687       /* now we need to restore the registers */
2688       /* if this isr has no bank i.e. is going to
2689          run with bank 0 , then we need to save more
2690          registers :-) */
2691       if (!SPEC_BANK (sym->etype))
2692         {
2693
2694           /* if this function does not call any other
2695              function then we can be economical and
2696              save only those registers that are used */
2697           if (!sym->hasFcall)
2698             {
2699               int i;
2700
2701               /* if any registers used */
2702               if (sym->regsUsed)
2703                 {
2704                   /* save the registers used */
2705                   for (i = sym->regsUsed->size; i >= 0; i--)
2706                     {
2707                       if (bitVectBitValue (sym->regsUsed, i) ||
2708                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2709                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2710                     }
2711                 }
2712
2713             }
2714           else
2715             {
2716               /* this function has  a function call cannot
2717                  determines register usage so we will have the
2718                  entire bank */
2719               unsaverbank (0, ic, FALSE);
2720             }
2721         }
2722
2723       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2724         {
2725           if (options.stack10bit)
2726             {
2727               emitcode ("pop", DP2_RESULT_REG);
2728               emitcode ("pop", "dpx1");
2729               emitcode ("pop", "dph1");
2730               emitcode ("pop", "dpl1");
2731             }
2732           emitcode ("pop", "dps");
2733           emitcode ("pop", "dpx");
2734         }
2735       if (!inExcludeList ("dph"))
2736         emitcode ("pop", "dph");
2737       if (!inExcludeList ("dpl"))
2738         emitcode ("pop", "dpl");
2739       if (!inExcludeList ("b"))
2740         emitcode ("pop", "b");
2741       if (!inExcludeList ("acc"))
2742         emitcode ("pop", "acc");
2743
2744       if (SPEC_CRTCL (sym->etype))
2745         emitcode ("setb", "ea");
2746
2747       /* if debug then send end of function */
2748 /*  if (options.debug && currFunc) { */
2749       if (currFunc)
2750         {
2751           _G.debugLine = 1;
2752           emitcode ("", "C$%s$%d$%d$%d ==.",
2753                     FileBaseName (ic->filename), currFunc->lastLine,
2754                     ic->level, ic->block);
2755           if (IS_STATIC (currFunc->etype))
2756             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2757           else
2758             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2759           _G.debugLine = 0;
2760         }
2761
2762       emitcode ("reti", "");
2763     }
2764   else
2765     {
2766       if (SPEC_CRTCL (sym->etype))
2767         emitcode ("setb", "ea");
2768
2769       if (sym->calleeSave)
2770         {
2771           int i;
2772
2773           /* if any registers used */
2774           if (sym->regsUsed)
2775             {
2776               /* save the registers used */
2777               for (i = sym->regsUsed->size; i >= 0; i--)
2778                 {
2779                   if (bitVectBitValue (sym->regsUsed, i) ||
2780                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2781                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2782                 }
2783             }
2784
2785         }
2786
2787       /* if debug then send end of function */
2788       if (currFunc)
2789         {
2790           _G.debugLine = 1;
2791           emitcode ("", "C$%s$%d$%d$%d ==.",
2792                     FileBaseName (ic->filename), currFunc->lastLine,
2793                     ic->level, ic->block);
2794           if (IS_STATIC (currFunc->etype))
2795             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2796           else
2797             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2798           _G.debugLine = 0;
2799         }
2800
2801       emitcode ("ret", "");
2802     }
2803
2804 }
2805
2806 /*-----------------------------------------------------------------*/
2807 /* genRet - generate code for return statement                     */
2808 /*-----------------------------------------------------------------*/
2809 static void
2810 genRet (iCode * ic)
2811 {
2812   int size, offset = 0, pushed = 0;
2813
2814   D (emitcode (";", "genRet ");
2815     );
2816
2817   /* if we have no return value then
2818      just generate the "ret" */
2819   if (!IC_LEFT (ic))
2820     goto jumpret;
2821
2822   /* we have something to return then
2823      move the return value into place */
2824   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
2825   size = AOP_SIZE (IC_LEFT (ic));
2826
2827   _startLazyDPSEvaluation ();
2828   while (size--)
2829     {
2830       char *l;
2831       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2832         {
2833           l = aopGet (AOP (IC_LEFT (ic)), offset++,
2834                       FALSE, TRUE, FALSE);
2835           emitcode ("push", "%s", l);
2836           pushed++;
2837         }
2838       else
2839         {
2840           l = aopGet (AOP (IC_LEFT (ic)), offset,
2841                       FALSE, FALSE, FALSE);
2842           if (strcmp (fReturn[offset], l))
2843             emitcode ("mov", "%s,%s", fReturn[offset++], l);
2844         }
2845     }
2846   _endLazyDPSEvaluation ();
2847
2848   if (pushed)
2849     {
2850       while (pushed)
2851         {
2852           pushed--;
2853           if (strcmp (fReturn[pushed], "a"))
2854             emitcode ("pop", fReturn[pushed]);
2855           else
2856             emitcode ("pop", "acc");
2857         }
2858     }
2859   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2860
2861 jumpret:
2862   /* generate a jump to the return label
2863      if the next is not the return statement */
2864   if (!(ic->next && ic->next->op == LABEL &&
2865         IC_LABEL (ic->next) == returnLabel))
2866
2867     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2868
2869 }
2870
2871 /*-----------------------------------------------------------------*/
2872 /* genLabel - generates a label                                    */
2873 /*-----------------------------------------------------------------*/
2874 static void
2875 genLabel (iCode * ic)
2876 {
2877   /* special case never generate */
2878   if (IC_LABEL (ic) == entryLabel)
2879     return;
2880
2881   D (emitcode (";", "genLabel ");
2882     );
2883
2884   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2885 }
2886
2887 /*-----------------------------------------------------------------*/
2888 /* genGoto - generates a ljmp                                      */
2889 /*-----------------------------------------------------------------*/
2890 static void
2891 genGoto (iCode * ic)
2892 {
2893   D (emitcode (";", "genGoto ");
2894     );
2895   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2896 }
2897
2898 /*-----------------------------------------------------------------*/
2899 /* findLabelBackwards: walks back through the iCode chain looking  */
2900 /* for the given label. Returns number of iCode instructions     */
2901 /* between that label and given ic.          */
2902 /* Returns zero if label not found.          */
2903 /*-----------------------------------------------------------------*/
2904 static int
2905 findLabelBackwards (iCode * ic, int key)
2906 {
2907   int count = 0;
2908
2909   while (ic->prev)
2910     {
2911       ic = ic->prev;
2912       count++;
2913
2914       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2915         {
2916           /* printf("findLabelBackwards = %d\n", count); */
2917           return count;
2918         }
2919     }
2920
2921   return 0;
2922 }
2923
2924 /*-----------------------------------------------------------------*/
2925 /* genPlusIncr :- does addition with increment if possible         */
2926 /*-----------------------------------------------------------------*/
2927 static bool
2928 genPlusIncr (iCode * ic)
2929 {
2930   unsigned int icount;
2931   unsigned int size = getDataSize (IC_RESULT (ic));
2932
2933   /* will try to generate an increment */
2934   /* if the right side is not a literal
2935      we cannot */
2936   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2937     return FALSE;
2938
2939   /* if the literal value of the right hand side
2940      is greater than 4 then it is not worth it */
2941   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2942     return FALSE;
2943
2944   /* if increment 16 bits in register */
2945   if (
2946        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
2947        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
2948        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2949        (size > 1) &&
2950        (icount == 1))
2951     {
2952       symbol *tlbl;
2953       int emitTlbl;
2954       int labelRange;
2955
2956       /* If the next instruction is a goto and the goto target
2957        * is <= 5 instructions previous to this, we can generate
2958        * jumps straight to that target.
2959        */
2960       if (ic->next && ic->next->op == GOTO
2961           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2962           && labelRange <= 5)
2963         {
2964           emitcode (";", "tail increment optimized (range %d)", labelRange);
2965           tlbl = IC_LABEL (ic->next);
2966           emitTlbl = 0;
2967         }
2968       else
2969         {
2970           tlbl = newiTempLabel (NULL);
2971           emitTlbl = 1;
2972         }
2973       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
2974       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2975           IS_AOP_PREG (IC_RESULT (ic)))
2976         emitcode ("cjne", "%s,#0x00,%05d$"
2977                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2978                   ,tlbl->key + 100);
2979       else
2980         {
2981           emitcode ("clr", "a");
2982           emitcode ("cjne", "a,%s,%05d$"
2983                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
2984                     ,tlbl->key + 100);
2985         }
2986
2987       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
2988       if (size > 2)
2989         {
2990           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2991               IS_AOP_PREG (IC_RESULT (ic)))
2992             emitcode ("cjne", "%s,#0x00,%05d$"
2993                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2994                       ,tlbl->key + 100);
2995           else
2996             emitcode ("cjne", "a,%s,%05d$"
2997                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
2998                       ,tlbl->key + 100);
2999
3000           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3001         }
3002       if (size > 3)
3003         {
3004           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3005               IS_AOP_PREG (IC_RESULT (ic)))
3006             emitcode ("cjne", "%s,#0x00,%05d$"
3007                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3008                       ,tlbl->key + 100);
3009           else
3010             {
3011               emitcode ("cjne", "a,%s,%05d$"
3012                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3013                         ,tlbl->key + 100);
3014             }
3015           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3016         }
3017
3018       if (emitTlbl)
3019         {
3020           emitcode ("", "%05d$:", tlbl->key + 100);
3021         }
3022       return TRUE;
3023     }
3024
3025   /* if the sizes are greater than 1 then we cannot */
3026   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3027       AOP_SIZE (IC_LEFT (ic)) > 1)
3028     return FALSE;
3029
3030   /* we can if the aops of the left & result match or
3031      if they are in registers and the registers are the
3032      same */
3033   if (
3034        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3035        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3036        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3037     {
3038
3039       if (icount > 3)
3040         {
3041           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3042           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3043           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3044         }
3045       else
3046         {
3047
3048           _startLazyDPSEvaluation ();
3049           while (icount--)
3050             {
3051               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3052             }
3053           _endLazyDPSEvaluation ();
3054         }
3055
3056       return TRUE;
3057     }
3058
3059   return FALSE;
3060 }
3061
3062 /*-----------------------------------------------------------------*/
3063 /* outBitAcc - output a bit in acc                                 */
3064 /*-----------------------------------------------------------------*/
3065 static void
3066 outBitAcc (operand * result)
3067 {
3068   symbol *tlbl = newiTempLabel (NULL);
3069   /* if the result is a bit */
3070   if (AOP_TYPE (result) == AOP_CRY)
3071     {
3072       aopPut (AOP (result), "a", 0);
3073     }
3074   else
3075     {
3076       emitcode ("jz", "%05d$", tlbl->key + 100);
3077       emitcode ("mov", "a,%s", one);
3078       emitcode ("", "%05d$:", tlbl->key + 100);
3079       outAcc (result);
3080     }
3081 }
3082
3083 /*-----------------------------------------------------------------*/
3084 /* genPlusBits - generates code for addition of two bits           */
3085 /*-----------------------------------------------------------------*/
3086 static void
3087 genPlusBits (iCode * ic)
3088 {
3089   D (emitcode (";", "genPlusBits ");
3090     );
3091   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3092     {
3093       symbol *lbl = newiTempLabel (NULL);
3094       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3096       emitcode ("cpl", "c");
3097       emitcode ("", "%05d$:", (lbl->key + 100));
3098       outBitC (IC_RESULT (ic));
3099     }
3100   else
3101     {
3102       emitcode ("clr", "a");
3103       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3104       emitcode ("rlc", "a");
3105       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3106       emitcode ("addc", "a,#0x00");
3107       outAcc (IC_RESULT (ic));
3108     }
3109 }
3110
3111 static void
3112 adjustArithmeticResult (iCode * ic)
3113 {
3114   if (opIsGptr (IC_RESULT (ic)) &&
3115       opIsGptr (IC_LEFT (ic)) &&
3116       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3117     {
3118       aopPut (AOP (IC_RESULT (ic)),
3119               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3120               GPTRSIZE - 1);
3121     }
3122
3123   if (opIsGptr (IC_RESULT (ic)) &&
3124       opIsGptr (IC_RIGHT (ic)) &&
3125       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3126     {
3127       aopPut (AOP (IC_RESULT (ic)),
3128             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3129               GPTRSIZE - 1);
3130     }
3131
3132   if (opIsGptr (IC_RESULT (ic)) &&
3133       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3134       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3135       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3136       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3137     {
3138       char buffer[5];
3139       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3140       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3141     }
3142 }
3143
3144 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3145 // (because all three operands are in far space).
3146 #define AOP_OP_3(ic) \
3147     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3148     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3149     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3150               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3151     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3152         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3153     { \
3154         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3155         fprintf(stderr,                                  \
3156                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3157     }
3158
3159 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3160 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3161 // will be set TRUE. The caller must then handle the case specially, noting
3162 // that the IC_RESULT operand is not aopOp'd.
3163 #define AOP_OP_3_NOFATAL(ic, rc) \
3164     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3165     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3166     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3167         isOperandInFarSpace(IC_RESULT(ic))) \
3168     { \
3169        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3170        rc = TRUE; \
3171     }  \
3172     else \
3173     { \
3174        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3175                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3176        rc = FALSE; \
3177        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3178            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3179        { \
3180             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3181             fprintf(stderr,                                  \
3182                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3183        } \
3184     }
3185
3186 // aopOp the left & right operands of an ic.
3187 #define AOP_OP_2(ic) \
3188     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3189     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3190
3191 // convienience macro.
3192 #define AOP_SET_LOCALS(ic) \
3193     left = IC_LEFT(ic); \
3194     right = IC_RIGHT(ic); \
3195     result = IC_RESULT(ic);
3196
3197
3198 // Given an integer value of pushedSize bytes on the stack,
3199 // adjust it to be resultSize bytes, either by discarding
3200 // the most significant bytes or by zero-padding.
3201 //
3202 // On exit from this macro, pushedSize will have been adjusted to
3203 // equal resultSize, and ACC may be trashed.
3204 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3205       /* If the pushed data is bigger than the result,          \
3206        * simply discard unused bytes. Icky, but works.          \
3207        */                                                       \
3208       while (pushedSize > resultSize)                           \
3209       {                                                         \
3210           D (emitcode (";", "discarding unused result byte."););\
3211           emitcode ("pop", "acc");                              \
3212           pushedSize--;                                         \
3213       }                                                         \
3214       if (pushedSize < resultSize)                              \
3215       {                                                         \
3216           emitcode ("clr", "a");                                \
3217           /* Conversly, we haven't pushed enough here.          \
3218            * just zero-pad, and all is well.                    \
3219            */                                                   \
3220           while (pushedSize < resultSize)                       \
3221           {                                                     \
3222               emitcode("push", "acc");                          \
3223               pushedSize++;                                     \
3224           }                                                     \
3225       }                                                         \
3226       assert(pushedSize == resultSize);
3227
3228 /*-----------------------------------------------------------------*/
3229 /* genPlus - generates code for addition                           */
3230 /*-----------------------------------------------------------------*/
3231 static void
3232 genPlus (iCode * ic)
3233 {
3234   int size, offset = 0;
3235   bool pushResult = FALSE;
3236   int rSize;
3237
3238   D (emitcode (";", "genPlus "););
3239
3240   /* special cases :- */
3241
3242   AOP_OP_3_NOFATAL (ic, pushResult);
3243   if (pushResult)
3244     {
3245       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3246     }
3247
3248   if (!pushResult)
3249     {
3250       /* if literal, literal on the right or
3251          if left requires ACC or right is already
3252          in ACC */
3253       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3254        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3255           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3256         {
3257           operand *t = IC_RIGHT (ic);
3258           IC_RIGHT (ic) = IC_LEFT (ic);
3259           IC_LEFT (ic) = t;
3260           emitcode (";", "Swapped plus args.");
3261         }
3262
3263       /* if both left & right are in bit
3264          space */
3265       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3266           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3267         {
3268           genPlusBits (ic);
3269           goto release;
3270         }
3271
3272       /* if left in bit space & right literal */
3273       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3274           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3275         {
3276           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3277           /* if result in bit space */
3278           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3279             {
3280               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3281                 emitcode ("cpl", "c");
3282               outBitC (IC_RESULT (ic));
3283             }
3284           else
3285             {
3286               size = getDataSize (IC_RESULT (ic));
3287               _startLazyDPSEvaluation ();
3288               while (size--)
3289                 {
3290                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3291                   emitcode ("addc", "a,#00");
3292                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3293                 }
3294               _endLazyDPSEvaluation ();
3295             }
3296           goto release;
3297         }
3298
3299       /* if I can do an increment instead
3300          of add then GOOD for ME */
3301       if (genPlusIncr (ic) == TRUE)
3302         {
3303           emitcode (";", "did genPlusIncr");
3304           goto release;
3305         }
3306
3307     }
3308   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3309
3310   _startLazyDPSEvaluation ();
3311   while (size--)
3312     {
3313       if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3314         {
3315           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3316           if (offset == 0)
3317             emitcode ("add", "a,%s",
3318                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3319           else
3320             emitcode ("addc", "a,%s",
3321                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3322         }
3323       else
3324         {
3325           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3326           if (offset == 0)
3327             emitcode ("add", "a,%s",
3328                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3329           else
3330             emitcode ("addc", "a,%s",
3331                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3332         }
3333       if (!pushResult)
3334         {
3335           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3336         }
3337       else
3338         {
3339           emitcode ("push", "acc");
3340         }
3341       offset++;
3342     }
3343   _endLazyDPSEvaluation ();
3344
3345   if (pushResult)
3346     {
3347       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3348
3349       size = getDataSize (IC_LEFT (ic));
3350       rSize = getDataSize (IC_RESULT (ic));
3351
3352       ADJUST_PUSHED_RESULT(size, rSize);
3353
3354       _startLazyDPSEvaluation ();
3355       while (size--)
3356         {
3357           emitcode ("pop", "acc");
3358           aopPut (AOP (IC_RESULT (ic)), "a", size);
3359         }
3360       _endLazyDPSEvaluation ();
3361     }
3362
3363   adjustArithmeticResult (ic);
3364
3365 release:
3366   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3367   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3368   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3369 }
3370
3371 /*-----------------------------------------------------------------*/
3372 /* genMinusDec :- does subtraction with deccrement if possible     */
3373 /*-----------------------------------------------------------------*/
3374 static bool
3375 genMinusDec (iCode * ic)
3376 {
3377   unsigned int icount;
3378   unsigned int size = getDataSize (IC_RESULT (ic));
3379
3380   /* will try to generate an increment */
3381   /* if the right side is not a literal
3382      we cannot */
3383   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3384     return FALSE;
3385
3386   /* if the literal value of the right hand side
3387      is greater than 4 then it is not worth it */
3388   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3389     return FALSE;
3390
3391   /* if decrement 16 bits in register */
3392   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3393       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3394       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3395       (size > 1) &&
3396       (icount == 1))
3397     {
3398       symbol *tlbl;
3399       int emitTlbl;
3400       int labelRange;
3401
3402       /* If the next instruction is a goto and the goto target
3403          * is <= 5 instructions previous to this, we can generate
3404          * jumps straight to that target.
3405        */
3406       if (ic->next && ic->next->op == GOTO
3407           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3408           && labelRange <= 5)
3409         {
3410           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3411           tlbl = IC_LABEL (ic->next);
3412           emitTlbl = 0;
3413         }
3414       else
3415         {
3416           tlbl = newiTempLabel (NULL);
3417           emitTlbl = 1;
3418         }
3419
3420       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3421       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3422           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3423           IS_AOP_PREG (IC_RESULT (ic)))
3424         emitcode ("cjne", "%s,#0xff,%05d$"
3425                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3426                   ,tlbl->key + 100);
3427       else
3428         {
3429           emitcode ("mov", "a,#0xff");
3430           emitcode ("cjne", "a,%s,%05d$"
3431                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3432                     ,tlbl->key + 100);
3433         }
3434       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3435       if (size > 2)
3436         {
3437           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3438               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3439               IS_AOP_PREG (IC_RESULT (ic)))
3440             emitcode ("cjne", "%s,#0xff,%05d$"
3441                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3442                       ,tlbl->key + 100);
3443           else
3444             {
3445               emitcode ("cjne", "a,%s,%05d$"
3446                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3447                         ,tlbl->key + 100);
3448             }
3449           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3450         }
3451       if (size > 3)
3452         {
3453           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3454               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3455               IS_AOP_PREG (IC_RESULT (ic)))
3456             emitcode ("cjne", "%s,#0xff,%05d$"
3457                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3458                       ,tlbl->key + 100);
3459           else
3460             {
3461               emitcode ("cjne", "a,%s,%05d$"
3462                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3463                         ,tlbl->key + 100);
3464             }
3465           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3466         }
3467       if (emitTlbl)
3468         {
3469           emitcode ("", "%05d$:", tlbl->key + 100);
3470         }
3471       return TRUE;
3472     }
3473
3474   /* if the sizes are greater than 1 then we cannot */
3475   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3476       AOP_SIZE (IC_LEFT (ic)) > 1)
3477     return FALSE;
3478
3479   /* we can if the aops of the left & result match or
3480      if they are in registers and the registers are the
3481      same */
3482   if (
3483        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3484        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3485        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3486     {
3487
3488       _startLazyDPSEvaluation ();
3489       while (icount--)
3490         {
3491           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3492         }
3493       _endLazyDPSEvaluation ();
3494
3495       return TRUE;
3496     }
3497
3498   return FALSE;
3499 }
3500
3501 /*-----------------------------------------------------------------*/
3502 /* addSign - complete with sign                                    */
3503 /*-----------------------------------------------------------------*/
3504 static void
3505 addSign (operand * result, int offset, int sign)
3506 {
3507   int size = (getDataSize (result) - offset);
3508   if (size > 0)
3509     {
3510       _startLazyDPSEvaluation();
3511       if (sign)
3512         {
3513           emitcode ("rlc", "a");
3514           emitcode ("subb", "a,acc");
3515           while (size--)
3516           {
3517             aopPut (AOP (result), "a", offset++);
3518           }
3519         }
3520       else
3521       {
3522         while (size--)
3523         {
3524           aopPut (AOP (result), zero, offset++);
3525         }
3526       }
3527       _endLazyDPSEvaluation();
3528     }
3529 }
3530
3531 /*-----------------------------------------------------------------*/
3532 /* genMinusBits - generates code for subtraction  of two bits      */
3533 /*-----------------------------------------------------------------*/
3534 static void
3535 genMinusBits (iCode * ic)
3536 {
3537   symbol *lbl = newiTempLabel (NULL);
3538
3539   D (emitcode (";", "genMinusBits "););
3540
3541   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3542     {
3543       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3544       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3545       emitcode ("cpl", "c");
3546       emitcode ("", "%05d$:", (lbl->key + 100));
3547       outBitC (IC_RESULT (ic));
3548     }
3549   else
3550     {
3551       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3552       emitcode ("subb", "a,acc");
3553       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3554       emitcode ("inc", "a");
3555       emitcode ("", "%05d$:", (lbl->key + 100));
3556       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3557       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3558     }
3559 }
3560
3561 /*-----------------------------------------------------------------*/
3562 /* genMinus - generates code for subtraction                       */
3563 /*-----------------------------------------------------------------*/
3564 static void
3565 genMinus (iCode * ic)
3566 {
3567   int size, offset = 0;
3568   int rSize;
3569   unsigned long lit = 0L;
3570   bool pushResult = FALSE;
3571
3572   D (emitcode (";", "genMinus "););
3573
3574   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3575   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3576   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3577       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3578     {
3579       pushResult = TRUE;
3580     }
3581   else
3582     {
3583       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3584
3585       /* special cases :- */
3586       /* if both left & right are in bit space */
3587       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3588           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3589         {
3590           genMinusBits (ic);
3591           goto release;
3592         }
3593
3594       /* if I can do an decrement instead
3595          of subtract then GOOD for ME */
3596       if (genMinusDec (ic) == TRUE)
3597         goto release;
3598
3599     }
3600
3601   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3602
3603   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3604     {
3605       CLRC;
3606     }
3607   else
3608     {
3609       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3610       lit = -(long) lit;
3611     }
3612
3613
3614   /* if literal, add a,#-lit, else normal subb */
3615   _startLazyDPSEvaluation ();
3616   while (size--)
3617     {
3618       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3619       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3620         emitcode ("subb", "a,%s",
3621                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3622       else
3623         {
3624           /* first add without previous c */
3625           if (!offset)
3626             emitcode ("add", "a,#0x%02x",
3627                       (unsigned int) (lit & 0x0FFL));
3628           else
3629             emitcode ("addc", "a,#0x%02x",
3630                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3631         }
3632
3633       if (pushResult)
3634         {
3635           emitcode ("push", "acc");
3636         }
3637       else
3638         {
3639           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3640         }
3641       offset++;
3642     }
3643   _endLazyDPSEvaluation ();
3644
3645   if (pushResult)
3646     {
3647       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3648
3649       size = getDataSize (IC_LEFT (ic));
3650       rSize = getDataSize (IC_RESULT (ic));
3651
3652       ADJUST_PUSHED_RESULT(size, rSize);
3653
3654       _startLazyDPSEvaluation ();
3655       while (size--)
3656         {
3657           emitcode ("pop", "acc");
3658           aopPut (AOP (IC_RESULT (ic)), "a", size);
3659         }
3660       _endLazyDPSEvaluation ();
3661     }
3662
3663   adjustArithmeticResult (ic);
3664
3665 release:
3666   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3667   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3668   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3669 }
3670
3671
3672 /*-----------------------------------------------------------------*/
3673 /* genMultbits :- multiplication of bits                           */
3674 /*-----------------------------------------------------------------*/
3675 static void
3676 genMultbits (operand * left,
3677              operand * right,
3678              operand * result)
3679 {
3680   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3681   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3682   outBitC (result);
3683 }
3684
3685
3686 /*-----------------------------------------------------------------*/
3687 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3688 /*-----------------------------------------------------------------*/
3689 static void
3690 genMultOneByte (operand * left,
3691                 operand * right,
3692                 operand * result)
3693 {
3694   sym_link *opetype = operandType (result);
3695   symbol *lbl;
3696   int size=AOP_SIZE(result);
3697
3698   emitcode (";",__FUNCTION__);
3699   if (size<1 || size>2) {
3700     // this should never happen
3701       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3702                AOP_SIZE(result), __FUNCTION__, lineno);
3703       exit (1);
3704   }
3705
3706   /* (if two literals: the value is computed before) */
3707   /* if one literal, literal on the right */
3708   if (AOP_TYPE (left) == AOP_LIT)
3709     {
3710       operand *t = right;
3711       right = left;
3712       left = t;
3713       emitcode (";", "swapped left and right");
3714     }
3715
3716   if (SPEC_USIGN(opetype)
3717       // ignore the sign of left and right, what else can we do?
3718       || (SPEC_USIGN(operandType(left)) && 
3719           SPEC_USIGN(operandType(right)))) {
3720     // just an unsigned 8*8=8/16 multiply
3721     //emitcode (";","unsigned");
3722     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3723     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3724     emitcode ("mul", "ab");
3725     aopPut (AOP (result), "a", 0);
3726     if (size==2) {
3727       aopPut (AOP (result), "b", 1);
3728     }
3729     return;
3730   }
3731
3732   // we have to do a signed multiply
3733
3734   emitcode (";", "signed");
3735   emitcode ("clr", "F0"); // reset sign flag
3736   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3737   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3738
3739   lbl=newiTempLabel(NULL);
3740   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3741   // left side is negative, 8-bit two's complement, this fails for -128
3742   emitcode ("setb", "F0"); // set sign flag
3743   emitcode ("cpl", "a");
3744   emitcode ("inc", "a");
3745
3746   emitcode ("", "%05d$:", lbl->key+100);
3747   emitcode ("xch", "a,b");
3748
3749   /* if literal */
3750   if (AOP_TYPE(right)==AOP_LIT) {
3751     /* AND literal negative */
3752     if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
3753       // two's complement for literal<0
3754       emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3755       emitcode ("cpl", "a");
3756       emitcode ("inc", "a");
3757     }
3758   } else {
3759     lbl=newiTempLabel(NULL);
3760     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3761     // right side is negative, 8-bit two's complement
3762     emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
3763     emitcode ("cpl", "a");
3764     emitcode ("inc", "a");
3765     emitcode ("", "%05d$:", lbl->key+100);
3766   }
3767   emitcode ("mul", "ab");
3768     
3769   lbl=newiTempLabel(NULL);
3770   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3771   // only ONE op was negative, we have to do a 8/16-bit two's complement
3772   emitcode ("cpl", "a"); // lsb
3773   if (size==1) {
3774     emitcode ("inc", "a");
3775   } else {
3776     emitcode ("add", "a,#1");
3777     emitcode ("xch", "a,b");
3778     emitcode ("cpl", "a"); // msb
3779     emitcode ("addc", "a,#0");
3780     emitcode ("xch", "a,b");
3781   }
3782
3783   emitcode ("", "%05d$:", lbl->key+100);
3784   aopPut (AOP (result), "a", 0);
3785   if (size==2) {
3786     aopPut (AOP (result), "b", 1);
3787   }
3788 }
3789
3790 /*-----------------------------------------------------------------*/
3791 /* genMult - generates code for multiplication                     */
3792 /*-----------------------------------------------------------------*/
3793 static void
3794 genMult (iCode * ic)
3795 {
3796   operand *left = IC_LEFT (ic);
3797   operand *right = IC_RIGHT (ic);
3798   operand *result = IC_RESULT (ic);
3799
3800   D (emitcode (";", "genMult "););
3801
3802   /* assign the amsops */
3803   AOP_OP_3 (ic);
3804
3805   /* special cases first */
3806   /* both are bits */
3807   if (AOP_TYPE (left) == AOP_CRY &&
3808       AOP_TYPE (right) == AOP_CRY)
3809     {
3810       genMultbits (left, right, result);
3811       goto release;
3812     }
3813
3814   /* if both are of size == 1 */
3815   if (AOP_SIZE (left) == 1 &&
3816       AOP_SIZE (right) == 1)
3817     {
3818       genMultOneByte (left, right, result);
3819       goto release;
3820     }
3821
3822   /* should have been converted to function call */
3823   assert (1);
3824
3825 release:
3826   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3827   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3828   freeAsmop (result, NULL, ic, TRUE);
3829 }
3830
3831 /*-----------------------------------------------------------------*/
3832 /* genDivbits :- division of bits                                  */
3833 /*-----------------------------------------------------------------*/
3834 static void
3835 genDivbits (operand * left,
3836             operand * right,
3837             operand * result)
3838 {
3839
3840   char *l;
3841
3842   /* the result must be bit */
3843   LOAD_AB_FOR_DIV (left, right, l);
3844   emitcode ("div", "ab");
3845   emitcode ("rrc", "a");
3846   aopPut (AOP (result), "c", 0);
3847 }
3848
3849 /*-----------------------------------------------------------------*/
3850 /* genDivOneByte : 8 bit division                                  */
3851 /*-----------------------------------------------------------------*/
3852 static void
3853 genDivOneByte (operand * left,
3854                operand * right,
3855                operand * result)
3856 {
3857   sym_link *opetype = operandType (result);
3858   char *l;
3859   symbol *lbl;
3860   int size, offset;
3861
3862   size = AOP_SIZE (result) - 1;
3863   offset = 1;
3864   /* signed or unsigned */
3865   if (SPEC_USIGN (opetype))
3866     {
3867       /* unsigned is easy */
3868       LOAD_AB_FOR_DIV (left, right, l);
3869       emitcode ("div", "ab");
3870       aopPut (AOP (result), "a", 0);
3871       while (size--)
3872         aopPut (AOP (result), zero, offset++);
3873       return;
3874     }
3875
3876   /* signed is a little bit more difficult */
3877
3878   /* save the signs of the operands */
3879   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3880   MOVA (l);
3881   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
3882   emitcode ("push", "acc");     /* save it on the stack */
3883
3884   /* now sign adjust for both left & right */
3885   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
3886   MOVA (l);
3887   lbl = newiTempLabel (NULL);
3888   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3889   emitcode ("cpl", "a");
3890   emitcode ("inc", "a");
3891   emitcode ("", "%05d$:", (lbl->key + 100));
3892   emitcode ("mov", "b,a");
3893
3894   /* sign adjust left side */
3895   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
3896   MOVA (l);
3897
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
3904   /* now the division */
3905   emitcode ("nop", "; workaround for DS80C390 div bug.");
3906   emitcode ("div", "ab");
3907   /* we are interested in the lower order
3908      only */
3909   emitcode ("mov", "b,a");
3910   lbl = newiTempLabel (NULL);
3911   emitcode ("pop", "acc");
3912   /* if there was an over flow we don't
3913      adjust the sign of the result */
3914   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3915   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3916   CLRC;
3917   emitcode ("clr", "a");
3918   emitcode ("subb", "a,b");
3919   emitcode ("mov", "b,a");
3920   emitcode ("", "%05d$:", (lbl->key + 100));
3921
3922   /* now we are done */
3923   aopPut (AOP (result), "b", 0);
3924   if (size > 0)
3925     {
3926       emitcode ("mov", "c,b.7");
3927       emitcode ("subb", "a,acc");
3928     }
3929   while (size--)
3930     aopPut (AOP (result), "a", offset++);
3931
3932 }
3933
3934 /*-----------------------------------------------------------------*/
3935 /* genDiv - generates code for division                            */
3936 /*-----------------------------------------------------------------*/
3937 static void
3938 genDiv (iCode * ic)
3939 {
3940   operand *left = IC_LEFT (ic);
3941   operand *right = IC_RIGHT (ic);
3942   operand *result = IC_RESULT (ic);
3943
3944   D (emitcode (";", "genDiv ");
3945     );
3946
3947   /* assign the amsops */
3948   AOP_OP_3 (ic);
3949
3950   /* special cases first */
3951   /* both are bits */
3952   if (AOP_TYPE (left) == AOP_CRY &&
3953       AOP_TYPE (right) == AOP_CRY)
3954     {
3955       genDivbits (left, right, result);
3956       goto release;
3957     }
3958
3959   /* if both are of size == 1 */
3960   if (AOP_SIZE (left) == 1 &&
3961       AOP_SIZE (right) == 1)
3962     {
3963       genDivOneByte (left, right, result);
3964       goto release;
3965     }
3966
3967   /* should have been converted to function call */
3968   assert (1);
3969 release:
3970   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3971   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3972   freeAsmop (result, NULL, ic, TRUE);
3973 }
3974
3975 /*-----------------------------------------------------------------*/
3976 /* genModbits :- modulus of bits                                   */
3977 /*-----------------------------------------------------------------*/
3978 static void
3979 genModbits (operand * left,
3980             operand * right,
3981             operand * result)
3982 {
3983
3984   char *l;
3985
3986   /* the result must be bit */
3987   LOAD_AB_FOR_DIV (left, right, l);
3988   emitcode ("div", "ab");
3989   emitcode ("mov", "a,b");
3990   emitcode ("rrc", "a");
3991   aopPut (AOP (result), "c", 0);
3992 }
3993
3994 /*-----------------------------------------------------------------*/
3995 /* genModOneByte : 8 bit modulus                                   */
3996 /*-----------------------------------------------------------------*/
3997 static void
3998 genModOneByte (operand * left,
3999                operand * right,
4000                operand * result)
4001 {
4002   sym_link *opetype = operandType (result);
4003   char *l;
4004   symbol *lbl;
4005
4006   /* signed or unsigned */
4007   if (SPEC_USIGN (opetype))
4008     {
4009       /* unsigned is easy */
4010       LOAD_AB_FOR_DIV (left, right, l);
4011       emitcode ("div", "ab");
4012       aopPut (AOP (result), "b", 0);
4013       return;
4014     }
4015
4016   /* signed is a little bit more difficult */
4017
4018   /* save the signs of the operands */
4019   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4020   MOVA (l);
4021
4022   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4023   emitcode ("push", "acc");     /* save it on the stack */
4024
4025   /* now sign adjust for both left & right */
4026   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4027   MOVA (l);
4028
4029   lbl = newiTempLabel (NULL);
4030   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4031   emitcode ("cpl", "a");
4032   emitcode ("inc", "a");
4033   emitcode ("", "%05d$:", (lbl->key + 100));
4034   emitcode ("mov", "b,a");
4035
4036   /* sign adjust left side */
4037   l = aopGet (AOP (left), 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
4046   /* now the multiplication */
4047   emitcode ("nop", "; workaround for DS80C390 div bug.");
4048   emitcode ("div", "ab");
4049   /* we are interested in the lower order
4050      only */
4051   lbl = newiTempLabel (NULL);
4052   emitcode ("pop", "acc");
4053   /* if there was an over flow we don't
4054      adjust the sign of the result */
4055   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4056   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4057   CLRC;
4058   emitcode ("clr", "a");
4059   emitcode ("subb", "a,b");
4060   emitcode ("mov", "b,a");
4061   emitcode ("", "%05d$:", (lbl->key + 100));
4062
4063   /* now we are done */
4064   aopPut (AOP (result), "b", 0);
4065
4066 }
4067
4068 /*-----------------------------------------------------------------*/
4069 /* genMod - generates code for division                            */
4070 /*-----------------------------------------------------------------*/
4071 static void
4072 genMod (iCode * ic)
4073 {
4074   operand *left = IC_LEFT (ic);
4075   operand *right = IC_RIGHT (ic);
4076   operand *result = IC_RESULT (ic);
4077
4078   D (emitcode (";", "genMod ");
4079     );
4080
4081   /* assign the amsops */
4082   AOP_OP_3 (ic);
4083
4084   /* special cases first */
4085   /* both are bits */
4086   if (AOP_TYPE (left) == AOP_CRY &&
4087       AOP_TYPE (right) == AOP_CRY)
4088     {
4089       genModbits (left, right, result);
4090       goto release;
4091     }
4092
4093   /* if both are of size == 1 */
4094   if (AOP_SIZE (left) == 1 &&
4095       AOP_SIZE (right) == 1)
4096     {
4097       genModOneByte (left, right, result);
4098       goto release;
4099     }
4100
4101   /* should have been converted to function call */
4102   assert (1);
4103
4104 release:
4105   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4106   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4107   freeAsmop (result, NULL, ic, TRUE);
4108 }
4109
4110 /*-----------------------------------------------------------------*/
4111 /* genIfxJump :- will create a jump depending on the ifx           */
4112 /*-----------------------------------------------------------------*/
4113 static void
4114 genIfxJump (iCode * ic, char *jval)
4115 {
4116   symbol *jlbl;
4117   symbol *tlbl = newiTempLabel (NULL);
4118   char *inst;
4119
4120   D (emitcode (";", "genIfxJump ");
4121     );
4122
4123   /* if true label then we jump if condition
4124      supplied is true */
4125   if (IC_TRUE (ic))
4126     {
4127       jlbl = IC_TRUE (ic);
4128       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4129                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4130     }
4131   else
4132     {
4133       /* false label is present */
4134       jlbl = IC_FALSE (ic);
4135       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4136                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4137     }
4138   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4139     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4140   else
4141     emitcode (inst, "%05d$", tlbl->key + 100);
4142   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4143   emitcode ("", "%05d$:", tlbl->key + 100);
4144
4145   /* mark the icode as generated */
4146   ic->generated = 1;
4147 }
4148
4149 /*-----------------------------------------------------------------*/
4150 /* genCmp :- greater or less than comparison                       */
4151 /*-----------------------------------------------------------------*/
4152 static void
4153 genCmp (operand * left, operand * right,
4154         iCode * ic, iCode * ifx, int sign)
4155 {
4156   int size, offset = 0;
4157   unsigned long lit = 0L;
4158   operand *result;
4159
4160   D (emitcode (";", "genCmp");
4161     );
4162
4163   result = IC_RESULT (ic);
4164
4165   /* if left & right are bit variables */
4166   if (AOP_TYPE (left) == AOP_CRY &&
4167       AOP_TYPE (right) == AOP_CRY)
4168     {
4169       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4170       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4171     }
4172   else
4173     {
4174       /* subtract right from left if at the
4175          end the carry flag is set then we know that
4176          left is greater than right */
4177       size = max (AOP_SIZE (left), AOP_SIZE (right));
4178
4179       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4180       if ((size == 1) && !sign &&
4181           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4182         {
4183           symbol *lbl = newiTempLabel (NULL);
4184           emitcode ("cjne", "%s,%s,%05d$",
4185                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4186                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4187                     lbl->key + 100);
4188           emitcode ("", "%05d$:", lbl->key + 100);
4189         }
4190       else
4191         {
4192           if (AOP_TYPE (right) == AOP_LIT)
4193             {
4194               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4195               /* optimize if(x < 0) or if(x >= 0) */
4196               if (lit == 0L)
4197                 {
4198                   if (!sign)
4199                     {
4200                       CLRC;
4201                     }
4202                   else
4203                     {
4204                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4205
4206                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4207                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4208
4209                       aopOp (result, ic, FALSE, FALSE);
4210
4211                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4212                         {
4213                           freeAsmop (result, NULL, ic, TRUE);
4214                           genIfxJump (ifx, "acc.7");
4215                           return;
4216                         }
4217                       else
4218                         {
4219                           emitcode ("rlc", "a");
4220                         }
4221                       goto release_freedLR;
4222                     }
4223                   goto release;
4224                 }
4225             }
4226           CLRC;
4227           while (size--)
4228             {
4229               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4230               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4231               emitcode (";", "genCmp #2");
4232               if (sign && (size == 0))
4233                 {
4234                   emitcode (";", "genCmp #3");
4235                   emitcode ("xrl", "a,#0x80");
4236                   if (AOP_TYPE (right) == AOP_LIT)
4237                     {
4238                       unsigned long lit = (unsigned long)
4239                       floatFromVal (AOP (right)->aopu.aop_lit);
4240                       emitcode (";", "genCmp #3.1");
4241                       emitcode ("subb", "a,#0x%02x",
4242                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4243                     }
4244                   else
4245                     {
4246                       emitcode (";", "genCmp #3.2");
4247                       if (AOP_NEEDSACC (right))
4248                         {
4249                           emitcode ("push", "acc");
4250                         }
4251                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4252                                                        FALSE, FALSE, FALSE));
4253                       emitcode ("xrl", "b,#0x80");
4254                       if (AOP_NEEDSACC (right))
4255                         {
4256                           emitcode ("pop", "acc");
4257                         }
4258                       emitcode ("subb", "a,b");
4259                     }
4260                 }
4261               else
4262                 {
4263                   const char *s;
4264
4265                   emitcode (";", "genCmp #4");
4266                   if (AOP_NEEDSACC (right))
4267                     {
4268                       /* Yuck!! */
4269                       emitcode (";", "genCmp #4.1");
4270                       emitcode ("xch", "a, b");
4271                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4272                       emitcode ("xch", "a, b");
4273                       s = "b";
4274                     }
4275                   else
4276                     {
4277                       emitcode (";", "genCmp #4.2");
4278                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4279                     }
4280
4281                   emitcode ("subb", "a,%s", s);
4282                 }
4283             }
4284         }
4285     }
4286
4287 release:
4288 /* Don't need the left & right operands any more; do need the result. */
4289   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4290   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4291
4292   aopOp (result, ic, FALSE, FALSE);
4293
4294 release_freedLR:
4295
4296   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4297     {
4298       outBitC (result);
4299     }
4300   else
4301     {
4302       /* if the result is used in the next
4303          ifx conditional branch then generate
4304          code a little differently */
4305       if (ifx)
4306         {
4307           genIfxJump (ifx, "c");
4308         }
4309       else
4310         {
4311           outBitC (result);
4312         }
4313       /* leave the result in acc */
4314     }
4315   freeAsmop (result, NULL, ic, TRUE);
4316 }
4317
4318 /*-----------------------------------------------------------------*/
4319 /* genCmpGt :- greater than comparison                             */
4320 /*-----------------------------------------------------------------*/
4321 static void
4322 genCmpGt (iCode * ic, iCode * ifx)
4323 {
4324   operand *left, *right;
4325   sym_link *letype, *retype;
4326   int sign;
4327
4328   D (emitcode (";", "genCmpGt ");
4329     );
4330
4331   left = IC_LEFT (ic);
4332   right = IC_RIGHT (ic);
4333
4334   letype = getSpec (operandType (left));
4335   retype = getSpec (operandType (right));
4336   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4337
4338   /* assign the left & right amsops */
4339   AOP_OP_2 (ic);
4340
4341   genCmp (right, left, ic, ifx, sign);
4342 }
4343
4344 /*-----------------------------------------------------------------*/
4345 /* genCmpLt - less than comparisons                                */
4346 /*-----------------------------------------------------------------*/
4347 static void
4348 genCmpLt (iCode * ic, iCode * ifx)
4349 {
4350   operand *left, *right;
4351   sym_link *letype, *retype;
4352   int sign;
4353
4354   D (emitcode (";", "genCmpLt "););
4355
4356   left = IC_LEFT (ic);
4357   right = IC_RIGHT (ic);
4358
4359   letype = getSpec (operandType (left));
4360   retype = getSpec (operandType (right));
4361   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4362
4363   /* assign the left & right amsops */
4364   AOP_OP_2 (ic);
4365
4366   genCmp (left, right, ic, ifx, sign);
4367 }
4368
4369 /*-----------------------------------------------------------------*/
4370 /* gencjneshort - compare and jump if not equal                    */
4371 /*-----------------------------------------------------------------*/
4372 static void
4373 gencjneshort (operand * left, operand * right, symbol * lbl)
4374 {
4375   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4376   int offset = 0;
4377   unsigned long lit = 0L;
4378
4379   D (emitcode (";", "gencjneshort");
4380     );
4381
4382   /* if the left side is a literal or
4383      if the right is in a pointer register and left
4384      is not */
4385   if ((AOP_TYPE (left) == AOP_LIT) ||
4386       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4387     {
4388       operand *t = right;
4389       right = left;
4390       left = t;
4391     }
4392
4393   if (AOP_TYPE (right) == AOP_LIT)
4394     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4395
4396   if (opIsGptr (left) || opIsGptr (right))
4397     {
4398       /* We are comparing a generic pointer to something.
4399        * Exclude the generic type byte from the comparison.
4400        */
4401       size--;
4402       D (emitcode (";", "cjneshort: generic ptr special case.");
4403         )
4404     }
4405
4406
4407   /* if the right side is a literal then anything goes */
4408   if (AOP_TYPE (right) == AOP_LIT &&
4409       AOP_TYPE (left) != AOP_DIR)
4410     {
4411       while (size--)
4412         {
4413           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4414           MOVA (l);
4415           emitcode ("cjne", "a,%s,%05d$",
4416                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4417                     lbl->key + 100);
4418           offset++;
4419         }
4420     }
4421
4422   /* if the right side is in a register or in direct space or
4423      if the left is a pointer register & right is not */
4424   else if (AOP_TYPE (right) == AOP_REG ||
4425            AOP_TYPE (right) == AOP_DIR ||
4426            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4427            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4428     {
4429       while (size--)
4430         {
4431           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4432           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4433               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4434             emitcode ("jnz", "%05d$", lbl->key + 100);
4435           else
4436             emitcode ("cjne", "a,%s,%05d$",
4437                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4438                       lbl->key + 100);
4439           offset++;
4440         }
4441     }
4442   else
4443     {
4444       /* right is a pointer reg need both a & b */
4445       while (size--)
4446         {
4447           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4448           if (strcmp (l, "b"))
4449             emitcode ("mov", "b,%s", l);
4450           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4451           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4452           offset++;
4453         }
4454     }
4455 }
4456
4457 /*-----------------------------------------------------------------*/
4458 /* gencjne - compare and jump if not equal                         */
4459 /*-----------------------------------------------------------------*/
4460 static void
4461 gencjne (operand * left, operand * right, symbol * lbl)
4462 {
4463   symbol *tlbl = newiTempLabel (NULL);
4464
4465   D (emitcode (";", "gencjne");
4466     );
4467
4468   gencjneshort (left, right, lbl);
4469
4470   emitcode ("mov", "a,%s", one);
4471   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4472   emitcode ("", "%05d$:", lbl->key + 100);
4473   emitcode ("clr", "a");
4474   emitcode ("", "%05d$:", tlbl->key + 100);
4475 }
4476
4477 /*-----------------------------------------------------------------*/
4478 /* genCmpEq - generates code for equal to                          */
4479 /*-----------------------------------------------------------------*/
4480 static void
4481 genCmpEq (iCode * ic, iCode * ifx)
4482 {
4483   operand *left, *right, *result;
4484
4485   D (emitcode (";", "genCmpEq ");
4486     );
4487
4488   AOP_OP_2 (ic);
4489   AOP_SET_LOCALS (ic);
4490
4491   /* if literal, literal on the right or
4492      if the right is in a pointer register and left
4493      is not */
4494   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4495       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4496     {
4497       operand *t = IC_RIGHT (ic);
4498       IC_RIGHT (ic) = IC_LEFT (ic);
4499       IC_LEFT (ic) = t;
4500     }
4501
4502   if (ifx &&                    /* !AOP_SIZE(result) */
4503       OP_SYMBOL (result) &&
4504       OP_SYMBOL (result)->regType == REG_CND)
4505     {
4506       symbol *tlbl;
4507       /* if they are both bit variables */
4508       if (AOP_TYPE (left) == AOP_CRY &&
4509           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4510         {
4511           if (AOP_TYPE (right) == AOP_LIT)
4512             {
4513               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4514               if (lit == 0L)
4515                 {
4516                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4517                   emitcode ("cpl", "c");
4518                 }
4519               else if (lit == 1L)
4520                 {
4521                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4522                 }
4523               else
4524                 {
4525                   emitcode ("clr", "c");
4526                 }
4527               /* AOP_TYPE(right) == AOP_CRY */
4528             }
4529           else
4530             {
4531               symbol *lbl = newiTempLabel (NULL);
4532               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4533               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4534               emitcode ("cpl", "c");
4535               emitcode ("", "%05d$:", (lbl->key + 100));
4536             }
4537           /* if true label then we jump if condition
4538              supplied is true */
4539           tlbl = newiTempLabel (NULL);
4540           if (IC_TRUE (ifx))
4541             {
4542               emitcode ("jnc", "%05d$", tlbl->key + 100);
4543               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4544             }
4545           else
4546             {
4547               emitcode ("jc", "%05d$", tlbl->key + 100);
4548               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4549             }
4550           emitcode ("", "%05d$:", tlbl->key + 100);
4551         }
4552       else
4553         {
4554           tlbl = newiTempLabel (NULL);
4555           gencjneshort (left, right, tlbl);
4556           if (IC_TRUE (ifx))
4557             {
4558               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4559               emitcode ("", "%05d$:", tlbl->key + 100);
4560             }
4561           else
4562             {
4563               symbol *lbl = newiTempLabel (NULL);
4564               emitcode ("sjmp", "%05d$", lbl->key + 100);
4565               emitcode ("", "%05d$:", tlbl->key + 100);
4566               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4567               emitcode ("", "%05d$:", lbl->key + 100);
4568             }
4569         }
4570       /* mark the icode as generated */
4571       ifx->generated = 1;
4572
4573       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4574       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4575       return;
4576     }
4577
4578   /* if they are both bit variables */
4579   if (AOP_TYPE (left) == AOP_CRY &&
4580       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4581     {
4582       if (AOP_TYPE (right) == AOP_LIT)
4583         {
4584           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4585           if (lit == 0L)
4586             {
4587               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4588               emitcode ("cpl", "c");
4589             }
4590           else if (lit == 1L)
4591             {
4592               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4593             }
4594           else
4595             {
4596               emitcode ("clr", "c");
4597             }
4598           /* AOP_TYPE(right) == AOP_CRY */
4599         }
4600       else
4601         {
4602           symbol *lbl = newiTempLabel (NULL);
4603           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4604           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4605           emitcode ("cpl", "c");
4606           emitcode ("", "%05d$:", (lbl->key + 100));
4607         }
4608
4609       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611
4612       aopOp (result, ic, TRUE, FALSE);
4613
4614       /* c = 1 if egal */
4615       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4616         {
4617           outBitC (result);
4618           goto release;
4619         }
4620       if (ifx)
4621         {
4622           genIfxJump (ifx, "c");
4623           goto release;
4624         }
4625       /* if the result is used in an arithmetic operation
4626          then put the result in place */
4627       outBitC (result);
4628     }
4629   else
4630     {
4631       gencjne (left, right, newiTempLabel (NULL));
4632
4633       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4634       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4635
4636       aopOp (result, ic, TRUE, FALSE);
4637
4638       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4639         {
4640           aopPut (AOP (result), "a", 0);
4641           goto release;
4642         }
4643       if (ifx)
4644         {
4645           genIfxJump (ifx, "a");
4646           goto release;
4647         }
4648       /* if the result is used in an arithmetic operation
4649          then put the result in place */
4650       if (AOP_TYPE (result) != AOP_CRY)
4651         outAcc (result);
4652       /* leave the result in acc */
4653     }
4654
4655 release:
4656   freeAsmop (result, NULL, ic, TRUE);
4657 }
4658
4659 /*-----------------------------------------------------------------*/
4660 /* ifxForOp - returns the icode containing the ifx for operand     */
4661 /*-----------------------------------------------------------------*/
4662 static iCode *
4663 ifxForOp (operand * op, iCode * ic)
4664 {
4665   /* if true symbol then needs to be assigned */
4666   if (IS_TRUE_SYMOP (op))
4667     return NULL;
4668
4669   /* if this has register type condition and
4670      the next instruction is ifx with the same operand
4671      and live to of the operand is upto the ifx only then */
4672   if (ic->next &&
4673       ic->next->op == IFX &&
4674       IC_COND (ic->next)->key == op->key &&
4675       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4676     return ic->next;
4677
4678   return NULL;
4679 }
4680 /*-----------------------------------------------------------------*/
4681 /* genAndOp - for && operation                                     */
4682 /*-----------------------------------------------------------------*/
4683 static void
4684 genAndOp (iCode * ic)
4685 {
4686   operand *left, *right, *result;
4687   symbol *tlbl;
4688
4689   D (emitcode (";", "genAndOp "););
4690
4691   /* note here that && operations that are in an
4692      if statement are taken away by backPatchLabels
4693      only those used in arthmetic operations remain */
4694   AOP_OP_2 (ic);
4695   AOP_SET_LOCALS (ic);
4696
4697   /* if both are bit variables */
4698   if (AOP_TYPE (left) == AOP_CRY &&
4699       AOP_TYPE (right) == AOP_CRY)
4700     {
4701       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4702       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4703       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4704       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705   
4706       aopOp (result,ic,FALSE, FALSE);
4707       outBitC (result);
4708     }
4709   else
4710     {
4711       tlbl = newiTempLabel (NULL);
4712       toBoolean (left);
4713       emitcode ("jz", "%05d$", tlbl->key + 100);
4714       toBoolean (right);
4715       emitcode ("", "%05d$:", tlbl->key + 100);
4716       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4717       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4718   
4719       aopOp (result,ic,FALSE, FALSE);
4720       outBitAcc (result);
4721     }
4722     freeAsmop (result, NULL, ic, TRUE);
4723 }
4724
4725
4726 /*-----------------------------------------------------------------*/
4727 /* genOrOp - for || operation                                      */
4728 /*-----------------------------------------------------------------*/
4729 static void
4730 genOrOp (iCode * ic)
4731 {
4732   operand *left, *right, *result;
4733   symbol *tlbl;
4734
4735   D (emitcode (";", "genOrOp "););
4736
4737   /* note here that || operations that are in an
4738      if statement are taken away by backPatchLabels
4739      only those used in arthmetic operations remain */
4740   AOP_OP_2 (ic);
4741   AOP_SET_LOCALS (ic);
4742
4743   /* if both are bit variables */
4744   if (AOP_TYPE (left) == AOP_CRY &&
4745       AOP_TYPE (right) == AOP_CRY)
4746     {
4747       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4748       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4749       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4751   
4752       aopOp (result,ic,FALSE, FALSE);
4753       
4754       outBitC (result);
4755     }
4756   else
4757     {
4758       tlbl = newiTempLabel (NULL);
4759       toBoolean (left);
4760       emitcode ("jnz", "%05d$", tlbl->key + 100);
4761       toBoolean (right);
4762       emitcode ("", "%05d$:", tlbl->key + 100);
4763       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4764       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4765   
4766       aopOp (result,ic,FALSE, FALSE);
4767       
4768       outBitAcc (result);
4769     }
4770
4771   freeAsmop (result, NULL, ic, TRUE);
4772 }
4773
4774 /*-----------------------------------------------------------------*/
4775 /* isLiteralBit - test if lit == 2^n                               */
4776 /*-----------------------------------------------------------------*/
4777 static int
4778 isLiteralBit (unsigned long lit)
4779 {
4780   unsigned long pw[32] =
4781   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4782    0x100L, 0x200L, 0x400L, 0x800L,
4783    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4784    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4785    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4786    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4787    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4788   int idx;
4789
4790   for (idx = 0; idx < 32; idx++)
4791     if (lit == pw[idx])
4792       return idx + 1;
4793   return 0;
4794 }
4795
4796 /*-----------------------------------------------------------------*/
4797 /* continueIfTrue -                                                */
4798 /*-----------------------------------------------------------------*/
4799 static void
4800 continueIfTrue (iCode * ic)
4801 {
4802   if (IC_TRUE (ic))
4803     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4804   ic->generated = 1;
4805 }
4806
4807 /*-----------------------------------------------------------------*/
4808 /* jmpIfTrue -                                                     */
4809 /*-----------------------------------------------------------------*/
4810 static void
4811 jumpIfTrue (iCode * ic)
4812 {
4813   if (!IC_TRUE (ic))
4814     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4815   ic->generated = 1;
4816 }
4817
4818 /*-----------------------------------------------------------------*/
4819 /* jmpTrueOrFalse -                                                */
4820 /*-----------------------------------------------------------------*/
4821 static void
4822 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4823 {
4824   // ugly but optimized by peephole
4825   if (IC_TRUE (ic))
4826     {
4827       symbol *nlbl = newiTempLabel (NULL);
4828       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4829       emitcode ("", "%05d$:", tlbl->key + 100);
4830       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4831       emitcode ("", "%05d$:", nlbl->key + 100);
4832     }
4833   else
4834     {
4835       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4836       emitcode ("", "%05d$:", tlbl->key + 100);
4837     }
4838   ic->generated = 1;
4839 }
4840
4841 // Generate code to perform a bit-wise logic operation
4842 // on two operands in far space (assumed to already have been 
4843 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
4844 // in far space. This requires pushing the result on the stack
4845 // then popping it into the result.
4846 static void
4847 genFarFarLogicOp(iCode *ic, char *logicOp)
4848 {
4849       int size, resultSize, compSize;
4850       int offset = 0;
4851       
4852       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
4853       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
4854                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
4855       
4856       _startLazyDPSEvaluation();
4857       for (size = compSize; (size--); offset++)
4858       {
4859           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
4860           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
4861           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
4862           
4863           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
4864           emitcode ("push", "acc");
4865       }
4866       _endLazyDPSEvaluation();
4867      
4868       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4869       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
4870       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
4871      
4872       resultSize = AOP_SIZE(IC_RESULT(ic));
4873
4874       ADJUST_PUSHED_RESULT(compSize, resultSize);
4875
4876       _startLazyDPSEvaluation();
4877       while (compSize--)
4878       {
4879           emitcode ("pop", "acc");
4880           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
4881       }
4882       _endLazyDPSEvaluation();
4883       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
4884 }
4885
4886
4887 /*-----------------------------------------------------------------*/
4888 /* genAnd  - code for and                                          */
4889 /*-----------------------------------------------------------------*/
4890 static void
4891 genAnd (iCode * ic, iCode * ifx)
4892 {
4893   operand *left, *right, *result;
4894   int size, offset = 0;
4895   unsigned long lit = 0L;
4896   int bytelit = 0;
4897   char buffer[10];
4898   bool pushResult;
4899
4900   D (emitcode (";", "genAnd "););
4901
4902   AOP_OP_3_NOFATAL (ic, pushResult);
4903   AOP_SET_LOCALS (ic);
4904
4905   if (pushResult)
4906   {
4907       genFarFarLogicOp(ic, "anl");
4908       return;
4909   }  
4910
4911 #ifdef DEBUG_TYPE
4912   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4913             AOP_TYPE (result),
4914             AOP_TYPE (left), AOP_TYPE (right));
4915   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4916             AOP_SIZE (result),
4917             AOP_SIZE (left), AOP_SIZE (right));
4918 #endif
4919
4920   /* if left is a literal & right is not then exchange them */
4921   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4922       AOP_NEEDSACC (left))
4923     {
4924       operand *tmp = right;
4925       right = left;
4926       left = tmp;
4927     }
4928
4929   /* if result = right then exchange them */
4930   if (sameRegs (AOP (result), AOP (right)))
4931     {
4932       operand *tmp = right;
4933       right = left;
4934       left = tmp;
4935     }
4936
4937   /* if right is bit then exchange them */
4938   if (AOP_TYPE (right) == AOP_CRY &&
4939       AOP_TYPE (left) != AOP_CRY)
4940     {
4941       operand *tmp = right;
4942       right = left;
4943       left = tmp;
4944     }
4945   if (AOP_TYPE (right) == AOP_LIT)
4946     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4947
4948   size = AOP_SIZE (result);
4949
4950   // if(bit & yy)
4951   // result = bit & yy;
4952   if (AOP_TYPE (left) == AOP_CRY)
4953     {
4954       // c = bit & literal;
4955       if (AOP_TYPE (right) == AOP_LIT)
4956         {
4957           if (lit & 1)
4958             {
4959               if (size && sameRegs (AOP (result), AOP (left)))
4960                 // no change
4961                 goto release;
4962               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4963             }
4964           else
4965             {
4966               // bit(result) = 0;
4967               if (size && (AOP_TYPE (result) == AOP_CRY))
4968                 {
4969                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4970                   goto release;
4971                 }
4972               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4973                 {
4974                   jumpIfTrue (ifx);
4975                   goto release;
4976                 }
4977               emitcode ("clr", "c");
4978             }
4979         }
4980       else
4981         {
4982           if (AOP_TYPE (right) == AOP_CRY)
4983             {
4984               // c = bit & bit;
4985               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4986               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4987             }
4988           else
4989             {
4990               // c = bit & val;
4991               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4992               // c = lsb
4993               emitcode ("rrc", "a");
4994               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4995             }
4996         }
4997       // bit = c
4998       // val = c
4999       if (size)
5000         outBitC (result);
5001       // if(bit & ...)
5002       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5003         genIfxJump (ifx, "c");
5004       goto release;
5005     }
5006
5007   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5008   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5009   if ((AOP_TYPE (right) == AOP_LIT) &&
5010       (AOP_TYPE (result) == AOP_CRY) &&
5011       (AOP_TYPE (left) != AOP_CRY))
5012     {
5013       int posbit = isLiteralBit (lit);
5014       /* left &  2^n */
5015       if (posbit)
5016         {
5017           posbit--;
5018           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5019           // bit = left & 2^n
5020           if (size)
5021             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5022           // if(left &  2^n)
5023           else
5024             {
5025               if (ifx)
5026                 {
5027                   sprintf (buffer, "acc.%d", posbit & 0x07);
5028                   genIfxJump (ifx, buffer);
5029                 }
5030               goto release;
5031             }
5032         }
5033       else
5034         {
5035           symbol *tlbl = newiTempLabel (NULL);
5036           int sizel = AOP_SIZE (left);
5037           if (size)
5038             emitcode ("setb", "c");
5039           while (sizel--)
5040             {
5041               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5042                 {
5043                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5044                   // byte ==  2^n ?
5045                   if ((posbit = isLiteralBit (bytelit)) != 0)
5046                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5047                   else
5048                     {
5049                       if (bytelit != 0x0FFL)
5050                         emitcode ("anl", "a,%s",
5051                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5052                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5053                     }
5054                 }
5055               offset++;
5056             }
5057           // bit = left & literal
5058           if (size)
5059             {
5060               emitcode ("clr", "c");
5061               emitcode ("", "%05d$:", tlbl->key + 100);
5062             }
5063           // if(left & literal)
5064           else
5065             {
5066               if (ifx)
5067                 jmpTrueOrFalse (ifx, tlbl);
5068               goto release;
5069             }
5070         }
5071       outBitC (result);
5072       goto release;
5073     }
5074
5075   /* if left is same as result */
5076   if (sameRegs (AOP (result), AOP (left)))
5077     {
5078       for (; size--; offset++)
5079         {
5080           if (AOP_TYPE (right) == AOP_LIT)
5081             {
5082               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5083                 continue;
5084               else if (bytelit == 0)
5085                 aopPut (AOP (result), zero, offset);
5086               else if (IS_AOP_PREG (result))
5087                 {
5088                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5089                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5090                   aopPut (AOP (result), "a", offset);
5091                 }
5092               else
5093                 emitcode ("anl", "%s,%s",
5094                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5095                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5096             }
5097           else
5098             {
5099               if (AOP_TYPE (left) == AOP_ACC)
5100                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5101               else
5102                 {
5103                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5104                   if (IS_AOP_PREG (result))
5105                     {
5106                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5107                       aopPut (AOP (result), "a", offset);
5108
5109                     }
5110                   else
5111                     emitcode ("anl", "%s,a",
5112                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5113                 }
5114             }
5115         }
5116     }
5117   else
5118     {
5119       // left & result in different registers
5120       if (AOP_TYPE (result) == AOP_CRY)
5121         {
5122           // result = bit
5123           // if(size), result in bit
5124           // if(!size && ifx), conditional oper: if(left & right)
5125           symbol *tlbl = newiTempLabel (NULL);
5126           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5127           if (size)
5128             emitcode ("setb", "c");
5129           while (sizer--)
5130             {
5131               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5132               emitcode ("anl", "a,%s",
5133                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5134               emitcode ("jnz", "%05d$", tlbl->key + 100);
5135               offset++;
5136             }
5137           if (size)
5138             {
5139               CLRC;
5140               emitcode ("", "%05d$:", tlbl->key + 100);
5141               outBitC (result);
5142             }
5143           else if (ifx)
5144             jmpTrueOrFalse (ifx, tlbl);
5145         }
5146       else
5147         {
5148           for (; (size--); offset++)
5149             {
5150               // normal case
5151               // result = left & right
5152               if (AOP_TYPE (right) == AOP_LIT)
5153                 {
5154                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5155                     {
5156                       aopPut (AOP (result),
5157                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5158                               offset);
5159                       continue;
5160                     }
5161                   else if (bytelit == 0)
5162                     {
5163                       aopPut (AOP (result), zero, offset);
5164                       continue;
5165                     }
5166                   D (emitcode (";", "better literal AND.");
5167                     );
5168                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5169                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5170                                                     FALSE, FALSE, FALSE));
5171
5172                 }
5173               else
5174                 {
5175                   // faster than result <- left, anl result,right
5176                   // and better if result is SFR
5177                   if (AOP_TYPE (left) == AOP_ACC)
5178                     {
5179                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5180                                                        FALSE, FALSE, FALSE));
5181                     }
5182                   else
5183                     {
5184                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5185                       emitcode ("anl", "a,%s",
5186                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5187                     }
5188                 }
5189               aopPut (AOP (result), "a", offset);
5190             }
5191         }
5192     }
5193
5194 release:
5195   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5196   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5197   freeAsmop (result, NULL, ic, TRUE);
5198 }
5199
5200
5201 /*-----------------------------------------------------------------*/
5202 /* genOr  - code for or                                            */
5203 /*-----------------------------------------------------------------*/
5204 static void
5205 genOr (iCode * ic, iCode * ifx)
5206 {
5207   operand *left, *right, *result;
5208   int size, offset = 0;
5209   unsigned long lit = 0L;
5210   bool     pushResult;
5211
5212   D (emitcode (";", "genOr "););
5213
5214   AOP_OP_3_NOFATAL (ic, pushResult);
5215   AOP_SET_LOCALS (ic);
5216
5217   if (pushResult)
5218   {
5219       genFarFarLogicOp(ic, "orl");
5220       return;
5221   }
5222
5223
5224 #ifdef DEBUG_TYPE
5225   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5226             AOP_TYPE (result),
5227             AOP_TYPE (left), AOP_TYPE (right));
5228   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5229             AOP_SIZE (result),
5230             AOP_SIZE (left), AOP_SIZE (right));
5231 #endif
5232
5233   /* if left is a literal & right is not then exchange them */
5234   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5235       AOP_NEEDSACC (left))
5236     {
5237       operand *tmp = right;
5238       right = left;
5239       left = tmp;
5240     }
5241
5242   /* if result = right then exchange them */
5243   if (sameRegs (AOP (result), AOP (right)))
5244     {
5245       operand *tmp = right;
5246       right = left;
5247       left = tmp;
5248     }
5249
5250   /* if right is bit then exchange them */
5251   if (AOP_TYPE (right) == AOP_CRY &&
5252       AOP_TYPE (left) != AOP_CRY)
5253     {
5254       operand *tmp = right;
5255       right = left;
5256       left = tmp;
5257     }
5258   if (AOP_TYPE (right) == AOP_LIT)
5259     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5260
5261   size = AOP_SIZE (result);
5262
5263   // if(bit | yy)
5264   // xx = bit | yy;
5265   if (AOP_TYPE (left) == AOP_CRY)
5266     {
5267       if (AOP_TYPE (right) == AOP_LIT)
5268         {
5269           // c = bit & literal;
5270           if (lit)
5271             {
5272               // lit != 0 => result = 1
5273               if (AOP_TYPE (result) == AOP_CRY)
5274                 {
5275                   if (size)
5276                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5277                   else if (ifx)
5278                     continueIfTrue (ifx);
5279                   goto release;
5280                 }
5281               emitcode ("setb", "c");
5282             }
5283           else
5284             {
5285               // lit == 0 => result = left
5286               if (size && sameRegs (AOP (result), AOP (left)))
5287                 goto release;
5288               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5289             }
5290         }
5291       else
5292         {
5293           if (AOP_TYPE (right) == AOP_CRY)
5294             {
5295               // c = bit | bit;
5296               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5297               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5298             }
5299           else
5300             {
5301               // c = bit | val;
5302               symbol *tlbl = newiTempLabel (NULL);
5303               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5304                 emitcode ("setb", "c");
5305               emitcode ("jb", "%s,%05d$",
5306                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5307               toBoolean (right);
5308               emitcode ("jnz", "%05d$", tlbl->key + 100);
5309               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5310                 {
5311                   jmpTrueOrFalse (ifx, tlbl);
5312                   goto release;
5313                 }
5314               else
5315                 {
5316                   CLRC;
5317                   emitcode ("", "%05d$:", tlbl->key + 100);
5318                 }
5319             }
5320         }
5321       // bit = c
5322       // val = c
5323       if (size)
5324         outBitC (result);
5325       // if(bit | ...)
5326       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5327         genIfxJump (ifx, "c");
5328       goto release;
5329     }
5330
5331   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5332   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5333   if ((AOP_TYPE (right) == AOP_LIT) &&
5334       (AOP_TYPE (result) == AOP_CRY) &&
5335       (AOP_TYPE (left) != AOP_CRY))
5336     {
5337       if (lit)
5338         {
5339           // result = 1
5340           if (size)
5341             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5342           else
5343             continueIfTrue (ifx);
5344           goto release;
5345         }
5346       else
5347         {
5348           // lit = 0, result = boolean(left)
5349           if (size)
5350             emitcode ("setb", "c");
5351           toBoolean (right);
5352           if (size)
5353             {
5354               symbol *tlbl = newiTempLabel (NULL);
5355               emitcode ("jnz", "%05d$", tlbl->key + 100);
5356               CLRC;
5357               emitcode ("", "%05d$:", tlbl->key + 100);
5358             }
5359           else
5360             {
5361               genIfxJump (ifx, "a");
5362               goto release;
5363             }
5364         }
5365       outBitC (result);
5366       goto release;
5367     }
5368
5369   /* if left is same as result */
5370   if (sameRegs (AOP (result), AOP (left)))
5371     {
5372       for (; size--; offset++)
5373         {
5374           if (AOP_TYPE (right) == AOP_LIT)
5375             {
5376               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5377                 {
5378                   continue;
5379                 }
5380               else
5381                 {
5382                   if (IS_AOP_PREG (left))
5383                     {
5384                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5385                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5386                       aopPut (AOP (result), "a", offset);
5387                     }
5388                   else
5389                     {
5390                       emitcode ("orl", "%s,%s",
5391                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5392                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5393                     }
5394                 }
5395             }
5396           else
5397             {
5398               if (AOP_TYPE (left) == AOP_ACC)
5399                 {
5400                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5401                 }
5402               else
5403                 {
5404                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5405                   if (IS_AOP_PREG (left))
5406                     {
5407                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5408                       aopPut (AOP (result), "a", offset);
5409                     }
5410                   else
5411                     {
5412                       emitcode ("orl", "%s,a",
5413                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5414                     }
5415                 }
5416             }
5417         }
5418     }
5419   else
5420     {
5421       // left & result in different registers
5422       if (AOP_TYPE (result) == AOP_CRY)
5423         {
5424           // result = bit
5425           // if(size), result in bit
5426           // if(!size && ifx), conditional oper: if(left | right)
5427           symbol *tlbl = newiTempLabel (NULL);
5428           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5429           if (size)
5430             emitcode ("setb", "c");
5431           while (sizer--)
5432             {
5433               MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5434               emitcode ("orl", "a,%s",
5435                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5436               emitcode ("jnz", "%05d$", tlbl->key + 100);
5437               offset++;
5438             }
5439           if (size)
5440             {
5441               CLRC;
5442               emitcode ("", "%05d$:", tlbl->key + 100);
5443               outBitC (result);
5444             }
5445           else if (ifx)
5446             jmpTrueOrFalse (ifx, tlbl);
5447         }
5448       else
5449         {
5450           for (; (size--); offset++)
5451             {
5452               // normal case
5453               // result = left & right
5454               if (AOP_TYPE (right) == AOP_LIT)
5455                 {
5456                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5457                     {
5458                       aopPut (AOP (result),
5459                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5460                               offset);
5461                       continue;
5462                     }
5463                   D (emitcode (";", "better literal OR.");
5464                     );
5465                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5466                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5467                                                     FALSE, FALSE, FALSE));
5468
5469                 }
5470               else
5471                 {
5472                   // faster than result <- left, anl result,right
5473                   // and better if result is SFR
5474                   if (AOP_TYPE (left) == AOP_ACC)
5475                     {
5476                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5477                                                        FALSE, FALSE, FALSE));
5478                     }
5479                   else
5480                     {
5481                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5482                       emitcode ("orl", "a,%s",
5483                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5484                     }
5485                 }
5486               aopPut (AOP (result), "a", offset);
5487             }
5488         }
5489     }
5490
5491 release:
5492   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5493   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494   freeAsmop (result, NULL, ic, TRUE);
5495 }
5496
5497 /*-----------------------------------------------------------------*/
5498 /* genXor - code for xclusive or                                   */
5499 /*-----------------------------------------------------------------*/
5500 static void
5501 genXor (iCode * ic, iCode * ifx)
5502 {
5503   operand *left, *right, *result;
5504   int size, offset = 0;
5505   unsigned long lit = 0L;
5506   bool pushResult;
5507
5508   D (emitcode (";", "genXor "););
5509
5510   AOP_OP_3_NOFATAL (ic, pushResult);
5511   AOP_SET_LOCALS (ic);
5512
5513   if (pushResult)
5514   {
5515       genFarFarLogicOp(ic, "xrl");
5516       return;
5517   }  
5518
5519 #ifdef DEBUG_TYPE
5520   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5521             AOP_TYPE (result),
5522             AOP_TYPE (left), AOP_TYPE (right));
5523   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5524             AOP_SIZE (result),
5525             AOP_SIZE (left), AOP_SIZE (right));
5526 #endif
5527
5528   /* if left is a literal & right is not ||
5529      if left needs acc & right does not */
5530   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5531       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5532     {
5533       operand *tmp = right;
5534       right = left;
5535       left = tmp;
5536     }
5537
5538   /* if result = right then exchange them */
5539   if (sameRegs (AOP (result), AOP (right)))
5540     {
5541       operand *tmp = right;
5542       right = left;
5543       left = tmp;
5544     }
5545
5546   /* if right is bit then exchange them */
5547   if (AOP_TYPE (right) == AOP_CRY &&
5548       AOP_TYPE (left) != AOP_CRY)
5549     {
5550       operand *tmp = right;
5551       right = left;
5552       left = tmp;
5553     }
5554   if (AOP_TYPE (right) == AOP_LIT)
5555     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5556
5557   size = AOP_SIZE (result);
5558
5559   // if(bit ^ yy)
5560   // xx = bit ^ yy;
5561   if (AOP_TYPE (left) == AOP_CRY)
5562     {
5563       if (AOP_TYPE (right) == AOP_LIT)
5564         {
5565           // c = bit & literal;
5566           if (lit >> 1)
5567             {
5568               // lit>>1  != 0 => result = 1
5569               if (AOP_TYPE (result) == AOP_CRY)
5570                 {
5571                   if (size)
5572                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5573                   else if (ifx)
5574                     continueIfTrue (ifx);
5575                   goto release;
5576                 }
5577               emitcode ("setb", "c");
5578             }
5579           else
5580             {
5581               // lit == (0 or 1)
5582               if (lit == 0)
5583                 {
5584                   // lit == 0, result = left
5585                   if (size && sameRegs (AOP (result), AOP (left)))
5586                     goto release;
5587                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5588                 }
5589               else
5590                 {
5591                   // lit == 1, result = not(left)
5592                   if (size && sameRegs (AOP (result), AOP (left)))
5593                     {
5594                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5595                       goto release;
5596                     }
5597                   else
5598                     {
5599                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5600                       emitcode ("cpl", "c");
5601                     }
5602                 }
5603             }
5604
5605         }
5606       else
5607         {
5608           // right != literal
5609           symbol *tlbl = newiTempLabel (NULL);
5610           if (AOP_TYPE (right) == AOP_CRY)
5611             {
5612               // c = bit ^ bit;
5613               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5614             }
5615           else
5616             {
5617               int sizer = AOP_SIZE (right);
5618               // c = bit ^ val
5619               // if val>>1 != 0, result = 1
5620               emitcode ("setb", "c");
5621               while (sizer)
5622                 {
5623                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5624                   if (sizer == 1)
5625                     // test the msb of the lsb
5626                     emitcode ("anl", "a,#0xfe");
5627                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5628                   sizer--;
5629                 }
5630               // val = (0,1)
5631               emitcode ("rrc", "a");
5632             }
5633           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5634           emitcode ("cpl", "c");
5635           emitcode ("", "%05d$:", (tlbl->key + 100));
5636         }
5637       // bit = c
5638       // val = c
5639       if (size)
5640         outBitC (result);
5641       // if(bit | ...)
5642       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5643         genIfxJump (ifx, "c");
5644       goto release;
5645     }
5646
5647   if (sameRegs (AOP (result), AOP (left)))
5648     {
5649       /* if left is same as result */
5650       for (; size--; offset++)
5651         {
5652           if (AOP_TYPE (right) == AOP_LIT)
5653             {
5654               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5655                 continue;
5656               else if (IS_AOP_PREG (left))
5657                 {
5658                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5659                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5660                   aopPut (AOP (result), "a", offset);
5661                 }
5662               else
5663                 emitcode ("xrl", "%s,%s",
5664                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5665                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5666             }
5667           else
5668             {
5669               if (AOP_TYPE (left) == AOP_ACC)
5670                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5671               else
5672                 {
5673                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5674                   if (IS_AOP_PREG (left))
5675                     {
5676                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5677                       aopPut (AOP (result), "a", offset);
5678                     }
5679                   else
5680                     emitcode ("xrl", "%s,a",
5681                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5682                 }
5683             }
5684         }
5685     }
5686   else
5687     {
5688       // left & result in different registers
5689       if (AOP_TYPE (result) == AOP_CRY)
5690         {
5691           // result = bit
5692           // if(size), result in bit
5693           // if(!size && ifx), conditional oper: if(left ^ right)
5694           symbol *tlbl = newiTempLabel (NULL);
5695           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5696           if (size)
5697             emitcode ("setb", "c");
5698           while (sizer--)
5699             {
5700               if ((AOP_TYPE (right) == AOP_LIT) &&
5701                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5702                 {
5703                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5704                 }
5705               else
5706                 {
5707                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5708                   emitcode ("xrl", "a,%s",
5709                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5710                 }
5711               emitcode ("jnz", "%05d$", tlbl->key + 100);
5712               offset++;
5713             }
5714           if (size)
5715             {
5716               CLRC;
5717               emitcode ("", "%05d$:", tlbl->key + 100);
5718               outBitC (result);
5719             }
5720           else if (ifx)
5721             jmpTrueOrFalse (ifx, tlbl);
5722         }
5723       else
5724         for (; (size--); offset++)
5725           {
5726             // normal case
5727             // result = left & right
5728             if (AOP_TYPE (right) == AOP_LIT)
5729               {
5730                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5731                   {
5732                     aopPut (AOP (result),
5733                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5734                             offset);
5735                     continue;
5736                   }
5737                 D (emitcode (";", "better literal XOR.");
5738                   );
5739                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5740                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
5741                                                   FALSE, FALSE, FALSE));
5742               }
5743             else
5744               {
5745                 // faster than result <- left, anl result,right
5746                 // and better if result is SFR
5747                 if (AOP_TYPE (left) == AOP_ACC)
5748                   {
5749                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
5750                                                      FALSE, FALSE, FALSE));
5751                   }
5752                 else
5753                   {
5754                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5755                     emitcode ("xrl", "a,%s",
5756                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5757                   }
5758               }
5759             aopPut (AOP (result), "a", offset);
5760           }
5761     }
5762
5763 release:
5764   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5765   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5766   freeAsmop (result, NULL, ic, TRUE);
5767 }
5768
5769 /*-----------------------------------------------------------------*/
5770 /* genInline - write the inline code out                           */
5771 /*-----------------------------------------------------------------*/
5772 static void
5773 genInline (iCode * ic)
5774 {
5775   char buffer[MAX_INLINEASM];
5776   char *bp = buffer;
5777   char *bp1 = buffer;
5778
5779   D (emitcode (";", "genInline ");
5780     );
5781
5782   _G.inLine += (!options.asmpeep);
5783   strcpy (buffer, IC_INLINE (ic));
5784
5785   /* emit each line as a code */
5786   while (*bp)
5787     {
5788       if (*bp == '\n')
5789         {
5790           *bp++ = '\0';
5791           emitcode (bp1, "");
5792           bp1 = bp;
5793         }
5794       else
5795         {
5796           if (*bp == ':')
5797             {
5798               bp++;
5799               *bp = '\0';
5800               bp++;
5801               emitcode (bp1, "");
5802               bp1 = bp;
5803             }
5804           else
5805             bp++;
5806         }
5807     }
5808   if (bp1 != bp)
5809     emitcode (bp1, "");
5810   /*     emitcode("",buffer); */
5811   _G.inLine -= (!options.asmpeep);
5812 }
5813
5814 /*-----------------------------------------------------------------*/
5815 /* genRRC - rotate right with carry                                */
5816 /*-----------------------------------------------------------------*/
5817 static void
5818 genRRC (iCode * ic)
5819 {
5820   operand *left, *result;
5821   int size, offset = 0;
5822   char *l;
5823
5824   D (emitcode (";", "genRRC ");
5825     );
5826
5827   /* rotate right with carry */
5828   left = IC_LEFT (ic);
5829   result = IC_RESULT (ic);
5830   aopOp (left, ic, FALSE, FALSE);
5831   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5832
5833   /* move it to the result */
5834   size = AOP_SIZE (result);
5835   offset = size - 1;
5836   CLRC;
5837
5838   _startLazyDPSEvaluation ();
5839   while (size--)
5840     {
5841       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5842       MOVA (l);
5843       emitcode ("rrc", "a");
5844       if (AOP_SIZE (result) > 1)
5845         aopPut (AOP (result), "a", offset--);
5846     }
5847   _endLazyDPSEvaluation ();
5848
5849   /* now we need to put the carry into the
5850      highest order byte of the result */
5851   if (AOP_SIZE (result) > 1)
5852     {
5853       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
5854       MOVA (l);
5855     }
5856   emitcode ("mov", "acc.7,c");
5857   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5858   freeAsmop (left, NULL, ic, TRUE);
5859   freeAsmop (result, NULL, ic, TRUE);
5860 }
5861
5862 /*-----------------------------------------------------------------*/
5863 /* genRLC - generate code for rotate left with carry               */
5864 /*-----------------------------------------------------------------*/
5865 static void
5866 genRLC (iCode * ic)
5867 {
5868   operand *left, *result;
5869   int size, offset = 0;
5870   char *l;
5871
5872   D (emitcode (";", "genRLC ");
5873     );
5874
5875   /* rotate right with carry */
5876   left = IC_LEFT (ic);
5877   result = IC_RESULT (ic);
5878   aopOp (left, ic, FALSE, FALSE);
5879   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5880
5881   /* move it to the result */
5882   size = AOP_SIZE (result);
5883   offset = 0;
5884   if (size--)
5885     {
5886       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5887       MOVA (l);
5888       emitcode ("add", "a,acc");
5889       if (AOP_SIZE (result) > 1)
5890         {
5891           aopPut (AOP (result), "a", offset++);
5892         }
5893
5894       _startLazyDPSEvaluation ();
5895       while (size--)
5896         {
5897           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5898           MOVA (l);
5899           emitcode ("rlc", "a");
5900           if (AOP_SIZE (result) > 1)
5901             aopPut (AOP (result), "a", offset++);
5902         }
5903       _endLazyDPSEvaluation ();
5904     }
5905   /* now we need to put the carry into the
5906      highest order byte of the result */
5907   if (AOP_SIZE (result) > 1)
5908     {
5909       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
5910       MOVA (l);
5911     }
5912   emitcode ("mov", "acc.0,c");
5913   aopPut (AOP (result), "a", 0);
5914   freeAsmop (left, NULL, ic, TRUE);
5915   freeAsmop (result, NULL, ic, TRUE);
5916 }
5917
5918 /*-----------------------------------------------------------------*/
5919 /* genGetHbit - generates code get highest order bit               */
5920 /*-----------------------------------------------------------------*/
5921 static void
5922 genGetHbit (iCode * ic)
5923 {
5924   operand *left, *result;
5925   left = IC_LEFT (ic);
5926   result = IC_RESULT (ic);
5927   aopOp (left, ic, FALSE, FALSE);
5928   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
5929
5930   D (emitcode (";", "genGetHbit ");
5931     );
5932
5933   /* get the highest order byte into a */
5934   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5935   if (AOP_TYPE (result) == AOP_CRY)
5936     {
5937       emitcode ("rlc", "a");
5938       outBitC (result);
5939     }
5940   else
5941     {
5942       emitcode ("rl", "a");
5943       emitcode ("anl", "a,#0x01");
5944       outAcc (result);
5945     }
5946
5947
5948   freeAsmop (left, NULL, ic, TRUE);
5949   freeAsmop (result, NULL, ic, TRUE);
5950 }
5951
5952 /*-----------------------------------------------------------------*/
5953 /* AccRol - rotate left accumulator by known count                 */
5954 /*-----------------------------------------------------------------*/
5955 static void
5956 AccRol (int shCount)
5957 {
5958   shCount &= 0x0007;            // shCount : 0..7
5959
5960   switch (shCount)
5961     {
5962     case 0:
5963       break;
5964     case 1:
5965       emitcode ("rl", "a");
5966       break;
5967     case 2:
5968       emitcode ("rl", "a");
5969       emitcode ("rl", "a");
5970       break;
5971     case 3:
5972       emitcode ("swap", "a");
5973       emitcode ("rr", "a");
5974       break;
5975     case 4:
5976       emitcode ("swap", "a");
5977       break;
5978     case 5:
5979       emitcode ("swap", "a");
5980       emitcode ("rl", "a");
5981       break;
5982     case 6:
5983       emitcode ("rr", "a");
5984       emitcode ("rr", "a");
5985       break;
5986     case 7:
5987       emitcode ("rr", "a");
5988       break;
5989     }
5990 }
5991
5992 /*-----------------------------------------------------------------*/
5993 /* AccLsh - left shift accumulator by known count                  */
5994 /*-----------------------------------------------------------------*/
5995 static void
5996 AccLsh (int shCount)
5997 {
5998   if (shCount != 0)
5999     {
6000       if (shCount == 1)
6001         emitcode ("add", "a,acc");
6002       else if (shCount == 2)
6003         {
6004           emitcode ("add", "a,acc");
6005           emitcode ("add", "a,acc");
6006         }
6007       else
6008         {
6009           /* rotate left accumulator */
6010           AccRol (shCount);
6011           /* and kill the lower order bits */
6012           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6013         }
6014     }
6015 }
6016
6017 /*-----------------------------------------------------------------*/
6018 /* AccRsh - right shift accumulator by known count                 */
6019 /*-----------------------------------------------------------------*/
6020 static void
6021 AccRsh (int shCount)
6022 {
6023   if (shCount != 0)
6024     {
6025       if (shCount == 1)
6026         {
6027           CLRC;
6028           emitcode ("rrc", "a");
6029         }
6030       else
6031         {
6032           /* rotate right accumulator */
6033           AccRol (8 - shCount);
6034           /* and kill the higher order bits */
6035           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6036         }
6037     }
6038 }
6039
6040 #ifdef BETTER_LITERAL_SHIFT
6041 /*-----------------------------------------------------------------*/
6042 /* AccSRsh - signed right shift accumulator by known count                 */
6043 /*-----------------------------------------------------------------*/
6044 static void
6045 AccSRsh (int shCount)
6046 {
6047   symbol *tlbl;
6048   if (shCount != 0)
6049     {
6050       if (shCount == 1)
6051         {
6052           emitcode ("mov", "c,acc.7");
6053           emitcode ("rrc", "a");
6054         }
6055       else if (shCount == 2)
6056         {
6057           emitcode ("mov", "c,acc.7");
6058           emitcode ("rrc", "a");
6059           emitcode ("mov", "c,acc.7");
6060           emitcode ("rrc", "a");
6061         }
6062       else
6063         {
6064           tlbl = newiTempLabel (NULL);
6065           /* rotate right accumulator */
6066           AccRol (8 - shCount);
6067           /* and kill the higher order bits */
6068           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6069           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6070           emitcode ("orl", "a,#0x%02x",
6071                     (unsigned char) ~SRMask[shCount]);
6072           emitcode ("", "%05d$:", tlbl->key + 100);
6073         }
6074     }
6075 }
6076 #endif
6077
6078 #ifdef BETTER_LITERAL_SHIFT
6079 /*-----------------------------------------------------------------*/
6080 /* shiftR1Left2Result - shift right one byte from left to result   */
6081 /*-----------------------------------------------------------------*/
6082 static void
6083 shiftR1Left2Result (operand * left, int offl,
6084                     operand * result, int offr,
6085                     int shCount, int sign)
6086 {
6087   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6088   /* shift right accumulator */
6089   if (sign)
6090     AccSRsh (shCount);
6091   else
6092     AccRsh (shCount);
6093   aopPut (AOP (result), "a", offr);
6094 }
6095 #endif
6096
6097 #ifdef BETTER_LITERAL_SHIFT
6098 /*-----------------------------------------------------------------*/
6099 /* shiftL1Left2Result - shift left one byte from left to result    */
6100 /*-----------------------------------------------------------------*/
6101 static void
6102 shiftL1Left2Result (operand * left, int offl,
6103                     operand * result, int offr, int shCount)
6104 {
6105   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6106   /* shift left accumulator */
6107   AccLsh (shCount);
6108   aopPut (AOP (result), "a", offr);
6109 }
6110 #endif
6111
6112 #ifdef BETTER_LITERAL_SHIFT
6113 /*-----------------------------------------------------------------*/
6114 /* movLeft2Result - move byte from left to result                  */
6115 /*-----------------------------------------------------------------*/
6116 static void
6117 movLeft2Result (operand * left, int offl,
6118                 operand * result, int offr, int sign)
6119 {
6120   char *l;
6121   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6122   {
6123       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6124
6125       if (*l == '@' && (IS_AOP_PREG (result)))
6126       {
6127           emitcode ("mov", "a,%s", l);
6128           aopPut (AOP (result), "a", offr);
6129       }
6130       else
6131       {
6132           if (!sign)
6133           {
6134             aopPut (AOP (result), l, offr);
6135           }
6136           else
6137             {
6138               /* MSB sign in acc.7 ! */
6139               if (getDataSize (left) == offl + 1)
6140                 {
6141                   emitcode ("mov", "a,%s", l);
6142                   aopPut (AOP (result), "a", offr);
6143                 }
6144             }
6145       }
6146   }
6147 }
6148 #endif
6149
6150 #ifdef BETTER_LITERAL_SHIFT
6151 /*-----------------------------------------------------------------*/
6152 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6153 /*-----------------------------------------------------------------*/
6154 static void
6155 AccAXRrl1 (char *x)
6156 {
6157   emitcode ("rrc", "a");
6158   emitcode ("xch", "a,%s", x);
6159   emitcode ("rrc", "a");
6160   emitcode ("xch", "a,%s", x);
6161 }
6162 #endif
6163
6164 #ifdef BETTER_LITERAL_SHIFT
6165 //REMOVE ME!!!
6166 /*-----------------------------------------------------------------*/
6167 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6168 /*-----------------------------------------------------------------*/
6169 static void
6170 AccAXLrl1 (char *x)
6171 {
6172   emitcode ("xch", "a,%s", x);
6173   emitcode ("rlc", "a");
6174   emitcode ("xch", "a,%s", x);
6175   emitcode ("rlc", "a");
6176 }
6177 #endif
6178
6179 #ifdef BETTER_LITERAL_SHIFT
6180 /*-----------------------------------------------------------------*/
6181 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6182 /*-----------------------------------------------------------------*/
6183 static void
6184 AccAXLsh1 (char *x)
6185 {
6186   emitcode ("xch", "a,%s", x);
6187   emitcode ("add", "a,acc");
6188   emitcode ("xch", "a,%s", x);
6189   emitcode ("rlc", "a");
6190 }
6191 #endif
6192
6193 #ifdef BETTER_LITERAL_SHIFT
6194 /*-----------------------------------------------------------------*/
6195 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6196 /*-----------------------------------------------------------------*/
6197 static void
6198 AccAXLsh (char *x, int shCount)
6199 {
6200   switch (shCount)
6201     {
6202     case 0:
6203       break;
6204     case 1:
6205       AccAXLsh1 (x);
6206       break;
6207     case 2:
6208       AccAXLsh1 (x);
6209       AccAXLsh1 (x);
6210       break;
6211     case 3:
6212     case 4:
6213     case 5:                     // AAAAABBB:CCCCCDDD
6214
6215       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6216
6217       emitcode ("anl", "a,#0x%02x",
6218                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6219
6220       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6221
6222       AccRol (shCount);         // DDDCCCCC:BBB00000
6223
6224       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6225
6226       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6227
6228       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6229
6230       emitcode ("anl", "a,#0x%02x",
6231                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6232
6233       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6234
6235       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6236
6237       break;
6238     case 6:                     // AAAAAABB:CCCCCCDD
6239       emitcode ("anl", "a,#0x%02x",
6240                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6241       emitcode ("mov", "c,acc.0");      // c = B
6242       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6243 #if 0
6244       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6245       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6246 #else
6247       emitcode("rrc","a"); 
6248       emitcode("xch","a,%s", x); 
6249       emitcode("rrc","a"); 
6250       emitcode("mov","c,acc.0"); //<< get correct bit 
6251       emitcode("xch","a,%s", x); 
6252
6253       emitcode("rrc","a"); 
6254       emitcode("xch","a,%s", x); 
6255       emitcode("rrc","a"); 
6256       emitcode("xch","a,%s", x); 
6257 #endif
6258       break;
6259     case 7:                     // a:x <<= 7
6260
6261       emitcode ("anl", "a,#0x%02x",
6262                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6263
6264       emitcode ("mov", "c,acc.0");      // c = B
6265
6266       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6267
6268       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6269
6270       break;
6271     default:
6272       break;
6273     }
6274 }
6275 #endif
6276
6277 #ifdef BETTER_LITERAL_SHIFT
6278 //REMOVE ME!!!
6279 /*-----------------------------------------------------------------*/
6280 /* AccAXRsh - right shift a:x known count (0..7)                   */
6281 /*-----------------------------------------------------------------*/
6282 static void
6283 AccAXRsh (char *x, int shCount)
6284 {
6285   switch (shCount)
6286     {
6287     case 0:
6288       break;
6289     case 1:
6290       CLRC;
6291       AccAXRrl1 (x);            // 0->a:x
6292
6293       break;
6294     case 2:
6295       CLRC;
6296       AccAXRrl1 (x);            // 0->a:x
6297
6298       CLRC;
6299       AccAXRrl1 (x);            // 0->a:x
6300
6301       break;
6302     case 3:
6303     case 4:
6304     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6305
6306       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6307
6308       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6309
6310       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6311
6312       emitcode ("anl", "a,#0x%02x",
6313                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6314
6315       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6316
6317       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6318
6319       emitcode ("anl", "a,#0x%02x",
6320                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6321
6322       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6323
6324       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6325
6326       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6327
6328       break;
6329     case 6:                     // AABBBBBB:CCDDDDDD
6330
6331       emitcode ("mov", "c,acc.7");
6332       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6333
6334       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6335
6336       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6337
6338       emitcode ("anl", "a,#0x%02x",
6339                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6340
6341       break;
6342     case 7:                     // ABBBBBBB:CDDDDDDD
6343
6344       emitcode ("mov", "c,acc.7");      // c = A
6345
6346       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6347
6348       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6349
6350       emitcode ("anl", "a,#0x%02x",
6351                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6352
6353       break;
6354     default:
6355       break;
6356     }
6357 }
6358 #endif
6359
6360 #ifdef BETTER_LITERAL_SHIFT
6361 //REMOVE ME!!!
6362 /*-----------------------------------------------------------------*/
6363 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6364 /*-----------------------------------------------------------------*/
6365 static void
6366 AccAXRshS (char *x, int shCount)
6367 {
6368   symbol *tlbl;
6369   switch (shCount)
6370     {
6371     case 0:
6372       break;
6373     case 1:
6374       emitcode ("mov", "c,acc.7");
6375       AccAXRrl1 (x);            // s->a:x
6376
6377       break;
6378     case 2:
6379       emitcode ("mov", "c,acc.7");
6380       AccAXRrl1 (x);            // s->a:x
6381
6382       emitcode ("mov", "c,acc.7");
6383       AccAXRrl1 (x);            // s->a:x
6384
6385       break;
6386     case 3:
6387     case 4:
6388     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6389
6390       tlbl = newiTempLabel (NULL);
6391       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6392
6393       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6394
6395       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6396
6397       emitcode ("anl", "a,#0x%02x",
6398                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6399
6400       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6401
6402       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6403
6404       emitcode ("anl", "a,#0x%02x",
6405                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6406
6407       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6408
6409       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6410
6411       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6412
6413       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6414       emitcode ("orl", "a,#0x%02x",
6415                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6416
6417       emitcode ("", "%05d$:", tlbl->key + 100);
6418       break;                    // SSSSAAAA:BBBCCCCC
6419
6420     case 6:                     // AABBBBBB:CCDDDDDD
6421
6422       tlbl = newiTempLabel (NULL);
6423       emitcode ("mov", "c,acc.7");
6424       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6425
6426       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6427
6428       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6429
6430       emitcode ("anl", "a,#0x%02x",
6431                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6432
6433       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6434       emitcode ("orl", "a,#0x%02x",
6435                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6436
6437       emitcode ("", "%05d$:", tlbl->key + 100);
6438       break;
6439     case 7:                     // ABBBBBBB:CDDDDDDD
6440
6441       tlbl = newiTempLabel (NULL);
6442       emitcode ("mov", "c,acc.7");      // c = A
6443
6444       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6445
6446       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6447
6448       emitcode ("anl", "a,#0x%02x",
6449                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6450
6451       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6452       emitcode ("orl", "a,#0x%02x",
6453                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6454
6455       emitcode ("", "%05d$:", tlbl->key + 100);
6456       break;
6457     default:
6458       break;
6459     }
6460 }
6461 #endif
6462
6463 #ifdef BETTER_LITERAL_SHIFT
6464 static void
6465 _loadLeftIntoAx(char    **lsb, 
6466                 operand *left, 
6467                 operand *result,
6468                 int     offl,
6469                 int     offr)
6470 {
6471   // Get the initial value from left into a pair of registers.
6472   // MSB must be in A, LSB can be any register.
6473   //
6474   // If the result is held in registers, it is an optimization
6475   // if the LSB can be held in the register which will hold the,
6476   // result LSB since this saves us from having to copy it into
6477   // the result following AccAXLsh.
6478   //
6479   // If the result is addressed indirectly, this is not a gain.
6480   if (AOP_NEEDSACC(result))
6481   {
6482        char *leftByte;
6483        
6484        _startLazyDPSEvaluation();
6485        if (AOP_TYPE(left) == AOP_DPTR2)
6486        {
6487            // Get MSB in A.
6488            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6489            // get LSB in DP2_RESULT_REG.
6490            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6491            assert(!strcmp(leftByte, DP2_RESULT_REG));
6492        }
6493        else
6494        {
6495            // get LSB into DP2_RESULT_REG
6496            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6497            if (strcmp(leftByte, DP2_RESULT_REG))
6498            {
6499                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6500            }
6501            // And MSB in A.
6502            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6503            assert(strcmp(leftByte, DP2_RESULT_REG));
6504            MOVA(leftByte);
6505        }
6506        _endLazyDPSEvaluation();
6507        *lsb = DP2_RESULT_REG;
6508   }
6509   else
6510   {
6511       if (sameRegs (AOP (result), AOP (left)) &&
6512         ((offl + MSB16) == offr))
6513       {
6514           /* don't crash result[offr] */
6515           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6516           emitcode ("xch", "a,%s", 
6517                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6518       }
6519       else
6520       {
6521           movLeft2Result (left, offl, result, offr, 0);
6522           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6523       }
6524       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6525       assert(strcmp(*lsb,"a"));      
6526   }
6527 }
6528
6529 static void
6530 _storeAxResults(char    *lsb,
6531                 operand *result,
6532                 int     offr)
6533 {
6534   _startLazyDPSEvaluation();
6535   if (AOP_NEEDSACC(result))
6536   {
6537       /* We have to explicitly update the result LSB.
6538        */
6539       emitcode("xch","a,%s", lsb);
6540       aopPut(AOP(result), "a", offr);
6541       emitcode("mov","a,%s", lsb);
6542   }
6543   if (getDataSize (result) > 1)
6544   {
6545       aopPut (AOP (result), "a", offr + MSB16);
6546   }
6547   _endLazyDPSEvaluation();
6548 }
6549
6550 /*-----------------------------------------------------------------*/
6551 /* shiftL2Left2Result - shift left two bytes from left to result   */
6552 /*-----------------------------------------------------------------*/
6553 static void
6554 shiftL2Left2Result (operand * left, int offl,
6555                     operand * result, int offr, int shCount)
6556 {
6557   char *lsb;
6558
6559   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6560   
6561   AccAXLsh (lsb, shCount);
6562   
6563   _storeAxResults(lsb, result, offr);
6564 }
6565 #endif
6566
6567 #ifdef BETTER_LITERAL_SHIFT
6568 /*-----------------------------------------------------------------*/
6569 /* shiftR2Left2Result - shift right two bytes from left to result  */
6570 /*-----------------------------------------------------------------*/
6571 static void
6572 shiftR2Left2Result (operand * left, int offl,
6573                     operand * result, int offr,
6574                     int shCount, int sign)
6575 {
6576   char *lsb;
6577   
6578   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6579   
6580   /* a:x >> shCount (x = lsb(result)) */
6581   if (sign)
6582   {
6583     AccAXRshS(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6584   }
6585   else
6586   {
6587     AccAXRsh(aopGet(AOP(result), offr, FALSE, FALSE, FALSE), shCount);
6588   }
6589   
6590   _storeAxResults(lsb, result, offr);
6591 }
6592 #endif
6593
6594 #if 0
6595 //REMOVE ME!!!
6596 /*-----------------------------------------------------------------*/
6597 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6598 /*-----------------------------------------------------------------*/
6599 static void
6600 shiftLLeftOrResult (operand * left, int offl,
6601                     operand * result, int offr, int shCount)
6602 {
6603   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6604   /* shift left accumulator */
6605   AccLsh (shCount);
6606   /* or with result */
6607   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6608   /* back to result */
6609   aopPut (AOP (result), "a", offr);
6610 }
6611 #endif
6612
6613 #if 0
6614 //REMOVE ME!!!
6615 /*-----------------------------------------------------------------*/
6616 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6617 /*-----------------------------------------------------------------*/
6618 static void
6619 shiftRLeftOrResult (operand * left, int offl,
6620                     operand * result, int offr, int shCount)
6621 {
6622   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6623   /* shift right accumulator */
6624   AccRsh (shCount);
6625   /* or with result */
6626   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6627   /* back to result */
6628   aopPut (AOP (result), "a", offr);
6629 }
6630 #endif
6631
6632 #ifdef BETTER_LITERAL_SHIFT
6633 /*-----------------------------------------------------------------*/
6634 /* genlshOne - left shift a one byte quantity by known count       */
6635 /*-----------------------------------------------------------------*/
6636 static void
6637 genlshOne (operand * result, operand * left, int shCount)
6638 {
6639   D (emitcode (";", "genlshOne "););
6640   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6641 }
6642 #endif
6643
6644 #ifdef BETTER_LITERAL_SHIFT
6645 /*-----------------------------------------------------------------*/
6646 /* genlshTwo - left shift two bytes by known amount != 0           */
6647 /*-----------------------------------------------------------------*/
6648 static void
6649 genlshTwo (operand * result, operand * left, int shCount)
6650 {
6651   int size;
6652
6653   D (emitcode (";", "genlshTwo "););
6654
6655   size = getDataSize (result);
6656
6657   /* if shCount >= 8 */
6658   if (shCount >= 8)
6659   {
6660       shCount -= 8;
6661
6662       _startLazyDPSEvaluation();
6663
6664       if (size > 1)
6665         {
6666           if (shCount)
6667           {
6668             _endLazyDPSEvaluation();
6669             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6670             aopPut (AOP (result), zero, LSB);       
6671           }
6672           else
6673           {
6674             movLeft2Result (left, LSB, result, MSB16, 0);
6675             aopPut (AOP (result), zero, LSB);
6676             _endLazyDPSEvaluation();
6677           }
6678         }
6679         else
6680         {
6681           aopPut (AOP (result), zero, LSB);
6682           _endLazyDPSEvaluation();
6683         }
6684   }
6685
6686   /*  1 <= shCount <= 7 */
6687   else
6688     {
6689       if (size == 1)
6690       {
6691         shiftL1Left2Result (left, LSB, result, LSB, shCount);
6692       }
6693       else
6694       {
6695         shiftL2Left2Result (left, LSB, result, LSB, shCount);
6696       }
6697     }
6698 }
6699 #endif
6700
6701 #if 0
6702 //REMOVE ME!!!
6703 /*-----------------------------------------------------------------*/
6704 /* shiftLLong - shift left one long from left to result            */
6705 /* offl = LSB or MSB16                                             */
6706 /*-----------------------------------------------------------------*/
6707 static void
6708 shiftLLong (operand * left, operand * result, int offr)
6709 {
6710   char *l;
6711   int size = AOP_SIZE (result);
6712
6713   if (size >= LSB + offr)
6714     {
6715       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
6716       MOVA (l);
6717       emitcode ("add", "a,acc");
6718       if (sameRegs (AOP (left), AOP (result)) &&
6719           size >= MSB16 + offr && offr != LSB)
6720         emitcode ("xch", "a,%s",
6721                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
6722       else
6723         aopPut (AOP (result), "a", LSB + offr);
6724     }
6725
6726   if (size >= MSB16 + offr)
6727     {
6728       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6729         {
6730           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
6731           MOVA (l);
6732         }
6733       emitcode ("rlc", "a");
6734       if (sameRegs (AOP (left), AOP (result)) &&
6735           size >= MSB24 + offr && offr != LSB)
6736         emitcode ("xch", "a,%s",
6737                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
6738       else
6739         aopPut (AOP (result), "a", MSB16 + offr);
6740     }
6741
6742   if (size >= MSB24 + offr)
6743     {
6744       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6745         {
6746           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
6747           MOVA (l);
6748         }
6749       emitcode ("rlc", "a");
6750       if (sameRegs (AOP (left), AOP (result)) &&
6751           size >= MSB32 + offr && offr != LSB)
6752         emitcode ("xch", "a,%s",
6753                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
6754       else
6755         aopPut (AOP (result), "a", MSB24 + offr);
6756     }
6757
6758   if (size > MSB32 + offr)
6759     {
6760       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6761         {
6762           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
6763           MOVA (l);
6764         }
6765       emitcode ("rlc", "a");
6766       aopPut (AOP (result), "a", MSB32 + offr);
6767     }
6768   if (offr != LSB)
6769     aopPut (AOP (result), zero, LSB);
6770 }
6771 #endif
6772
6773 #if 0
6774 //REMOVE ME!!!
6775 /*-----------------------------------------------------------------*/
6776 /* genlshFour - shift four byte by a known amount != 0             */
6777 /*-----------------------------------------------------------------*/
6778 static void
6779 genlshFour (operand * result, operand * left, int shCount)
6780 {
6781   int size;
6782
6783   D (emitcode (";", "genlshFour ");
6784     );
6785
6786   size = AOP_SIZE (result);
6787
6788   /* if shifting more that 3 bytes */
6789   if (shCount >= 24)
6790     {
6791       shCount -= 24;
6792       if (shCount)
6793         /* lowest order of left goes to the highest
6794            order of the destination */
6795         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6796       else
6797         movLeft2Result (left, LSB, result, MSB32, 0);
6798       aopPut (AOP (result), zero, LSB);
6799       aopPut (AOP (result), zero, MSB16);
6800       aopPut (AOP (result), zero, MSB24);
6801       return;
6802     }
6803
6804   /* more than two bytes */
6805   else if (shCount >= 16)
6806     {
6807       /* lower order two bytes goes to higher order two bytes */
6808       shCount -= 16;
6809       /* if some more remaining */
6810       if (shCount)
6811         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6812       else
6813         {
6814           movLeft2Result (left, MSB16, result, MSB32, 0);
6815           movLeft2Result (left, LSB, result, MSB24, 0);
6816         }
6817       aopPut (AOP (result), zero, MSB16);
6818       aopPut (AOP (result), zero, LSB);
6819       return;
6820     }
6821
6822   /* if more than 1 byte */
6823   else if (shCount >= 8)
6824     {
6825       /* lower order three bytes goes to higher order  three bytes */
6826       shCount -= 8;
6827       if (size == 2)
6828         {
6829           if (shCount)
6830             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6831           else
6832             movLeft2Result (left, LSB, result, MSB16, 0);
6833         }
6834       else
6835         {                       /* size = 4 */
6836           if (shCount == 0)
6837             {
6838               movLeft2Result (left, MSB24, result, MSB32, 0);
6839               movLeft2Result (left, MSB16, result, MSB24, 0);
6840               movLeft2Result (left, LSB, result, MSB16, 0);
6841               aopPut (AOP (result), zero, LSB);
6842             }
6843           else if (shCount == 1)
6844             shiftLLong (left, result, MSB16);
6845           else
6846             {
6847               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6848               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6849               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6850               aopPut (AOP (result), zero, LSB);
6851             }
6852         }
6853     }
6854
6855   /* 1 <= shCount <= 7 */
6856   else if (shCount <= 2)
6857     {
6858       shiftLLong (left, result, LSB);
6859       if (shCount == 2)
6860         shiftLLong (result, result, LSB);
6861     }
6862   /* 3 <= shCount <= 7, optimize */
6863   else
6864     {
6865       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6866       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6867       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6868     }
6869 }
6870 #endif
6871
6872 #ifdef BETTER_LITERAL_SHIFT
6873 /*-----------------------------------------------------------------*/
6874 /* genLeftShiftLiteral - left shifting by known count              */
6875 /*-----------------------------------------------------------------*/
6876 static bool
6877 genLeftShiftLiteral (operand * left,
6878                      operand * right,
6879                      operand * result,
6880                      iCode * ic)
6881 {
6882   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6883   int size;
6884
6885   size = getSize (operandType (result));
6886
6887   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
6888
6889   /* We only handle certain easy cases so far. */
6890   if ((shCount != 0)
6891    && (shCount < (size * 8))
6892    && (size != 1)
6893    && (size != 2))
6894   {
6895       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
6896       return FALSE;
6897   }
6898
6899   freeAsmop (right, NULL, ic, TRUE);
6900
6901   aopOp(left, ic, FALSE, FALSE);
6902   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
6903
6904 #if 1 // debug spew
6905   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
6906   {
6907         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
6908         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
6909         {
6910            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
6911         }
6912   }
6913   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
6914   {
6915         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
6916         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
6917         {
6918            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
6919         }       
6920   }  
6921 #endif
6922   
6923 #if VIEW_SIZE
6924   emitcode ("; shift left ", "result %d, left %d", size,
6925             AOP_SIZE (left));
6926 #endif
6927
6928   /* I suppose that the left size >= result size */
6929   if (shCount == 0)
6930   {
6931         _startLazyDPSEvaluation();
6932         while (size--)
6933         {
6934           movLeft2Result (left, size, result, size, 0);
6935         }
6936         _endLazyDPSEvaluation();
6937   }
6938   else if (shCount >= (size * 8))
6939   {
6940     _startLazyDPSEvaluation();
6941     while (size--)
6942     {
6943       aopPut (AOP (result), zero, size);
6944     }
6945     _endLazyDPSEvaluation();
6946   }
6947   else
6948   {
6949       switch (size)
6950         {
6951         case 1:
6952           genlshOne (result, left, shCount);
6953           break;
6954
6955         case 2:
6956           genlshTwo (result, left, shCount);
6957           break;
6958 #if 0
6959         case 4:
6960           genlshFour (result, left, shCount);
6961           break;
6962 #endif
6963         default:
6964           fprintf(stderr, "*** ack! mystery literal shift!\n");   
6965           break;
6966         }
6967     }
6968   freeAsmop (left, NULL, ic, TRUE);
6969   freeAsmop (result, NULL, ic, TRUE);
6970   return TRUE;
6971 }
6972 #endif
6973
6974 /*-----------------------------------------------------------------*/
6975 /* genLeftShift - generates code for left shifting                 */
6976 /*-----------------------------------------------------------------*/
6977 static void
6978 genLeftShift (iCode * ic)
6979 {
6980   operand *left, *right, *result;
6981   int size, offset;
6982   char *l;
6983   symbol *tlbl, *tlbl1;
6984
6985   D (emitcode (";", "genLeftShift "););
6986
6987   right = IC_RIGHT (ic);
6988   left = IC_LEFT (ic);
6989   result = IC_RESULT (ic);
6990
6991   aopOp (right, ic, FALSE, FALSE);
6992
6993
6994 #ifdef BETTER_LITERAL_SHIFT
6995   /* if the shift count is known then do it
6996      as efficiently as possible */
6997   if (AOP_TYPE (right) == AOP_LIT)
6998     {
6999       if (genLeftShiftLiteral (left, right, result, ic))
7000       {
7001         return;
7002       }
7003     }
7004 #endif
7005
7006   /* shift count is unknown then we have to form
7007      a loop get the loop count in B : Note: we take
7008      only the lower order byte since shifting
7009      more that 32 bits make no sense anyway, ( the
7010      largest size of an object can be only 32 bits ) */
7011
7012   if (AOP_TYPE (right) == AOP_LIT)
7013   {
7014       /* Really should be handled by genLeftShiftLiteral,
7015        * but since I'm too lazy to fix that today, at least we can make
7016        * some small improvement.
7017        */
7018        emitcode("mov", "b,#0x%02x",
7019                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7020   }
7021   else
7022   {
7023         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7024         emitcode ("inc", "b");
7025   }
7026   freeAsmop (right, NULL, ic, TRUE);
7027   aopOp (left, ic, FALSE, FALSE);
7028   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7029
7030   /* now move the left to the result if they are not the
7031      same */
7032   if (!sameRegs (AOP (left), AOP (result)) &&
7033       AOP_SIZE (result) > 1)
7034     {
7035
7036       size = AOP_SIZE (result);
7037       offset = 0;
7038       _startLazyDPSEvaluation ();
7039       while (size--)
7040         {
7041           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7042           if (*l == '@' && (IS_AOP_PREG (result)))
7043             {
7044
7045               emitcode ("mov", "a,%s", l);
7046               aopPut (AOP (result), "a", offset);
7047             }
7048           else
7049             aopPut (AOP (result), l, offset);
7050           offset++;
7051         }
7052       _endLazyDPSEvaluation ();
7053     }
7054
7055   tlbl = newiTempLabel (NULL);
7056   size = AOP_SIZE (result);
7057   offset = 0;
7058   tlbl1 = newiTempLabel (NULL);
7059
7060   /* if it is only one byte then */
7061   if (size == 1)
7062     {
7063       symbol *tlbl1 = newiTempLabel (NULL);
7064
7065       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7066       MOVA (l);
7067       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7068       emitcode ("", "%05d$:", tlbl->key + 100);
7069       emitcode ("add", "a,acc");
7070       emitcode ("", "%05d$:", tlbl1->key + 100);
7071       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7072       aopPut (AOP (result), "a", 0);
7073       goto release;
7074     }
7075
7076   reAdjustPreg (AOP (result));
7077
7078   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7079   emitcode ("", "%05d$:", tlbl->key + 100);
7080   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7081   MOVA (l);
7082   emitcode ("add", "a,acc");
7083   aopPut (AOP (result), "a", offset++);
7084   _startLazyDPSEvaluation ();
7085   while (--size)
7086     {
7087       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7088       MOVA (l);
7089       emitcode ("rlc", "a");
7090       aopPut (AOP (result), "a", offset++);
7091     }
7092   _endLazyDPSEvaluation ();
7093   reAdjustPreg (AOP (result));
7094
7095   emitcode ("", "%05d$:", tlbl1->key + 100);
7096   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7097 release:
7098   freeAsmop (left, NULL, ic, TRUE);
7099   freeAsmop (result, NULL, ic, TRUE);
7100 }
7101
7102 #ifdef BETTER_LITERAL_SHIFT
7103 /*-----------------------------------------------------------------*/
7104 /* genrshOne - right shift a one byte quantity by known count      */
7105 /*-----------------------------------------------------------------*/
7106 static void
7107 genrshOne (operand * result, operand * left,
7108            int shCount, int sign)
7109 {
7110   D (emitcode (";", "genrshOne"););
7111   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7112 }
7113 #endif
7114
7115 #ifdef BETTER_LITERAL_SHIFT
7116 /*-----------------------------------------------------------------*/
7117 /* genrshTwo - right shift two bytes by known amount != 0          */
7118 /*-----------------------------------------------------------------*/
7119 static void
7120 genrshTwo (operand * result, operand * left,
7121            int shCount, int sign)
7122 {
7123   D (emitcode (";", "genrshTwo"););
7124
7125   /* if shCount >= 8 */
7126   if (shCount >= 8)
7127     {
7128       shCount -= 8;
7129       _startLazyDPSEvaluation();
7130       if (shCount)
7131       {
7132         shiftR1Left2Result (left, MSB16, result, LSB,
7133                             shCount, sign);
7134       }                     
7135       else
7136       {
7137         movLeft2Result (left, MSB16, result, LSB, sign);
7138       }
7139       addSign (result, MSB16, sign);
7140       _endLazyDPSEvaluation();
7141     }
7142
7143   /*  1 <= shCount <= 7 */
7144   else
7145   {
7146     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7147   }
7148 }
7149 #endif
7150
7151 #if 0
7152 //REMOVE ME!!!
7153 /*-----------------------------------------------------------------*/
7154 /* shiftRLong - shift right one long from left to result           */
7155 /* offl = LSB or MSB16                                             */
7156 /*-----------------------------------------------------------------*/
7157 static void
7158 shiftRLong (operand * left, int offl,
7159             operand * result, int sign)
7160 {
7161   if (!sign)
7162     emitcode ("clr", "c");
7163   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE));
7164   if (sign)
7165     emitcode ("mov", "c,acc.7");
7166   emitcode ("rrc", "a");
7167   aopPut (AOP (result), "a", MSB32 - offl);
7168   if (offl == MSB16)
7169     /* add sign of "a" */
7170     addSign (result, MSB32, sign);
7171
7172   MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE));
7173   emitcode ("rrc", "a");
7174   aopPut (AOP (result), "a", MSB24 - offl);
7175
7176   MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
7177   emitcode ("rrc", "a");
7178   aopPut (AOP (result), "a", MSB16 - offl);
7179
7180   if (offl == LSB)
7181     {
7182       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, TRUE));
7183       emitcode ("rrc", "a");
7184       aopPut (AOP (result), "a", LSB);
7185     }
7186 }
7187 #endif
7188
7189 #if 0
7190 //REMOVE ME!!!
7191 /*-----------------------------------------------------------------*/
7192 /* genrshFour - shift four byte by a known amount != 0             */
7193 /*-----------------------------------------------------------------*/
7194 static void
7195 genrshFour (operand * result, operand * left,
7196             int shCount, int sign)
7197 {
7198   D (emitcode (";", "genrshFour");
7199     );
7200
7201   /* if shifting more that 3 bytes */
7202   if (shCount >= 24)
7203     {
7204       shCount -= 24;
7205       if (shCount)
7206         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7207       else
7208         movLeft2Result (left, MSB32, result, LSB, sign);
7209       addSign (result, MSB16, sign);
7210     }
7211   else if (shCount >= 16)
7212     {
7213       shCount -= 16;
7214       if (shCount)
7215         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7216       else
7217         {
7218           movLeft2Result (left, MSB24, result, LSB, 0);
7219           movLeft2Result (left, MSB32, result, MSB16, sign);
7220         }
7221       addSign (result, MSB24, sign);
7222     }
7223   else if (shCount >= 8)
7224     {
7225       shCount -= 8;
7226       if (shCount == 1)
7227         shiftRLong (left, MSB16, result, sign);
7228       else if (shCount == 0)
7229         {
7230           movLeft2Result (left, MSB16, result, LSB, 0);
7231           movLeft2Result (left, MSB24, result, MSB16, 0);
7232           movLeft2Result (left, MSB32, result, MSB24, sign);
7233           addSign (result, MSB32, sign);
7234         }
7235       else
7236         {
7237           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7238           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7239           /* the last shift is signed */
7240           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7241           addSign (result, MSB32, sign);
7242         }
7243     }
7244   else
7245     {                           /* 1 <= shCount <= 7 */
7246       if (shCount <= 2)
7247         {
7248           shiftRLong (left, LSB, result, sign);
7249           if (shCount == 2)
7250             shiftRLong (result, LSB, result, sign);
7251         }
7252       else
7253         {
7254           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7255           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7256           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7257         }
7258     }
7259 }
7260 #endif
7261
7262 #ifdef BETTER_LITERAL_SHIFT
7263 /*-----------------------------------------------------------------*/
7264 /* genRightShiftLiteral - right shifting by known count            */
7265 /*-----------------------------------------------------------------*/
7266 static bool
7267 genRightShiftLiteral (operand * left,
7268                       operand * right,
7269                       operand * result,
7270                       iCode * ic,
7271                       int sign)
7272 {
7273   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7274   int size;
7275
7276   size = getSize (operandType (result));
7277
7278   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7279
7280   /* We only handle certain easy cases so far. */
7281   if ((shCount != 0)
7282    && (shCount < (size * 8))
7283    && (size != 1)
7284    && (size != 2))
7285   {
7286       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7287       return FALSE;
7288   }
7289
7290   freeAsmop (right, NULL, ic, TRUE);
7291
7292   aopOp (left, ic, FALSE, FALSE);
7293   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7294
7295 #if VIEW_SIZE
7296   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7297             AOP_SIZE (left));
7298 #endif
7299
7300   /* test the LEFT size !!! */
7301
7302   /* I suppose that the left size >= result size */
7303   if (shCount == 0)
7304   {
7305       size = getDataSize (result);
7306       _startLazyDPSEvaluation();
7307       while (size--)
7308       {
7309         movLeft2Result (left, size, result, size, 0);
7310       }
7311       _endLazyDPSEvaluation();
7312   }
7313   else if (shCount >= (size * 8))
7314     {
7315       if (sign)
7316       {
7317         /* get sign in acc.7 */
7318         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7319       }
7320       addSign (result, LSB, sign);
7321     }
7322   else
7323     {
7324       switch (size)
7325         {
7326         case 1:
7327           genrshOne (result, left, shCount, sign);
7328           break;
7329
7330         case 2:
7331           genrshTwo (result, left, shCount, sign);
7332           break;
7333 #if 0
7334         case 4:
7335           genrshFour (result, left, shCount, sign);
7336           break;
7337 #endif    
7338         default:
7339           break;
7340         }
7341
7342       freeAsmop (left, NULL, ic, TRUE);
7343       freeAsmop (result, NULL, ic, TRUE);
7344     }
7345     return TRUE;
7346 }
7347 #endif
7348
7349 /*-----------------------------------------------------------------*/
7350 /* genSignedRightShift - right shift of signed number              */
7351 /*-----------------------------------------------------------------*/
7352 static void
7353 genSignedRightShift (iCode * ic)
7354 {
7355   operand *right, *left, *result;
7356   int size, offset;
7357   char *l;
7358   symbol *tlbl, *tlbl1;
7359
7360   D (emitcode (";", "genSignedRightShift "););
7361
7362   /* we do it the hard way put the shift count in b
7363      and loop thru preserving the sign */
7364
7365   right = IC_RIGHT (ic);
7366   left = IC_LEFT (ic);
7367   result = IC_RESULT (ic);
7368
7369   aopOp (right, ic, FALSE, FALSE);
7370
7371 #ifdef BETTER_LITERAL_SHIFT
7372   if (AOP_TYPE (right) == AOP_LIT)
7373     {
7374       if (genRightShiftLiteral (left, right, result, ic, 1))
7375       {
7376         return;
7377       }
7378     }
7379 #endif
7380   /* shift count is unknown then we have to form
7381      a loop get the loop count in B : Note: we take
7382      only the lower order byte since shifting
7383      more that 32 bits make no sense anyway, ( the
7384      largest size of an object can be only 32 bits ) */
7385
7386   if (AOP_TYPE (right) == AOP_LIT)
7387   {
7388       /* Really should be handled by genRightShiftLiteral,
7389        * but since I'm too lazy to fix that today, at least we can make
7390        * some small improvement.
7391        */
7392        emitcode("mov", "b,#0x%02x",
7393                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7394   }
7395   else
7396   {
7397         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7398         emitcode ("inc", "b");
7399   }
7400   freeAsmop (right, NULL, ic, TRUE);
7401   aopOp (left, ic, FALSE, FALSE);
7402   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7403
7404   /* now move the left to the result if they are not the
7405      same */
7406   if (!sameRegs (AOP (left), AOP (result)) &&
7407       AOP_SIZE (result) > 1)
7408     {
7409
7410       size = AOP_SIZE (result);
7411       offset = 0;
7412       _startLazyDPSEvaluation ();
7413       while (size--)
7414         {
7415           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7416           if (*l == '@' && IS_AOP_PREG (result))
7417             {
7418
7419               emitcode ("mov", "a,%s", l);
7420               aopPut (AOP (result), "a", offset);
7421             }
7422           else
7423             aopPut (AOP (result), l, offset);
7424           offset++;
7425         }
7426       _endLazyDPSEvaluation ();
7427     }
7428
7429   /* mov the highest order bit to OVR */
7430   tlbl = newiTempLabel (NULL);
7431   tlbl1 = newiTempLabel (NULL);
7432
7433   size = AOP_SIZE (result);
7434   offset = size - 1;
7435   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7436   emitcode ("rlc", "a");
7437   emitcode ("mov", "ov,c");
7438   /* if it is only one byte then */
7439   if (size == 1)
7440     {
7441       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7442       MOVA (l);
7443       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7444       emitcode ("", "%05d$:", tlbl->key + 100);
7445       emitcode ("mov", "c,ov");
7446       emitcode ("rrc", "a");
7447       emitcode ("", "%05d$:", tlbl1->key + 100);
7448       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7449       aopPut (AOP (result), "a", 0);
7450       goto release;
7451     }
7452
7453   reAdjustPreg (AOP (result));
7454   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7455   emitcode ("", "%05d$:", tlbl->key + 100);
7456   emitcode ("mov", "c,ov");
7457   _startLazyDPSEvaluation ();
7458   while (size--)
7459     {
7460       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7461       MOVA (l);
7462       emitcode ("rrc", "a");
7463       aopPut (AOP (result), "a", offset--);
7464     }
7465   _endLazyDPSEvaluation ();
7466   reAdjustPreg (AOP (result));
7467   emitcode ("", "%05d$:", tlbl1->key + 100);
7468   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7469
7470 release:
7471   freeAsmop (left, NULL, ic, TRUE);
7472   freeAsmop (result, NULL, ic, TRUE);
7473 }
7474
7475 /*-----------------------------------------------------------------*/
7476 /* genRightShift - generate code for right shifting                */
7477 /*-----------------------------------------------------------------*/
7478 static void
7479 genRightShift (iCode * ic)
7480 {
7481   operand *right, *left, *result;
7482   sym_link *retype;
7483   int size, offset;
7484   char *l;
7485   symbol *tlbl, *tlbl1;
7486
7487   D (emitcode (";", "genRightShift "););
7488
7489   /* if signed then we do it the hard way preserve the
7490      sign bit moving it inwards */
7491   retype = getSpec (operandType (IC_RESULT (ic)));
7492
7493   if (!SPEC_USIGN (retype))
7494     {
7495       genSignedRightShift (ic);
7496       return;
7497     }
7498
7499   /* signed & unsigned types are treated the same : i.e. the
7500      signed is NOT propagated inwards : quoting from the
7501      ANSI - standard : "for E1 >> E2, is equivalent to division
7502      by 2**E2 if unsigned or if it has a non-negative value,
7503      otherwise the result is implementation defined ", MY definition
7504      is that the sign does not get propagated */
7505
7506   right = IC_RIGHT (ic);
7507   left = IC_LEFT (ic);
7508   result = IC_RESULT (ic);
7509
7510   aopOp (right, ic, FALSE, FALSE);
7511
7512 #ifdef BETTER_LITERAL_SHIFT
7513   /* if the shift count is known then do it
7514      as efficiently as possible */
7515   if (AOP_TYPE (right) == AOP_LIT)
7516     {
7517       if (genRightShiftLiteral (left, right, result, ic, 0))
7518       {
7519         return;
7520       }
7521     }
7522 #endif
7523
7524   /* shift count is unknown then we have to form
7525      a loop get the loop count in B : Note: we take
7526      only the lower order byte since shifting
7527      more that 32 bits make no sense anyway, ( the
7528      largest size of an object can be only 32 bits ) */
7529   
7530   if (AOP_TYPE (right) == AOP_LIT)
7531   {
7532       /* Really should be handled by genRightShiftLiteral,
7533        * but since I'm too lazy to fix that today, at least we can make
7534        * some small improvement.
7535        */
7536        emitcode("mov", "b,#0x%02x",
7537                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7538   }
7539   else
7540   {
7541         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7542         emitcode ("inc", "b");
7543   }
7544   freeAsmop (right, NULL, ic, TRUE);
7545   aopOp (left, ic, FALSE, FALSE);
7546   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7547
7548   /* now move the left to the result if they are not the
7549      same */
7550   if (!sameRegs (AOP (left), AOP (result)) &&
7551       AOP_SIZE (result) > 1)
7552     {
7553
7554       size = AOP_SIZE (result);
7555       offset = 0;
7556       _startLazyDPSEvaluation ();
7557       while (size--)
7558         {
7559           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7560           if (*l == '@' && IS_AOP_PREG (result))
7561             {
7562
7563               emitcode ("mov", "a,%s", l);
7564               aopPut (AOP (result), "a", offset);
7565             }
7566           else
7567             aopPut (AOP (result), l, offset);
7568           offset++;
7569         }
7570       _endLazyDPSEvaluation ();
7571     }
7572
7573   tlbl = newiTempLabel (NULL);
7574   tlbl1 = newiTempLabel (NULL);
7575   size = AOP_SIZE (result);
7576   offset = size - 1;
7577
7578   /* if it is only one byte then */
7579   if (size == 1)
7580     {
7581       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7582       MOVA (l);
7583       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7584       emitcode ("", "%05d$:", tlbl->key + 100);
7585       CLRC;
7586       emitcode ("rrc", "a");
7587       emitcode ("", "%05d$:", tlbl1->key + 100);
7588       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7589       aopPut (AOP (result), "a", 0);
7590       goto release;
7591     }
7592
7593   reAdjustPreg (AOP (result));
7594   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7595   emitcode ("", "%05d$:", tlbl->key + 100);
7596   CLRC;
7597   _startLazyDPSEvaluation ();
7598   while (size--)
7599     {
7600       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7601       MOVA (l);
7602       emitcode ("rrc", "a");
7603       aopPut (AOP (result), "a", offset--);
7604     }
7605   _endLazyDPSEvaluation ();
7606   reAdjustPreg (AOP (result));
7607
7608   emitcode ("", "%05d$:", tlbl1->key + 100);
7609   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7610
7611 release:
7612   freeAsmop (left, NULL, ic, TRUE);
7613   freeAsmop (result, NULL, ic, TRUE);
7614 }
7615
7616 /*-----------------------------------------------------------------*/
7617 /* genUnpackBits - generates code for unpacking bits               */
7618 /*-----------------------------------------------------------------*/
7619 static void
7620 genUnpackBits (operand * result, char *rname, int ptype)
7621 {
7622   int shCnt;
7623   int rlen = 0;
7624   sym_link *etype;
7625   int offset = 0;
7626
7627   D (emitcode (";", "genUnpackBits ");
7628     );
7629
7630   etype = getSpec (operandType (result));
7631
7632   /* read the first byte  */
7633   switch (ptype)
7634     {
7635
7636     case POINTER:
7637     case IPOINTER:
7638       emitcode ("mov", "a,@%s", rname);
7639       break;
7640
7641     case PPOINTER:
7642       emitcode ("movx", "a,@%s", rname);
7643       break;
7644
7645     case FPOINTER:
7646       emitcode ("movx", "a,@dptr");
7647       break;
7648
7649     case CPOINTER:
7650       emitcode ("clr", "a");
7651       emitcode ("movc", "a", "@a+dptr");
7652       break;
7653
7654     case GPOINTER:
7655       emitcode ("lcall", "__gptrget");
7656       break;
7657     }
7658
7659   /* if we have bitdisplacement then it fits   */
7660   /* into this byte completely or if length is */
7661   /* less than a byte                          */
7662   if ((shCnt = SPEC_BSTR (etype)) ||
7663       (SPEC_BLEN (etype) <= 8))
7664     {
7665
7666       /* shift right acc */
7667       AccRsh (shCnt);
7668
7669       emitcode ("anl", "a,#0x%02x",
7670                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7671       aopPut (AOP (result), "a", offset);
7672       return;
7673     }
7674
7675   /* bit field did not fit in a byte  */
7676   rlen = SPEC_BLEN (etype) - 8;
7677   aopPut (AOP (result), "a", offset++);
7678
7679   while (1)
7680     {
7681
7682       switch (ptype)
7683         {
7684         case POINTER:
7685         case IPOINTER:
7686           emitcode ("inc", "%s", rname);
7687           emitcode ("mov", "a,@%s", rname);
7688           break;
7689
7690         case PPOINTER:
7691           emitcode ("inc", "%s", rname);
7692           emitcode ("movx", "a,@%s", rname);
7693           break;
7694
7695         case FPOINTER:
7696           emitcode ("inc", "dptr");
7697           emitcode ("movx", "a,@dptr");
7698           break;
7699
7700         case CPOINTER:
7701           emitcode ("clr", "a");
7702           emitcode ("inc", "dptr");
7703           emitcode ("movc", "a", "@a+dptr");
7704           break;
7705
7706         case GPOINTER:
7707           emitcode ("inc", "dptr");
7708           emitcode ("lcall", "__gptrget");
7709           break;
7710         }
7711
7712       rlen -= 8;
7713       /* if we are done */
7714       if (rlen < 8)
7715         break;
7716
7717       aopPut (AOP (result), "a", offset++);
7718
7719     }
7720
7721   if (rlen)
7722     {
7723       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
7724       aopPut (AOP (result), "a", offset);
7725     }
7726
7727   return;
7728 }
7729
7730
7731 /*-----------------------------------------------------------------*/
7732 /* genDataPointerGet - generates code when ptr offset is known     */
7733 /*-----------------------------------------------------------------*/
7734 static void
7735 genDataPointerGet (operand * left,
7736                    operand * result,
7737                    iCode * ic)
7738 {
7739   char *l;
7740   char buffer[256];
7741   int size, offset = 0;
7742   aopOp (result, ic, TRUE, FALSE);
7743
7744   /* get the string representation of the name */
7745   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
7746   size = AOP_SIZE (result);
7747   _startLazyDPSEvaluation ();
7748   while (size--)
7749     {
7750       if (offset)
7751         sprintf (buffer, "(%s + %d)", l + 1, offset);
7752       else
7753         sprintf (buffer, "%s", l + 1);
7754       aopPut (AOP (result), buffer, offset++);
7755     }
7756   _endLazyDPSEvaluation ();
7757
7758   freeAsmop (left, NULL, ic, TRUE);
7759   freeAsmop (result, NULL, ic, TRUE);
7760 }
7761
7762 /*-----------------------------------------------------------------*/
7763 /* genNearPointerGet - emitcode for near pointer fetch             */
7764 /*-----------------------------------------------------------------*/
7765 static void
7766 genNearPointerGet (operand * left,
7767                    operand * result,
7768                    iCode * ic)
7769 {
7770   asmop *aop = NULL;
7771   regs *preg = NULL;
7772   char *rname;
7773   sym_link *rtype, *retype, *letype;
7774   sym_link *ltype = operandType (left);
7775   char buffer[80];
7776
7777   rtype = operandType (result);
7778   retype = getSpec (rtype);
7779   letype = getSpec (ltype);
7780
7781   aopOp (left, ic, FALSE, FALSE);
7782
7783   /* if left is rematerialisable and
7784      result is not bit variable type and
7785      the left is pointer to data space i.e
7786      lower 128 bytes of space */
7787   if (AOP_TYPE (left) == AOP_IMMD &&
7788       !IS_BITVAR (retype) &&
7789       !IS_BITVAR (letype) &&
7790       DCL_TYPE (ltype) == POINTER)
7791     {
7792       genDataPointerGet (left, result, ic);
7793       return;
7794     }
7795
7796   /* if the value is already in a pointer register
7797      then don't need anything more */
7798   if (!AOP_INPREG (AOP (left)))
7799     {
7800       /* otherwise get a free pointer register */
7801       aop = newAsmop (0);
7802       preg = getFreePtr (ic, &aop, FALSE);
7803       emitcode ("mov", "%s,%s",
7804                 preg->name,
7805                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7806       rname = preg->name;
7807     }
7808   else
7809     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7810
7811   freeAsmop (left, NULL, ic, TRUE);
7812   aopOp (result, ic, FALSE, FALSE);
7813
7814   /* if bitfield then unpack the bits */
7815   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7816     genUnpackBits (result, rname, POINTER);
7817   else
7818     {
7819       /* we have can just get the values */
7820       int size = AOP_SIZE (result);
7821       int offset = 0;
7822
7823       while (size--)
7824         {
7825           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7826             {
7827
7828               emitcode ("mov", "a,@%s", rname);
7829               aopPut (AOP (result), "a", offset);
7830             }
7831           else
7832             {
7833               sprintf (buffer, "@%s", rname);
7834               aopPut (AOP (result), buffer, offset);
7835             }
7836           offset++;
7837           if (size)
7838             emitcode ("inc", "%s", rname);
7839         }
7840     }
7841
7842   /* now some housekeeping stuff */
7843   if (aop)
7844     {
7845       /* we had to allocate for this iCode */
7846       freeAsmop (NULL, aop, ic, TRUE);
7847     }
7848   else
7849     {
7850       /* we did not allocate which means left
7851          already in a pointer register, then
7852          if size > 0 && this could be used again
7853          we have to point it back to where it
7854          belongs */
7855       if (AOP_SIZE (result) > 1 &&
7856           !OP_SYMBOL (left)->remat &&
7857           (OP_SYMBOL (left)->liveTo > ic->seq ||
7858            ic->depth))
7859         {
7860           int size = AOP_SIZE (result) - 1;
7861           while (size--)
7862             emitcode ("dec", "%s", rname);
7863         }
7864     }
7865
7866   /* done */
7867   freeAsmop (result, NULL, ic, TRUE);
7868
7869 }
7870
7871 /*-----------------------------------------------------------------*/
7872 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7873 /*-----------------------------------------------------------------*/
7874 static void
7875 genPagedPointerGet (operand * left,
7876                     operand * result,
7877                     iCode * ic)
7878 {
7879   asmop *aop = NULL;
7880   regs *preg = NULL;
7881   char *rname;
7882   sym_link *rtype, *retype, *letype;
7883
7884   rtype = operandType (result);
7885   retype = getSpec (rtype);
7886   letype = getSpec (operandType (left));
7887   aopOp (left, ic, FALSE, FALSE);
7888
7889   /* if the value is already in a pointer register
7890      then don't need anything more */
7891   if (!AOP_INPREG (AOP (left)))
7892     {
7893       /* otherwise get a free pointer register */
7894       aop = newAsmop (0);
7895       preg = getFreePtr (ic, &aop, FALSE);
7896       emitcode ("mov", "%s,%s",
7897                 preg->name,
7898                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
7899       rname = preg->name;
7900     }
7901   else
7902     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
7903
7904   freeAsmop (left, NULL, ic, TRUE);
7905   aopOp (result, ic, FALSE, FALSE);
7906
7907   /* if bitfield then unpack the bits */
7908   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7909     genUnpackBits (result, rname, PPOINTER);
7910   else
7911     {
7912       /* we have can just get the values */
7913       int size = AOP_SIZE (result);
7914       int offset = 0;
7915
7916       while (size--)
7917         {
7918
7919           emitcode ("movx", "a,@%s", rname);
7920           aopPut (AOP (result), "a", offset);
7921
7922           offset++;
7923
7924           if (size)
7925             emitcode ("inc", "%s", rname);
7926         }
7927     }
7928
7929   /* now some housekeeping stuff */
7930   if (aop)
7931     {
7932       /* we had to allocate for this iCode */
7933       freeAsmop (NULL, aop, ic, TRUE);
7934     }
7935   else
7936     {
7937       /* we did not allocate which means left
7938          already in a pointer register, then
7939          if size > 0 && this could be used again
7940          we have to point it back to where it
7941          belongs */
7942       if (AOP_SIZE (result) > 1 &&
7943           !OP_SYMBOL (left)->remat &&
7944           (OP_SYMBOL (left)->liveTo > ic->seq ||
7945            ic->depth))
7946         {
7947           int size = AOP_SIZE (result) - 1;
7948           while (size--)
7949             emitcode ("dec", "%s", rname);
7950         }
7951     }
7952
7953   /* done */
7954   freeAsmop (result, NULL, ic, TRUE);
7955
7956
7957 }
7958
7959 /*-----------------------------------------------------------------*/
7960 /* genFarPointerGet - gget value from far space                    */
7961 /*-----------------------------------------------------------------*/
7962 static void
7963 genFarPointerGet (operand * left,
7964                   operand * result, iCode * ic)
7965 {
7966   int size, offset;
7967   sym_link *retype = getSpec (operandType (result));
7968   sym_link *letype = getSpec (operandType (left));
7969   D (emitcode (";", "genFarPointerGet");
7970     );
7971
7972   aopOp (left, ic, FALSE, FALSE);
7973
7974   /* if the operand is already in dptr
7975      then we do nothing else we move the value to dptr */
7976   if (AOP_TYPE (left) != AOP_STR)
7977     {
7978       /* if this is remateriazable */
7979       if (AOP_TYPE (left) == AOP_IMMD)
7980         {
7981           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
7982         }
7983       else
7984         {
7985           /* we need to get it byte by byte */
7986           _startLazyDPSEvaluation ();
7987           if (AOP_TYPE (left) != AOP_DPTR)
7988             {
7989               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
7990               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
7991               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
7992             }
7993           else
7994             {
7995               /* We need to generate a load to DPTR indirect through DPTR. */
7996               D (emitcode (";", "genFarPointerGet -- indirection special case.");
7997                 );
7998               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
7999               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8000               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8001               emitcode ("pop", "dph");
8002               emitcode ("pop", "dpl");
8003             }
8004           _endLazyDPSEvaluation ();
8005         }
8006     }
8007   /* so dptr know contains the address */
8008   freeAsmop (left, NULL, ic, TRUE);
8009   aopOp (result, ic, FALSE, TRUE);
8010
8011   /* if bit then unpack */
8012   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8013     genUnpackBits (result, "dptr", FPOINTER);
8014   else
8015     {
8016       size = AOP_SIZE (result);
8017       offset = 0;
8018
8019       _startLazyDPSEvaluation ();
8020       while (size--)
8021         {
8022
8023           genSetDPTR (0);
8024           _flushLazyDPS ();
8025
8026           emitcode ("movx", "a,@dptr");
8027           if (size)
8028             emitcode ("inc", "dptr");
8029
8030           aopPut (AOP (result), "a", offset++);
8031         }
8032       _endLazyDPSEvaluation ();
8033     }
8034
8035   freeAsmop (result, NULL, ic, TRUE);
8036 }
8037
8038 /*-----------------------------------------------------------------*/
8039 /* emitcodePointerGet - gget value from code space                  */
8040 /*-----------------------------------------------------------------*/
8041 static void
8042 emitcodePointerGet (operand * left,
8043                     operand * result, iCode * ic)
8044 {
8045   int size, offset;
8046   sym_link *retype = getSpec (operandType (result));
8047
8048   aopOp (left, ic, FALSE, FALSE);
8049
8050   /* if the operand is already in dptr
8051      then we do nothing else we move the value to dptr */
8052   if (AOP_TYPE (left) != AOP_STR)
8053     {
8054       /* if this is remateriazable */
8055       if (AOP_TYPE (left) == AOP_IMMD)
8056         {
8057           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8058         }
8059       else
8060         {                       /* we need to get it byte by byte */
8061           _startLazyDPSEvaluation ();
8062           if (AOP_TYPE (left) != AOP_DPTR)
8063             {
8064               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8065               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8066               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8067             }
8068           else
8069             {
8070               /* We need to generate a load to DPTR indirect through DPTR. */
8071               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8072                 );
8073               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8074               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8075               emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8076               emitcode ("pop", "dph");
8077               emitcode ("pop", "dpl");
8078             }
8079           _endLazyDPSEvaluation ();
8080         }
8081     }
8082   /* so dptr know contains the address */
8083   freeAsmop (left, NULL, ic, TRUE);
8084   aopOp (result, ic, FALSE, TRUE);
8085
8086   /* if bit then unpack */
8087   if (IS_BITVAR (retype))
8088     genUnpackBits (result, "dptr", CPOINTER);
8089   else
8090     {
8091       size = AOP_SIZE (result);
8092       offset = 0;
8093
8094       _startLazyDPSEvaluation ();
8095       while (size--)
8096         {
8097           genSetDPTR (0);
8098           _flushLazyDPS ();
8099
8100           emitcode ("clr", "a");
8101           emitcode ("movc", "a,@a+dptr");
8102           if (size)
8103             emitcode ("inc", "dptr");
8104           aopPut (AOP (result), "a", offset++);
8105         }
8106       _endLazyDPSEvaluation ();
8107     }
8108
8109   freeAsmop (result, NULL, ic, TRUE);
8110 }
8111
8112 /*-----------------------------------------------------------------*/
8113 /* genGenPointerGet - gget value from generic pointer space        */
8114 /*-----------------------------------------------------------------*/
8115 static void
8116 genGenPointerGet (operand * left,
8117                   operand * result, iCode * ic)
8118 {
8119   int size, offset;
8120   sym_link *retype = getSpec (operandType (result));
8121   sym_link *letype = getSpec (operandType (left));
8122
8123   D (emitcode (";", "genGenPointerGet "); );
8124
8125   aopOp (left, ic, FALSE, TRUE);
8126
8127   /* if the operand is already in dptr
8128      then we do nothing else we move the value to dptr */
8129   if (AOP_TYPE (left) != AOP_STR)
8130     {
8131       /* if this is remateriazable */
8132       if (AOP_TYPE (left) == AOP_IMMD)
8133         {
8134           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8135           emitcode ("mov", "b,#%d", pointerCode (retype));
8136         }
8137       else
8138         {                       /* we need to get it byte by byte */
8139           _startLazyDPSEvaluation ();
8140           if (AOP(left)->type==AOP_DPTR2) {
8141             char *l;
8142             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8143             genSetDPTR(0);
8144             _flushLazyDPS();
8145             emitcode ("mov", "dpl,%s ;jwk lazy genGenPointerGet", l);
8146             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8147             genSetDPTR(0);
8148             _flushLazyDPS();
8149             emitcode ("mov", "dph,%s ;jwk lazy genGenPointerGet", l);
8150             l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8151             genSetDPTR(0);
8152             _flushLazyDPS();
8153             emitcode ("mov", "dpx,%s ;jwk lazy genGenPointerGet", l);
8154             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8155           } else {
8156             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8157             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8158             emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8159             emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8160           }
8161           _endLazyDPSEvaluation ();
8162         }
8163     }
8164   /* so dptr know contains the address */
8165   freeAsmop (left, NULL, ic, TRUE);
8166   aopOp (result, ic, FALSE, TRUE);
8167
8168   /* if bit then unpack */
8169   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8170     genUnpackBits (result, "dptr", GPOINTER);
8171   else
8172     {
8173       size = AOP_SIZE (result);
8174       offset = 0;
8175
8176       while (size--)
8177         {
8178           emitcode ("lcall", "__gptrget");
8179           aopPut (AOP (result), "a", offset++);
8180           if (size)
8181             emitcode ("inc", "dptr");
8182         }
8183     }
8184
8185   freeAsmop (result, NULL, ic, TRUE);
8186 }
8187
8188 /*-----------------------------------------------------------------*/
8189 /* genPointerGet - generate code for pointer get                   */
8190 /*-----------------------------------------------------------------*/
8191 static void
8192 genPointerGet (iCode * ic)
8193 {
8194   operand *left, *result;
8195   sym_link *type, *etype;
8196   int p_type;
8197
8198   D (emitcode (";", "genPointerGet ");
8199     );
8200
8201   left = IC_LEFT (ic);
8202   result = IC_RESULT (ic);
8203
8204   /* depending on the type of pointer we need to
8205      move it to the correct pointer register */
8206   type = operandType (left);
8207   etype = getSpec (type);
8208   /* if left is of type of pointer then it is simple */
8209   if (IS_PTR (type) && !IS_FUNC (type->next))
8210     p_type = DCL_TYPE (type);
8211   else
8212     {
8213       /* we have to go by the storage class */
8214       p_type = PTR_TYPE (SPEC_OCLS (etype));
8215     }
8216
8217   /* now that we have the pointer type we assign
8218      the pointer values */
8219   switch (p_type)
8220     {
8221
8222     case POINTER:
8223     case IPOINTER:
8224       genNearPointerGet (left, result, ic);
8225       break;
8226
8227     case PPOINTER:
8228       genPagedPointerGet (left, result, ic);
8229       break;
8230
8231     case FPOINTER:
8232       genFarPointerGet (left, result, ic);
8233       break;
8234
8235     case CPOINTER:
8236       emitcodePointerGet (left, result, ic);
8237       break;
8238
8239     case GPOINTER:
8240       genGenPointerGet (left, result, ic);
8241       break;
8242     }
8243
8244 }
8245
8246 /*-----------------------------------------------------------------*/
8247 /* genPackBits - generates code for packed bit storage             */
8248 /*-----------------------------------------------------------------*/
8249 static void
8250 genPackBits (sym_link * etype,
8251              operand * right,
8252              char *rname, int p_type)
8253 {
8254   int shCount = 0;
8255   int offset = 0;
8256   int rLen = 0;
8257   int blen, bstr;
8258   char *l;
8259
8260   blen = SPEC_BLEN (etype);
8261   bstr = SPEC_BSTR (etype);
8262
8263   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8264   MOVA (l);
8265
8266   /* if the bit lenth is less than or    */
8267   /* it exactly fits a byte then         */
8268   if (SPEC_BLEN (etype) <= 8)
8269     {
8270       shCount = SPEC_BSTR (etype);
8271
8272       /* shift left acc */
8273       AccLsh (shCount);
8274
8275       if (SPEC_BLEN (etype) < 8)
8276         {                       /* if smaller than a byte */
8277
8278
8279           switch (p_type)
8280             {
8281             case POINTER:
8282               emitcode ("mov", "b,a");
8283               emitcode ("mov", "a,@%s", rname);
8284               break;
8285
8286             case FPOINTER:
8287               emitcode ("mov", "b,a");
8288               emitcode ("movx", "a,@dptr");
8289               break;
8290
8291             case GPOINTER:
8292               emitcode ("push", "b");
8293               emitcode ("push", "acc");
8294               emitcode ("lcall", "__gptrget");
8295               emitcode ("pop", "b");
8296               break;
8297             }
8298
8299           emitcode ("anl", "a,#0x%02x", (unsigned char)
8300                     ((unsigned char) (0xFF << (blen + bstr)) |
8301                      (unsigned char) (0xFF >> (8 - bstr))));
8302           emitcode ("orl", "a,b");
8303           if (p_type == GPOINTER)
8304             emitcode ("pop", "b");
8305         }
8306     }
8307
8308   switch (p_type)
8309     {
8310     case POINTER:
8311       emitcode ("mov", "@%s,a", rname);
8312       break;
8313
8314     case FPOINTER:
8315       emitcode ("movx", "@dptr,a");
8316       break;
8317
8318     case GPOINTER:
8319       emitcode ("lcall", "__gptrput");
8320       break;
8321     }
8322
8323   /* if we r done */
8324   if (SPEC_BLEN (etype) <= 8)
8325     return;
8326
8327   emitcode ("inc", "%s", rname);
8328   rLen = SPEC_BLEN (etype);
8329
8330   /* now generate for lengths greater than one byte */
8331   while (1)
8332     {
8333
8334       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8335
8336       rLen -= 8;
8337       if (rLen < 8)
8338         break;
8339
8340       switch (p_type)
8341         {
8342         case POINTER:
8343           if (*l == '@')
8344             {
8345               MOVA (l);
8346               emitcode ("mov", "@%s,a", rname);
8347             }
8348           else
8349             emitcode ("mov", "@%s,%s", rname, l);
8350           break;
8351
8352         case FPOINTER:
8353           MOVA (l);
8354           emitcode ("movx", "@dptr,a");
8355           break;
8356
8357         case GPOINTER:
8358           MOVA (l);
8359           emitcode ("lcall", "__gptrput");
8360           break;
8361         }
8362       emitcode ("inc", "%s", rname);
8363     }
8364
8365   MOVA (l);
8366
8367   /* last last was not complete */
8368   if (rLen)
8369     {
8370       /* save the byte & read byte */
8371       switch (p_type)
8372         {
8373         case POINTER:
8374           emitcode ("mov", "b,a");
8375           emitcode ("mov", "a,@%s", rname);
8376           break;
8377
8378         case FPOINTER:
8379           emitcode ("mov", "b,a");
8380           emitcode ("movx", "a,@dptr");
8381           break;
8382
8383         case GPOINTER:
8384           emitcode ("push", "b");
8385           emitcode ("push", "acc");
8386           emitcode ("lcall", "__gptrget");
8387           emitcode ("pop", "b");
8388           break;
8389         }
8390
8391       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8392       emitcode ("orl", "a,b");
8393     }
8394
8395   if (p_type == GPOINTER)
8396     emitcode ("pop", "b");
8397
8398   switch (p_type)
8399     {
8400
8401     case POINTER:
8402       emitcode ("mov", "@%s,a", rname);
8403       break;
8404
8405     case FPOINTER:
8406       emitcode ("movx", "@dptr,a");
8407       break;
8408
8409     case GPOINTER:
8410       emitcode ("lcall", "__gptrput");
8411       break;
8412     }
8413 }
8414 /*-----------------------------------------------------------------*/
8415 /* genDataPointerSet - remat pointer to data space                 */
8416 /*-----------------------------------------------------------------*/
8417 static void
8418 genDataPointerSet (operand * right,
8419                    operand * result,
8420                    iCode * ic)
8421 {
8422   int size, offset = 0;
8423   char *l, buffer[256];
8424
8425   aopOp (right, ic, FALSE, FALSE);
8426
8427   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8428   size = AOP_SIZE (right);
8429   while (size--)
8430     {
8431       if (offset)
8432         sprintf (buffer, "(%s + %d)", l + 1, offset);
8433       else
8434         sprintf (buffer, "%s", l + 1);
8435       emitcode ("mov", "%s,%s", buffer,
8436                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8437     }
8438
8439   freeAsmop (right, NULL, ic, TRUE);
8440   freeAsmop (result, NULL, ic, TRUE);
8441 }
8442
8443 /*-----------------------------------------------------------------*/
8444 /* genNearPointerSet - emitcode for near pointer put                */
8445 /*-----------------------------------------------------------------*/
8446 static void
8447 genNearPointerSet (operand * right,
8448                    operand * result,
8449                    iCode * ic)
8450 {
8451   asmop *aop = NULL;
8452   regs *preg = NULL;
8453   char *rname, *l;
8454   sym_link *retype, *letype;
8455   sym_link *ptype = operandType (result);
8456
8457   retype = getSpec (operandType (right));
8458   letype = getSpec (ptype);
8459
8460   aopOp (result, ic, FALSE, FALSE);
8461
8462   /* if the result is rematerializable &
8463      in data space & not a bit variable */
8464   if (AOP_TYPE (result) == AOP_IMMD &&
8465       DCL_TYPE (ptype) == POINTER &&
8466       !IS_BITVAR (retype) &&
8467       !IS_BITVAR (letype))
8468     {
8469       genDataPointerSet (right, result, ic);
8470       return;
8471     }
8472
8473   /* if the value is already in a pointer register
8474      then don't need anything more */
8475   if (!AOP_INPREG (AOP (result)))
8476     {
8477       /* otherwise get a free pointer register */
8478       aop = newAsmop (0);
8479       preg = getFreePtr (ic, &aop, FALSE);
8480       emitcode ("mov", "%s,%s",
8481                 preg->name,
8482                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8483       rname = preg->name;
8484     }
8485   else
8486     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8487
8488   freeAsmop (result, NULL, ic, TRUE);
8489   aopOp (right, ic, FALSE, FALSE);
8490
8491   /* if bitfield then unpack the bits */
8492   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8493     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8494   else
8495     {
8496       /* we have can just get the values */
8497       int size = AOP_SIZE (right);
8498       int offset = 0;
8499
8500       while (size--)
8501         {
8502           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8503           if (*l == '@')
8504             {
8505               MOVA (l);
8506               emitcode ("mov", "@%s,a", rname);
8507             }
8508           else
8509             emitcode ("mov", "@%s,%s", rname, l);
8510           if (size)
8511             emitcode ("inc", "%s", rname);
8512           offset++;
8513         }
8514     }
8515
8516   /* now some housekeeping stuff */
8517   if (aop)
8518     {
8519       /* we had to allocate for this iCode */
8520       freeAsmop (NULL, aop, ic, TRUE);
8521     }
8522   else
8523     {
8524       /* we did not allocate which means left
8525          already in a pointer register, then
8526          if size > 0 && this could be used again
8527          we have to point it back to where it
8528          belongs */
8529       if (AOP_SIZE (right) > 1 &&
8530           !OP_SYMBOL (result)->remat &&
8531           (OP_SYMBOL (result)->liveTo > ic->seq ||
8532            ic->depth))
8533         {
8534           int size = AOP_SIZE (right) - 1;
8535           while (size--)
8536             emitcode ("dec", "%s", rname);
8537         }
8538     }
8539
8540   /* done */
8541   freeAsmop (right, NULL, ic, TRUE);
8542
8543
8544 }
8545
8546 /*-----------------------------------------------------------------*/
8547 /* genPagedPointerSet - emitcode for Paged pointer put             */
8548 /*-----------------------------------------------------------------*/
8549 static void
8550 genPagedPointerSet (operand * right,
8551                     operand * result,
8552                     iCode * ic)
8553 {
8554   asmop *aop = NULL;
8555   regs *preg = NULL;
8556   char *rname, *l;
8557   sym_link *retype, *letype;
8558
8559   retype = getSpec (operandType (right));
8560   letype = getSpec (operandType (result));
8561
8562   aopOp (result, ic, FALSE, FALSE);
8563
8564   /* if the value is already in a pointer register
8565      then don't need anything more */
8566   if (!AOP_INPREG (AOP (result)))
8567     {
8568       /* otherwise get a free pointer register */
8569       aop = newAsmop (0);
8570       preg = getFreePtr (ic, &aop, FALSE);
8571       emitcode ("mov", "%s,%s",
8572                 preg->name,
8573                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8574       rname = preg->name;
8575     }
8576   else
8577     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8578
8579   freeAsmop (result, NULL, ic, TRUE);
8580   aopOp (right, ic, FALSE, FALSE);
8581
8582   /* if bitfield then unpack the bits */
8583   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8584     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8585   else
8586     {
8587       /* we have can just get the values */
8588       int size = AOP_SIZE (right);
8589       int offset = 0;
8590
8591       while (size--)
8592         {
8593           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8594
8595           MOVA (l);
8596           emitcode ("movx", "@%s,a", rname);
8597
8598           if (size)
8599             emitcode ("inc", "%s", rname);
8600
8601           offset++;
8602         }
8603     }
8604
8605   /* now some housekeeping stuff */
8606   if (aop)
8607     {
8608       /* we had to allocate for this iCode */
8609       freeAsmop (NULL, aop, ic, TRUE);
8610     }
8611   else
8612     {
8613       /* we did not allocate which means left
8614          already in a pointer register, then
8615          if size > 0 && this could be used again
8616          we have to point it back to where it
8617          belongs */
8618       if (AOP_SIZE (right) > 1 &&
8619           !OP_SYMBOL (result)->remat &&
8620           (OP_SYMBOL (result)->liveTo > ic->seq ||
8621            ic->depth))
8622         {
8623           int size = AOP_SIZE (right) - 1;
8624           while (size--)
8625             emitcode ("dec", "%s", rname);
8626         }
8627     }
8628
8629   /* done */
8630   freeAsmop (right, NULL, ic, TRUE);
8631
8632
8633 }
8634
8635 /*-----------------------------------------------------------------*/
8636 /* genFarPointerSet - set value from far space                     */
8637 /*-----------------------------------------------------------------*/
8638 static void
8639 genFarPointerSet (operand * right,
8640                   operand * result, iCode * ic)
8641 {
8642   int size, offset;
8643   sym_link *retype = getSpec (operandType (right));
8644   sym_link *letype = getSpec (operandType (result));
8645
8646   aopOp (result, ic, FALSE, FALSE);
8647
8648   /* if the operand is already in dptr
8649      then we do nothing else we move the value to dptr */
8650   if (AOP_TYPE (result) != AOP_STR)
8651     {
8652       /* if this is remateriazable */
8653       if (AOP_TYPE (result) == AOP_IMMD)
8654         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8655       else
8656         {
8657           /* we need to get it byte by byte */
8658           _startLazyDPSEvaluation ();
8659           if (AOP_TYPE (result) != AOP_DPTR)
8660             {
8661               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8662               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8663               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8664             }
8665           else
8666             {
8667               /* We need to generate a load to DPTR indirect through DPTR. */
8668               D (emitcode (";", "genFarPointerSet -- indirection special case.");
8669                 );
8670               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
8671               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
8672               emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8673               emitcode ("pop", "dph");
8674               emitcode ("pop", "dpl");
8675             }
8676           _endLazyDPSEvaluation ();
8677         }
8678     }
8679   /* so dptr know contains the address */
8680   freeAsmop (result, NULL, ic, TRUE);
8681   aopOp (right, ic, FALSE, TRUE);
8682
8683   /* if bit then unpack */
8684   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8685     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8686   else
8687     {
8688       size = AOP_SIZE (right);
8689       offset = 0;
8690
8691       _startLazyDPSEvaluation ();
8692       while (size--)
8693         {
8694           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8695           MOVA (l);
8696
8697           genSetDPTR (0);
8698           _flushLazyDPS ();
8699
8700           emitcode ("movx", "@dptr,a");
8701           if (size)
8702             emitcode ("inc", "dptr");
8703         }
8704       _endLazyDPSEvaluation ();
8705     }
8706
8707   freeAsmop (right, NULL, ic, TRUE);
8708 }
8709
8710 /*-----------------------------------------------------------------*/
8711 /* genGenPointerSet - set value from generic pointer space         */
8712 /*-----------------------------------------------------------------*/
8713 static void
8714 genGenPointerSet (operand * right,
8715                   operand * result, iCode * ic)
8716 {
8717   int size, offset;
8718   sym_link *retype = getSpec (operandType (right));
8719   sym_link *letype = getSpec (operandType (result));
8720
8721   aopOp (result, ic, FALSE, TRUE);
8722
8723   /* if the operand is already in dptr
8724      then we do nothing else we move the value to dptr */
8725   if (AOP_TYPE (result) != AOP_STR)
8726     {
8727       _startLazyDPSEvaluation ();
8728       /* if this is remateriazable */
8729       if (AOP_TYPE (result) == AOP_IMMD)
8730         {
8731           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8732           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
8733         }
8734       else
8735         {                       /* we need to get it byte by byte */
8736           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
8737           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
8738           emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
8739           emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
8740         }
8741       _endLazyDPSEvaluation ();
8742     }
8743   /* so dptr know contains the address */
8744   freeAsmop (result, NULL, ic, TRUE);
8745   aopOp (right, ic, FALSE, TRUE);
8746
8747   /* if bit then unpack */
8748   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8749     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8750   else
8751     {
8752       size = AOP_SIZE (right);
8753       offset = 0;
8754
8755       _startLazyDPSEvaluation ();
8756       while (size--)
8757         {
8758           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8759           MOVA (l);
8760
8761           genSetDPTR (0);
8762           _flushLazyDPS ();
8763
8764           emitcode ("lcall", "__gptrput");
8765           if (size)
8766             emitcode ("inc", "dptr");
8767         }
8768       _endLazyDPSEvaluation ();
8769     }
8770
8771   freeAsmop (right, NULL, ic, TRUE);
8772 }
8773
8774 /*-----------------------------------------------------------------*/
8775 /* genPointerSet - stores the value into a pointer location        */
8776 /*-----------------------------------------------------------------*/
8777 static void
8778 genPointerSet (iCode * ic)
8779 {
8780   operand *right, *result;
8781   sym_link *type, *etype;
8782   int p_type;
8783
8784   D (emitcode (";", "genPointerSet ");
8785     );
8786
8787   right = IC_RIGHT (ic);
8788   result = IC_RESULT (ic);
8789
8790   /* depending on the type of pointer we need to
8791      move it to the correct pointer register */
8792   type = operandType (result);
8793   etype = getSpec (type);
8794   /* if left is of type of pointer then it is simple */
8795   if (IS_PTR (type) && !IS_FUNC (type->next))
8796     {
8797       p_type = DCL_TYPE (type);
8798     }
8799   else
8800     {
8801       /* we have to go by the storage class */
8802       p_type = PTR_TYPE (SPEC_OCLS (etype));
8803     }
8804
8805   /* now that we have the pointer type we assign
8806      the pointer values */
8807   switch (p_type)
8808     {
8809
8810     case POINTER:
8811     case IPOINTER:
8812       genNearPointerSet (right, result, ic);
8813       break;
8814
8815     case PPOINTER:
8816       genPagedPointerSet (right, result, ic);
8817       break;
8818
8819     case FPOINTER:
8820       genFarPointerSet (right, result, ic);
8821       break;
8822
8823     case GPOINTER:
8824       genGenPointerSet (right, result, ic);
8825       break;
8826     }
8827
8828 }
8829
8830 /*-----------------------------------------------------------------*/
8831 /* genIfx - generate code for Ifx statement                        */
8832 /*-----------------------------------------------------------------*/
8833 static void
8834 genIfx (iCode * ic, iCode * popIc)
8835 {
8836   operand *cond = IC_COND (ic);
8837   int isbit = 0;
8838
8839   D (emitcode (";", "genIfx "););
8840
8841   aopOp (cond, ic, FALSE, FALSE);
8842
8843   /* get the value into acc */
8844   if (AOP_TYPE (cond) != AOP_CRY)
8845     toBoolean (cond);
8846   else
8847     isbit = 1;
8848   /* the result is now in the accumulator */
8849   freeAsmop (cond, NULL, ic, TRUE);
8850
8851   /* if there was something to be popped then do it */
8852   if (popIc)
8853     genIpop (popIc);
8854
8855   /* if the condition is  a bit variable */
8856   if (isbit && IS_ITEMP (cond) &&
8857       SPIL_LOC (cond))
8858     genIfxJump (ic, SPIL_LOC (cond)->rname);
8859   else if (isbit && !IS_ITEMP (cond))
8860     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8861   else
8862     genIfxJump (ic, "a");
8863
8864   ic->generated = 1;
8865 }
8866
8867 /*-----------------------------------------------------------------*/
8868 /* genAddrOf - generates code for address of                       */
8869 /*-----------------------------------------------------------------*/
8870 static void
8871 genAddrOf (iCode * ic)
8872 {
8873   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8874   int size, offset;
8875
8876   D (emitcode (";", "genAddrOf ");
8877     );
8878
8879   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
8880
8881   /* if the operand is on the stack then we
8882      need to get the stack offset of this
8883      variable */
8884   if (sym->onStack)
8885     {
8886       /* if it has an offset then we need to compute
8887          it */
8888       if (sym->stack)
8889         {
8890           emitcode ("mov", "a,_bp");
8891           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8892           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8893         }
8894       else
8895         {
8896           /* we can just move _bp */
8897           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8898         }
8899       /* fill the result with zero */
8900       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8901
8902
8903       if (options.stack10bit && size < (FPTRSIZE - 1))
8904         {
8905           fprintf (stderr,
8906                    "*** warning: pointer to stack var truncated.\n");
8907         }
8908
8909       offset = 1;
8910       while (size--)
8911         {
8912           /* Yuck! */
8913           if (options.stack10bit && offset == 2)
8914             {
8915               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
8916             }
8917           else
8918             {
8919               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8920             }
8921         }
8922
8923       goto release;
8924     }
8925
8926   /* object not on stack then we need the name */
8927   size = AOP_SIZE (IC_RESULT (ic));
8928   offset = 0;
8929
8930   while (size--)
8931     {
8932       char s[SDCC_NAME_MAX];
8933       if (offset)
8934         sprintf (s, "#(%s >> %d)",
8935                  sym->rname,
8936                  offset * 8);
8937       else
8938         sprintf (s, "#%s", sym->rname);
8939       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8940     }
8941
8942 release:
8943   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8944
8945 }
8946
8947 /*-----------------------------------------------------------------*/
8948 /* genFarFarAssign - assignment when both are in far space         */
8949 /*-----------------------------------------------------------------*/
8950 static void
8951 genFarFarAssign (operand * result, operand * right, iCode * ic)
8952 {
8953   int size = AOP_SIZE (right);
8954   int offset = 0;
8955   symbol *rSym = NULL;
8956
8957   if (size == 1)
8958   {
8959       /* quick & easy case. */
8960       D(emitcode(";","genFarFarAssign (1 byte case)"););      
8961       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
8962       freeAsmop (right, NULL, ic, FALSE);
8963       /* now assign DPTR to result */
8964       _G.accInUse++;
8965       aopOp(result, ic, FALSE, FALSE);
8966       _G.accInUse--;
8967       aopPut(AOP(result), "a", 0);
8968       freeAsmop(result, NULL, ic, FALSE);
8969       return;
8970   }
8971   
8972   /* See if we've got an underlying symbol to abuse. */
8973   if (IS_SYMOP(result) && OP_SYMBOL(result))
8974   {
8975       if (IS_TRUE_SYMOP(result))
8976       {
8977           rSym = OP_SYMBOL(result);
8978       }
8979       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
8980       {
8981           rSym = OP_SYMBOL(result)->usl.spillLoc;
8982       }
8983   }
8984              
8985   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
8986   {
8987       /* We can use the '390 auto-toggle feature to good effect here. */
8988       
8989       D(emitcode(";","genFarFarAssign ('390 auto-toggle fun)"););
8990       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
8991       emitcode ("mov", "dptr,#%s", rSym->rname); 
8992       /* DP2 = result, DP1 = right, DP1 is current. */
8993       while (size)
8994       {
8995           emitcode("movx", "a,@dptr");
8996           emitcode("movx", "@dptr,a");
8997           if (--size)
8998           {
8999                emitcode("inc", "dptr");
9000                emitcode("inc", "dptr");
9001           }
9002       }
9003       emitcode("mov", "dps, #0");
9004       freeAsmop (right, NULL, ic, FALSE);
9005   }
9006   else
9007   {
9008       D (emitcode (";", "genFarFarAssign"););
9009       aopOp (result, ic, TRUE, TRUE);
9010
9011       _startLazyDPSEvaluation ();
9012       
9013       while (size--)
9014         {
9015           aopPut (AOP (result),
9016                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9017           offset++;
9018         }
9019       _endLazyDPSEvaluation ();
9020       freeAsmop (result, NULL, ic, FALSE);
9021       freeAsmop (right, NULL, ic, FALSE);
9022   }
9023 }
9024
9025 /*-----------------------------------------------------------------*/
9026 /* genAssign - generate code for assignment                        */
9027 /*-----------------------------------------------------------------*/
9028 static void
9029 genAssign (iCode * ic)
9030 {
9031   operand *result, *right;
9032   int size, offset;
9033   unsigned long lit = 0L;
9034
9035   D (emitcode (";", "genAssign ");
9036     );
9037
9038   result = IC_RESULT (ic);
9039   right = IC_RIGHT (ic);
9040
9041   /* if they are the same */
9042   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9043     return;
9044
9045   aopOp (right, ic, FALSE, FALSE);
9046
9047   emitcode (";", "genAssign: resultIsFar = %s",
9048             isOperandInFarSpace (result) ?
9049             "TRUE" : "FALSE");
9050
9051   /* special case both in far space */
9052   if ((AOP_TYPE (right) == AOP_DPTR ||
9053        AOP_TYPE (right) == AOP_DPTR2) &&
9054   /* IS_TRUE_SYMOP(result)       && */
9055       isOperandInFarSpace (result))
9056     {
9057       genFarFarAssign (result, right, ic);
9058       return;
9059     }
9060
9061   aopOp (result, ic, TRUE, FALSE);
9062
9063   /* if they are the same registers */
9064   if (sameRegs (AOP (right), AOP (result)))
9065     goto release;
9066
9067   /* if the result is a bit */
9068   if (AOP_TYPE (result) == AOP_CRY)
9069     {
9070
9071       /* if the right size is a literal then
9072          we know what the value is */
9073       if (AOP_TYPE (right) == AOP_LIT)
9074         {
9075           if (((int) operandLitValue (right)))
9076             aopPut (AOP (result), one, 0);
9077           else
9078             aopPut (AOP (result), zero, 0);
9079           goto release;
9080         }
9081
9082       /* the right is also a bit variable */
9083       if (AOP_TYPE (right) == AOP_CRY)
9084         {
9085           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9086           aopPut (AOP (result), "c", 0);
9087           goto release;
9088         }
9089
9090       /* we need to or */
9091       toBoolean (right);
9092       aopPut (AOP (result), "a", 0);
9093       goto release;
9094     }
9095
9096   /* bit variables done */
9097   /* general case */
9098   size = AOP_SIZE (result);
9099   offset = 0;
9100   if (AOP_TYPE (right) == AOP_LIT)
9101     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9102
9103   if ((size > 1) &&
9104       (AOP_TYPE (result) != AOP_REG) &&
9105       (AOP_TYPE (right) == AOP_LIT) &&
9106       !IS_FLOAT (operandType (right)))
9107     {
9108       _startLazyDPSEvaluation ();
9109       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9110         {
9111           aopPut (AOP (result),
9112                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9113                   offset);
9114           offset++;
9115           size--;
9116         }
9117       /* And now fill the rest with zeros. */
9118       if (size)
9119         {
9120           emitcode ("clr", "a");
9121         }
9122       while (size--)
9123         {
9124           aopPut (AOP (result), "a", offset++);
9125         }
9126       _endLazyDPSEvaluation ();
9127     }
9128   else
9129     {
9130       _startLazyDPSEvaluation ();
9131       while (size--)
9132         {
9133           aopPut (AOP (result),
9134                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9135                   offset);
9136           offset++;
9137         }
9138       _endLazyDPSEvaluation ();
9139     }
9140
9141 release:
9142   freeAsmop (right, NULL, ic, FALSE);
9143   freeAsmop (result, NULL, ic, TRUE);
9144 }
9145
9146 /*-----------------------------------------------------------------*/
9147 /* genJumpTab - generates code for jump table                      */
9148 /*-----------------------------------------------------------------*/
9149 static void
9150 genJumpTab (iCode * ic)
9151 {
9152   symbol *jtab;
9153   char *l;
9154
9155   D (emitcode (";", "genJumpTab ");
9156     );
9157
9158   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9159   /* get the condition into accumulator */
9160   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9161   MOVA (l);
9162   /* multiply by four! */
9163   emitcode ("add", "a,acc");
9164   emitcode ("add", "a,acc");
9165   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9166
9167   jtab = newiTempLabel (NULL);
9168   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9169   emitcode ("jmp", "@a+dptr");
9170   emitcode ("", "%05d$:", jtab->key + 100);
9171   /* now generate the jump labels */
9172   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9173        jtab = setNextItem (IC_JTLABELS (ic)))
9174     emitcode ("ljmp", "%05d$", jtab->key + 100);
9175
9176 }
9177
9178 /*-----------------------------------------------------------------*/
9179 /* genCast - gen code for casting                                  */
9180 /*-----------------------------------------------------------------*/
9181 static void
9182 genCast (iCode * ic)
9183 {
9184   operand *result = IC_RESULT (ic);
9185   sym_link *ctype = operandType (IC_LEFT (ic));
9186   sym_link *rtype = operandType (IC_RIGHT (ic));
9187   operand *right = IC_RIGHT (ic);
9188   int size, offset;
9189
9190   D (emitcode (";", "genCast ");
9191     );
9192
9193   /* if they are equivalent then do nothing */
9194   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9195     return;
9196
9197   aopOp (right, ic, FALSE, FALSE);
9198   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9199
9200   /* if the result is a bit */
9201   if (AOP_TYPE (result) == AOP_CRY)
9202     {
9203       /* if the right size is a literal then
9204          we know what the value is */
9205       if (AOP_TYPE (right) == AOP_LIT)
9206         {
9207           if (((int) operandLitValue (right)))
9208             aopPut (AOP (result), one, 0);
9209           else
9210             aopPut (AOP (result), zero, 0);
9211
9212           goto release;
9213         }
9214
9215       /* the right is also a bit variable */
9216       if (AOP_TYPE (right) == AOP_CRY)
9217         {
9218           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9219           aopPut (AOP (result), "c", 0);
9220           goto release;
9221         }
9222
9223       /* we need to or */
9224       toBoolean (right);
9225       aopPut (AOP (result), "a", 0);
9226       goto release;
9227     }
9228
9229   /* if they are the same size : or less */
9230   if (AOP_SIZE (result) <= AOP_SIZE (right))
9231     {
9232
9233       /* if they are in the same place */
9234       if (sameRegs (AOP (right), AOP (result)))
9235         goto release;
9236
9237       /* if they in different places then copy */
9238       size = AOP_SIZE (result);
9239       offset = 0;
9240       _startLazyDPSEvaluation ();
9241       while (size--)
9242         {
9243           aopPut (AOP (result),
9244                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9245                   offset);
9246           offset++;
9247         }
9248       _endLazyDPSEvaluation ();
9249       goto release;
9250     }
9251
9252
9253   /* if the result is of type pointer */
9254   if (IS_PTR (ctype))
9255     {
9256
9257       int p_type;
9258       sym_link *type = operandType (right);
9259
9260       /* pointer to generic pointer */
9261       if (IS_GENPTR (ctype))
9262         {
9263           char *l = zero;
9264
9265           if (IS_PTR (type))
9266             {
9267               p_type = DCL_TYPE (type);
9268             }
9269           else
9270             {
9271 #if OLD_CAST_BEHAVIOR
9272               /* KV: we are converting a non-pointer type to
9273                * a generic pointer. This (ifdef'd out) code
9274                * says that the resulting generic pointer
9275                * should have the same class as the storage
9276                * location of the non-pointer variable.
9277                *
9278                * For example, converting an int (which happens
9279                * to be stored in DATA space) to a pointer results
9280                * in a DATA generic pointer; if the original int
9281                * in XDATA space, so will be the resulting pointer.
9282                *
9283                * I don't like that behavior, and thus this change:
9284                * all such conversions will be forced to XDATA and
9285                * throw a warning. If you want some non-XDATA
9286                * type, or you want to suppress the warning, you
9287                * must go through an intermediate cast, like so:
9288                *
9289                * char _generic *gp = (char _xdata *)(intVar);
9290                */
9291               sym_link *etype = getSpec (type);
9292
9293               /* we have to go by the storage class */
9294               if (SPEC_OCLS (etype) != generic)
9295                 {
9296                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9297                 }
9298               else
9299 #endif
9300                 {
9301                   /* Converting unknown class (i.e. register variable)
9302                    * to generic pointer. This is not good, but
9303                    * we'll make a guess (and throw a warning).
9304                    */
9305                   p_type = FPOINTER;
9306                   werror (W_INT_TO_GEN_PTR_CAST);
9307                 }
9308             }
9309
9310           /* the first two bytes are known */
9311           size = GPTRSIZE - 1;
9312           offset = 0;
9313           _startLazyDPSEvaluation ();
9314           while (size--)
9315             {
9316               aopPut (AOP (result),
9317                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9318                       offset);
9319               offset++;
9320             }
9321           _endLazyDPSEvaluation ();
9322
9323           /* the last byte depending on type */
9324           switch (p_type)
9325             {
9326             case IPOINTER:
9327             case POINTER:
9328               l = zero;
9329               break;
9330             case FPOINTER:
9331               l = one;
9332               break;
9333             case CPOINTER:
9334               l = "#0x02";
9335               break;
9336             case PPOINTER:
9337               l = "#0x03";
9338               break;
9339
9340             default:
9341               /* this should never happen */
9342               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9343                       "got unknown pointer type");
9344               exit (1);
9345             }
9346           aopPut (AOP (result), l, GPTRSIZE - 1);
9347           goto release;
9348         }
9349
9350       /* just copy the pointers */
9351       size = AOP_SIZE (result);
9352       offset = 0;
9353       _startLazyDPSEvaluation ();
9354       while (size--)
9355         {
9356           aopPut (AOP (result),
9357                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9358                   offset);
9359           offset++;
9360         }
9361       _endLazyDPSEvaluation ();
9362       goto release;
9363     }
9364
9365   /* so we now know that the size of destination is greater
9366      than the size of the source */
9367   /* we move to result for the size of source */
9368   size = AOP_SIZE (right);
9369   offset = 0;
9370   _startLazyDPSEvaluation ();
9371   while (size--)
9372     {
9373       aopPut (AOP (result),
9374               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9375               offset);
9376       offset++;
9377     }
9378   _endLazyDPSEvaluation ();
9379
9380   /* now depending on the sign of the source && destination */
9381   size = AOP_SIZE (result) - AOP_SIZE (right);
9382   /* if unsigned or not an integral type */
9383   /* also, if the source is a bit, we don't need to sign extend, because
9384    * it can't possibly have set the sign bit.
9385    */
9386   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9387     {
9388       while (size--)
9389         {
9390           aopPut (AOP (result), zero, offset++);
9391         }
9392     }
9393   else
9394     {
9395       /* we need to extend the sign :{ */
9396       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9397                         FALSE, FALSE, TRUE);
9398       MOVA (l);
9399       emitcode ("rlc", "a");
9400       emitcode ("subb", "a,acc");
9401       while (size--)
9402         aopPut (AOP (result), "a", offset++);
9403     }
9404
9405   /* we are done hurray !!!! */
9406
9407 release:
9408   freeAsmop (right, NULL, ic, TRUE);
9409   freeAsmop (result, NULL, ic, TRUE);
9410
9411 }
9412
9413 /*-----------------------------------------------------------------*/
9414 /* genDjnz - generate decrement & jump if not zero instrucion      */
9415 /*-----------------------------------------------------------------*/
9416 static int
9417 genDjnz (iCode * ic, iCode * ifx)
9418 {
9419   symbol *lbl, *lbl1;
9420   if (!ifx)
9421     return 0;
9422
9423   /* if the if condition has a false label
9424      then we cannot save */
9425   if (IC_FALSE (ifx))
9426     return 0;
9427
9428   /* if the minus is not of the form
9429      a = a - 1 */
9430   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9431       !IS_OP_LITERAL (IC_RIGHT (ic)))
9432     return 0;
9433
9434   if (operandLitValue (IC_RIGHT (ic)) != 1)
9435     return 0;
9436
9437   /* if the size of this greater than one then no
9438      saving */
9439   if (getSize (operandType (IC_RESULT (ic))) > 1)
9440     return 0;
9441
9442   /* otherwise we can save BIG */
9443   D(emitcode(";", "genDjnz"););
9444
9445   lbl = newiTempLabel (NULL);
9446   lbl1 = newiTempLabel (NULL);
9447
9448   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9449
9450   if (AOP_NEEDSACC(IC_RESULT(ic)))
9451   {
9452       /* If the result is accessed indirectly via
9453        * the accumulator, we must explicitly write
9454        * it back after the decrement.
9455        */
9456       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9457       
9458       if (strcmp(rByte, "a"))
9459       {
9460            /* Something is hopelessly wrong */
9461            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9462                    __FILE__, __LINE__);
9463            /* We can just give up; the generated code will be inefficient,
9464             * but what the hey.
9465             */
9466            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9467            return 0;
9468       }
9469       emitcode ("dec", "%s", rByte);
9470       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9471       emitcode ("jnz", "%05d$", lbl->key + 100);
9472   }
9473   else if (IS_AOP_PREG (IC_RESULT (ic)))
9474     {
9475       emitcode ("dec", "%s",
9476                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9477       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9478       emitcode ("jnz", "%05d$", lbl->key + 100);
9479     }
9480   else
9481     {
9482       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9483                 lbl->key + 100);
9484     }
9485   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9486   emitcode ("", "%05d$:", lbl->key + 100);
9487   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9488   emitcode ("", "%05d$:", lbl1->key + 100);
9489
9490   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9491   ifx->generated = 1;
9492   return 1;
9493 }
9494
9495 /*-----------------------------------------------------------------*/
9496 /* genReceive - generate code for a receive iCode                  */
9497 /*-----------------------------------------------------------------*/
9498 static void
9499 genReceive (iCode * ic)
9500 {
9501
9502   D (emitcode (";", "genReceive ");
9503     );
9504
9505   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9506       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9507        IS_TRUE_SYMOP (IC_RESULT (ic))))
9508     {
9509       int size = getSize (operandType (IC_RESULT (ic)));
9510       int offset = fReturnSizeDS390 - size;
9511       while (size--)
9512         {
9513           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9514                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9515           offset++;
9516         }
9517       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9518       size = AOP_SIZE (IC_RESULT (ic));
9519       offset = 0;
9520       while (size--)
9521         {
9522           emitcode ("pop", "acc");
9523           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
9524         }
9525
9526     }
9527   else
9528     {
9529       _G.accInUse++;
9530       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9531       _G.accInUse--;
9532       assignResultValue (IC_RESULT (ic));
9533     }
9534
9535   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9536 }
9537
9538 /*-----------------------------------------------------------------*/
9539 /* gen390Code - generate code for Dallas 390 based controllers     */
9540 /*-----------------------------------------------------------------*/
9541 void
9542 gen390Code (iCode * lic)
9543 {
9544   iCode *ic;
9545   int cln = 0;
9546
9547   lineHead = lineCurr = NULL;
9548
9549 #if 0
9550   //REMOVE ME!!!
9551   /* print the allocation information */
9552   if (allocInfo)
9553     printAllocInfo (currFunc, codeOutFile);
9554 #endif
9555   /* if debug information required */
9556   if (options.debug && currFunc)
9557     {
9558       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
9559       _G.debugLine = 1;
9560       if (IS_STATIC (currFunc->etype))
9561         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9562       else
9563         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9564       _G.debugLine = 0;
9565     }
9566   /* stack pointer name */
9567   if (options.useXstack)
9568     spname = "_spx";
9569   else
9570     spname = "sp";
9571
9572
9573   for (ic = lic; ic; ic = ic->next)
9574     {
9575
9576       if (cln != ic->lineno)
9577         {
9578           if (options.debug)
9579             {
9580               _G.debugLine = 1;
9581               emitcode ("", "C$%s$%d$%d$%d ==.",
9582                         FileBaseName (ic->filename), ic->lineno,
9583                         ic->level, ic->block);
9584               _G.debugLine = 0;
9585             }
9586           emitcode (";", "%s %d", ic->filename, ic->lineno);
9587           cln = ic->lineno;
9588         }
9589       /* if the result is marked as
9590          spilt and rematerializable or code for
9591          this has already been generated then
9592          do nothing */
9593       if (resultRemat (ic) || ic->generated)
9594         continue;
9595
9596       /* depending on the operation */
9597       switch (ic->op)
9598         {
9599         case '!':
9600           genNot (ic);
9601           break;
9602
9603         case '~':
9604           genCpl (ic);
9605           break;
9606
9607         case UNARYMINUS:
9608           genUminus (ic);
9609           break;
9610
9611         case IPUSH:
9612           genIpush (ic);
9613           break;
9614
9615         case IPOP:
9616           /* IPOP happens only when trying to restore a
9617              spilt live range, if there is an ifx statement
9618              following this pop then the if statement might
9619              be using some of the registers being popped which
9620              would destory the contents of the register so
9621              we need to check for this condition and handle it */
9622           if (ic->next &&
9623               ic->next->op == IFX &&
9624               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9625             genIfx (ic->next, ic);
9626           else
9627             genIpop (ic);
9628           break;
9629
9630         case CALL:
9631           genCall (ic);
9632           break;
9633
9634         case PCALL:
9635           genPcall (ic);
9636           break;
9637
9638         case FUNCTION:
9639           genFunction (ic);
9640           break;
9641
9642         case ENDFUNCTION:
9643           genEndFunction (ic);
9644           break;
9645
9646         case RETURN:
9647           genRet (ic);
9648           break;
9649
9650         case LABEL:
9651           genLabel (ic);
9652           break;
9653
9654         case GOTO:
9655           genGoto (ic);
9656           break;
9657
9658         case '+':
9659           genPlus (ic);
9660           break;
9661
9662         case '-':
9663           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9664             genMinus (ic);
9665           break;
9666
9667         case '*':
9668           genMult (ic);
9669           break;
9670
9671         case '/':
9672           genDiv (ic);
9673           break;
9674
9675         case '%':
9676           genMod (ic);
9677           break;
9678
9679         case '>':
9680           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9681           break;
9682
9683         case '<':
9684           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9685           break;
9686
9687         case LE_OP:
9688         case GE_OP:
9689         case NE_OP:
9690
9691           /* note these two are xlated by algebraic equivalence
9692              during parsing SDCC.y */
9693           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9694                   "got '>=' or '<=' shouldn't have come here");
9695           break;
9696
9697         case EQ_OP:
9698           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9699           break;
9700
9701         case AND_OP:
9702           genAndOp (ic);
9703           break;
9704
9705         case OR_OP:
9706           genOrOp (ic);
9707           break;
9708
9709         case '^':
9710           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9711           break;
9712
9713         case '|':
9714           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9715           break;
9716
9717         case BITWISEAND:
9718           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9719           break;
9720
9721         case INLINEASM:
9722           genInline (ic);
9723           break;
9724
9725         case RRC:
9726           genRRC (ic);
9727           break;
9728
9729         case RLC:
9730           genRLC (ic);
9731           break;
9732
9733         case GETHBIT:
9734           genGetHbit (ic);
9735           break;
9736
9737         case LEFT_OP:
9738           genLeftShift (ic);
9739           break;
9740
9741         case RIGHT_OP:
9742           genRightShift (ic);
9743           break;
9744
9745         case GET_VALUE_AT_ADDRESS:
9746           genPointerGet (ic);
9747           break;
9748
9749         case '=':
9750           if (POINTER_SET (ic))
9751             genPointerSet (ic);
9752           else
9753             genAssign (ic);
9754           break;
9755
9756         case IFX:
9757           genIfx (ic, NULL);
9758           break;
9759
9760         case ADDRESS_OF:
9761           genAddrOf (ic);
9762           break;
9763
9764         case JUMPTABLE:
9765           genJumpTab (ic);
9766           break;
9767
9768         case CAST:
9769           genCast (ic);
9770           break;
9771
9772         case RECEIVE:
9773           genReceive (ic);
9774           break;
9775
9776         case SEND:
9777           addSet (&_G.sendSet, ic);
9778           break;
9779
9780         default:
9781           ic = ic;
9782         }
9783     }
9784
9785
9786   /* now we are ready to call the
9787      peep hole optimizer */
9788   if (!options.nopeep)
9789     peepHole (&lineHead);
9790
9791   /* now do the actual printing */
9792   printLine (lineHead, codeOutFile);
9793   return;
9794 }