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