added seperate segments for initialized data
[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   DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
8
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <common.h>
34 #include "ralloc.h"
35 #include "gen.h"
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #define BETTER_LITERAL_SHIFT
57
58 char *aopLiteral (value * val, int offset);
59
60 /* this is the down and dirty file with all kinds of
61    kludgy & hacky stuff. This is what it is all about
62    CODE GENERATION for a specific MCU . some of the
63    routines may be reusable, will have to see */
64
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
67 static char *spname;
68
69 #define D(x) x
70
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73
74 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
81 {"a", "b"};
82
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short bInUse;
91     short inLine;
92     short debugLine;
93     short nRegsSaved;
94     set *sendSet;
95   }
96 _G;
97
98 static void saveRBank (int, iCode *, bool);
99
100 #define RESULTONSTACK(x) \
101                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
102                          IC_RESULT(x)->aop->type == AOP_STK )
103
104 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
105 #define MOVA(x) { char *_mova_tmp = strdup(x); \
106                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107                  { \
108                     emitcode("mov","a,%s",_mova_tmp); \
109                  } \
110                  free(_mova_tmp); \
111                 }
112 #define CLRC    emitcode("clr","c")
113 #define SETC    emitcode("setb","c")
114
115 // A scratch register which will be used to hold
116 // result bytes from operands in far space via DPTR2.
117 #define DP2_RESULT_REG  "ap"
118
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
121
122 static unsigned char SLMask[] =
123 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
124  0xE0, 0xC0, 0x80, 0x00};
125 static unsigned char SRMask[] =
126 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
127  0x07, 0x03, 0x01, 0x00};
128
129 #define LSB     0
130 #define MSB16   1
131 #define MSB24   2
132 #define MSB32   3
133
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple    */
136 /*-----------------------------------------------------------------*/
137 static void
138 emitcode (char *inst, char *fmt,...)
139 {
140   va_list ap;
141   char lb[INITIAL_INLINEASM];
142   char *lbp = lb;
143
144   va_start (ap, fmt);
145
146   if (inst && *inst)
147     {
148       if (fmt && *fmt)
149         sprintf (lb, "%s\t", inst);
150       else
151         sprintf (lb, "%s", inst);
152       tvsprintf (lb + (strlen (lb)), fmt, ap);
153     }
154   else
155     tvsprintf (lb, fmt, ap);
156
157   while (isspace (*lbp))
158     lbp++;
159
160   if (lbp && *lbp)
161     lineCurr = (lineCurr ?
162                 connectLine (lineCurr, newLineNode (lb)) :
163                 (lineHead = newLineNode (lb)));
164   lineCurr->isInline = _G.inLine;
165   lineCurr->isDebug = _G.debugLine;
166   va_end (ap);
167 }
168
169 /*-----------------------------------------------------------------*/
170 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
171 /*-----------------------------------------------------------------*/
172 static regs *
173 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 {
175   bool r0iu = FALSE, r1iu = FALSE;
176   bool r0ou = FALSE, r1ou = FALSE;
177
178   /* the logic: if r0 & r1 used in the instruction
179      then we are in trouble otherwise */
180
181   /* first check if r0 & r1 are used by this
182      instruction, in which case we are in trouble */
183   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
184   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
185   if (r0iu && r1iu) {
186       goto endOfWorld;
187     }
188
189   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
190   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191
192   /* if no usage of r0 then return it */
193   if (!r0iu && !r0ou)
194     {
195       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
196       (*aopp)->type = AOP_R0;
197
198       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
199     }
200
201   /* if no usage of r1 then return it */
202   if (!r1iu && !r1ou)
203     {
204       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
205       (*aopp)->type = AOP_R1;
206
207       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
208     }
209
210   /* now we know they both have usage */
211   /* if r0 not used in this instruction */
212   if (!r0iu)
213     {
214       /* push it if not already pushed */
215       if (!_G.r0Pushed)
216         {
217           emitcode ("push", "%s",
218                     ds390_regWithIdx (R0_IDX)->dname);
219           _G.r0Pushed++;
220         }
221
222       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
223       (*aopp)->type = AOP_R0;
224
225       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
226     }
227
228   /* if r1 not used then */
229
230   if (!r1iu)
231     {
232       /* push it if not already pushed */
233       if (!_G.r1Pushed)
234         {
235           emitcode ("push", "%s",
236                     ds390_regWithIdx (R1_IDX)->dname);
237           _G.r1Pushed++;
238         }
239
240       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
241       (*aopp)->type = AOP_R1;
242       return ds390_regWithIdx (R1_IDX);
243     }
244
245 endOfWorld:
246   /* I said end of world but not quite end of world yet */
247   /* if this is a result then we can push it on the stack */
248   if (result)
249     {
250       (*aopp)->type = AOP_STK;
251       return NULL;
252     }
253
254   /* other wise this is true end of the world */
255   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
256           "getFreePtr should never reach here");
257   exit (1);
258 }
259
260 /*-----------------------------------------------------------------*/
261 /* newAsmop - creates a new asmOp                                  */
262 /*-----------------------------------------------------------------*/
263 static asmop *
264 newAsmop (short type)
265 {
266   asmop *aop;
267
268   aop = Safe_calloc (1, sizeof (asmop));
269   aop->type = type;
270   return aop;
271 }
272
273 static int _currentDPS;         /* Current processor DPS. */
274 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
275 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
276
277 /*-----------------------------------------------------------------*/
278 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
279 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
280 /* alternate DPTR (DPL1/DPH1/DPX1).          */
281 /*-----------------------------------------------------------------*/
282 static void
283 genSetDPTR (int n)
284 {
285
286   /* If we are doing lazy evaluation, simply note the desired
287    * change, but don't emit any code yet.
288    */
289   if (_lazyDPS)
290     {
291       _desiredDPS = n;
292       return;
293     }
294
295   if (!n)
296     {
297       emitcode ("mov", "dps, #0x00");
298     }
299   else
300     {
301       TR_DPTR("#1");
302       emitcode ("mov", "dps, #0x01");
303     }
304 }
305
306 /*-----------------------------------------------------------------*/
307 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /*                   */
309 /* Any code that operates on DPTR (NB: not on the individual     */
310 /* components, like DPH) *must* call _flushLazyDPS() before using  */
311 /* DPTR within a lazy DPS evaluation block.        */
312 /*                   */
313 /* Note that aopPut and aopGet already contain the proper calls to */
314 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
315 /* DPS evaluation block.             */
316 /*                   */
317 /* Also, _flushLazyDPS must be called before any flow control      */
318 /* operations that could potentially branch out of the block.    */
319 /*                         */
320 /* Lazy DPS evaluation is simply an optimization (though an      */
321 /* important one), so if in doubt, leave it out.       */
322 /*-----------------------------------------------------------------*/
323 static void
324 _startLazyDPSEvaluation (void)
325 {
326   _currentDPS = 0;
327   _desiredDPS = 0;
328 #ifdef BETTER_LITERAL_SHIFT  
329   _lazyDPS++;
330 #else
331   _lazyDPS = 1;
332 #endif  
333 }
334
335 /*-----------------------------------------------------------------*/
336 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
337 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /* block.                */
339 /*-----------------------------------------------------------------*/
340 static void
341 _flushLazyDPS (void)
342 {
343   if (!_lazyDPS)
344     {
345       /* nothing to do. */
346       return;
347     }
348
349   if (_desiredDPS != _currentDPS)
350     {
351       if (_desiredDPS)
352         {
353           emitcode ("inc", "dps");
354         }
355       else
356         {
357           emitcode ("dec", "dps");
358         }
359       _currentDPS = _desiredDPS;
360     }
361 }
362
363 /*-----------------------------------------------------------------*/
364 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
365 /*                   */
366 /* Forces us back to the safe state (standard DPTR selected).    */
367 /*-----------------------------------------------------------------*/
368 static void
369 _endLazyDPSEvaluation (void)
370 {
371 #ifdef BETTER_LITERAL_SHIFT  
372   _lazyDPS--;
373 #else
374   _lazyDPS = 0;
375 #endif    
376   if (!_lazyDPS)
377   {
378     if (_currentDPS)
379     {
380       genSetDPTR (0);
381       _flushLazyDPS ();
382     }
383     _currentDPS = 0;
384     _desiredDPS = 0;
385   }
386 }
387
388
389
390 /*-----------------------------------------------------------------*/
391 /* pointerCode - returns the code for a pointer type               */
392 /*-----------------------------------------------------------------*/
393 static int
394 pointerCode (sym_link * etype)
395 {
396
397   return PTR_TYPE (SPEC_OCLS (etype));
398
399 }
400
401 /*-----------------------------------------------------------------*/
402 /* aopForSym - for a true symbol                                   */
403 /*-----------------------------------------------------------------*/
404 static asmop *
405 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
406 {
407   asmop *aop;
408   memmap *space = SPEC_OCLS (sym->etype);
409
410   /* if already has one */
411   if (sym->aop)
412     return sym->aop;
413
414   /* assign depending on the storage class */
415   /* if it is on the stack or indirectly addressable */
416   /* space we need to assign either r0 or r1 to it   */
417   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418     {
419       sym->aop = aop = newAsmop (0);
420       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
421       aop->size = getSize (sym->type);
422
423       /* now assign the address of the variable to
424          the pointer register */
425       if (aop->type != AOP_STK)
426         {
427
428           if (sym->onStack)
429             {
430               if (_G.accInUse)
431                 emitcode ("push", "acc");
432
433               if (_G.bInUse)
434                 emitcode ("push", "b");
435
436               emitcode ("mov", "a,_bp");
437               emitcode ("add", "a,#!constbyte",
438                         ((sym->stack < 0) ?
439                          ((char) (sym->stack - _G.nRegsSaved)) :
440                          ((char) sym->stack)) & 0xff);
441               emitcode ("mov", "%s,a",
442                         aop->aopu.aop_ptr->name);
443
444               if (_G.bInUse)
445                 emitcode ("pop", "b");
446
447               if (_G.accInUse)
448                 emitcode ("pop", "acc");
449             }
450           else
451             emitcode ("mov", "%s,#%s",
452                       aop->aopu.aop_ptr->name,
453                       sym->rname);
454           aop->paged = space->paged;
455         }
456       else
457         aop->aopu.aop_stk = sym->stack;
458       return aop;
459     }
460
461   if (sym->onStack && options.stack10bit)
462     {
463       /* It's on the 10 bit stack, which is located in
464        * far data space.
465        */
466
467       if (_G.accInUse)
468         emitcode ("push", "acc");
469
470       if (_G.bInUse)
471         emitcode ("push", "b");
472
473       emitcode ("mov", "a,_bpx");
474       emitcode ("clr","c");
475       emitcode ("subb", "a,#!constbyte",
476                 -((sym->stack < 0) ?
477                   ((short) (sym->stack - _G.nRegsSaved)) :
478                   ((short) sym->stack)) & 0xff);
479       emitcode ("mov","b,a");
480       emitcode ("mov","a,_bpx+1");
481       emitcode ("subb","a,#!constbyte",(-((sym->stack < 0) ?
482                                      ((short) (sym->stack - _G.nRegsSaved)) :
483                                      ((short) sym->stack)) >> 8) & 0xff);
484       if (useDP2) {
485           if (options.model == MODEL_FLAT24)
486               emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
487           TR_DPTR("#2");
488           emitcode ("mov", "dph1,a");
489           emitcode ("mov", "dpl1,b");
490       } else {
491           if (options.model == MODEL_FLAT24)
492               emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
493           emitcode ("mov", "dph,a");
494           emitcode ("mov", "dpl,b");
495       }
496
497       if (_G.bInUse)
498         emitcode ("pop", "b");
499
500       if (_G.accInUse)
501         emitcode ("pop", "acc");
502
503       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
504       aop->size = getSize (sym->type);
505       return aop;
506     }
507
508   /* if in bit space */
509   if (IN_BITSPACE (space))
510     {
511       sym->aop = aop = newAsmop (AOP_CRY);
512       aop->aopu.aop_dir = sym->rname;
513       aop->size = getSize (sym->type);
514       return aop;
515     }
516   /* if it is in direct space */
517   if (IN_DIRSPACE (space))
518     {
519       sym->aop = aop = newAsmop (AOP_DIR);
520       aop->aopu.aop_dir = sym->rname;
521       aop->size = getSize (sym->type);
522       return aop;
523     }
524
525   /* special case for a function */
526   if (IS_FUNC (sym->type))
527     {
528       sym->aop = aop = newAsmop (AOP_IMMD);
529       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
530       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
531       aop->size = FPTRSIZE;
532       return aop;
533     }
534
535   /* only remaining is far space */
536   /* in which case DPTR gets the address */
537   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
538   if (useDP2)
539     {
540       genSetDPTR (1);
541       _flushLazyDPS ();
542       emitcode ("mov", "dptr,#%s", sym->rname);
543       genSetDPTR (0);
544     }
545   else
546     {
547       emitcode ("mov", "dptr,#%s", sym->rname);
548     }
549   aop->size = getSize (sym->type);
550
551   /* if it is in code space */
552   if (IN_CODESPACE (space))
553     aop->code = 1;
554
555   return aop;
556 }
557
558 /*-----------------------------------------------------------------*/
559 /* aopForRemat - rematerialzes an object                           */
560 /*-----------------------------------------------------------------*/
561 static asmop *
562 aopForRemat (symbol * sym)
563 {
564   iCode *ic = sym->rematiCode;
565   asmop *aop = newAsmop (AOP_IMMD);
566   int ptr_type =0;
567   int val = 0;
568
569   for (;;)
570     {
571       if (ic->op == '+')
572         val += (int) operandLitValue (IC_RIGHT (ic));
573       else if (ic->op == '-')
574         val -= (int) operandLitValue (IC_RIGHT (ic));
575       else if (IS_CAST_ICODE(ic)) {
576               sym_link *from_type = operandType(IC_RIGHT(ic));
577               aop->aopu.aop_immd.from_cast_remat = 1;
578               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
579               ptr_type = DCL_TYPE(from_type);
580               if (ptr_type == IPOINTER) {
581                 // bug #481053
582                 ptr_type = POINTER;
583               }
584               continue ;
585       } else break;
586       
587       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
588     }
589
590   if (val)
591     sprintf (buffer, "(%s %c 0x%04x)",
592              OP_SYMBOL (IC_LEFT (ic))->rname,
593              val >= 0 ? '+' : '-',
594              abs (val) & 0xffff);
595   else
596     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
597
598   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
599   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
600   /* set immd2 field if required */
601   if (aop->aopu.aop_immd.from_cast_remat) {
602           tsprintf(buffer,"#!constbyte",ptr_type);
603           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
604           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
605   }
606
607   return aop;
608 }
609
610 /*-----------------------------------------------------------------*/
611 /* regsInCommon - two operands have some registers in common       */
612 /*-----------------------------------------------------------------*/
613 static bool
614 regsInCommon (operand * op1, operand * op2)
615 {
616   symbol *sym1, *sym2;
617   int i;
618
619   /* if they have registers in common */
620   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
621     return FALSE;
622
623   sym1 = OP_SYMBOL (op1);
624   sym2 = OP_SYMBOL (op2);
625
626   if (sym1->nRegs == 0 || sym2->nRegs == 0)
627     return FALSE;
628
629   for (i = 0; i < sym1->nRegs; i++)
630     {
631       int j;
632       if (!sym1->regs[i])
633         continue;
634
635       for (j = 0; j < sym2->nRegs; j++)
636         {
637           if (!sym2->regs[j])
638             continue;
639
640           if (sym2->regs[j] == sym1->regs[i])
641             return TRUE;
642         }
643     }
644
645   return FALSE;
646 }
647
648 /*-----------------------------------------------------------------*/
649 /* operandsEqu - equivalent                                        */
650 /*-----------------------------------------------------------------*/
651 static bool
652 operandsEqu (operand * op1, operand * op2)
653 {
654   symbol *sym1, *sym2;
655
656   /* if they not symbols */
657   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
658     return FALSE;
659
660   sym1 = OP_SYMBOL (op1);
661   sym2 = OP_SYMBOL (op2);
662
663   /* if both are itemps & one is spilt
664      and the other is not then false */
665   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
666       sym1->isspilt != sym2->isspilt)
667     return FALSE;
668
669   /* if they are the same */
670   if (sym1 == sym2)
671     return TRUE;
672
673   if (strcmp (sym1->rname, sym2->rname) == 0)
674     return TRUE;
675
676
677   /* if left is a tmp & right is not */
678   if (IS_ITEMP (op1) &&
679       !IS_ITEMP (op2) &&
680       sym1->isspilt &&
681       (sym1->usl.spillLoc == sym2))
682     return TRUE;
683
684   if (IS_ITEMP (op2) &&
685       !IS_ITEMP (op1) &&
686       sym2->isspilt &&
687       sym1->level > 0 &&
688       (sym2->usl.spillLoc == sym1))
689     return TRUE;
690
691   return FALSE;
692 }
693
694 /*-----------------------------------------------------------------*/
695 /* sameRegs - two asmops have the same registers                   */
696 /*-----------------------------------------------------------------*/
697 static bool
698 sameRegs (asmop * aop1, asmop * aop2)
699 {
700   int i;
701
702   if (aop1 == aop2)
703     {
704       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
705         {
706           return FALSE;
707         }
708       return TRUE;
709     }
710
711   if (aop1->type != AOP_REG ||
712       aop2->type != AOP_REG)
713     return FALSE;
714
715   if (aop1->size != aop2->size)
716     return FALSE;
717
718   for (i = 0; i < aop1->size; i++)
719     if (aop1->aopu.aop_reg[i] !=
720         aop2->aopu.aop_reg[i])
721       return FALSE;
722
723   return TRUE;
724 }
725
726 /*-----------------------------------------------------------------*/
727 /* aopOp - allocates an asmop for an operand  :                    */
728 /*-----------------------------------------------------------------*/
729 static void
730 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
731 {
732   asmop *aop;
733   symbol *sym;
734   int i;
735
736   if (!op)
737     return;
738
739   /* if this a literal */
740   if (IS_OP_LITERAL (op))
741     {
742       op->aop = aop = newAsmop (AOP_LIT);
743       aop->aopu.aop_lit = op->operand.valOperand;
744       aop->size = getSize (operandType (op));
745       return;
746     }
747
748   /* if already has a asmop then continue */
749   if (op->aop)
750     return;
751
752   /* if the underlying symbol has a aop */
753   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
754     {
755       op->aop = OP_SYMBOL (op)->aop;
756       return;
757     }
758
759   /* if this is a true symbol */
760   if (IS_TRUE_SYMOP (op))
761     {
762       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
763       return;
764     }
765
766   /* this is a temporary : this has
767      only four choices :
768      a) register
769      b) spillocation
770      c) rematerialize
771      d) conditional
772      e) can be a return use only */
773
774   sym = OP_SYMBOL (op);
775
776
777   /* if the type is a conditional */
778   if (sym->regType == REG_CND)
779     {
780       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
781       aop->size = 0;
782       return;
783     }
784
785   /* if it is spilt then two situations
786      a) is rematerialize
787      b) has a spill location */
788   if (sym->isspilt || sym->nRegs == 0)
789     {
790
791       /* rematerialize it NOW */
792       if (sym->remat)
793         {
794           sym->aop = op->aop = aop =
795             aopForRemat (sym);
796           aop->size = getSize (sym->type);
797           return;
798         }
799
800       if (sym->accuse)
801         {
802           int i;
803           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
804           aop->size = getSize (sym->type);
805           for (i = 0; i < 2; i++)
806             aop->aopu.aop_str[i] = accUse[i];
807           return;
808         }
809
810       if (sym->ruonly)
811         {
812           int i;
813
814           if (useDP2)
815             {
816               /* a AOP_STR uses DPTR, but DPTR is already in use;
817                * we're just hosed.
818                */
819               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
820             }
821
822           aop = op->aop = sym->aop = newAsmop (AOP_STR);
823           aop->size = getSize (sym->type);
824           for (i = 0; i < (int) fReturnSizeDS390; i++)
825             aop->aopu.aop_str[i] = fReturn[i];
826           return;
827         }
828
829       /* else spill location  */
830       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
831           /* force a new aop if sizes differ */
832           sym->usl.spillLoc->aop = NULL;
833       }
834       sym->aop = op->aop = aop =
835         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
836       aop->size = getSize (sym->type);
837       return;
838     }
839
840   /* must be in a register */
841   sym->aop = op->aop = aop = newAsmop (AOP_REG);
842   aop->size = sym->nRegs;
843   for (i = 0; i < sym->nRegs; i++)
844     aop->aopu.aop_reg[i] = sym->regs[i];
845 }
846
847 /*-----------------------------------------------------------------*/
848 /* freeAsmop - free up the asmop given to an operand               */
849 /*----------------------------------------------------------------*/
850 static void
851 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
852 {
853   asmop *aop;
854
855   if (!op)
856     aop = aaop;
857   else
858     aop = op->aop;
859
860   if (!aop)
861     return;
862
863   if (aop->freed)
864     goto dealloc;
865
866   aop->freed = 1;
867
868   /* depending on the asmop type only three cases need work AOP_RO
869      , AOP_R1 && AOP_STK */
870   switch (aop->type)
871     {
872     case AOP_R0:
873       if (_G.r0Pushed)
874         {
875           if (pop)
876             {
877               emitcode ("pop", "ar0");
878               _G.r0Pushed--;
879             }
880         }
881       bitVectUnSetBit (ic->rUsed, R0_IDX);
882       break;
883
884     case AOP_R1:
885       if (_G.r1Pushed)
886         {
887           if (pop)
888             {
889               emitcode ("pop", "ar1");
890               _G.r1Pushed--;
891             }
892         }
893       bitVectUnSetBit (ic->rUsed, R1_IDX);
894       break;
895
896     case AOP_STK:
897       {
898         int sz = aop->size;
899         int stk = aop->aopu.aop_stk + aop->size;
900         bitVectUnSetBit (ic->rUsed, R0_IDX);
901         bitVectUnSetBit (ic->rUsed, R1_IDX);
902
903         getFreePtr (ic, &aop, FALSE);
904
905         if (options.stack10bit)
906           {
907             /* I'm not sure what to do here yet... */
908             /* #STUB */
909             fprintf (stderr,
910                      "*** Warning: probably generating bad code for "
911                      "10 bit stack mode.\n");
912           }
913
914         if (stk)
915           {
916             emitcode ("mov", "a,_bp");
917             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
918             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
919           }
920         else
921           {
922             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
923           }
924
925         while (sz--)
926           {
927             emitcode ("pop", "acc");
928             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
929             if (!sz)
930               break;
931             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
932           }
933         op->aop = aop;
934         freeAsmop (op, NULL, ic, TRUE);
935         if (_G.r0Pushed)
936           {
937             emitcode ("pop", "ar0");
938             _G.r0Pushed--;
939           }
940
941         if (_G.r1Pushed)
942           {
943             emitcode ("pop", "ar1");
944             _G.r1Pushed--;
945           }
946       }
947     }
948
949 dealloc:
950   /* all other cases just dealloc */
951   if (op)
952     {
953       op->aop = NULL;
954       if (IS_SYMOP (op))
955         {
956           OP_SYMBOL (op)->aop = NULL;
957           /* if the symbol has a spill */
958           if (SPIL_LOC (op))
959             SPIL_LOC (op)->aop = NULL;
960         }
961     }
962 }
963
964 /*------------------------------------------------------------------*/
965 /* aopGet - for fetching value of the aop                           */
966 /*                    */
967 /* Set canClobberACC if you are sure it is OK to clobber the value  */
968 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
969 /* just less efficient.               */
970 /*------------------------------------------------------------------*/
971
972 static char *
973 aopGet (asmop * aop,
974         int offset,
975         bool bit16,
976         bool dname,
977         bool canClobberACC)
978 {
979   char *s = buffer;
980   char *rs;
981
982   /* offset is greater than
983      size then zero */
984   if (offset > (aop->size - 1) &&
985       aop->type != AOP_LIT)
986     return zero;
987
988   /* depending on type */
989   switch (aop->type)
990     {
991
992     case AOP_R0:
993     case AOP_R1:
994       /* if we need to increment it */
995       while (offset > aop->coff)
996         {
997           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
998           aop->coff++;
999         }
1000
1001       while (offset < aop->coff)
1002         {
1003           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1004           aop->coff--;
1005         }
1006
1007       aop->coff = offset;
1008       if (aop->paged)
1009         {
1010           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1011           return (dname ? "acc" : "a");
1012         }
1013       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1014       rs = Safe_calloc (1, strlen (s) + 1);
1015       strcpy (rs, s);
1016       return rs;
1017
1018     case AOP_DPTR:
1019     case AOP_DPTR2:
1020
1021       if (aop->type == AOP_DPTR2)
1022         {
1023           genSetDPTR (1);
1024           if (!canClobberACC)
1025             {
1026                     TR_AP("#1");
1027                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1028             }
1029         }
1030
1031       _flushLazyDPS ();
1032
1033       while (offset > aop->coff)
1034         {
1035           emitcode ("inc", "dptr");
1036           aop->coff++;
1037         }
1038
1039       while (offset < aop->coff)
1040         {
1041           emitcode ("lcall", "__decdptr");
1042           aop->coff--;
1043         }
1044
1045       aop->coff = offset;
1046       if (aop->code)
1047         {
1048           emitcode ("clr", "a");
1049           emitcode ("movc", "a,@a+dptr");
1050         }
1051       else
1052         {
1053           emitcode ("movx", "a,@dptr");
1054         }
1055
1056       if (aop->type == AOP_DPTR2)
1057         {
1058           genSetDPTR (0);
1059           if (!canClobberACC)
1060             {
1061        TR_AP("#2");
1062               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1063               return DP2_RESULT_REG;
1064             }
1065         }
1066       return (dname ? "acc" : "a");
1067
1068     case AOP_IMMD:
1069       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1070               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1071       } else if (bit16)
1072         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1073       else if (offset) {
1074           switch (offset) {
1075           case 1:
1076               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1077               break;
1078           case 2:
1079               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1080               break;
1081           case 3:
1082               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1083               break;
1084           default: /* should not need this (just in case) */
1085               sprintf (s, "#(%s >> %d)",
1086                        aop->aopu.aop_immd.aop_immd1,
1087                        offset * 8);
1088           }
1089       }
1090       else
1091         sprintf (s, "#%s",
1092                  aop->aopu.aop_immd.aop_immd1);
1093       rs = Safe_calloc (1, strlen (s) + 1);
1094       strcpy (rs, s);
1095       return rs;
1096
1097     case AOP_DIR:
1098       if (offset)
1099         sprintf (s, "(%s + %d)",
1100                  aop->aopu.aop_dir,
1101                  offset);
1102       else
1103         sprintf (s, "%s", aop->aopu.aop_dir);
1104       rs = Safe_calloc (1, strlen (s) + 1);
1105       strcpy (rs, s);
1106       return rs;
1107
1108     case AOP_REG:
1109       if (dname)
1110         return aop->aopu.aop_reg[offset]->dname;
1111       else
1112         return aop->aopu.aop_reg[offset]->name;
1113
1114     case AOP_CRY:
1115       emitcode ("clr", "a");
1116       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1117       emitcode ("rlc", "a");
1118       return (dname ? "acc" : "a");
1119
1120     case AOP_ACC:
1121       if (!offset && dname)
1122         return "acc";
1123       return aop->aopu.aop_str[offset];
1124
1125     case AOP_LIT:
1126       return aopLiteral (aop->aopu.aop_lit, offset);
1127
1128     case AOP_STR:
1129       aop->coff = offset;
1130       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1131           dname)
1132         return "acc";
1133
1134       return aop->aopu.aop_str[offset];
1135
1136     }
1137
1138   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1139           "aopget got unsupported aop->type");
1140   exit (1);
1141 }
1142 /*-----------------------------------------------------------------*/
1143 /* aopPut - puts a string for a aop                                */
1144 /*-----------------------------------------------------------------*/
1145 static void
1146 aopPut (asmop * aop, char *s, int offset)
1147 {
1148   char *d = buffer;
1149
1150   if (aop->size && offset > (aop->size - 1))
1151     {
1152       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1153               "aopPut got offset > aop->size");
1154       exit (1);
1155     }
1156
1157   /* will assign value to value */
1158   /* depending on where it is ofcourse */
1159   switch (aop->type)
1160     {
1161     case AOP_DIR:
1162       if (offset)
1163         sprintf (d, "(%s + %d)",
1164                  aop->aopu.aop_dir, offset);
1165       else
1166         sprintf (d, "%s", aop->aopu.aop_dir);
1167
1168       if (strcmp (d, s))
1169         emitcode ("mov", "%s,%s", d, s);
1170
1171       break;
1172
1173     case AOP_REG:
1174       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1175           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1176         {
1177           if (*s == '@' ||
1178               strcmp (s, "r0") == 0 ||
1179               strcmp (s, "r1") == 0 ||
1180               strcmp (s, "r2") == 0 ||
1181               strcmp (s, "r3") == 0 ||
1182               strcmp (s, "r4") == 0 ||
1183               strcmp (s, "r5") == 0 ||
1184               strcmp (s, "r6") == 0 ||
1185               strcmp (s, "r7") == 0)
1186             emitcode ("mov", "%s,%s",
1187                       aop->aopu.aop_reg[offset]->dname, s);
1188           else
1189             emitcode ("mov", "%s,%s",
1190                       aop->aopu.aop_reg[offset]->name, s);
1191         }
1192       break;
1193
1194     case AOP_DPTR:
1195     case AOP_DPTR2:
1196
1197       if (aop->type == AOP_DPTR2)
1198         {
1199           genSetDPTR (1);
1200         }
1201       _flushLazyDPS ();
1202
1203       if (aop->code)
1204         {
1205           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1206                   "aopPut writting to code space");
1207           exit (1);
1208         }
1209
1210       while (offset > aop->coff)
1211         {
1212           aop->coff++;
1213           emitcode ("inc", "dptr");
1214         }
1215
1216       while (offset < aop->coff)
1217         {
1218           aop->coff--;
1219           emitcode ("lcall", "__decdptr");
1220         }
1221
1222       aop->coff = offset;
1223
1224       /* if not in accumulater */
1225       MOVA (s);
1226
1227       emitcode ("movx", "@dptr,a");
1228
1229       if (aop->type == AOP_DPTR2)
1230         {
1231           genSetDPTR (0);
1232         }
1233       break;
1234
1235     case AOP_R0:
1236     case AOP_R1:
1237       while (offset > aop->coff)
1238         {
1239           aop->coff++;
1240           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1241         }
1242       while (offset < aop->coff)
1243         {
1244           aop->coff--;
1245           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1246         }
1247       aop->coff = offset;
1248
1249       if (aop->paged)
1250         {
1251           MOVA (s);
1252           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1253
1254         }
1255       else if (*s == '@')
1256         {
1257           MOVA (s);
1258           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1259         }
1260       else if (strcmp (s, "r0") == 0 ||
1261                strcmp (s, "r1") == 0 ||
1262                strcmp (s, "r2") == 0 ||
1263                strcmp (s, "r3") == 0 ||
1264                strcmp (s, "r4") == 0 ||
1265                strcmp (s, "r5") == 0 ||
1266                strcmp (s, "r6") == 0 ||
1267                strcmp (s, "r7") == 0)
1268         {
1269           char buffer[10];
1270           sprintf (buffer, "a%s", s);
1271           emitcode ("mov", "@%s,%s",
1272                     aop->aopu.aop_ptr->name, buffer);
1273         }
1274       else
1275         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1276
1277       break;
1278
1279     case AOP_STK:
1280       if (strcmp (s, "a") == 0)
1281         emitcode ("push", "acc");
1282       else
1283         if (*s=='@') {
1284           MOVA(s);
1285           emitcode ("push", "acc");
1286         } else {
1287           emitcode ("push", s);
1288         }
1289
1290       break;
1291
1292     case AOP_CRY:
1293       /* if bit variable */
1294       if (!aop->aopu.aop_dir)
1295         {
1296           emitcode ("clr", "a");
1297           emitcode ("rlc", "a");
1298         }
1299       else
1300         {
1301           if (s == zero)
1302             emitcode ("clr", "%s", aop->aopu.aop_dir);
1303           else if (s == one)
1304             emitcode ("setb", "%s", aop->aopu.aop_dir);
1305           else if (!strcmp (s, "c"))
1306             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1307           else
1308             {
1309               if (strcmp (s, "a"))
1310                 {
1311                   MOVA (s);
1312                 }
1313               {
1314                 symbol *lbl = newiTempLabel (NULL);
1315                 emitcode ("clr", "c");
1316                 emitcode ("jz", "!tlabel", lbl->key + 100);
1317                 emitcode ("cpl", "c");
1318                 emitcode ("", "!tlabeldef", lbl->key + 100);
1319                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1320               }
1321             }
1322         }
1323       break;
1324
1325     case AOP_STR:
1326       aop->coff = offset;
1327       if (strcmp (aop->aopu.aop_str[offset], s))
1328         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1329       break;
1330
1331     case AOP_ACC:
1332       aop->coff = offset;
1333       if (!offset && (strcmp (s, "acc") == 0))
1334         break;
1335
1336       if (strcmp (aop->aopu.aop_str[offset], s))
1337         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1338       break;
1339
1340     default:
1341       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1342               "aopPut got unsupported aop->type");
1343       exit (1);
1344     }
1345
1346 }
1347
1348
1349 /*--------------------------------------------------------------------*/
1350 /* reAdjustPreg - points a register back to where it should (coff==0) */
1351 /*--------------------------------------------------------------------*/
1352 static void
1353 reAdjustPreg (asmop * aop)
1354 {
1355   if ((aop->coff==0) || (aop->size <= 1)) {
1356     return;
1357   }
1358
1359   switch (aop->type)
1360     {
1361     case AOP_R0:
1362     case AOP_R1:
1363       while (aop->coff--)
1364         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1365       break;
1366     case AOP_DPTR:
1367     case AOP_DPTR2:
1368       if (aop->type == AOP_DPTR2)
1369         {
1370           genSetDPTR (1);
1371           _flushLazyDPS ();
1372         }
1373       while (aop->coff--)
1374         {
1375           emitcode ("lcall", "__decdptr");
1376         }
1377
1378       if (aop->type == AOP_DPTR2)
1379         {
1380           genSetDPTR (0);
1381         }
1382       break;
1383
1384     }
1385   aop->coff=0;
1386 }
1387
1388 #define AOP(op) op->aop
1389 #define AOP_TYPE(op) AOP(op)->type
1390 #define AOP_SIZE(op) AOP(op)->size
1391 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1392                        AOP_TYPE(x) == AOP_R0))
1393
1394 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1395                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1396                          AOP(x)->paged))
1397
1398 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1399                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1400                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1401
1402 /* Workaround for DS80C390 bug: div ab may return bogus results
1403  * if A is accessed in instruction immediately before the div.
1404  *
1405  * Will be fixed in B4 rev of processor, Dallas claims.
1406  */
1407
1408 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1409     if (!AOP_NEEDSACC(RIGHT))         \
1410     {               \
1411       /* We can load A first, then B, since     \
1412        * B (the RIGHT operand) won't clobber A,   \
1413        * thus avoiding touching A right before the div. \
1414        */             \
1415       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1416       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1417       MOVA(L);            \
1418       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1419     }               \
1420     else              \
1421     {               \
1422       /* Just stuff in a nop after loading A. */    \
1423       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1424       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1425       MOVA(L);            \
1426       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1427     }
1428
1429 /*-----------------------------------------------------------------*/
1430 /* genNotFloat - generates not for float operations              */
1431 /*-----------------------------------------------------------------*/
1432 static void
1433 genNotFloat (operand * op, operand * res)
1434 {
1435   int size, offset;
1436   char *l;
1437   symbol *tlbl;
1438
1439   D (emitcode (";", "genNotFloat ");
1440     );
1441
1442   /* we will put 127 in the first byte of
1443      the result */
1444   aopPut (AOP (res), "#127", 0);
1445   size = AOP_SIZE (op) - 1;
1446   offset = 1;
1447
1448   _startLazyDPSEvaluation ();
1449   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1450   MOVA (l);
1451
1452   while (size--)
1453     {
1454       emitcode ("orl", "a,%s",
1455                 aopGet (op->aop,
1456                         offset++, FALSE, FALSE, FALSE));
1457     }
1458   _endLazyDPSEvaluation ();
1459
1460   tlbl = newiTempLabel (NULL);
1461   aopPut (res->aop, one, 1);
1462   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1463   aopPut (res->aop, zero, 1);
1464   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1465
1466   size = res->aop->size - 2;
1467   offset = 2;
1468   /* put zeros in the rest */
1469   while (size--)
1470     aopPut (res->aop, zero, offset++);
1471 }
1472
1473 /*-----------------------------------------------------------------*/
1474 /* opIsGptr: returns non-zero if the passed operand is       */
1475 /* a generic pointer type.             */
1476 /*-----------------------------------------------------------------*/
1477 static int
1478 opIsGptr (operand * op)
1479 {
1480   sym_link *type = operandType (op);
1481
1482   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1483     {
1484       return 1;
1485     }
1486   return 0;
1487 }
1488
1489 /*-----------------------------------------------------------------*/
1490 /* getDataSize - get the operand data size                         */
1491 /*-----------------------------------------------------------------*/
1492 static int
1493 getDataSize (operand * op)
1494 {
1495   int size;
1496   size = AOP_SIZE (op);
1497   if (size == GPTRSIZE)
1498     {
1499       sym_link *type = operandType (op);
1500       if (IS_GENPTR (type))
1501         {
1502           /* generic pointer; arithmetic operations
1503            * should ignore the high byte (pointer type).
1504            */
1505           size--;
1506         }
1507     }
1508   return size;
1509 }
1510
1511 /*-----------------------------------------------------------------*/
1512 /* outAcc - output Acc                                             */
1513 /*-----------------------------------------------------------------*/
1514 static void
1515 outAcc (operand * result)
1516 {
1517   int size, offset;
1518   size = getDataSize (result);
1519   if (size)
1520     {
1521       aopPut (AOP (result), "a", 0);
1522       size--;
1523       offset = 1;
1524       /* unsigned or positive */
1525       while (size--)
1526         {
1527           aopPut (AOP (result), zero, offset++);
1528         }
1529     }
1530 }
1531
1532 /*-----------------------------------------------------------------*/
1533 /* outBitC - output a bit C                                        */
1534 /*-----------------------------------------------------------------*/
1535 static void
1536 outBitC (operand * result)
1537 {
1538   /* if the result is bit */
1539   if (AOP_TYPE (result) == AOP_CRY)
1540     {
1541       aopPut (AOP (result), "c", 0);
1542     }
1543   else
1544     {
1545       emitcode ("clr", "a");
1546       emitcode ("rlc", "a");
1547       outAcc (result);
1548     }
1549 }
1550
1551 /*-----------------------------------------------------------------*/
1552 /* toBoolean - emit code for orl a,operator(sizeop)                */
1553 /*-----------------------------------------------------------------*/
1554 static void
1555 toBoolean (operand * oper)
1556 {
1557   int   size = AOP_SIZE (oper) - 1;
1558   int   offset = 1;
1559   bool usedB = FALSE;
1560
1561   /* The generic part of a generic pointer should
1562    * not participate in it's truth value.
1563    *
1564    * i.e. 0x10000000 is zero.
1565    */
1566   if (opIsGptr (oper))
1567     {
1568       D (emitcode (";", "toBoolean: generic ptr special case.");
1569         );
1570       size--;
1571     }
1572
1573   _startLazyDPSEvaluation ();
1574   if (AOP_NEEDSACC (oper) && size)
1575     {
1576       usedB = TRUE;
1577       emitcode ("push", "b");
1578       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1579     }
1580   else
1581     {
1582       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1583     }
1584   while (size--)
1585     {
1586       if (usedB)
1587         {
1588           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1589         }
1590       else
1591         {
1592           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1593         }
1594     }
1595   _endLazyDPSEvaluation ();
1596
1597   if (usedB)
1598     {
1599       emitcode ("mov", "a,b");
1600       emitcode ("pop", "b");
1601     }
1602 }
1603
1604
1605 /*-----------------------------------------------------------------*/
1606 /* genNot - generate code for ! operation                          */
1607 /*-----------------------------------------------------------------*/
1608 static void
1609 genNot (iCode * ic)
1610 {
1611   symbol *tlbl;
1612   sym_link *optype = operandType (IC_LEFT (ic));
1613
1614   D (emitcode (";", "genNot ");
1615     );
1616
1617   /* assign asmOps to operand & result */
1618   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1619   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1620
1621   /* if in bit space then a special case */
1622   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1623     {
1624       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1625       emitcode ("cpl", "c");
1626       outBitC (IC_RESULT (ic));
1627       goto release;
1628     }
1629
1630   /* if type float then do float */
1631   if (IS_FLOAT (optype))
1632     {
1633       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1634       goto release;
1635     }
1636
1637   toBoolean (IC_LEFT (ic));
1638
1639   tlbl = newiTempLabel (NULL);
1640   emitcode ("cjne", "a,#0x01,!tlabel", tlbl->key + 100);
1641   emitcode ("", "!tlabeldef", tlbl->key + 100);
1642   outBitC (IC_RESULT (ic));
1643
1644 release:
1645   /* release the aops */
1646   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1647   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1648 }
1649
1650
1651 /*-----------------------------------------------------------------*/
1652 /* genCpl - generate code for complement                           */
1653 /*-----------------------------------------------------------------*/
1654 static void
1655 genCpl (iCode * ic)
1656 {
1657   int offset = 0;
1658   int size;
1659
1660   D (emitcode (";", "genCpl ");
1661     );
1662
1663
1664   /* assign asmOps to operand & result */
1665   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1666   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1667
1668   /* if both are in bit space then
1669      a special case */
1670   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1671       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1672     {
1673
1674       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1675       emitcode ("cpl", "c");
1676       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1677       goto release;
1678     }
1679
1680   size = AOP_SIZE (IC_RESULT (ic));
1681   _startLazyDPSEvaluation ();
1682   while (size--)
1683     {
1684       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1685       MOVA (l);
1686       emitcode ("cpl", "a");
1687       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1688     }
1689   _endLazyDPSEvaluation ();
1690
1691
1692 release:
1693   /* release the aops */
1694   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1695   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1696 }
1697
1698 /*-----------------------------------------------------------------*/
1699 /* genUminusFloat - unary minus for floating points                */
1700 /*-----------------------------------------------------------------*/
1701 static void
1702 genUminusFloat (operand * op, operand * result)
1703 {
1704   int size, offset = 0;
1705   char *l;
1706   /* for this we just need to flip the
1707      first it then copy the rest in place */
1708   D (emitcode (";", "genUminusFloat");
1709     );
1710
1711   _startLazyDPSEvaluation ();
1712   size = AOP_SIZE (op) - 1;
1713   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1714   MOVA (l);
1715
1716   emitcode ("cpl", "acc.7");
1717   aopPut (AOP (result), "a", 3);
1718
1719   while (size--)
1720     {
1721       aopPut (AOP (result),
1722               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1723               offset);
1724       offset++;
1725     }
1726   _endLazyDPSEvaluation ();
1727 }
1728
1729 /*-----------------------------------------------------------------*/
1730 /* genUminus - unary minus code generation                         */
1731 /*-----------------------------------------------------------------*/
1732 static void
1733 genUminus (iCode * ic)
1734 {
1735   int offset, size;
1736   sym_link *optype, *rtype;
1737
1738   D (emitcode (";", "genUminus ");
1739     );
1740
1741
1742   /* assign asmops */
1743   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1744   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1745
1746   /* if both in bit space then special
1747      case */
1748   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1749       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1750     {
1751
1752       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1753       emitcode ("cpl", "c");
1754       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1755       goto release;
1756     }
1757
1758   optype = operandType (IC_LEFT (ic));
1759   rtype = operandType (IC_RESULT (ic));
1760
1761   /* if float then do float stuff */
1762   if (IS_FLOAT (optype))
1763     {
1764       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1765       goto release;
1766     }
1767
1768   /* otherwise subtract from zero */
1769   size = AOP_SIZE (IC_LEFT (ic));
1770   offset = 0;
1771   _startLazyDPSEvaluation ();
1772   while (size--)
1773     {
1774       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1775       if (!strcmp (l, "a"))
1776         {
1777           if (offset == 0)
1778             SETC;
1779           emitcode ("cpl", "a");
1780           emitcode ("addc", "a,#0");
1781         }
1782       else
1783         {
1784           if (offset == 0)
1785             CLRC;
1786           emitcode ("clr", "a");
1787           emitcode ("subb", "a,%s", l);
1788         }
1789       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1790     }
1791   _endLazyDPSEvaluation ();
1792
1793   /* if any remaining bytes in the result */
1794   /* we just need to propagate the sign   */
1795   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1796     {
1797       emitcode ("rlc", "a");
1798       emitcode ("subb", "a,acc");
1799       while (size--)
1800         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1801     }
1802
1803 release:
1804   /* release the aops */
1805   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1806   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1807 }
1808
1809 /*-----------------------------------------------------------------*/
1810 /* saveRegisters - will look for a call and save the registers     */
1811 /*-----------------------------------------------------------------*/
1812 static void
1813 saveRegisters (iCode * lic)
1814 {
1815   int i;
1816   iCode *ic;
1817   bitVect *rsave;
1818   sym_link *detype;
1819
1820   /* look for call */
1821   for (ic = lic; ic; ic = ic->next)
1822     if (ic->op == CALL || ic->op == PCALL)
1823       break;
1824
1825   if (!ic)
1826     {
1827       fprintf (stderr, "found parameter push with no function call\n");
1828       return;
1829     }
1830
1831   /* if the registers have been saved already then
1832      do nothing */
1833   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1834
1835   /* special case if DPTR alive across a function call then must save it 
1836      even though callee saves */
1837   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1838       int i =0;
1839       rsave = newBitVect(ic->rMask->size);
1840       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1841           if (bitVectBitValue(ic->rMask,i))
1842               rsave = bitVectSetBit(rsave,i);
1843       }
1844   } else {
1845     /* safe the registers in use at this time but skip the
1846        ones for the result */
1847     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1848                            ds390_rUmaskForOp (IC_RESULT(ic)));
1849   }
1850   ic->regsSaved = 1;
1851   if (options.useXstack)
1852     {
1853       if (bitVectBitValue (rsave, R0_IDX))
1854         emitcode ("mov", "b,r0");
1855       emitcode ("mov", "r0,%s", spname);
1856       for (i = 0; i < ds390_nRegs; i++)
1857         {
1858           if (bitVectBitValue (rsave, i))
1859             {
1860               if (i == R0_IDX)
1861                 emitcode ("mov", "a,b");
1862               else
1863                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1864               emitcode ("movx", "@r0,a");
1865               emitcode ("inc", "r0");
1866             }
1867         }
1868       emitcode ("mov", "%s,r0", spname);
1869       if (bitVectBitValue (rsave, R0_IDX))
1870         emitcode ("mov", "r0,b");
1871     }
1872   else
1873     for (i = 0; i < ds390_nRegs; i++)
1874       {
1875         if (bitVectBitValue (rsave, i))
1876           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1877       }
1878
1879   detype = getSpec (operandType (IC_LEFT (ic)));
1880 }
1881
1882 /*-----------------------------------------------------------------*/
1883 /* unsaveRegisters - pop the pushed registers                      */
1884 /*-----------------------------------------------------------------*/
1885 static void
1886 unsaveRegisters (iCode * ic)
1887 {
1888   int i;
1889   bitVect *rsave;
1890
1891   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1892       int i =0;
1893       rsave = newBitVect(ic->rMask->size);
1894       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1895           if (bitVectBitValue(ic->rMask,i))
1896               rsave = bitVectSetBit(rsave,i);
1897       }
1898   } else {
1899     /* restore the registers in use at this time but skip the
1900        ones for the result */
1901     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1902                            ds390_rUmaskForOp (IC_RESULT(ic)));
1903   }
1904   if (options.useXstack)
1905     {
1906       emitcode ("mov", "r0,%s", spname);
1907       for (i = ds390_nRegs; i >= 0; i--)
1908         {
1909           if (bitVectBitValue (rsave, i))
1910             {
1911               emitcode ("dec", "r0");
1912               emitcode ("movx", "a,@r0");
1913               if (i == R0_IDX)
1914                 emitcode ("mov", "b,a");
1915               else
1916                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1917             }
1918
1919         }
1920       emitcode ("mov", "%s,r0", spname);
1921       if (bitVectBitValue (rsave, R0_IDX))
1922         emitcode ("mov", "r0,b");
1923     }
1924   else
1925     for (i = ds390_nRegs; i >= 0; i--)
1926       {
1927         if (bitVectBitValue (rsave, i))
1928           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1929       }
1930
1931 }
1932
1933
1934 /*-----------------------------------------------------------------*/
1935 /* pushSide -                */
1936 /*-----------------------------------------------------------------*/
1937 static void
1938 pushSide (operand * oper, int size)
1939 {
1940   int offset = 0;
1941   _startLazyDPSEvaluation ();
1942   while (size--)
1943     {
1944       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1945       if (AOP_TYPE (oper) != AOP_REG &&
1946           AOP_TYPE (oper) != AOP_DIR &&
1947           strcmp (l, "a"))
1948         {
1949           emitcode ("mov", "a,%s", l);
1950           emitcode ("push", "acc");
1951         }
1952       else
1953         emitcode ("push", "%s", l);
1954     }
1955   _endLazyDPSEvaluation ();
1956 }
1957
1958 /*-----------------------------------------------------------------*/
1959 /* assignResultValue -               */
1960 /*-----------------------------------------------------------------*/
1961 static void
1962 assignResultValue (operand * oper)
1963 {
1964   int offset = 0;
1965   int size = AOP_SIZE (oper);
1966
1967   _startLazyDPSEvaluation ();
1968   while (size--)
1969     {
1970       aopPut (AOP (oper), fReturn[offset], offset);
1971       offset++;
1972     }
1973   _endLazyDPSEvaluation ();
1974 }
1975
1976
1977 /*-----------------------------------------------------------------*/
1978 /* genXpush - pushes onto the external stack                       */
1979 /*-----------------------------------------------------------------*/
1980 static void
1981 genXpush (iCode * ic)
1982 {
1983   asmop *aop = newAsmop (0);
1984   regs *r;
1985   int size, offset = 0;
1986
1987   D (emitcode (";", "genXpush ");
1988     );
1989
1990   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1991   r = getFreePtr (ic, &aop, FALSE);
1992
1993
1994   emitcode ("mov", "%s,_spx", r->name);
1995
1996   size = AOP_SIZE (IC_LEFT (ic));
1997   _startLazyDPSEvaluation ();
1998   while (size--)
1999     {
2000
2001       char *l = aopGet (AOP (IC_LEFT (ic)),
2002                         offset++, FALSE, FALSE, TRUE);
2003       MOVA (l);
2004       emitcode ("movx", "@%s,a", r->name);
2005       emitcode ("inc", "%s", r->name);
2006
2007     }
2008   _endLazyDPSEvaluation ();
2009
2010
2011   emitcode ("mov", "_spx,%s", r->name);
2012
2013   freeAsmop (NULL, aop, ic, TRUE);
2014   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2015 }
2016
2017 /*-----------------------------------------------------------------*/
2018 /* genIpush - genrate code for pushing this gets a little complex  */
2019 /*-----------------------------------------------------------------*/
2020 static void
2021 genIpush (iCode * ic)
2022 {
2023   int size, offset = 0;
2024   char *l;
2025
2026   D (emitcode (";", "genIpush ");
2027     );
2028
2029   /* if this is not a parm push : ie. it is spill push
2030      and spill push is always done on the local stack */
2031   if (!ic->parmPush)
2032     {
2033
2034       /* and the item is spilt then do nothing */
2035       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2036         return;
2037
2038       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2039       size = AOP_SIZE (IC_LEFT (ic));
2040       /* push it on the stack */
2041       _startLazyDPSEvaluation ();
2042       while (size--)
2043         {
2044           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2045           if (*l == '#')
2046             {
2047               MOVA (l);
2048               l = "acc";
2049             }
2050           emitcode ("push", "%s", l);
2051         }
2052       _endLazyDPSEvaluation ();
2053       return;
2054     }
2055
2056   /* this is a paramter push: in this case we call
2057      the routine to find the call and save those
2058      registers that need to be saved */
2059   saveRegisters (ic);
2060
2061   /* if use external stack then call the external
2062      stack pushing routine */
2063   if (options.useXstack)
2064     {
2065       genXpush (ic);
2066       return;
2067     }
2068
2069   /* then do the push */
2070   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2071
2072   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2073   size = AOP_SIZE (IC_LEFT (ic));
2074
2075   _startLazyDPSEvaluation ();
2076   while (size--)
2077     {
2078       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2079       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2080           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2081           strcmp (l, "a"))
2082         {
2083           emitcode ("mov", "a,%s", l);
2084           emitcode ("push", "acc");
2085         }
2086       else
2087         emitcode ("push", "%s", l);
2088     }
2089   _endLazyDPSEvaluation ();
2090
2091   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2092 }
2093
2094 /*-----------------------------------------------------------------*/
2095 /* genIpop - recover the registers: can happen only for spilling   */
2096 /*-----------------------------------------------------------------*/
2097 static void
2098 genIpop (iCode * ic)
2099 {
2100   int size, offset;
2101
2102   D (emitcode (";", "genIpop ");
2103     );
2104
2105
2106   /* if the temp was not pushed then */
2107   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2108     return;
2109
2110   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2111   size = AOP_SIZE (IC_LEFT (ic));
2112   offset = (size - 1);
2113   _startLazyDPSEvaluation ();
2114   while (size--)
2115     {
2116       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2117                                      FALSE, TRUE, TRUE));
2118     }
2119   _endLazyDPSEvaluation ();
2120
2121   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* unsaveRBank - restores the resgister bank from stack            */
2126 /*-----------------------------------------------------------------*/
2127 static void
2128 unsaveRBank (int bank, iCode * ic, bool popPsw)
2129 {
2130   int i;
2131   asmop *aop = NULL;
2132   regs *r = NULL;
2133
2134   if (options.useXstack)
2135   {
2136       if (!ic)
2137       {
2138           /* Assume r0 is available for use. */
2139           r = ds390_regWithIdx (R0_IDX);;          
2140       } 
2141       else
2142       {
2143           aop = newAsmop (0);
2144           r = getFreePtr (ic, &aop, FALSE);
2145       }
2146       emitcode ("mov", "%s,_spx", r->name);      
2147   }
2148   
2149   if (popPsw)
2150     {
2151       if (options.useXstack)
2152       {
2153           emitcode ("movx", "a,@%s", r->name);
2154           emitcode ("mov", "psw,a");
2155           emitcode ("dec", "%s", r->name);
2156         }
2157       else
2158       {
2159         emitcode ("pop", "psw");
2160       }
2161     }
2162
2163   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2164     {
2165       if (options.useXstack)
2166         {
2167           emitcode ("movx", "a,@%s", r->name);
2168           emitcode ("mov", "(%s+%d),a",
2169                     regs390[i].base, 8 * bank + regs390[i].offset);
2170           emitcode ("dec", "%s", r->name);
2171
2172         }
2173       else
2174         emitcode ("pop", "(%s+%d)",
2175                   regs390[i].base, 8 * bank + regs390[i].offset);
2176     }
2177
2178   if (options.useXstack)
2179     {
2180       emitcode ("mov", "_spx,%s", r->name);
2181     }
2182     
2183   if (aop)
2184   {
2185       freeAsmop (NULL, aop, ic, TRUE);  
2186   }    
2187 }
2188
2189 /*-----------------------------------------------------------------*/
2190 /* saveRBank - saves an entire register bank on the stack          */
2191 /*-----------------------------------------------------------------*/
2192 static void
2193 saveRBank (int bank, iCode * ic, bool pushPsw)
2194 {
2195   int i;
2196   asmop *aop = NULL;
2197   regs *r = NULL;
2198
2199   if (options.useXstack)
2200     {
2201         if (!ic)
2202         {
2203           /* Assume r0 is available for use. */
2204                   r = ds390_regWithIdx (R0_IDX);;
2205         }
2206         else
2207         {
2208           aop = newAsmop (0);
2209           r = getFreePtr (ic, &aop, FALSE);
2210         }
2211         emitcode ("mov", "%s,_spx", r->name);    
2212     }
2213
2214   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2215     {
2216       if (options.useXstack)
2217         {
2218           emitcode ("inc", "%s", r->name);
2219           emitcode ("mov", "a,(%s+%d)",
2220                     regs390[i].base, 8 * bank + regs390[i].offset);
2221           emitcode ("movx", "@%s,a", r->name);
2222         }
2223       else
2224         emitcode ("push", "(%s+%d)",
2225                   regs390[i].base, 8 * bank + regs390[i].offset);
2226     }
2227
2228   if (pushPsw)
2229     {
2230       if (options.useXstack)
2231         {
2232           emitcode ("mov", "a,psw");
2233           emitcode ("movx", "@%s,a", r->name);
2234           emitcode ("inc", "%s", r->name);
2235           emitcode ("mov", "_spx,%s", r->name);
2236         }
2237       else
2238       {
2239         emitcode ("push", "psw");
2240       }
2241
2242       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2243     }
2244   
2245   if (aop)
2246   {
2247        freeAsmop (NULL, aop, ic, TRUE);
2248   }    
2249     
2250   if (ic)
2251   {  
2252       ic->bankSaved = 1;
2253   }
2254 }
2255
2256 /*-----------------------------------------------------------------*/
2257 /* genCall - generates a call statement                            */
2258 /*-----------------------------------------------------------------*/
2259 static void
2260 genCall (iCode * ic)
2261 {
2262   sym_link *dtype;
2263   bool restoreBank = FALSE;
2264   bool swapBanks = FALSE;
2265
2266   D (emitcode (";", "genCall "););
2267
2268   /* if we are calling a not _naked function that is not using
2269      the same register bank then we need to save the
2270      destination registers on the stack */
2271   dtype = operandType (IC_LEFT (ic));
2272   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2273       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2274       IFFUNC_ISISR (currFunc->type))
2275   {
2276       if (!ic->bankSaved) 
2277       {
2278            /* This is unexpected; the bank should have been saved in
2279             * genFunction.
2280             */
2281            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2282            restoreBank = TRUE;
2283       }
2284       swapBanks = TRUE;
2285   }
2286   
2287     /* if caller saves & we have not saved then */
2288     if (!ic->regsSaved)
2289       saveRegisters (ic);
2290   
2291   /* if send set is not empty the assign */
2292   /* We've saved all the registers we care about;
2293   * therefore, we may clobber any register not used
2294   * in the calling convention (i.e. anything not in
2295   * fReturn.
2296   */
2297   if (_G.sendSet)
2298     {
2299       iCode *sic;
2300
2301       for (sic = setFirstItem (_G.sendSet); sic;
2302            sic = setNextItem (_G.sendSet))
2303         {
2304           int size, offset = 0;
2305
2306 #if 0
2307           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2308           size = AOP_SIZE (IC_LEFT (sic));
2309
2310           _startLazyDPSEvaluation ();
2311           while (size--)
2312             {
2313               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2314                                 FALSE, FALSE, TRUE);
2315                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2316                 {
2317                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2318                 }
2319                 else if (strcmp (l, fReturn[offset]))
2320                 {
2321                     emitcode ("mov", "%s,%s",
2322                               fReturn[offset],
2323                               l);
2324                 }
2325               offset++;
2326             }
2327           _endLazyDPSEvaluation ();
2328           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2329           {
2330               size = AOP_SIZE (IC_LEFT (sic));
2331               if (size)
2332               {
2333                  size--;
2334               }
2335               while (size)
2336               {
2337                    size--;
2338                    emitcode("mov", "%s,%s",
2339                                     fReturn[size], regs390[size].name);
2340               }
2341           }
2342 #else
2343           // we know that dpl(hxb) is the result, so
2344           _startLazyDPSEvaluation ();
2345           size=getSize(operandType(IC_LEFT(sic)));
2346           if (size>1) {
2347             aopOp (IC_LEFT (sic), sic, FALSE, 
2348                    (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2349           } else {
2350             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2351           }
2352           while (size--)
2353             {
2354               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2355                                 FALSE, FALSE, TRUE);
2356               if (strcmp (l, fReturn[offset]))
2357                 {
2358                   emitcode ("mov", "%s,%s",
2359                             fReturn[offset],
2360                             l);
2361                 }
2362               offset++;
2363             }
2364           _endLazyDPSEvaluation ();
2365 #endif
2366           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2367         }
2368       _G.sendSet = NULL;
2369     }  
2370     
2371   if (swapBanks)
2372   {
2373         emitcode ("mov", "psw,#!constbyte", 
2374            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2375   }
2376
2377   /* make the call */
2378   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2379                             OP_SYMBOL (IC_LEFT (ic))->rname :
2380                             OP_SYMBOL (IC_LEFT (ic))->name));
2381
2382   if (swapBanks)
2383   {
2384        emitcode ("mov", "psw,#!constbyte", 
2385           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2386   }
2387
2388   /* if we need assign a result value */
2389   if ((IS_ITEMP (IC_RESULT (ic)) &&
2390        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2391         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2392         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2393       IS_TRUE_SYMOP (IC_RESULT (ic)))
2394     {
2395       if (isOperandInFarSpace (IC_RESULT (ic))
2396           && getSize (operandType (IC_RESULT (ic))) <= 2)
2397         {
2398           int size = getSize (operandType (IC_RESULT (ic)));
2399
2400           /* Special case for 1 or 2 byte return in far space. */
2401           MOVA (fReturn[0]);
2402           if (size > 1)
2403             {
2404               emitcode ("mov", "b,%s", fReturn[1]);
2405             }
2406
2407           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2408           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2409
2410           if (size > 1)
2411             {
2412               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2413             }
2414           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2415         }
2416       else
2417         {
2418           _G.accInUse++;
2419           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2420           _G.accInUse--;
2421
2422           assignResultValue (IC_RESULT (ic));
2423
2424           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2425         }
2426     }
2427
2428   /* adjust the stack for parameters if
2429      required */
2430   if (ic->parmBytes) {
2431       if (options.stack10bit) {
2432           emitcode ("clr","c");
2433           emitcode ("mov","a,sp");
2434           emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2435           emitcode ("mov","sp,a");
2436           emitcode ("mov","a,esp");
2437           emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2438           emitcode ("mov","esp,a");       
2439       } else {
2440           int i;
2441           if (ic->parmBytes > 3) {
2442               emitcode ("mov", "a,%s", spname);
2443               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2444               emitcode ("mov", "%s,a", spname);
2445           } else
2446               for (i = 0; i < ic->parmBytes; i++)
2447                   emitcode ("dec", "%s", spname);
2448       }
2449   }
2450
2451   /* if we hade saved some registers then unsave them */
2452   if (ic->regsSaved)
2453     unsaveRegisters (ic);
2454
2455   /* if register bank was saved then pop them */
2456   if (restoreBank)
2457     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2458 }
2459
2460 /*-----------------------------------------------------------------*/
2461 /* genPcall - generates a call by pointer statement                */
2462 /*-----------------------------------------------------------------*/
2463 static void
2464 genPcall (iCode * ic)
2465 {
2466   sym_link *dtype;
2467   symbol *rlbl = newiTempLabel (NULL);
2468   bool restoreBank=FALSE;
2469
2470   D (emitcode (";", "genPcall ");
2471     );
2472
2473
2474   /* if caller saves & we have not saved then */
2475   if (!ic->regsSaved)
2476     saveRegisters (ic);
2477
2478   /* if we are calling a function that is not using
2479      the same register bank then we need to save the
2480      destination registers on the stack */
2481   dtype = operandType (IC_LEFT (ic));
2482   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2483       IFFUNC_ISISR (currFunc->type) &&
2484       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2485     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2486     restoreBank=TRUE;
2487   }
2488
2489   /* push the return address on to the stack */
2490   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2491   emitcode ("push", "acc");
2492   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2493   emitcode ("push", "acc");
2494
2495   if (options.model == MODEL_FLAT24)
2496     {
2497       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2498       emitcode ("push", "acc");
2499     }
2500
2501   /* now push the calling address */
2502   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2503
2504   pushSide (IC_LEFT (ic), FPTRSIZE);
2505
2506   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2507
2508   /* if send set is not empty the assign */
2509   if (_G.sendSet)
2510     {
2511       iCode *sic;
2512
2513       for (sic = setFirstItem (_G.sendSet); sic;
2514            sic = setNextItem (_G.sendSet))
2515         {
2516           int size, offset = 0;
2517
2518           // we know that dpl(hxb) is the result, so
2519           _startLazyDPSEvaluation ();
2520           size=getSize(operandType(IC_LEFT(sic)));
2521           if (size>1) {
2522             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2523           } else {
2524             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2525           }
2526           while (size--)
2527             {
2528               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2529                                 FALSE, FALSE, TRUE);
2530               if (strcmp (l, fReturn[offset]))
2531                 {
2532                   emitcode ("mov", "%s,%s",
2533                             fReturn[offset],
2534                             l);
2535                 }
2536               offset++;
2537             }
2538           _endLazyDPSEvaluation ();
2539           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2540         }
2541       _G.sendSet = NULL;
2542     }
2543
2544   emitcode ("ret", "");
2545   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2546
2547
2548   /* if we need assign a result value */
2549   if ((IS_ITEMP (IC_RESULT (ic)) &&
2550        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2551         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2552       IS_TRUE_SYMOP (IC_RESULT (ic)))
2553     {
2554
2555       _G.accInUse++;
2556       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2557       _G.accInUse--;
2558
2559       assignResultValue (IC_RESULT (ic));
2560
2561       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2562     }
2563
2564   /* adjust the stack for parameters if
2565      required */
2566   if (ic->parmBytes)
2567     {
2568       int i;
2569       if (ic->parmBytes > 3)
2570         {
2571           emitcode ("mov", "a,%s", spname);
2572           emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2573           emitcode ("mov", "%s,a", spname);
2574         }
2575       else
2576         for (i = 0; i < ic->parmBytes; i++)
2577           emitcode ("dec", "%s", spname);
2578
2579     }
2580
2581   /* if register bank was saved then unsave them */
2582   if (restoreBank)
2583     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2584   
2585   /* if we hade saved some registers then
2586      unsave them */
2587   if (ic->regsSaved)
2588     unsaveRegisters (ic);
2589
2590 }
2591
2592 /*-----------------------------------------------------------------*/
2593 /* resultRemat - result  is rematerializable                       */
2594 /*-----------------------------------------------------------------*/
2595 static int
2596 resultRemat (iCode * ic)
2597 {
2598   if (SKIP_IC (ic) || ic->op == IFX)
2599     return 0;
2600
2601   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2602     {
2603       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2604       if (sym->remat && !POINTER_SET (ic))
2605         return 1;
2606     }
2607
2608   return 0;
2609 }
2610
2611 #if defined(__BORLANDC__) || defined(_MSC_VER)
2612 #define STRCASECMP stricmp
2613 #else
2614 #define STRCASECMP strcasecmp
2615 #endif
2616
2617 /*-----------------------------------------------------------------*/
2618 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2619 /*-----------------------------------------------------------------*/
2620 static bool
2621 inExcludeList (char *s)
2622 {
2623   int i = 0;
2624
2625   if (options.excludeRegs[i] &&
2626       STRCASECMP (options.excludeRegs[i], "none") == 0)
2627     return FALSE;
2628
2629   for (i = 0; options.excludeRegs[i]; i++)
2630     {
2631       if (options.excludeRegs[i] &&
2632           STRCASECMP (s, options.excludeRegs[i]) == 0)
2633         return TRUE;
2634     }
2635   return FALSE;
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genFunction - generated code for function entry                 */
2640 /*-----------------------------------------------------------------*/
2641 static void
2642 genFunction (iCode * ic)
2643 {
2644   symbol *sym;
2645   sym_link *ftype;
2646   bool   switchedPSW = FALSE;
2647
2648   D (emitcode (";", "genFunction "););
2649
2650   _G.nRegsSaved = 0;
2651   /* create the function header */
2652   emitcode (";", "-----------------------------------------");
2653   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2654   emitcode (";", "-----------------------------------------");
2655
2656   emitcode ("", "%s:", sym->rname);
2657   ftype = operandType (IC_LEFT (ic));
2658
2659   if (IFFUNC_ISNAKED(ftype))
2660   {
2661       emitcode(";", "naked function: no prologue.");
2662       return;
2663   }
2664   
2665   if (options.stack_probe) 
2666       emitcode ("lcall","__stack_probe");
2667   /* if critical function then turn interrupts off */
2668   if (IFFUNC_ISCRITICAL (ftype))
2669     emitcode ("clr", "ea");
2670
2671   /* here we need to generate the equates for the
2672      register bank if required */
2673   if (FUNC_REGBANK (ftype) != rbank)
2674     {
2675       int i;
2676
2677       rbank = FUNC_REGBANK (ftype);
2678       for (i = 0; i < ds390_nRegs; i++)
2679         {
2680           if (regs390[i].print) {
2681               if (strcmp (regs390[i].base, "0") == 0)
2682                   emitcode ("", "%s = !constbyte",
2683                             regs390[i].dname,
2684                             8 * rbank + regs390[i].offset);
2685               else
2686                   emitcode ("", "%s = %s + !constbyte",
2687                             regs390[i].dname,
2688                             regs390[i].base,
2689                             8 * rbank + regs390[i].offset);
2690           }
2691         }
2692     }
2693
2694   /* if this is an interrupt service routine then
2695      save acc, b, dpl, dph  */
2696   if (IFFUNC_ISISR (sym->type))
2697     {
2698
2699       if (!inExcludeList ("acc"))
2700         emitcode ("push", "acc");
2701       if (!inExcludeList ("b"))
2702         emitcode ("push", "b");
2703       if (!inExcludeList ("dpl"))
2704         emitcode ("push", "dpl");
2705       if (!inExcludeList ("dph"))
2706         emitcode ("push", "dph");
2707       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2708         {
2709           emitcode ("push", "dpx");
2710           /* Make sure we're using standard DPTR */
2711           emitcode ("push", "dps");
2712           emitcode ("mov", "dps, #0x00");
2713           if (options.stack10bit)
2714             {
2715               /* This ISR could conceivably use DPTR2. Better save it. */
2716               emitcode ("push", "dpl1");
2717               emitcode ("push", "dph1");
2718               emitcode ("push", "dpx1");
2719               emitcode ("push",  DP2_RESULT_REG);
2720             }
2721         }
2722       /* if this isr has no bank i.e. is going to
2723          run with bank 0 , then we need to save more
2724          registers :-) */
2725       if (!FUNC_REGBANK (sym->type))
2726         {
2727
2728           /* if this function does not call any other
2729              function then we can be economical and
2730              save only those registers that are used */
2731           if (!IFFUNC_HASFCALL(sym->type))
2732             {
2733               int i;
2734
2735               /* if any registers used */
2736               if (sym->regsUsed)
2737                 {
2738                   /* save the registers used */
2739                   for (i = 0; i < sym->regsUsed->size; i++)
2740                     {
2741                       if (bitVectBitValue (sym->regsUsed, i) ||
2742                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2743                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2744                     }
2745                 }
2746
2747             }
2748           else
2749             {
2750               /* this function has  a function call cannot
2751                  determines register usage so we will have to push the
2752                  entire bank */
2753               saveRBank (0, ic, FALSE);
2754             }
2755         }
2756         else
2757         {
2758             /* This ISR uses a non-zero bank.
2759              *
2760              * We assume that the bank is available for our
2761              * exclusive use.
2762              *
2763              * However, if this ISR calls a function which uses some
2764              * other bank, we must save that bank entirely.
2765              */
2766             unsigned long banksToSave = 0;
2767             
2768             if (IFFUNC_HASFCALL(sym->type))
2769             {
2770
2771 #define MAX_REGISTER_BANKS 4
2772
2773                 iCode *i;
2774                 int ix;
2775
2776                 for (i = ic; i; i = i->next)
2777                 {
2778                     if (i->op == ENDFUNCTION)
2779                     {
2780                         /* we got to the end OK. */
2781                         break;
2782                     }
2783                     
2784                     if (i->op == CALL)
2785                     {
2786                         sym_link *dtype;
2787                         
2788                         dtype = operandType (IC_LEFT(i));
2789                         if (dtype 
2790                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2791                         {
2792                              /* Mark this bank for saving. */
2793                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2794                              {
2795                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2796                              }
2797                              else
2798                              {
2799                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2800                              }
2801                              
2802                              /* And note that we don't need to do it in 
2803                               * genCall.
2804                               */
2805                              i->bankSaved = 1;
2806                         }
2807                     }
2808                     if (i->op == PCALL)
2809                     {
2810                         /* This is a mess; we have no idea what
2811                          * register bank the called function might
2812                          * use.
2813                          *
2814                          * The only thing I can think of to do is
2815                          * throw a warning and hope.
2816                          */
2817                         werror(W_FUNCPTR_IN_USING_ISR);   
2818                     }
2819                 }
2820
2821                 if (banksToSave && options.useXstack)
2822                 {
2823                     /* Since we aren't passing it an ic, 
2824                      * saveRBank will assume r0 is available to abuse.
2825                      *
2826                      * So switch to our (trashable) bank now, so
2827                      * the caller's R0 isn't trashed.
2828                      */
2829                     emitcode ("push", "psw");
2830                     emitcode ("mov", "psw,#!constbyte", 
2831                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2832                     switchedPSW = TRUE;
2833                 }
2834                 
2835                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2836                 {
2837                      if (banksToSave & (1 << ix))
2838                      {
2839                          saveRBank(ix, NULL, FALSE);
2840                      }
2841                 }
2842             }
2843             // jwk: this needs a closer look
2844             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2845         }
2846     }
2847   else
2848     {
2849       /* if callee-save to be used for this function
2850          then save the registers being used in this function */
2851       if (IFFUNC_CALLEESAVES(sym->type))
2852         {
2853           int i;
2854
2855           /* if any registers used */
2856           if (sym->regsUsed)
2857             {
2858               /* save the registers used */
2859               for (i = 0; i < sym->regsUsed->size; i++)
2860                 {
2861                   if (bitVectBitValue (sym->regsUsed, i) ||
2862                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2863                     {
2864                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2865                       _G.nRegsSaved++;
2866                     }
2867                 }
2868             }
2869         }
2870     }
2871
2872   /* set the register bank to the desired value */
2873   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2874    && !switchedPSW)
2875     {
2876       emitcode ("push", "psw");
2877       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2878     }
2879
2880   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2881       if (options.stack10bit) {
2882           emitcode ("push","_bpx");
2883           emitcode ("push","_bpx+1");
2884           emitcode ("mov","_bpx,%s",spname);
2885           emitcode ("mov","_bpx+1,esp");
2886           emitcode ("anl","_bpx+1,#3");
2887       } else {
2888           if (options.useXstack) {
2889               emitcode ("mov", "r0,%s", spname);
2890               emitcode ("mov", "a,_bp");
2891               emitcode ("movx", "@r0,a");
2892               emitcode ("inc", "%s", spname);
2893           } else {
2894               /* set up the stack */
2895               emitcode ("push", "_bp"); /* save the callers stack  */
2896           }
2897           emitcode ("mov", "_bp,%s", spname);
2898       }
2899   }
2900
2901   /* adjust the stack for the function */
2902   if (sym->stack) {
2903       int i = sym->stack;
2904       if (options.stack10bit) {
2905           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2906           assert (sym->recvSize <= 4);
2907           emitcode ("mov","a,sp");
2908           emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2909           emitcode ("mov","sp,a");
2910           emitcode ("mov","a,esp");
2911           emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2912           emitcode ("mov","esp,a");
2913       } else {
2914           if (i > 256)
2915               werror (W_STACK_OVERFLOW, sym->name);
2916           
2917           if (i > 3 && sym->recvSize < 4) {
2918               
2919               emitcode ("mov", "a,sp");
2920               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2921               emitcode ("mov", "sp,a");
2922               
2923           } else
2924               while (i--)
2925                   emitcode ("inc", "sp");
2926       }
2927   }
2928
2929   if (sym->xstack)
2930     {
2931
2932       emitcode ("mov", "a,_spx");
2933       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2934       emitcode ("mov", "_spx,a");
2935     }
2936
2937 }
2938
2939 /*-----------------------------------------------------------------*/
2940 /* genEndFunction - generates epilogue for functions               */
2941 /*-----------------------------------------------------------------*/
2942 static void
2943 genEndFunction (iCode * ic)
2944 {
2945   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2946
2947   D (emitcode (";", "genEndFunction "););
2948
2949   if (IFFUNC_ISNAKED(sym->type))
2950   {
2951       emitcode(";", "naked function: no epilogue.");
2952       return;
2953   }
2954
2955   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2956       if (options.stack10bit) {
2957           emitcode ("mov", "sp,_bpx", spname);
2958           emitcode ("mov", "esp,_bpx+1", spname);
2959       } else {
2960           emitcode ("mov", "%s,_bp", spname);
2961       }
2962   }
2963
2964   /* if use external stack but some variables were
2965      added to the local stack then decrement the
2966      local stack */
2967   if (options.useXstack && sym->stack) {
2968       emitcode ("mov", "a,sp");
2969       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2970       emitcode ("mov", "sp,a");
2971   }
2972
2973
2974   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2975       if (options.useXstack) {
2976           emitcode ("mov", "r0,%s", spname);
2977           emitcode ("movx", "a,@r0");
2978           emitcode ("mov", "_bp,a");
2979           emitcode ("dec", "%s", spname);
2980       } else {
2981           if (options.stack10bit) {
2982               emitcode ("pop", "_bpx+1");
2983               emitcode ("pop", "_bpx");
2984           } else {
2985               emitcode ("pop", "_bp");
2986           }
2987       }
2988   }
2989
2990   /* restore the register bank  */
2991   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2992   {
2993     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2994      || !options.useXstack)
2995     {
2996         /* Special case of ISR using non-zero bank with useXstack
2997          * is handled below.
2998          */
2999         emitcode ("pop", "psw");
3000     }
3001   }
3002
3003   if (IFFUNC_ISISR (sym->type))
3004     {
3005
3006       /* now we need to restore the registers */
3007       /* if this isr has no bank i.e. is going to
3008          run with bank 0 , then we need to save more
3009          registers :-) */
3010       if (!FUNC_REGBANK (sym->type))
3011         {
3012           /* if this function does not call any other
3013              function then we can be economical and
3014              save only those registers that are used */
3015           if (!IFFUNC_HASFCALL(sym->type))
3016             {
3017               int i;
3018
3019               /* if any registers used */
3020               if (sym->regsUsed)
3021                 {
3022                   /* save the registers used */
3023                   for (i = sym->regsUsed->size; i >= 0; i--)
3024                     {
3025                       if (bitVectBitValue (sym->regsUsed, i) ||
3026                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3027                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3028                     }
3029                 }
3030
3031             }
3032           else
3033             {
3034               /* this function has  a function call cannot
3035                  determines register usage so we will have to pop the
3036                  entire bank */
3037               unsaveRBank (0, ic, FALSE);
3038             }
3039         }
3040         else
3041         {
3042             /* This ISR uses a non-zero bank.
3043              *
3044              * Restore any register banks saved by genFunction
3045              * in reverse order.
3046              */
3047           // jwk: this needs a closer look
3048             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3049             int ix;
3050           
3051             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3052             {
3053                 if (savedBanks & (1 << ix))
3054                 {
3055                     unsaveRBank(ix, NULL, FALSE);
3056                 }
3057             }
3058             
3059             if (options.useXstack)
3060             {
3061                 /* Restore bank AFTER calling unsaveRBank,
3062                  * since it can trash r0.
3063                  */
3064                 emitcode ("pop", "psw");
3065             }
3066         }
3067
3068       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3069         {
3070           if (options.stack10bit)
3071             {
3072               emitcode ("pop", DP2_RESULT_REG);
3073               emitcode ("pop", "dpx1");
3074               emitcode ("pop", "dph1");
3075               emitcode ("pop", "dpl1");
3076             }
3077           emitcode ("pop", "dps");
3078           emitcode ("pop", "dpx");
3079         }
3080       if (!inExcludeList ("dph"))
3081         emitcode ("pop", "dph");
3082       if (!inExcludeList ("dpl"))
3083         emitcode ("pop", "dpl");
3084       if (!inExcludeList ("b"))
3085         emitcode ("pop", "b");
3086       if (!inExcludeList ("acc"))
3087         emitcode ("pop", "acc");
3088
3089       if (IFFUNC_ISCRITICAL (sym->type))
3090         emitcode ("setb", "ea");
3091
3092       /* if debug then send end of function */
3093       if (options.debug && currFunc) {
3094           _G.debugLine = 1;
3095           emitcode ("", "C$%s$%d$%d$%d ==.",
3096                     FileBaseName (ic->filename), currFunc->lastLine,
3097                     ic->level, ic->block);
3098           if (IS_STATIC (currFunc->etype))
3099             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3100           else
3101             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3102           _G.debugLine = 0;
3103         }
3104
3105       emitcode ("reti", "");
3106     }
3107   else
3108     {
3109       if (IFFUNC_ISCRITICAL (sym->type))
3110         emitcode ("setb", "ea");
3111
3112       if (IFFUNC_CALLEESAVES(sym->type))
3113         {
3114           int i;
3115
3116           /* if any registers used */
3117           if (sym->regsUsed)
3118             {
3119               /* save the registers used */
3120               for (i = sym->regsUsed->size; i >= 0; i--)
3121                 {
3122                   if (bitVectBitValue (sym->regsUsed, i) ||
3123                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3124                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3125                 }
3126             }
3127
3128         }
3129
3130       /* if debug then send end of function */
3131       if (options.debug && currFunc)
3132         {
3133           _G.debugLine = 1;
3134           emitcode ("", "C$%s$%d$%d$%d ==.",
3135                     FileBaseName (ic->filename), currFunc->lastLine,
3136                     ic->level, ic->block);
3137           if (IS_STATIC (currFunc->etype))
3138             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3139           else
3140             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3141           _G.debugLine = 0;
3142         }
3143
3144       emitcode ("ret", "");
3145     }
3146
3147 }
3148
3149 /*-----------------------------------------------------------------*/
3150 /* genRet - generate code for return statement                     */
3151 /*-----------------------------------------------------------------*/
3152 static void
3153 genRet (iCode * ic)
3154 {
3155   int size, offset = 0, pushed = 0;
3156
3157   D (emitcode (";", "genRet ");
3158     );
3159
3160   /* if we have no return value then
3161      just generate the "ret" */
3162   if (!IC_LEFT (ic))
3163     goto jumpret;
3164
3165   /* we have something to return then
3166      move the return value into place */
3167   aopOp (IC_LEFT (ic), ic, FALSE, 
3168          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3169   size = AOP_SIZE (IC_LEFT (ic));
3170
3171   _startLazyDPSEvaluation ();
3172   while (size--)
3173     {
3174       char *l;
3175       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3176         {
3177           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3178                       FALSE, TRUE, FALSE);
3179           emitcode ("push", "%s", l);
3180           pushed++;
3181         }
3182       else
3183         {
3184           /* Since A is the last element of fReturn,
3185            * is is OK to clobber it in the aopGet.
3186            */
3187           l = aopGet (AOP (IC_LEFT (ic)), offset,
3188                       FALSE, FALSE, TRUE);
3189           if (strcmp (fReturn[offset], l))
3190             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3191         }
3192     }
3193   _endLazyDPSEvaluation ();
3194
3195   if (pushed)
3196     {
3197       while (pushed)
3198         {
3199           pushed--;
3200           if (strcmp (fReturn[pushed], "a"))
3201             emitcode ("pop", fReturn[pushed]);
3202           else
3203             emitcode ("pop", "acc");
3204         }
3205     }
3206   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3207
3208 jumpret:
3209   /* generate a jump to the return label
3210      if the next is not the return statement */
3211   if (!(ic->next && ic->next->op == LABEL &&
3212         IC_LABEL (ic->next) == returnLabel))
3213
3214     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3215
3216 }
3217
3218 /*-----------------------------------------------------------------*/
3219 /* genLabel - generates a label                                    */
3220 /*-----------------------------------------------------------------*/
3221 static void
3222 genLabel (iCode * ic)
3223 {
3224   /* special case never generate */
3225   if (IC_LABEL (ic) == entryLabel)
3226     return;
3227
3228   D (emitcode (";", "genLabel ");
3229     );
3230
3231   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3232 }
3233
3234 /*-----------------------------------------------------------------*/
3235 /* genGoto - generates a ljmp                                      */
3236 /*-----------------------------------------------------------------*/
3237 static void
3238 genGoto (iCode * ic)
3239 {
3240   D (emitcode (";", "genGoto ");
3241     );
3242   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3243 }
3244
3245 /*-----------------------------------------------------------------*/
3246 /* findLabelBackwards: walks back through the iCode chain looking  */
3247 /* for the given label. Returns number of iCode instructions     */
3248 /* between that label and given ic.          */
3249 /* Returns zero if label not found.          */
3250 /*-----------------------------------------------------------------*/
3251 static int
3252 findLabelBackwards (iCode * ic, int key)
3253 {
3254   int count = 0;
3255
3256   while (ic->prev)
3257     {
3258       ic = ic->prev;
3259       count++;
3260
3261       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3262         {
3263           /* printf("findLabelBackwards = %d\n", count); */
3264           return count;
3265         }
3266     }
3267
3268   return 0;
3269 }
3270
3271 /*-----------------------------------------------------------------*/
3272 /* genPlusIncr :- does addition with increment if possible         */
3273 /*-----------------------------------------------------------------*/
3274 static bool
3275 genPlusIncr (iCode * ic)
3276 {
3277   unsigned int icount;
3278   unsigned int size = getDataSize (IC_RESULT (ic));
3279
3280   /* will try to generate an increment */
3281   /* if the right side is not a literal
3282      we cannot */
3283   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3284     return FALSE;
3285
3286   /* if the literal value of the right hand side
3287      is greater than 4 then it is not worth it */
3288   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3289     return FALSE;
3290
3291   /* if increment 16 bits in register */
3292   if (
3293        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3294        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3295        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3296        (size > 1) &&
3297        (icount == 1))
3298     {
3299       symbol *tlbl;
3300       int emitTlbl;
3301       int labelRange;
3302
3303       /* If the next instruction is a goto and the goto target
3304        * is <= 5 instructions previous to this, we can generate
3305        * jumps straight to that target.
3306        */
3307       if (ic->next && ic->next->op == GOTO
3308           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3309           && labelRange <= 5)
3310         {
3311           emitcode (";", "tail increment optimized (range %d)", labelRange);
3312           tlbl = IC_LABEL (ic->next);
3313           emitTlbl = 0;
3314         }
3315       else
3316         {
3317           tlbl = newiTempLabel (NULL);
3318           emitTlbl = 1;
3319         }
3320       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3321       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3322           IS_AOP_PREG (IC_RESULT (ic)))
3323         emitcode ("cjne", "%s,#0x00,!tlabel"
3324                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3325                   ,tlbl->key + 100);
3326       else
3327         {
3328           emitcode ("clr", "a");
3329           emitcode ("cjne", "a,%s,!tlabel"
3330                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3331                     ,tlbl->key + 100);
3332         }
3333
3334       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3335       if (size > 2)
3336         {
3337           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3338               IS_AOP_PREG (IC_RESULT (ic)))
3339             emitcode ("cjne", "%s,#0x00,!tlabel"
3340                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3341                       ,tlbl->key + 100);
3342           else
3343             emitcode ("cjne", "a,%s,!tlabel"
3344                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3345                       ,tlbl->key + 100);
3346
3347           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3348         }
3349       if (size > 3)
3350         {
3351           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3352               IS_AOP_PREG (IC_RESULT (ic)))
3353             emitcode ("cjne", "%s,#0x00,!tlabel"
3354                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3355                       ,tlbl->key + 100);
3356           else
3357             {
3358               emitcode ("cjne", "a,%s,!tlabel"
3359                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3360                         ,tlbl->key + 100);
3361             }
3362           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3363         }
3364
3365       if (emitTlbl)
3366         {
3367           emitcode ("", "!tlabeldef", tlbl->key + 100);
3368         }
3369       return TRUE;
3370     }
3371
3372   /* if the sizes are greater than 1 then we cannot */
3373   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3374       AOP_SIZE (IC_LEFT (ic)) > 1)
3375     return FALSE;
3376
3377   /* we can if the aops of the left & result match or
3378      if they are in registers and the registers are the
3379      same */
3380   if (
3381        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3382        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3383        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3384     {
3385
3386       if (icount > 3)
3387         {
3388           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3389           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3390           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3391         }
3392       else
3393         {
3394
3395           _startLazyDPSEvaluation ();
3396           while (icount--)
3397             {
3398               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3399             }
3400           _endLazyDPSEvaluation ();
3401         }
3402
3403       return TRUE;
3404     }
3405
3406   return FALSE;
3407 }
3408
3409 /*-----------------------------------------------------------------*/
3410 /* outBitAcc - output a bit in acc                                 */
3411 /*-----------------------------------------------------------------*/
3412 static void
3413 outBitAcc (operand * result)
3414 {
3415   symbol *tlbl = newiTempLabel (NULL);
3416   /* if the result is a bit */
3417   if (AOP_TYPE (result) == AOP_CRY)
3418     {
3419       aopPut (AOP (result), "a", 0);
3420     }
3421   else
3422     {
3423       emitcode ("jz", "!tlabel", tlbl->key + 100);
3424       emitcode ("mov", "a,%s", one);
3425       emitcode ("", "!tlabeldef", tlbl->key + 100);
3426       outAcc (result);
3427     }
3428 }
3429
3430 /*-----------------------------------------------------------------*/
3431 /* genPlusBits - generates code for addition of two bits           */
3432 /*-----------------------------------------------------------------*/
3433 static void
3434 genPlusBits (iCode * ic)
3435 {
3436   D (emitcode (";", "genPlusBits ");
3437     );
3438   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3439     {
3440       symbol *lbl = newiTempLabel (NULL);
3441       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3442       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3443       emitcode ("cpl", "c");
3444       emitcode ("", "!tlabeldef", (lbl->key + 100));
3445       outBitC (IC_RESULT (ic));
3446     }
3447   else
3448     {
3449       emitcode ("clr", "a");
3450       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3451       emitcode ("rlc", "a");
3452       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3453       emitcode ("addc", "a,#0x00");
3454       outAcc (IC_RESULT (ic));
3455     }
3456 }
3457
3458 static void
3459 adjustArithmeticResult (iCode * ic)
3460 {
3461   if (opIsGptr (IC_RESULT (ic)) &&
3462       opIsGptr (IC_LEFT (ic)) &&
3463       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3464     {
3465       aopPut (AOP (IC_RESULT (ic)),
3466               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3467               GPTRSIZE - 1);
3468     }
3469
3470   if (opIsGptr (IC_RESULT (ic)) &&
3471       opIsGptr (IC_RIGHT (ic)) &&
3472       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3473     {
3474       aopPut (AOP (IC_RESULT (ic)),
3475             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3476               GPTRSIZE - 1);
3477     }
3478
3479   if (opIsGptr (IC_RESULT (ic)) &&
3480       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3481       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3482       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3483       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3484     {
3485       char buffer[5];
3486       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3487       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3488     }
3489 }
3490
3491 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3492       // Please don't bring it back without a really good reason.
3493 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3494 // (because all three operands are in far space).
3495 #define AOP_OP_3(ic) \
3496     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3497     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3498     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3499               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3500     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3501         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3502     { \
3503         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3504         fprintf(stderr,                                  \
3505                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3506     }
3507 #endif
3508
3509 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3510 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3511 // will be set TRUE. The caller must then handle the case specially, noting
3512 // that the IC_RESULT operand is not aopOp'd.
3513 #define AOP_OP_3_NOFATAL(ic, rc) \
3514     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3515     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3516                                   (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3517     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3518         (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3519     { \
3520        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3521        rc = TRUE; \
3522     }  \
3523     else \
3524     { \
3525        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3526                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3527        rc = FALSE; \
3528        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3529            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3530        { \
3531             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3532             fprintf(stderr,                                  \
3533                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3534        } \
3535     }
3536
3537 // aopOp the left & right operands of an ic.
3538 #define AOP_OP_2(ic) \
3539     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3540     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3541
3542 // convienience macro.
3543 #define AOP_SET_LOCALS(ic) \
3544     left = IC_LEFT(ic); \
3545     right = IC_RIGHT(ic); \
3546     result = IC_RESULT(ic);
3547
3548
3549 // Given an integer value of pushedSize bytes on the stack,
3550 // adjust it to be resultSize bytes, either by discarding
3551 // the most significant bytes or by zero-padding.
3552 //
3553 // On exit from this macro, pushedSize will have been adjusted to
3554 // equal resultSize, and ACC may be trashed.
3555 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3556       /* If the pushed data is bigger than the result,          \
3557        * simply discard unused bytes. Icky, but works.          \
3558        */                                                       \
3559       while (pushedSize > resultSize)                           \
3560       {                                                         \
3561           D (emitcode (";", "discarding unused result byte."););\
3562           emitcode ("pop", "acc");                              \
3563           pushedSize--;                                         \
3564       }                                                         \
3565       if (pushedSize < resultSize)                              \
3566       {                                                         \
3567           emitcode ("clr", "a");                                \
3568           /* Conversly, we haven't pushed enough here.          \
3569            * just zero-pad, and all is well.                    \
3570            */                                                   \
3571           while (pushedSize < resultSize)                       \
3572           {                                                     \
3573               emitcode("push", "acc");                          \
3574               pushedSize++;                                     \
3575           }                                                     \
3576       }                                                         \
3577       assert(pushedSize == resultSize);
3578
3579 /*-----------------------------------------------------------------*/
3580 /* genPlus - generates code for addition                           */
3581 /*-----------------------------------------------------------------*/
3582 static void
3583 genPlus (iCode * ic)
3584 {
3585   int size, offset = 0;
3586   bool pushResult = FALSE;
3587   int rSize;
3588
3589   D (emitcode (";", "genPlus "););
3590
3591   /* special cases :- */
3592   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3593       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3594       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3595       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3596       if (size <= 9) {
3597           while (size--) emitcode ("inc","dptr");
3598       } else {
3599           emitcode ("mov","a,dpl");
3600           emitcode ("add","a,#!constbyte",size & 0xff);
3601           emitcode ("mov","dpl,a");
3602           emitcode ("mov","a,dph");
3603           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3604           emitcode ("mov","dph,a");
3605           emitcode ("mov","a,dpx");
3606           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3607           emitcode ("mov","dpx,a");
3608       }
3609       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3610       return ;
3611   }
3612   if ( IS_SYMOP(IC_LEFT(ic)) && 
3613        OP_SYMBOL(IC_LEFT(ic))->remat &&
3614        isOperandInFarSpace(IC_RIGHT(ic))) {
3615       operand *op = IC_RIGHT(ic);
3616       IC_RIGHT(ic) = IC_LEFT(ic);
3617       IC_LEFT(ic) = op;
3618   }
3619                 
3620   AOP_OP_3_NOFATAL (ic, pushResult);
3621   if (pushResult)
3622     {
3623       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3624     }
3625
3626   if (!pushResult)
3627     {
3628       /* if literal, literal on the right or
3629          if left requires ACC or right is already
3630          in ACC */
3631       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3632        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3633           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3634         {
3635           operand *t = IC_RIGHT (ic);
3636           IC_RIGHT (ic) = IC_LEFT (ic);
3637           IC_LEFT (ic) = t;
3638           emitcode (";", "Swapped plus args.");
3639         }
3640
3641       /* if both left & right are in bit
3642          space */
3643       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3644           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3645         {
3646           genPlusBits (ic);
3647           goto release;
3648         }
3649
3650       /* if left in bit space & right literal */
3651       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3652           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3653         {
3654           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3655           /* if result in bit space */
3656           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3657             {
3658               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3659                 emitcode ("cpl", "c");
3660               outBitC (IC_RESULT (ic));
3661             }
3662           else
3663             {
3664               size = getDataSize (IC_RESULT (ic));
3665               _startLazyDPSEvaluation ();
3666               while (size--)
3667                 {
3668                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3669                   emitcode ("addc", "a,#0");
3670                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3671                 }
3672               _endLazyDPSEvaluation ();
3673             }
3674           goto release;
3675         }
3676
3677       /* if I can do an increment instead
3678          of add then GOOD for ME */
3679       if (genPlusIncr (ic) == TRUE)
3680         {
3681           emitcode (";", "did genPlusIncr");
3682           goto release;
3683         }
3684
3685     }
3686   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3687
3688   _startLazyDPSEvaluation ();
3689   while (size--)
3690     {
3691       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3692         {
3693           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3694           if (offset == 0)
3695             emitcode ("add", "a,%s",
3696                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3697           else
3698             emitcode ("addc", "a,%s",
3699                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3700         }
3701       else
3702         {
3703           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3704           {
3705               /* right is going to use ACC or we would have taken the
3706                * above branch.
3707                */
3708               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3709        TR_AP("#3");
3710               D(emitcode(";", "+ AOP_ACC special case."););
3711               emitcode("xch", "a, %s", DP2_RESULT_REG);
3712           }
3713           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3714           if (offset == 0)
3715           {
3716             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3717             {
3718          TR_AP("#4");
3719                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3720             }
3721             else
3722             {
3723                 emitcode ("add", "a,%s",
3724                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3725             }
3726           }
3727           else
3728           {
3729             emitcode ("addc", "a,%s",
3730                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3731           }
3732         }
3733       if (!pushResult)
3734         {
3735           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3736         }
3737       else
3738         {
3739           emitcode ("push", "acc");
3740         }
3741       offset++;
3742     }
3743   _endLazyDPSEvaluation ();
3744
3745   if (pushResult)
3746     {
3747       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3748
3749       size = getDataSize (IC_LEFT (ic));
3750       rSize = getDataSize (IC_RESULT (ic));
3751
3752       ADJUST_PUSHED_RESULT(size, rSize);
3753
3754       _startLazyDPSEvaluation ();
3755       while (size--)
3756         {
3757           emitcode ("pop", "acc");
3758           aopPut (AOP (IC_RESULT (ic)), "a", size);
3759         }
3760       _endLazyDPSEvaluation ();
3761     }
3762
3763   adjustArithmeticResult (ic);
3764
3765 release:
3766   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3767   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3768   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3769 }
3770
3771 /*-----------------------------------------------------------------*/
3772 /* genMinusDec :- does subtraction with deccrement if possible     */
3773 /*-----------------------------------------------------------------*/
3774 static bool
3775 genMinusDec (iCode * ic)
3776 {
3777   unsigned int icount;
3778   unsigned int size = getDataSize (IC_RESULT (ic));
3779
3780   /* will try to generate an increment */
3781   /* if the right side is not a literal
3782      we cannot */
3783   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3784     return FALSE;
3785
3786   /* if the literal value of the right hand side
3787      is greater than 4 then it is not worth it */
3788   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3789     return FALSE;
3790
3791   /* if decrement 16 bits in register */
3792   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3793       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3794       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3795       (size > 1) &&
3796       (icount == 1))
3797     {
3798       symbol *tlbl;
3799       int emitTlbl;
3800       int labelRange;
3801
3802       /* If the next instruction is a goto and the goto target
3803          * is <= 5 instructions previous to this, we can generate
3804          * jumps straight to that target.
3805        */
3806       if (ic->next && ic->next->op == GOTO
3807           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3808           && labelRange <= 5)
3809         {
3810           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3811           tlbl = IC_LABEL (ic->next);
3812           emitTlbl = 0;
3813         }
3814       else
3815         {
3816           tlbl = newiTempLabel (NULL);
3817           emitTlbl = 1;
3818         }
3819
3820       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3821       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3822           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3823           IS_AOP_PREG (IC_RESULT (ic)))
3824         emitcode ("cjne", "%s,#0xff,!tlabel"
3825                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3826                   ,tlbl->key + 100);
3827       else
3828         {
3829           emitcode ("mov", "a,#0xff");
3830           emitcode ("cjne", "a,%s,!tlabel"
3831                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3832                     ,tlbl->key + 100);
3833         }
3834       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3835       if (size > 2)
3836         {
3837           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3838               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3839               IS_AOP_PREG (IC_RESULT (ic)))
3840             emitcode ("cjne", "%s,#0xff,!tlabel"
3841                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3842                       ,tlbl->key + 100);
3843           else
3844             {
3845               emitcode ("cjne", "a,%s,!tlabel"
3846                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3847                         ,tlbl->key + 100);
3848             }
3849           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3850         }
3851       if (size > 3)
3852         {
3853           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3854               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3855               IS_AOP_PREG (IC_RESULT (ic)))
3856             emitcode ("cjne", "%s,#0xff,!tlabel"
3857                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3858                       ,tlbl->key + 100);
3859           else
3860             {
3861               emitcode ("cjne", "a,%s,!tlabel"
3862                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3863                         ,tlbl->key + 100);
3864             }
3865           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3866         }
3867       if (emitTlbl)
3868         {
3869           emitcode ("", "!tlabeldef", tlbl->key + 100);
3870         }
3871       return TRUE;
3872     }
3873
3874   /* if the sizes are greater than 1 then we cannot */
3875   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3876       AOP_SIZE (IC_LEFT (ic)) > 1)
3877     return FALSE;
3878
3879   /* we can if the aops of the left & result match or
3880      if they are in registers and the registers are the
3881      same */
3882   if (
3883        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3884        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3885        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3886     {
3887
3888       _startLazyDPSEvaluation ();
3889       while (icount--)
3890         {
3891           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3892         }
3893       _endLazyDPSEvaluation ();
3894
3895       return TRUE;
3896     }
3897
3898   return FALSE;
3899 }
3900
3901 /*-----------------------------------------------------------------*/
3902 /* addSign - complete with sign                                    */
3903 /*-----------------------------------------------------------------*/
3904 static void
3905 addSign (operand * result, int offset, int sign)
3906 {
3907   int size = (getDataSize (result) - offset);
3908   if (size > 0)
3909     {
3910       _startLazyDPSEvaluation();
3911       if (sign)
3912         {
3913           emitcode ("rlc", "a");
3914           emitcode ("subb", "a,acc");
3915           while (size--)
3916           {
3917             aopPut (AOP (result), "a", offset++);
3918           }
3919         }
3920       else
3921       {
3922         while (size--)
3923         {
3924           aopPut (AOP (result), zero, offset++);
3925         }
3926       }
3927       _endLazyDPSEvaluation();
3928     }
3929 }
3930
3931 /*-----------------------------------------------------------------*/
3932 /* genMinusBits - generates code for subtraction  of two bits      */
3933 /*-----------------------------------------------------------------*/
3934 static void
3935 genMinusBits (iCode * ic)
3936 {
3937   symbol *lbl = newiTempLabel (NULL);
3938
3939   D (emitcode (";", "genMinusBits "););
3940
3941   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3942     {
3943       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3944       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3945       emitcode ("cpl", "c");
3946       emitcode ("", "!tlabeldef", (lbl->key + 100));
3947       outBitC (IC_RESULT (ic));
3948     }
3949   else
3950     {
3951       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3952       emitcode ("subb", "a,acc");
3953       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3954       emitcode ("inc", "a");
3955       emitcode ("", "!tlabeldef", (lbl->key + 100));
3956       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3957       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3958     }
3959 }
3960
3961 /*-----------------------------------------------------------------*/
3962 /* genMinus - generates code for subtraction                       */
3963 /*-----------------------------------------------------------------*/
3964 static void
3965 genMinus (iCode * ic)
3966 {
3967   int size, offset = 0;
3968   int rSize;
3969   unsigned long lit = 0L;
3970   bool pushResult = FALSE;
3971
3972   D (emitcode (";", "genMinus "););
3973
3974   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3975   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3976   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3977       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3978     {
3979       pushResult = TRUE;
3980     }
3981   else
3982     {
3983       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3984
3985       /* special cases :- */
3986       /* if both left & right are in bit space */
3987       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3988           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3989         {
3990           genMinusBits (ic);
3991           goto release;
3992         }
3993
3994       /* if I can do an decrement instead
3995          of subtract then GOOD for ME */
3996       if (genMinusDec (ic) == TRUE)
3997         goto release;
3998
3999     }
4000
4001   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4002
4003   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4004     {
4005       CLRC;
4006     }
4007   else
4008     {
4009       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4010       lit = -(long) lit;
4011     }
4012
4013
4014   /* if literal, add a,#-lit, else normal subb */
4015   _startLazyDPSEvaluation ();
4016   while (size--)
4017     {
4018       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4019       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4020         emitcode ("subb", "a,%s",
4021                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4022       else
4023         {
4024           /* first add without previous c */
4025           if (!offset) {
4026             if (!size && lit==-1) {
4027               emitcode ("dec", "a");
4028             } else {
4029               emitcode ("add", "a,#!constbyte",
4030                         (unsigned int) (lit & 0x0FFL));
4031             }
4032           } else {
4033             emitcode ("addc", "a,#!constbyte",
4034                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4035           }
4036         }
4037
4038       if (pushResult)
4039         {
4040           emitcode ("push", "acc");
4041         }
4042       else
4043         {
4044           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4045         }
4046       offset++;
4047     }
4048   _endLazyDPSEvaluation ();
4049
4050   if (pushResult)
4051     {
4052       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4053
4054       size = getDataSize (IC_LEFT (ic));
4055       rSize = getDataSize (IC_RESULT (ic));
4056
4057       ADJUST_PUSHED_RESULT(size, rSize);
4058
4059       _startLazyDPSEvaluation ();
4060       while (size--)
4061         {
4062           emitcode ("pop", "acc");
4063           aopPut (AOP (IC_RESULT (ic)), "a", size);
4064         }
4065       _endLazyDPSEvaluation ();
4066     }
4067
4068   adjustArithmeticResult (ic);
4069
4070 release:
4071   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4072   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4073   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4074 }
4075
4076
4077 /*-----------------------------------------------------------------*/
4078 /* genMultbits :- multiplication of bits                           */
4079 /*-----------------------------------------------------------------*/
4080 static void
4081 genMultbits (operand * left,
4082              operand * right,
4083              operand * result,
4084              iCode   * ic)
4085 {
4086   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4087   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4088   aopOp(result, ic, TRUE, FALSE);
4089   outBitC (result);
4090 }
4091
4092
4093 /*-----------------------------------------------------------------*/
4094 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4095 /*-----------------------------------------------------------------*/
4096 static void
4097 genMultOneByte (operand * left,
4098                 operand * right,
4099                 operand * result,
4100                 iCode   * ic)
4101 {
4102   sym_link *opetype = operandType (result);
4103   symbol *lbl;
4104
4105
4106   /* (if two literals: the value is computed before) */
4107   /* if one literal, literal on the right */
4108   if (AOP_TYPE (left) == AOP_LIT)
4109     {
4110       operand *t = right;
4111       right = left;
4112       left = t;
4113       emitcode (";", "swapped left and right");
4114     }
4115
4116   if (SPEC_USIGN(opetype)
4117       // ignore the sign of left and right, what else can we do?
4118       || (SPEC_USIGN(operandType(left)) && 
4119           SPEC_USIGN(operandType(right)))) {
4120     // just an unsigned 8*8=8/16 multiply
4121     //emitcode (";","unsigned");
4122     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4123     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4124     emitcode ("mul", "ab");
4125    
4126     _G.accInUse++; _G.bInUse++;
4127     aopOp(result, ic, TRUE, FALSE);
4128       
4129       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4130       {
4131           // this should never happen
4132           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4133                    AOP_SIZE(result), __FILE__, lineno);
4134           exit (1);
4135       }      
4136       
4137     aopPut (AOP (result), "a", 0);
4138     _G.accInUse--; _G.bInUse--;
4139     if (AOP_SIZE(result)==2) 
4140     {
4141       aopPut (AOP (result), "b", 1);
4142     }
4143     return;
4144   }
4145
4146   // we have to do a signed multiply
4147
4148   emitcode (";", "signed");
4149   emitcode ("clr", "F0"); // reset sign flag
4150   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4151
4152   lbl=newiTempLabel(NULL);
4153   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4154   // left side is negative, 8-bit two's complement, this fails for -128
4155   emitcode ("setb", "F0"); // set sign flag
4156   emitcode ("cpl", "a");
4157   emitcode ("inc", "a");
4158
4159   emitcode ("", "!tlabeldef", lbl->key+100);
4160
4161   /* if literal */
4162   if (AOP_TYPE(right)==AOP_LIT) {
4163     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4164     /* AND literal negative */
4165     if ((int) val < 0) {
4166       emitcode ("cpl", "F0"); // complement sign flag
4167       emitcode ("mov", "b,#!constbyte", -val);
4168     } else {
4169       emitcode ("mov", "b,#!constbyte", val);
4170     }
4171   } else {
4172     lbl=newiTempLabel(NULL);
4173     emitcode ("mov", "b,a");
4174     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4175     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4176     // right side is negative, 8-bit two's complement
4177     emitcode ("cpl", "F0"); // complement sign flag
4178     emitcode ("cpl", "a");
4179     emitcode ("inc", "a");
4180     emitcode ("", "!tlabeldef", lbl->key+100);
4181   }
4182   emitcode ("mul", "ab");
4183     
4184   _G.accInUse++;_G.bInUse++;
4185   aopOp(result, ic, TRUE, FALSE);
4186     
4187   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4188   {
4189     // this should never happen
4190       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4191                AOP_SIZE(result), __FILE__, lineno);
4192       exit (1);
4193   }    
4194     
4195   lbl=newiTempLabel(NULL);
4196   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4197   // only ONE op was negative, we have to do a 8/16-bit two's complement
4198   emitcode ("cpl", "a"); // lsb
4199   if (AOP_SIZE(result)==1) {
4200     emitcode ("inc", "a");
4201   } else {
4202     emitcode ("add", "a,#1");
4203     emitcode ("xch", "a,b");
4204     emitcode ("cpl", "a"); // msb
4205     emitcode ("addc", "a,#0");
4206     emitcode ("xch", "a,b");
4207   }
4208
4209   emitcode ("", "!tlabeldef", lbl->key+100);
4210   aopPut (AOP (result), "a", 0);
4211   _G.accInUse--;_G.bInUse--;
4212   if (AOP_SIZE(result)==2) {
4213     aopPut (AOP (result), "b", 1);
4214   }
4215 }
4216
4217 /*-----------------------------------------------------------------*/
4218 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4219 /*-----------------------------------------------------------------*/
4220 static void genMultTwoByte (operand *left, operand *right, 
4221                             operand *result, iCode *ic)
4222 {
4223         sym_link *retype = getSpec(operandType(right));
4224         sym_link *letype = getSpec(operandType(left));
4225         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4226         symbol *lbl;
4227
4228         if (AOP_TYPE (left) == AOP_LIT) {
4229                 operand *t = right;
4230                 right = left;
4231                 left = t;
4232         }
4233         /* save EA bit in F1 */
4234         lbl = newiTempLabel(NULL);
4235         emitcode ("setb","F1");
4236         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4237         emitcode ("clr","F1");
4238         emitcode("","!tlabeldef",lbl->key+100);
4239
4240         /* load up MB with right */
4241         if (!umult) {
4242                 emitcode("clr","F0");
4243                 if (AOP_TYPE(right) == AOP_LIT) {
4244                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4245                         if (val < 0) {
4246                                 emitcode("setb","F0");
4247                                 val = -val;
4248                         }
4249                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4250                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4251                 } else {
4252                         lbl = newiTempLabel(NULL);
4253                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4254                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4255                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4256                         emitcode ("xch", "a,b");
4257                         emitcode ("cpl","a");
4258                         emitcode ("add", "a,#1");
4259                         emitcode ("xch", "a,b");
4260                         emitcode ("cpl", "a"); // msb
4261                         emitcode ("addc", "a,#0");
4262                         emitcode ("setb","F0");
4263                         emitcode ("","!tlabeldef",lbl->key+100);
4264                         emitcode ("mov","mb,b");
4265                         emitcode ("mov","mb,a");
4266                 }
4267         } else {
4268                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4269                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4270         }
4271         /* load up MA with left */
4272         if (!umult) {
4273                 lbl = newiTempLabel(NULL);
4274                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4275                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4276                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4277                 emitcode ("xch", "a,b");
4278                 emitcode ("cpl","a");
4279                 emitcode ("add", "a,#1");
4280                 emitcode ("xch", "a,b");
4281                 emitcode ("cpl", "a"); // msb
4282                 emitcode ("addc","a,#0");
4283                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4284                 emitcode ("setb","F0");
4285                 emitcode ("","!tlabeldef",lbl->key+100);
4286                 emitcode ("mov","ma,b");
4287                 emitcode ("mov","ma,a");
4288         } else {
4289                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4290                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4291         }
4292         /* wait for multiplication to finish */
4293         lbl = newiTempLabel(NULL);
4294         emitcode("","!tlabeldef", lbl->key+100);
4295         emitcode("mov","a,mcnt1");
4296         emitcode("anl","a,#0x80");
4297         emitcode("jnz","!tlabel",lbl->key+100);
4298         
4299         freeAsmop (left, NULL, ic, TRUE);
4300         freeAsmop (right, NULL, ic,TRUE);
4301         aopOp(result, ic, TRUE, FALSE);
4302
4303         /* if unsigned then simple */   
4304         if (umult) {
4305                 emitcode ("mov","a,ma");
4306                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4307                 emitcode ("mov","a,ma");
4308                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4309                 aopPut(AOP(result),"ma",1);
4310                 aopPut(AOP(result),"ma",0);
4311         } else {
4312                 emitcode("push","ma");
4313                 emitcode("push","ma");
4314                 emitcode("push","ma");
4315                 MOVA("ma");
4316                 /* negate result if needed */
4317                 lbl = newiTempLabel(NULL);      
4318                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4319                 emitcode("cpl","a");
4320                 emitcode("add","a,#1");
4321                 emitcode("","!tlabeldef", lbl->key+100);
4322                 if (AOP_TYPE(result) == AOP_ACC)
4323                 {
4324                     D(emitcode(";", "ACC special case."););
4325                     /* We know result is the only live aop, and 
4326                      * it's obviously not a DPTR2, so AP is available.
4327                      */
4328                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4329                 }
4330                 else
4331                 {
4332                     aopPut(AOP(result),"a",0);
4333                 }
4334             
4335                 emitcode("pop","acc");
4336                 lbl = newiTempLabel(NULL);      
4337                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4338                 emitcode("cpl","a");
4339                 emitcode("addc","a,#0");
4340                 emitcode("","!tlabeldef", lbl->key+100);
4341                 aopPut(AOP(result),"a",1);
4342                 emitcode("pop","acc");
4343                 if (AOP_SIZE(result) >= 3) {
4344                         lbl = newiTempLabel(NULL);      
4345                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4346                         emitcode("cpl","a");
4347                         emitcode("addc","a,#0");                        
4348                         emitcode("","!tlabeldef", lbl->key+100);
4349                         aopPut(AOP(result),"a",2);
4350                 }
4351                 emitcode("pop","acc");
4352                 if (AOP_SIZE(result) >= 4) {
4353                         lbl = newiTempLabel(NULL);      
4354                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4355                         emitcode("cpl","a");
4356                         emitcode("addc","a,#0");                        
4357                         emitcode("","!tlabeldef", lbl->key+100);
4358                         aopPut(AOP(result),"a",3);
4359                 }
4360                 if (AOP_TYPE(result) == AOP_ACC)
4361                 {
4362                     /* We stashed the result away above. */
4363                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4364                 }           
4365                 
4366         }
4367         freeAsmop (result, NULL, ic, TRUE);
4368
4369         /* restore EA bit in F1 */
4370         lbl = newiTempLabel(NULL);
4371         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4372         emitcode ("setb","EA");
4373         emitcode("","!tlabeldef",lbl->key+100);
4374         return ;
4375 }
4376
4377 /*-----------------------------------------------------------------*/
4378 /* genMult - generates code for multiplication                     */
4379 /*-----------------------------------------------------------------*/
4380 static void
4381 genMult (iCode * ic)
4382 {
4383   operand *left = IC_LEFT (ic);
4384   operand *right = IC_RIGHT (ic);
4385   operand *result = IC_RESULT (ic);
4386
4387   D (emitcode (";", "genMult "););
4388
4389   /* assign the amsops */
4390   AOP_OP_2 (ic);
4391
4392   /* special cases first */
4393   /* both are bits */
4394   if (AOP_TYPE (left) == AOP_CRY &&
4395       AOP_TYPE (right) == AOP_CRY)
4396     {
4397       genMultbits (left, right, result, ic);
4398       goto release;
4399     }
4400
4401   /* if both are of size == 1 */
4402   if (AOP_SIZE (left) == 1 &&
4403       AOP_SIZE (right) == 1)
4404     {
4405       genMultOneByte (left, right, result, ic);
4406       goto release;
4407     }
4408
4409   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4410           /* use the ds390 ARITHMETIC accel UNIT */
4411           genMultTwoByte (left, right, result, ic);
4412           return ;
4413   }
4414   /* should have been converted to function call */
4415   assert (0);
4416
4417 release:
4418   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4419   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4420   freeAsmop (result, NULL, ic, TRUE);
4421 }
4422
4423 /*-----------------------------------------------------------------*/
4424 /* genDivbits :- division of bits                                  */
4425 /*-----------------------------------------------------------------*/
4426 static void
4427 genDivbits (operand * left,
4428             operand * right,
4429             operand * result,
4430             iCode   * ic)
4431 {
4432
4433   char *l;
4434
4435   /* the result must be bit */
4436   LOAD_AB_FOR_DIV (left, right, l);
4437   emitcode ("div", "ab");
4438   emitcode ("rrc", "a");
4439   aopOp(result, ic, TRUE, FALSE);
4440     
4441   aopPut (AOP (result), "c", 0);
4442 }
4443
4444 /*-----------------------------------------------------------------*/
4445 /* genDivOneByte : 8 bit division                                  */
4446 /*-----------------------------------------------------------------*/
4447 static void
4448 genDivOneByte (operand * left,
4449                operand * right,
4450                operand * result,
4451                iCode   * ic)
4452 {
4453   sym_link *opetype = operandType (result);
4454   char *l;
4455   symbol *lbl;
4456   int size, offset;
4457
4458   offset = 1;
4459   /* signed or unsigned */
4460   if (SPEC_USIGN (opetype))
4461     {
4462         /* unsigned is easy */
4463         LOAD_AB_FOR_DIV (left, right, l);
4464         emitcode ("div", "ab");
4465
4466         _G.accInUse++;
4467         aopOp(result, ic, TRUE, FALSE);
4468         aopPut (AOP (result), "a", 0);
4469         _G.accInUse--;
4470
4471         size = AOP_SIZE (result) - 1;
4472         
4473         while (size--)
4474         {
4475             aopPut (AOP (result), zero, offset++);
4476         }
4477       return;
4478     }
4479
4480   /* signed is a little bit more difficult */
4481
4482   /* save the signs of the operands */
4483   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4484   MOVA (l);
4485   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4486   emitcode ("push", "acc");     /* save it on the stack */
4487
4488   /* now sign adjust for both left & right */
4489   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4490   MOVA (l);
4491   lbl = newiTempLabel (NULL);
4492   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4493   emitcode ("cpl", "a");
4494   emitcode ("inc", "a");
4495   emitcode ("", "!tlabeldef", (lbl->key + 100));
4496   emitcode ("mov", "b,a");
4497
4498   /* sign adjust left side */
4499   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4500   MOVA (l);
4501
4502   lbl = newiTempLabel (NULL);
4503   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4504   emitcode ("cpl", "a");
4505   emitcode ("inc", "a");
4506   emitcode ("", "!tlabeldef", (lbl->key + 100));
4507
4508   /* now the division */
4509   emitcode ("nop", "; workaround for DS80C390 div bug.");
4510   emitcode ("div", "ab");
4511   /* we are interested in the lower order
4512      only */
4513   emitcode ("mov", "b,a");
4514   lbl = newiTempLabel (NULL);
4515   emitcode ("pop", "acc");
4516   /* if there was an over flow we don't
4517      adjust the sign of the result */
4518   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4519   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4520   CLRC;
4521   emitcode ("clr", "a");
4522   emitcode ("subb", "a,b");
4523   emitcode ("mov", "b,a");
4524   emitcode ("", "!tlabeldef", (lbl->key + 100));
4525
4526   /* now we are done */
4527   _G.accInUse++;     _G.bInUse++;
4528     aopOp(result, ic, TRUE, FALSE);
4529     
4530     aopPut (AOP (result), "b", 0);
4531     
4532     size = AOP_SIZE (result) - 1;
4533     
4534     if (size > 0)
4535     {
4536       emitcode ("mov", "c,b.7");
4537       emitcode ("subb", "a,acc");
4538     }
4539     while (size--)
4540     {
4541         aopPut (AOP (result), "a", offset++);
4542     }
4543     _G.accInUse--;     _G.bInUse--;
4544
4545 }
4546
4547 /*-----------------------------------------------------------------*/
4548 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4549 /*-----------------------------------------------------------------*/
4550 static void genDivTwoByte (operand *left, operand *right, 
4551                             operand *result, iCode *ic)
4552 {
4553         sym_link *retype = getSpec(operandType(right));
4554         sym_link *letype = getSpec(operandType(left));
4555         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4556         symbol *lbl;
4557
4558         /* save EA bit in F1 */
4559         lbl = newiTempLabel(NULL);
4560         emitcode ("setb","F1");
4561         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4562         emitcode ("clr","F1");
4563         emitcode("","!tlabeldef",lbl->key+100);
4564
4565         /* load up MA with left */
4566         if (!umult) {
4567                 emitcode("clr","F0");
4568                 lbl = newiTempLabel(NULL);
4569                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4570                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4571                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4572                 emitcode ("xch", "a,b");
4573                 emitcode ("cpl","a");
4574                 emitcode ("add", "a,#1");
4575                 emitcode ("xch", "a,b");
4576                 emitcode ("cpl", "a"); // msb
4577                 emitcode ("addc","a,#0");
4578                 emitcode ("setb","F0");
4579                 emitcode ("","!tlabeldef",lbl->key+100);
4580                 emitcode ("mov","ma,b");
4581                 emitcode ("mov","ma,a");
4582         } else {
4583                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4584                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4585         }
4586
4587         /* load up MB with right */
4588         if (!umult) {
4589                 if (AOP_TYPE(right) == AOP_LIT) {
4590                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4591                         if (val < 0) {
4592                                 lbl = newiTempLabel(NULL);
4593                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4594                                 emitcode("setb","F0");
4595                                 emitcode ("","!tlabeldef",lbl->key+100);
4596                                 val = -val;
4597                         } 
4598                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4599                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4600                 } else {
4601                         lbl = newiTempLabel(NULL);
4602                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4603                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4604                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4605                         emitcode ("xch", "a,b");
4606                         emitcode ("cpl","a");
4607                         emitcode ("add", "a,#1");
4608                         emitcode ("xch", "a,b");
4609                         emitcode ("cpl", "a"); // msb
4610                         emitcode ("addc", "a,#0");
4611                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4612                         emitcode ("setb","F0");
4613                         emitcode ("","!tlabeldef",lbl->key+100);
4614                         emitcode ("mov","mb,b");
4615                         emitcode ("mov","mb,a");
4616                 }
4617         } else {
4618                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4619                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4620         }
4621
4622         /* wait for multiplication to finish */
4623         lbl = newiTempLabel(NULL);
4624         emitcode("","!tlabeldef", lbl->key+100);
4625         emitcode("mov","a,mcnt1");
4626         emitcode("anl","a,#0x80");
4627         emitcode("jnz","!tlabel",lbl->key+100);
4628         
4629         freeAsmop (left, NULL, ic, TRUE);
4630         freeAsmop (right, NULL, ic,TRUE);
4631         aopOp(result, ic, TRUE, FALSE);
4632
4633         /* if unsigned then simple */   
4634         if (umult) {
4635                 aopPut(AOP(result),"ma",1);
4636                 aopPut(AOP(result),"ma",0);
4637         } else {
4638                 emitcode("push","ma");
4639                 MOVA("ma");
4640                 /* negate result if needed */
4641                 lbl = newiTempLabel(NULL);      
4642                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4643                 emitcode("cpl","a");
4644                 emitcode("add","a,#1");
4645                 emitcode("","!tlabeldef", lbl->key+100);
4646                 aopPut(AOP(result),"a",0);
4647                 emitcode("pop","acc");
4648                 lbl = newiTempLabel(NULL);      
4649                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4650                 emitcode("cpl","a");
4651                 emitcode("addc","a,#0");
4652                 emitcode("","!tlabeldef", lbl->key+100);
4653                 aopPut(AOP(result),"a",1);
4654         }
4655         freeAsmop (result, NULL, ic, TRUE);
4656         /* restore EA bit in F1 */
4657         lbl = newiTempLabel(NULL);
4658         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4659         emitcode ("setb","EA");
4660         emitcode("","!tlabeldef",lbl->key+100);
4661         return ;
4662 }
4663
4664 /*-----------------------------------------------------------------*/
4665 /* genDiv - generates code for division                            */
4666 /*-----------------------------------------------------------------*/
4667 static void
4668 genDiv (iCode * ic)
4669 {
4670   operand *left = IC_LEFT (ic);
4671   operand *right = IC_RIGHT (ic);
4672   operand *result = IC_RESULT (ic);
4673
4674   D (emitcode (";", "genDiv "););
4675
4676   /* assign the amsops */
4677   AOP_OP_2 (ic);
4678
4679   /* special cases first */
4680   /* both are bits */
4681   if (AOP_TYPE (left) == AOP_CRY &&
4682       AOP_TYPE (right) == AOP_CRY)
4683     {
4684       genDivbits (left, right, result, ic);
4685       goto release;
4686     }
4687
4688   /* if both are of size == 1 */
4689   if (AOP_SIZE (left) == 1 &&
4690       AOP_SIZE (right) == 1)
4691     {
4692       genDivOneByte (left, right, result, ic);
4693       goto release;
4694     }
4695
4696   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4697           /* use the ds390 ARITHMETIC accel UNIT */
4698           genDivTwoByte (left, right, result, ic);
4699           return ;
4700   }
4701   /* should have been converted to function call */
4702   assert (0);
4703 release:
4704   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706   freeAsmop (result, NULL, ic, TRUE);
4707 }
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genModbits :- modulus of bits                                   */
4711 /*-----------------------------------------------------------------*/
4712 static void
4713 genModbits (operand * left,
4714             operand * right,
4715             operand * result,
4716             iCode   * ic)
4717 {
4718
4719   char *l;
4720
4721   /* the result must be bit */
4722   LOAD_AB_FOR_DIV (left, right, l);
4723   emitcode ("div", "ab");
4724   emitcode ("mov", "a,b");
4725   emitcode ("rrc", "a");
4726   aopOp(result, ic, TRUE, FALSE);
4727   aopPut (AOP (result), "c", 0);
4728 }
4729
4730 /*-----------------------------------------------------------------*/
4731 /* genModOneByte : 8 bit modulus                                   */
4732 /*-----------------------------------------------------------------*/
4733 static void
4734 genModOneByte (operand * left,
4735                operand * right,
4736                operand * result,
4737                iCode   * ic)
4738 {
4739   sym_link *opetype = operandType (result);
4740   char *l;
4741   symbol *lbl;
4742
4743   /* signed or unsigned */
4744   if (SPEC_USIGN (opetype))
4745     {
4746       /* unsigned is easy */
4747       LOAD_AB_FOR_DIV (left, right, l);
4748       emitcode ("div", "ab");
4749       aopOp(result, ic, TRUE, FALSE);   
4750       aopPut (AOP (result), "b", 0);
4751       return;
4752     }
4753
4754   /* signed is a little bit more difficult */
4755
4756   /* save the signs of the operands */
4757   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4758   MOVA (l);
4759
4760   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4761   emitcode ("push", "acc");     /* save it on the stack */
4762
4763   /* now sign adjust for both left & right */
4764   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4765   MOVA (l);
4766
4767   lbl = newiTempLabel (NULL);
4768   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4769   emitcode ("cpl", "a");
4770   emitcode ("inc", "a");
4771   emitcode ("", "!tlabeldef", (lbl->key + 100));
4772   emitcode ("mov", "b,a");
4773
4774   /* sign adjust left side */
4775   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4776   MOVA (l);
4777
4778   lbl = newiTempLabel (NULL);
4779   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4780   emitcode ("cpl", "a");
4781   emitcode ("inc", "a");
4782   emitcode ("", "!tlabeldef", (lbl->key + 100));
4783
4784   /* now the multiplication */
4785   emitcode ("nop", "; workaround for DS80C390 div bug.");
4786   emitcode ("div", "ab");
4787   /* we are interested in the lower order
4788      only */
4789   lbl = newiTempLabel (NULL);
4790   emitcode ("pop", "acc");
4791   /* if there was an over flow we don't
4792      adjust the sign of the result */
4793   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4794   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4795   CLRC;
4796   emitcode ("clr", "a");
4797   emitcode ("subb", "a,b");
4798   emitcode ("mov", "b,a");
4799   emitcode ("", "!tlabeldef", (lbl->key + 100));
4800   
4801   _G.bInUse++;
4802   /* now we are done */
4803   aopOp(result, ic, TRUE, FALSE);    
4804   aopPut (AOP (result), "b", 0);
4805   _G.bInUse--;
4806
4807 }
4808
4809 /*-----------------------------------------------------------------*/
4810 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4811 /*-----------------------------------------------------------------*/
4812 static void genModTwoByte (operand *left, operand *right, 
4813                             operand *result, iCode *ic)
4814 {
4815         sym_link *retype = getSpec(operandType(right));
4816         sym_link *letype = getSpec(operandType(left));
4817         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4818         symbol *lbl;
4819
4820         /* load up MA with left */
4821         /* save EA bit in F1 */
4822         lbl = newiTempLabel(NULL);
4823         emitcode ("setb","F1");
4824         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4825         emitcode ("clr","F1");
4826         emitcode("","!tlabeldef",lbl->key+100);
4827
4828         if (!umult) {
4829                 lbl = newiTempLabel(NULL);
4830                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4831                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4832                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4833                 emitcode ("xch", "a,b");
4834                 emitcode ("cpl","a");
4835                 emitcode ("add", "a,#1");
4836                 emitcode ("xch", "a,b");
4837                 emitcode ("cpl", "a"); // msb
4838                 emitcode ("addc","a,#0");
4839                 emitcode ("","!tlabeldef",lbl->key+100);
4840                 emitcode ("mov","ma,b");
4841                 emitcode ("mov","ma,a");
4842         } else {
4843                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4844                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4845         }
4846
4847         /* load up MB with right */
4848         if (!umult) {
4849                 if (AOP_TYPE(right) == AOP_LIT) {
4850                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4851                         if (val < 0) {
4852                                 val = -val;
4853                         } 
4854                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4855                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4856                 } else {
4857                         lbl = newiTempLabel(NULL);
4858                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4859                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4860                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4861                         emitcode ("xch", "a,b");
4862                         emitcode ("cpl","a");
4863                         emitcode ("add", "a,#1");
4864                         emitcode ("xch", "a,b");
4865                         emitcode ("cpl", "a"); // msb
4866                         emitcode ("addc", "a,#0");
4867                         emitcode ("","!tlabeldef",lbl->key+100);
4868                         emitcode ("mov","mb,b");
4869                         emitcode ("mov","mb,a");
4870                 }
4871         } else {
4872                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4873                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4874         }
4875
4876         /* wait for multiplication to finish */
4877         lbl = newiTempLabel(NULL);
4878         emitcode("","!tlabeldef", lbl->key+100);
4879         emitcode("mov","a,mcnt1");
4880         emitcode("anl","a,#0x80");
4881         emitcode("jnz","!tlabel",lbl->key+100);
4882         
4883         freeAsmop (left, NULL, ic, TRUE);
4884         freeAsmop (right, NULL, ic,TRUE);
4885         aopOp(result, ic, TRUE, FALSE);
4886
4887         aopPut(AOP(result),"mb",1);
4888         aopPut(AOP(result),"mb",0);
4889         freeAsmop (result, NULL, ic, TRUE);
4890
4891         /* restore EA bit in F1 */
4892         lbl = newiTempLabel(NULL);
4893         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4894         emitcode ("setb","EA");
4895         emitcode("","!tlabeldef",lbl->key+100);
4896         return ;
4897 }
4898
4899 /*-----------------------------------------------------------------*/
4900 /* genMod - generates code for division                            */
4901 /*-----------------------------------------------------------------*/
4902 static void
4903 genMod (iCode * ic)
4904 {
4905   operand *left = IC_LEFT (ic);
4906   operand *right = IC_RIGHT (ic);
4907   operand *result = IC_RESULT (ic);
4908
4909   D (emitcode (";", "genMod "); );
4910
4911   /* assign the amsops */
4912   AOP_OP_2 (ic);
4913
4914   /* special cases first */
4915   /* both are bits */
4916   if (AOP_TYPE (left) == AOP_CRY &&
4917       AOP_TYPE (right) == AOP_CRY)
4918     {
4919       genModbits (left, right, result, ic);
4920       goto release;
4921     }
4922
4923   /* if both are of size == 1 */
4924   if (AOP_SIZE (left) == 1 &&
4925       AOP_SIZE (right) == 1)
4926     {
4927       genModOneByte (left, right, result, ic);
4928       goto release;
4929     }
4930
4931   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4932           /* use the ds390 ARITHMETIC accel UNIT */
4933           genModTwoByte (left, right, result, ic);
4934           return ;
4935   }
4936
4937   /* should have been converted to function call */
4938   assert (0);
4939
4940 release:
4941   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4942   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4943   freeAsmop (result, NULL, ic, TRUE);
4944 }
4945
4946 /*-----------------------------------------------------------------*/
4947 /* genIfxJump :- will create a jump depending on the ifx           */
4948 /*-----------------------------------------------------------------*/
4949 static void
4950 genIfxJump (iCode * ic, char *jval)
4951 {
4952   symbol *jlbl;
4953   symbol *tlbl = newiTempLabel (NULL);
4954   char *inst;
4955
4956   D (emitcode (";", "genIfxJump ");
4957     );
4958
4959   /* if true label then we jump if condition
4960      supplied is true */
4961   if (IC_TRUE (ic))
4962     {
4963       jlbl = IC_TRUE (ic);
4964       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4965                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4966     }
4967   else
4968     {
4969       /* false label is present */
4970       jlbl = IC_FALSE (ic);
4971       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4972                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4973     }
4974   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4975     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
4976   else
4977     emitcode (inst, "!tlabel", tlbl->key + 100);
4978   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
4979   emitcode ("", "!tlabeldef", tlbl->key + 100);
4980
4981   /* mark the icode as generated */
4982   ic->generated = 1;
4983 }
4984
4985 /*-----------------------------------------------------------------*/
4986 /* genCmp :- greater or less than comparison                       */
4987 /*-----------------------------------------------------------------*/
4988 static void
4989 genCmp (operand * left, operand * right,
4990         iCode * ic, iCode * ifx, int sign)
4991 {
4992   int size, offset = 0;
4993   unsigned long lit = 0L;
4994   operand *result;
4995
4996   D (emitcode (";", "genCmp");
4997     );
4998
4999   result = IC_RESULT (ic);
5000
5001   /* if left & right are bit variables */
5002   if (AOP_TYPE (left) == AOP_CRY &&
5003       AOP_TYPE (right) == AOP_CRY)
5004     {
5005       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5006       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5007     }
5008   else
5009     {
5010       /* subtract right from left if at the
5011          end the carry flag is set then we know that
5012          left is greater than right */
5013       size = max (AOP_SIZE (left), AOP_SIZE (right));
5014
5015       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5016       if ((size == 1) && !sign &&
5017           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5018         {
5019           symbol *lbl = newiTempLabel (NULL);
5020           emitcode ("cjne", "%s,%s,!tlabel",
5021                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5022                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5023                     lbl->key + 100);
5024           emitcode ("", "!tlabeldef", lbl->key + 100);
5025         }
5026       else
5027         {
5028           if (AOP_TYPE (right) == AOP_LIT)
5029             {
5030               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5031               /* optimize if(x < 0) or if(x >= 0) */
5032               if (lit == 0L)
5033                 {
5034                   if (!sign)
5035                     {
5036                       CLRC;
5037                     }
5038                   else
5039                     {
5040                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5041
5042                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5043                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5044
5045                       aopOp (result, ic, FALSE, FALSE);
5046
5047                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5048                         {
5049                           freeAsmop (result, NULL, ic, TRUE);
5050                           genIfxJump (ifx, "acc.7");
5051                           return;
5052                         }
5053                       else
5054                         {
5055                           emitcode ("rlc", "a");
5056                         }
5057                       goto release_freedLR;
5058                     }
5059                   goto release;
5060                 }
5061             }
5062           CLRC;
5063           while (size--)
5064             {
5065               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5066               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5067               //emitcode (";", "genCmp #2");
5068               if (sign && (size == 0))
5069                 {
5070                   //emitcode (";", "genCmp #3");
5071                   emitcode ("xrl", "a,#0x80");
5072                   if (AOP_TYPE (right) == AOP_LIT)
5073                     {
5074                       unsigned long lit = (unsigned long)
5075                       floatFromVal (AOP (right)->aopu.aop_lit);
5076                       //emitcode (";", "genCmp #3.1");
5077                       emitcode ("subb", "a,#!constbyte",
5078                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5079                     }
5080                   else
5081                     {
5082                       //emitcode (";", "genCmp #3.2");
5083                       if (AOP_NEEDSACC (right))
5084                         {
5085                           emitcode ("push", "acc");
5086                         }
5087                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5088                                                        FALSE, FALSE, FALSE));
5089                       emitcode ("xrl", "b,#0x80");
5090                       if (AOP_NEEDSACC (right))
5091                         {
5092                           emitcode ("pop", "acc");
5093                         }
5094                       emitcode ("subb", "a,b");
5095                     }
5096                 }
5097               else
5098                 {
5099                   const char *s;
5100
5101                   //emitcode (";", "genCmp #4");
5102                   if (AOP_NEEDSACC (right))
5103                     {
5104                       /* Yuck!! */
5105                       //emitcode (";", "genCmp #4.1");
5106                       emitcode ("xch", "a, b");
5107                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5108                       emitcode ("xch", "a, b");
5109                       s = "b";
5110                     }
5111                   else
5112                     {
5113                       //emitcode (";", "genCmp #4.2");
5114                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5115                     }
5116
5117                   emitcode ("subb", "a,%s", s);
5118                 }
5119             }
5120         }
5121     }
5122
5123 release:
5124 /* Don't need the left & right operands any more; do need the result. */
5125   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5126   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5127
5128   aopOp (result, ic, FALSE, FALSE);
5129
5130 release_freedLR:
5131
5132   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5133     {
5134       outBitC (result);
5135     }
5136   else
5137     {
5138       /* if the result is used in the next
5139          ifx conditional branch then generate
5140          code a little differently */
5141       if (ifx)
5142         {
5143           genIfxJump (ifx, "c");
5144         }
5145       else
5146         {
5147           outBitC (result);
5148         }
5149       /* leave the result in acc */
5150     }
5151   freeAsmop (result, NULL, ic, TRUE);
5152 }
5153
5154 /*-----------------------------------------------------------------*/
5155 /* genCmpGt :- greater than comparison                             */
5156 /*-----------------------------------------------------------------*/
5157 static void
5158 genCmpGt (iCode * ic, iCode * ifx)
5159 {
5160   operand *left, *right;
5161   sym_link *letype, *retype;
5162   int sign;
5163
5164   D (emitcode (";", "genCmpGt ");
5165     );
5166
5167   left = IC_LEFT (ic);
5168   right = IC_RIGHT (ic);
5169
5170   letype = getSpec (operandType (left));
5171   retype = getSpec (operandType (right));
5172   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5173
5174   /* assign the left & right amsops */
5175   AOP_OP_2 (ic);
5176
5177   genCmp (right, left, ic, ifx, sign);
5178 }
5179
5180 /*-----------------------------------------------------------------*/
5181 /* genCmpLt - less than comparisons                                */
5182 /*-----------------------------------------------------------------*/
5183 static void
5184 genCmpLt (iCode * ic, iCode * ifx)
5185 {
5186   operand *left, *right;
5187   sym_link *letype, *retype;
5188   int sign;
5189
5190   D (emitcode (";", "genCmpLt "););
5191
5192   left = IC_LEFT (ic);
5193   right = IC_RIGHT (ic);
5194
5195   letype = getSpec (operandType (left));
5196   retype = getSpec (operandType (right));
5197   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5198
5199   /* assign the left & right amsops */
5200   AOP_OP_2 (ic);
5201
5202   genCmp (left, right, ic, ifx, sign);
5203 }
5204
5205 /*-----------------------------------------------------------------*/
5206 /* gencjneshort - compare and jump if not equal                    */
5207 /*-----------------------------------------------------------------*/
5208 static void
5209 gencjneshort (operand * left, operand * right, symbol * lbl)
5210 {
5211   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5212   int offset = 0;
5213   unsigned long lit = 0L;
5214
5215   D (emitcode (";", "gencjneshort");
5216     );
5217
5218   /* if the left side is a literal or
5219      if the right is in a pointer register and left
5220      is not */
5221   if ((AOP_TYPE (left) == AOP_LIT) ||
5222       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5223     {
5224       operand *t = right;
5225       right = left;
5226       left = t;
5227     }
5228
5229   if (AOP_TYPE (right) == AOP_LIT)
5230     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5231
5232   if (opIsGptr (left) || opIsGptr (right))
5233     {
5234       /* We are comparing a generic pointer to something.
5235        * Exclude the generic type byte from the comparison.
5236        */
5237       size--;
5238       D (emitcode (";", "cjneshort: generic ptr special case.");
5239         )
5240     }
5241
5242
5243   /* if the right side is a literal then anything goes */
5244   if (AOP_TYPE (right) == AOP_LIT &&
5245       AOP_TYPE (left) != AOP_DIR)
5246     {
5247       while (size--)
5248         {
5249           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5250           MOVA (l);
5251           emitcode ("cjne", "a,%s,!tlabel",
5252                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5253                     lbl->key + 100);
5254           offset++;
5255         }
5256     }
5257
5258   /* if the right side is in a register or in direct space or
5259      if the left is a pointer register & right is not */
5260   else if (AOP_TYPE (right) == AOP_REG ||
5261            AOP_TYPE (right) == AOP_DIR ||
5262            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5263            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5264     {
5265       while (size--)
5266         {
5267           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5268           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5269               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5270             emitcode ("jnz", "!tlabel", lbl->key + 100);
5271           else
5272             emitcode ("cjne", "a,%s,!tlabel",
5273                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5274                       lbl->key + 100);
5275           offset++;
5276         }
5277     }
5278   else
5279     {
5280       /* right is a pointer reg need both a & b */
5281       while (size--)
5282         {
5283           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5284           if (strcmp (l, "b"))
5285             emitcode ("mov", "b,%s", l);
5286           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5287           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5288           offset++;
5289         }
5290     }
5291 }
5292
5293 /*-----------------------------------------------------------------*/
5294 /* gencjne - compare and jump if not equal                         */
5295 /*-----------------------------------------------------------------*/
5296 static void
5297 gencjne (operand * left, operand * right, symbol * lbl)
5298 {
5299   symbol *tlbl = newiTempLabel (NULL);
5300
5301   D (emitcode (";", "gencjne");
5302     );
5303
5304   gencjneshort (left, right, lbl);
5305
5306   emitcode ("mov", "a,%s", one);
5307   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5308   emitcode ("", "!tlabeldef", lbl->key + 100);
5309   emitcode ("clr", "a");
5310   emitcode ("", "!tlabeldef", tlbl->key + 100);
5311 }
5312
5313 /*-----------------------------------------------------------------*/
5314 /* genCmpEq - generates code for equal to                          */
5315 /*-----------------------------------------------------------------*/
5316 static void
5317 genCmpEq (iCode * ic, iCode * ifx)
5318 {
5319   operand *left, *right, *result;
5320
5321   D (emitcode (";", "genCmpEq ");
5322     );
5323
5324   AOP_OP_2 (ic);
5325   AOP_SET_LOCALS (ic);
5326
5327   /* if literal, literal on the right or
5328      if the right is in a pointer register and left
5329      is not */
5330   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5331       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5332     {
5333       operand *t = IC_RIGHT (ic);
5334       IC_RIGHT (ic) = IC_LEFT (ic);
5335       IC_LEFT (ic) = t;
5336     }
5337
5338   if (ifx &&                    /* !AOP_SIZE(result) */
5339       OP_SYMBOL (result) &&
5340       OP_SYMBOL (result)->regType == REG_CND)
5341     {
5342       symbol *tlbl;
5343       /* if they are both bit variables */
5344       if (AOP_TYPE (left) == AOP_CRY &&
5345           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5346         {
5347           if (AOP_TYPE (right) == AOP_LIT)
5348             {
5349               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5350               if (lit == 0L)
5351                 {
5352                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5353                   emitcode ("cpl", "c");
5354                 }
5355               else if (lit == 1L)
5356                 {
5357                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5358                 }
5359               else
5360                 {
5361                   emitcode ("clr", "c");
5362                 }
5363               /* AOP_TYPE(right) == AOP_CRY */
5364             }
5365           else
5366             {
5367               symbol *lbl = newiTempLabel (NULL);
5368               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5369               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5370               emitcode ("cpl", "c");
5371               emitcode ("", "!tlabeldef", (lbl->key + 100));
5372             }
5373           /* if true label then we jump if condition
5374              supplied is true */
5375           tlbl = newiTempLabel (NULL);
5376           if (IC_TRUE (ifx))
5377             {
5378               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5379               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5380             }
5381           else
5382             {
5383               emitcode ("jc", "!tlabel", tlbl->key + 100);
5384               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5385             }
5386           emitcode ("", "!tlabeldef", tlbl->key + 100);
5387         }
5388       else
5389         {
5390           tlbl = newiTempLabel (NULL);
5391           gencjneshort (left, right, tlbl);
5392           if (IC_TRUE (ifx))
5393             {
5394               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5395               emitcode ("", "!tlabeldef", tlbl->key + 100);
5396             }
5397           else
5398             {
5399               symbol *lbl = newiTempLabel (NULL);
5400               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5401               emitcode ("", "!tlabeldef", tlbl->key + 100);
5402               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5403               emitcode ("", "!tlabeldef", lbl->key + 100);
5404             }
5405         }
5406       /* mark the icode as generated */
5407       ifx->generated = 1;
5408
5409       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5410       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5411       return;
5412     }
5413
5414   /* if they are both bit variables */
5415   if (AOP_TYPE (left) == AOP_CRY &&
5416       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5417     {
5418       if (AOP_TYPE (right) == AOP_LIT)
5419         {
5420           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5421           if (lit == 0L)
5422             {
5423               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5424               emitcode ("cpl", "c");
5425             }
5426           else if (lit == 1L)
5427             {
5428               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5429             }
5430           else
5431             {
5432               emitcode ("clr", "c");
5433             }
5434           /* AOP_TYPE(right) == AOP_CRY */
5435         }
5436       else
5437         {
5438           symbol *lbl = newiTempLabel (NULL);
5439           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5440           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5441           emitcode ("cpl", "c");
5442           emitcode ("", "!tlabeldef", (lbl->key + 100));
5443         }
5444
5445       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5446       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5447
5448       aopOp (result, ic, TRUE, FALSE);
5449
5450       /* c = 1 if egal */
5451       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5452         {
5453           outBitC (result);
5454           goto release;
5455         }
5456       if (ifx)
5457         {
5458           genIfxJump (ifx, "c");
5459           goto release;
5460         }
5461       /* if the result is used in an arithmetic operation
5462          then put the result in place */
5463       outBitC (result);
5464     }
5465   else
5466     {
5467       gencjne (left, right, newiTempLabel (NULL));
5468
5469       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5470       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5471
5472       aopOp (result, ic, TRUE, FALSE);
5473
5474       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5475         {
5476           aopPut (AOP (result), "a", 0);
5477           goto release;
5478         }
5479       if (ifx)
5480         {
5481           genIfxJump (ifx, "a");
5482           goto release;
5483         }
5484       /* if the result is used in an arithmetic operation
5485          then put the result in place */
5486       if (AOP_TYPE (result) != AOP_CRY)
5487         outAcc (result);
5488       /* leave the result in acc */
5489     }
5490
5491 release:
5492   freeAsmop (result, NULL, ic, TRUE);
5493 }
5494
5495 /*-----------------------------------------------------------------*/
5496 /* ifxForOp - returns the icode containing the ifx for operand     */
5497 /*-----------------------------------------------------------------*/
5498 static iCode *
5499 ifxForOp (operand * op, iCode * ic)
5500 {
5501   /* if true symbol then needs to be assigned */
5502   if (IS_TRUE_SYMOP (op))
5503     return NULL;
5504
5505   /* if this has register type condition and
5506      the next instruction is ifx with the same operand
5507      and live to of the operand is upto the ifx only then */
5508   if (ic->next &&
5509       ic->next->op == IFX &&
5510       IC_COND (ic->next)->key == op->key &&
5511       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5512     return ic->next;
5513
5514   return NULL;
5515 }
5516 /*-----------------------------------------------------------------*/
5517 /* hasInc - operand is incremented before any other use            */
5518 /*-----------------------------------------------------------------*/
5519 static iCode *
5520 hasInc (operand *op, iCode *ic)
5521 {
5522   sym_link *type = operandType(op);
5523   sym_link *retype = getSpec (type);
5524   iCode *lic = ic->next;
5525   int isize ;
5526   
5527   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5528   if (!IS_SYMOP(op)) return NULL;
5529
5530   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5531   isize = getSize(type->next);
5532   while (lic) {
5533       /* if operand of the form op = op + <sizeof *op> */
5534       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5535           isOperandEqual(IC_RESULT(lic),op) && 
5536           isOperandLiteral(IC_RIGHT(lic)) &&
5537           operandLitValue(IC_RIGHT(lic)) == isize) {
5538           return lic;
5539       }
5540       /* if the operand used or deffed */
5541       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5542           return NULL;
5543       }
5544       /* if GOTO or IFX */
5545       if (lic->op == IFX || lic->op == GOTO) break;
5546       lic = lic->next;
5547   }
5548   return NULL;
5549 }
5550
5551 /*-----------------------------------------------------------------*/
5552 /* genAndOp - for && operation                                     */
5553 /*-----------------------------------------------------------------*/
5554 static void
5555 genAndOp (iCode * ic)
5556 {
5557   operand *left, *right, *result;
5558   symbol *tlbl;
5559
5560   D (emitcode (";", "genAndOp "););
5561
5562   /* note here that && operations that are in an
5563      if statement are taken away by backPatchLabels
5564      only those used in arthmetic operations remain */
5565   AOP_OP_2 (ic);
5566   AOP_SET_LOCALS (ic);
5567
5568   /* if both are bit variables */
5569   if (AOP_TYPE (left) == AOP_CRY &&
5570       AOP_TYPE (right) == AOP_CRY)
5571     {
5572       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5573       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5574       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5575       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5576   
5577       aopOp (result,ic,FALSE, FALSE);
5578       outBitC (result);
5579     }
5580   else
5581     {
5582       tlbl = newiTempLabel (NULL);
5583       toBoolean (left);
5584       emitcode ("jz", "!tlabel", tlbl->key + 100);
5585       toBoolean (right);
5586       emitcode ("", "!tlabeldef", tlbl->key + 100);
5587       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5588       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5589   
5590       aopOp (result,ic,FALSE, FALSE);
5591       outBitAcc (result);
5592     }
5593     freeAsmop (result, NULL, ic, TRUE);
5594 }
5595
5596
5597 /*-----------------------------------------------------------------*/
5598 /* genOrOp - for || operation                                      */
5599 /*-----------------------------------------------------------------*/
5600 static void
5601 genOrOp (iCode * ic)
5602 {
5603   operand *left, *right, *result;
5604   symbol *tlbl;
5605
5606   D (emitcode (";", "genOrOp "););
5607
5608   /* note here that || operations that are in an
5609      if statement are taken away by backPatchLabels
5610      only those used in arthmetic operations remain */
5611   AOP_OP_2 (ic);
5612   AOP_SET_LOCALS (ic);
5613
5614   /* if both are bit variables */
5615   if (AOP_TYPE (left) == AOP_CRY &&
5616       AOP_TYPE (right) == AOP_CRY)
5617     {
5618       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5619       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5620       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5621       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5622   
5623       aopOp (result,ic,FALSE, FALSE);
5624       
5625       outBitC (result);
5626     }
5627   else
5628     {
5629       tlbl = newiTempLabel (NULL);
5630       toBoolean (left);
5631       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5632       toBoolean (right);
5633       emitcode ("", "!tlabeldef", tlbl->key + 100);
5634       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5635       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5636   
5637       aopOp (result,ic,FALSE, FALSE);
5638       
5639       outBitAcc (result);
5640     }
5641
5642   freeAsmop (result, NULL, ic, TRUE);
5643 }
5644
5645 /*-----------------------------------------------------------------*/
5646 /* isLiteralBit - test if lit == 2^n                               */
5647 /*-----------------------------------------------------------------*/
5648 static int
5649 isLiteralBit (unsigned long lit)
5650 {
5651   unsigned long pw[32] =
5652   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5653    0x100L, 0x200L, 0x400L, 0x800L,
5654    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5655    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5656    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5657    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5658    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5659   int idx;
5660
5661   for (idx = 0; idx < 32; idx++)
5662     if (lit == pw[idx])
5663       return idx + 1;
5664   return 0;
5665 }
5666
5667 /*-----------------------------------------------------------------*/
5668 /* continueIfTrue -                                                */
5669 /*-----------------------------------------------------------------*/
5670 static void
5671 continueIfTrue (iCode * ic)
5672 {
5673   if (IC_TRUE (ic))
5674     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5675   ic->generated = 1;
5676 }
5677
5678 /*-----------------------------------------------------------------*/
5679 /* jmpIfTrue -                                                     */
5680 /*-----------------------------------------------------------------*/
5681 static void
5682 jumpIfTrue (iCode * ic)
5683 {
5684   if (!IC_TRUE (ic))
5685     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5686   ic->generated = 1;
5687 }
5688
5689 /*-----------------------------------------------------------------*/
5690 /* jmpTrueOrFalse -                                                */
5691 /*-----------------------------------------------------------------*/
5692 static void
5693 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5694 {
5695   // ugly but optimized by peephole
5696   if (IC_TRUE (ic))
5697     {
5698       symbol *nlbl = newiTempLabel (NULL);
5699       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5700       emitcode ("", "!tlabeldef", tlbl->key + 100);
5701       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5702       emitcode ("", "!tlabeldef", nlbl->key + 100);
5703     }
5704   else
5705     {
5706       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5707       emitcode ("", "!tlabeldef", tlbl->key + 100);
5708     }
5709   ic->generated = 1;
5710 }
5711
5712 // Generate code to perform a bit-wise logic operation
5713 // on two operands in far space (assumed to already have been 
5714 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5715 // in far space. This requires pushing the result on the stack
5716 // then popping it into the result.
5717 static void
5718 genFarFarLogicOp(iCode *ic, char *logicOp)
5719 {
5720       int size, resultSize, compSize;
5721       int offset = 0;
5722       
5723       TR_AP("#5");
5724       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5725       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5726                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5727       
5728       _startLazyDPSEvaluation();
5729       for (size = compSize; (size--); offset++)
5730       {
5731           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5732           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5733           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5734           
5735           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5736           emitcode ("push", "acc");
5737       }
5738       _endLazyDPSEvaluation();
5739      
5740       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5741       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5742       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5743      
5744       resultSize = AOP_SIZE(IC_RESULT(ic));
5745
5746       ADJUST_PUSHED_RESULT(compSize, resultSize);
5747
5748       _startLazyDPSEvaluation();
5749       while (compSize--)
5750       {
5751           emitcode ("pop", "acc");
5752           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5753       }
5754       _endLazyDPSEvaluation();
5755       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5756 }
5757
5758
5759 /*-----------------------------------------------------------------*/
5760 /* genAnd  - code for and                                          */
5761 /*-----------------------------------------------------------------*/
5762 static void
5763 genAnd (iCode * ic, iCode * ifx)
5764 {
5765   operand *left, *right, *result;
5766   int size, offset = 0;
5767   unsigned long lit = 0L;
5768   int bytelit = 0;
5769   char buffer[10];
5770   bool pushResult;
5771
5772   D (emitcode (";", "genAnd "););
5773
5774   AOP_OP_3_NOFATAL (ic, pushResult);
5775   AOP_SET_LOCALS (ic);
5776
5777   if (pushResult)
5778   {
5779       genFarFarLogicOp(ic, "anl");
5780       return;
5781   }  
5782
5783 #ifdef DEBUG_TYPE
5784   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5785             AOP_TYPE (result),
5786             AOP_TYPE (left), AOP_TYPE (right));
5787   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5788             AOP_SIZE (result),
5789             AOP_SIZE (left), AOP_SIZE (right));
5790 #endif
5791
5792   /* if left is a literal & right is not then exchange them */
5793   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5794 #ifdef LOGIC_OPS_BROKEN      
5795     ||  AOP_NEEDSACC (left)
5796 #endif
5797     )
5798     {
5799       operand *tmp = right;
5800       right = left;
5801       left = tmp;
5802     }
5803
5804   /* if result = right then exchange them */
5805   if (sameRegs (AOP (result), AOP (right)))
5806     {
5807       operand *tmp = right;
5808       right = left;
5809       left = tmp;
5810     }
5811
5812   /* if right is bit then exchange them */
5813   if (AOP_TYPE (right) == AOP_CRY &&
5814       AOP_TYPE (left) != AOP_CRY)
5815     {
5816       operand *tmp = right;
5817       right = left;
5818       left = tmp;
5819     }
5820   if (AOP_TYPE (right) == AOP_LIT)
5821     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5822
5823   size = AOP_SIZE (result);
5824
5825   // if(bit & yy)
5826   // result = bit & yy;
5827   if (AOP_TYPE (left) == AOP_CRY)
5828     {
5829       // c = bit & literal;
5830       if (AOP_TYPE (right) == AOP_LIT)
5831         {
5832           if (lit & 1)
5833             {
5834               if (size && sameRegs (AOP (result), AOP (left)))
5835                 // no change
5836                 goto release;
5837               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5838             }
5839           else
5840             {
5841               // bit(result) = 0;
5842               if (size && (AOP_TYPE (result) == AOP_CRY))
5843                 {
5844                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5845                   goto release;
5846                 }
5847               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5848                 {
5849                   jumpIfTrue (ifx);
5850                   goto release;
5851                 }
5852               emitcode ("clr", "c");
5853             }
5854         }
5855       else
5856         {
5857           if (AOP_TYPE (right) == AOP_CRY)
5858             {
5859               // c = bit & bit;
5860               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5861               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5862             }
5863           else
5864             {
5865               // c = bit & val;
5866               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5867               // c = lsb
5868               emitcode ("rrc", "a");
5869               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5870             }
5871         }
5872       // bit = c
5873       // val = c
5874       if (size)
5875         outBitC (result);
5876       // if(bit & ...)
5877       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5878         genIfxJump (ifx, "c");
5879       goto release;
5880     }
5881
5882   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5883   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5884   if ((AOP_TYPE (right) == AOP_LIT) &&
5885       (AOP_TYPE (result) == AOP_CRY) &&
5886       (AOP_TYPE (left) != AOP_CRY))
5887     {
5888       int posbit = isLiteralBit (lit);
5889       /* left &  2^n */
5890       if (posbit)
5891         {
5892           posbit--;
5893           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5894           // bit = left & 2^n
5895           if (size)
5896             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5897           // if(left &  2^n)
5898           else
5899             {
5900               if (ifx)
5901                 {
5902                   sprintf (buffer, "acc.%d", posbit & 0x07);
5903                   genIfxJump (ifx, buffer);
5904                 }
5905               goto release;
5906             }
5907         }
5908       else
5909         {
5910           symbol *tlbl = newiTempLabel (NULL);
5911           int sizel = AOP_SIZE (left);
5912           if (size)
5913             emitcode ("setb", "c");
5914           while (sizel--)
5915             {
5916               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5917                 {
5918                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5919                   // byte ==  2^n ?
5920                   if ((posbit = isLiteralBit (bytelit)) != 0)
5921                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5922                   else
5923                     {
5924                       if (bytelit != 0x0FFL)
5925                         emitcode ("anl", "a,%s",
5926                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5927                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5928                     }
5929                 }
5930               offset++;
5931             }
5932           // bit = left & literal
5933           if (size)
5934             {
5935               emitcode ("clr", "c");
5936               emitcode ("", "!tlabeldef", tlbl->key + 100);
5937             }
5938           // if(left & literal)
5939           else
5940             {
5941               if (ifx)
5942                 jmpTrueOrFalse (ifx, tlbl);
5943               goto release;
5944             }
5945         }
5946       outBitC (result);
5947       goto release;
5948     }
5949
5950   /* if left is same as result */
5951   if (sameRegs (AOP (result), AOP (left)))
5952     {
5953       for (; size--; offset++)
5954         {
5955           if (AOP_TYPE (right) == AOP_LIT)
5956             {
5957               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5958                 continue;
5959               else if (bytelit == 0)
5960                 aopPut (AOP (result), zero, offset);
5961               else if (IS_AOP_PREG (result))
5962                 {
5963                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5964                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5965                   aopPut (AOP (result), "a", offset);
5966                 }
5967               else
5968                 emitcode ("anl", "%s,%s",
5969                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5970                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5971             }
5972           else
5973             {
5974               if (AOP_TYPE (left) == AOP_ACC)
5975                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5976               else
5977                 {
5978                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5979                   if (IS_AOP_PREG (result))
5980                     {
5981                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5982                       aopPut (AOP (result), "a", offset);
5983
5984                     }
5985                   else
5986                     emitcode ("anl", "%s,a",
5987                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5988                 }
5989             }
5990         }
5991     }
5992   else
5993     {
5994       // left & result in different registers
5995       if (AOP_TYPE (result) == AOP_CRY)
5996         {
5997           // result = bit
5998           // if(size), result in bit
5999           // if(!size && ifx), conditional oper: if(left & right)
6000           symbol *tlbl = newiTempLabel (NULL);
6001           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6002           if (size)
6003             emitcode ("setb", "c");
6004           while (sizer--)
6005             {
6006               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6007                 emitcode ("anl", "a,%s",
6008                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6009               } else {
6010                 if (AOP_TYPE(left)==AOP_ACC) {
6011                   emitcode("mov", "b,a");
6012                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6013                   emitcode("anl", "a,b");
6014                 }else {
6015                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6016                   emitcode ("anl", "a,%s",
6017                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6018                 }
6019               }
6020               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6021               offset++;
6022             }
6023           if (size)
6024             {
6025               CLRC;
6026               emitcode ("", "!tlabeldef", tlbl->key + 100);
6027               outBitC (result);
6028             }
6029           else if (ifx)
6030             jmpTrueOrFalse (ifx, tlbl);
6031         }
6032       else
6033         {
6034           for (; (size--); offset++)
6035             {
6036               // normal case
6037               // result = left & right
6038               if (AOP_TYPE (right) == AOP_LIT)
6039                 {
6040                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6041                     {
6042                       aopPut (AOP (result),
6043                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6044                               offset);
6045                       continue;
6046                     }
6047                   else if (bytelit == 0)
6048                     {
6049                       aopPut (AOP (result), zero, offset);
6050                       continue;
6051                     }
6052                   D (emitcode (";", "better literal AND."););
6053                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6054                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6055                                                     FALSE, FALSE, FALSE));
6056
6057                 }
6058               else
6059                 {
6060                   // faster than result <- left, anl result,right
6061                   // and better if result is SFR
6062                   if (AOP_TYPE (left) == AOP_ACC)
6063                     {
6064                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6065                                                        FALSE, FALSE, FALSE));
6066                     }
6067                   else
6068                     {
6069                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6070                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6071                       {
6072                           emitcode("mov", "b,a");
6073                           rOp = "b";
6074                       }
6075                         
6076                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6077                       emitcode ("anl", "a,%s", rOp);
6078                     }                   
6079                 }
6080               aopPut (AOP (result), "a", offset);
6081             }
6082         }
6083     }
6084
6085 release:
6086   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6087   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6088   freeAsmop (result, NULL, ic, TRUE);
6089 }
6090
6091
6092 /*-----------------------------------------------------------------*/
6093 /* genOr  - code for or                                            */
6094 /*-----------------------------------------------------------------*/
6095 static void
6096 genOr (iCode * ic, iCode * ifx)
6097 {
6098   operand *left, *right, *result;
6099   int size, offset = 0;
6100   unsigned long lit = 0L;
6101   bool     pushResult;
6102
6103   D (emitcode (";", "genOr "););
6104
6105   AOP_OP_3_NOFATAL (ic, pushResult);
6106   AOP_SET_LOCALS (ic);
6107
6108   if (pushResult)
6109   {
6110       genFarFarLogicOp(ic, "orl");
6111       return;
6112   }
6113
6114
6115 #ifdef DEBUG_TYPE
6116   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6117             AOP_TYPE (result),
6118             AOP_TYPE (left), AOP_TYPE (right));
6119   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6120             AOP_SIZE (result),
6121             AOP_SIZE (left), AOP_SIZE (right));
6122 #endif
6123
6124   /* if left is a literal & right is not then exchange them */
6125   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6126 #ifdef LOGIC_OPS_BROKEN
6127    || AOP_NEEDSACC (left) // I think this is a net loss now.
6128 #endif      
6129       )
6130     {
6131       operand *tmp = right;
6132       right = left;
6133       left = tmp;
6134     }
6135
6136   /* if result = right then exchange them */
6137   if (sameRegs (AOP (result), AOP (right)))
6138     {
6139       operand *tmp = right;
6140       right = left;
6141       left = tmp;
6142     }
6143
6144   /* if right is bit then exchange them */
6145   if (AOP_TYPE (right) == AOP_CRY &&
6146       AOP_TYPE (left) != AOP_CRY)
6147     {
6148       operand *tmp = right;
6149       right = left;
6150       left = tmp;
6151     }
6152   if (AOP_TYPE (right) == AOP_LIT)
6153     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6154
6155   size = AOP_SIZE (result);
6156
6157   // if(bit | yy)
6158   // xx = bit | yy;
6159   if (AOP_TYPE (left) == AOP_CRY)
6160     {
6161       if (AOP_TYPE (right) == AOP_LIT)
6162         {
6163           // c = bit & literal;
6164           if (lit)
6165             {
6166               // lit != 0 => result = 1
6167               if (AOP_TYPE (result) == AOP_CRY)
6168                 {
6169                   if (size)
6170                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6171                   else if (ifx)
6172                     continueIfTrue (ifx);
6173                   goto release;
6174                 }
6175               emitcode ("setb", "c");
6176             }
6177           else
6178             {
6179               // lit == 0 => result = left
6180               if (size && sameRegs (AOP (result), AOP (left)))
6181                 goto release;
6182               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6183             }
6184         }
6185       else
6186         {
6187           if (AOP_TYPE (right) == AOP_CRY)
6188             {
6189               // c = bit | bit;
6190               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6191               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6192             }
6193           else
6194             {
6195               // c = bit | val;
6196               symbol *tlbl = newiTempLabel (NULL);
6197               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6198                 emitcode ("setb", "c");
6199               emitcode ("jb", "%s,!tlabel",
6200                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6201               toBoolean (right);
6202               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6203               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6204                 {
6205                   jmpTrueOrFalse (ifx, tlbl);
6206                   goto release;
6207                 }
6208               else
6209                 {
6210                   CLRC;
6211                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6212                 }
6213             }
6214         }
6215       // bit = c
6216       // val = c
6217       if (size)
6218         outBitC (result);
6219       // if(bit | ...)
6220       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6221         genIfxJump (ifx, "c");
6222       goto release;
6223     }
6224
6225   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6226   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6227   if ((AOP_TYPE (right) == AOP_LIT) &&
6228       (AOP_TYPE (result) == AOP_CRY) &&
6229       (AOP_TYPE (left) != AOP_CRY))
6230     {
6231       if (lit)
6232         {
6233           // result = 1
6234           if (size)
6235             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6236           else
6237             continueIfTrue (ifx);
6238           goto release;
6239         }
6240       else
6241         {
6242           // lit = 0, result = boolean(left)
6243           if (size)
6244             emitcode ("setb", "c");
6245           toBoolean (right);
6246           if (size)
6247             {
6248               symbol *tlbl = newiTempLabel (NULL);
6249               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6250               CLRC;
6251               emitcode ("", "!tlabeldef", tlbl->key + 100);
6252             }
6253           else
6254             {
6255               genIfxJump (ifx, "a");
6256               goto release;
6257             }
6258         }
6259       outBitC (result);
6260       goto release;
6261     }
6262
6263   /* if left is same as result */
6264   if (sameRegs (AOP (result), AOP (left)))
6265     {
6266       for (; size--; offset++)
6267         {
6268           if (AOP_TYPE (right) == AOP_LIT)
6269             {
6270               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6271                 {
6272                   continue;
6273                 }
6274               else
6275                 {
6276                   if (IS_AOP_PREG (left))
6277                     {
6278                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6279                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6280                       aopPut (AOP (result), "a", offset);
6281                     }
6282                   else
6283                     {
6284                       emitcode ("orl", "%s,%s",
6285                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6286                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6287                     }
6288                 }
6289             }
6290           else
6291             {
6292               if (AOP_TYPE (left) == AOP_ACC)
6293                 {
6294                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6295                 }
6296               else
6297                 {
6298                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6299                   if (IS_AOP_PREG (left))
6300                     {
6301                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6302                       aopPut (AOP (result), "a", offset);
6303                     }
6304                   else
6305                     {
6306                       emitcode ("orl", "%s,a",
6307                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6308                     }
6309                 }
6310             }
6311         }
6312     }
6313   else
6314     {
6315       // left & result in different registers
6316       if (AOP_TYPE (result) == AOP_CRY)
6317         {
6318           // result = bit
6319           // if(size), result in bit
6320           // if(!size && ifx), conditional oper: if(left | right)
6321           symbol *tlbl = newiTempLabel (NULL);
6322           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6323           if (size)
6324             emitcode ("setb", "c");
6325           while (sizer--)
6326             {
6327               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6328                 emitcode ("orl", "a,%s",
6329                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6330               } else {
6331                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6332                 emitcode ("orl", "a,%s",
6333                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6334               }
6335               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6336               offset++;
6337             }
6338           if (size)
6339             {
6340               CLRC;
6341               emitcode ("", "!tlabeldef", tlbl->key + 100);
6342               outBitC (result);
6343             }
6344           else if (ifx)
6345             jmpTrueOrFalse (ifx, tlbl);
6346         }
6347       else
6348         {
6349             _startLazyDPSEvaluation();
6350           for (; (size--); offset++)
6351             {
6352               // normal case
6353               // result = left & right
6354               if (AOP_TYPE (right) == AOP_LIT)
6355                 {
6356                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6357                     {
6358                       aopPut (AOP (result),
6359                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6360                               offset);
6361                       continue;
6362                     }
6363                   D (emitcode (";", "better literal OR."););
6364                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6365                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6366                                                     FALSE, FALSE, FALSE));
6367
6368                 }
6369               else
6370                 {
6371                   // faster than result <- left, anl result,right
6372                   // and better if result is SFR
6373                   if (AOP_TYPE (left) == AOP_ACC)
6374                     {
6375                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6376                                                        FALSE, FALSE, FALSE));
6377                     }
6378                   else
6379                     {
6380                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6381                         
6382                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6383                       {
6384                           emitcode("mov", "b,a");
6385                           rOp = "b";
6386                       }
6387                         
6388                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6389                       emitcode ("orl", "a,%s", rOp);
6390                     }
6391                 }
6392               aopPut (AOP (result), "a", offset);
6393             }
6394             _endLazyDPSEvaluation();
6395         }
6396     }
6397
6398 release:
6399   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6400   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6401   freeAsmop (result, NULL, ic, TRUE);
6402 }
6403
6404 /*-----------------------------------------------------------------*/
6405 /* genXor - code for xclusive or                                   */
6406 /*-----------------------------------------------------------------*/
6407 static void
6408 genXor (iCode * ic, iCode * ifx)
6409 {
6410   operand *left, *right, *result;
6411   int size, offset = 0;
6412   unsigned long lit = 0L;
6413   bool pushResult;
6414
6415   D (emitcode (";", "genXor "););
6416
6417   AOP_OP_3_NOFATAL (ic, pushResult);
6418   AOP_SET_LOCALS (ic);
6419
6420   if (pushResult)
6421   {
6422       genFarFarLogicOp(ic, "xrl");
6423       return;
6424   }  
6425
6426 #ifdef DEBUG_TYPE
6427   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6428             AOP_TYPE (result),
6429             AOP_TYPE (left), AOP_TYPE (right));
6430   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6431             AOP_SIZE (result),
6432             AOP_SIZE (left), AOP_SIZE (right));
6433 #endif
6434
6435   /* if left is a literal & right is not ||
6436      if left needs acc & right does not */
6437   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6438 #ifdef LOGIC_OPS_BROKEN      
6439       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6440 #endif
6441      )
6442     {
6443       operand *tmp = right;
6444       right = left;
6445       left = tmp;
6446     }
6447
6448   /* if result = right then exchange them */
6449   if (sameRegs (AOP (result), AOP (right)))
6450     {
6451       operand *tmp = right;
6452       right = left;
6453       left = tmp;
6454     }
6455
6456   /* if right is bit then exchange them */
6457   if (AOP_TYPE (right) == AOP_CRY &&
6458       AOP_TYPE (left) != AOP_CRY)
6459     {
6460       operand *tmp = right;
6461       right = left;
6462       left = tmp;
6463     }
6464   if (AOP_TYPE (right) == AOP_LIT)
6465     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6466
6467   size = AOP_SIZE (result);
6468
6469   // if(bit ^ yy)
6470   // xx = bit ^ yy;
6471   if (AOP_TYPE (left) == AOP_CRY)
6472     {
6473       if (AOP_TYPE (right) == AOP_LIT)
6474         {
6475           // c = bit & literal;
6476           if (lit >> 1)
6477             {
6478               // lit>>1  != 0 => result = 1
6479               if (AOP_TYPE (result) == AOP_CRY)
6480                 {
6481                   if (size)
6482                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6483                   else if (ifx)
6484                     continueIfTrue (ifx);
6485                   goto release;
6486                 }
6487               emitcode ("setb", "c");
6488             }
6489           else
6490             {
6491               // lit == (0 or 1)
6492               if (lit == 0)
6493                 {
6494                   // lit == 0, result = left
6495                   if (size && sameRegs (AOP (result), AOP (left)))
6496                     goto release;
6497                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6498                 }
6499               else
6500                 {
6501                   // lit == 1, result = not(left)
6502                   if (size && sameRegs (AOP (result), AOP (left)))
6503                     {
6504                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6505                       goto release;
6506                     }
6507                   else
6508                     {
6509                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6510                       emitcode ("cpl", "c");
6511                     }
6512                 }
6513             }
6514
6515         }
6516       else
6517         {
6518           // right != literal
6519           symbol *tlbl = newiTempLabel (NULL);
6520           if (AOP_TYPE (right) == AOP_CRY)
6521             {
6522               // c = bit ^ bit;
6523               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6524             }
6525           else
6526             {
6527               int sizer = AOP_SIZE (right);
6528               // c = bit ^ val
6529               // if val>>1 != 0, result = 1
6530               emitcode ("setb", "c");
6531               while (sizer)
6532                 {
6533                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6534                   if (sizer == 1)
6535                     // test the msb of the lsb
6536                     emitcode ("anl", "a,#0xfe");
6537                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6538                   sizer--;
6539                 }
6540               // val = (0,1)
6541               emitcode ("rrc", "a");
6542             }
6543           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6544           emitcode ("cpl", "c");
6545           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6546         }
6547       // bit = c
6548       // val = c
6549       if (size)
6550         outBitC (result);
6551       // if(bit | ...)
6552       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6553         genIfxJump (ifx, "c");
6554       goto release;
6555     }
6556
6557   if (sameRegs (AOP (result), AOP (left)))
6558     {
6559       /* if left is same as result */
6560       for (; size--; offset++)
6561         {
6562           if (AOP_TYPE (right) == AOP_LIT)
6563             {
6564               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6565                 continue;
6566               else if (IS_AOP_PREG (left))
6567                 {
6568                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6569                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6570                   aopPut (AOP (result), "a", offset);
6571                 }
6572               else
6573                 emitcode ("xrl", "%s,%s",
6574                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6575                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6576             }
6577           else
6578             {
6579               if (AOP_TYPE (left) == AOP_ACC)
6580                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6581               else
6582                 {
6583                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6584                   if (IS_AOP_PREG (left))
6585                     {
6586                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6587                       aopPut (AOP (result), "a", offset);
6588                     }
6589                   else
6590                     emitcode ("xrl", "%s,a",
6591                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6592                 }
6593             }
6594         }
6595     }
6596   else
6597     {
6598       // left & result in different registers
6599       if (AOP_TYPE (result) == AOP_CRY)
6600         {
6601           // result = bit
6602           // if(size), result in bit
6603           // if(!size && ifx), conditional oper: if(left ^ right)
6604           symbol *tlbl = newiTempLabel (NULL);
6605           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6606                   
6607           if (size)
6608             emitcode ("setb", "c");
6609           while (sizer--)
6610             {
6611               if ((AOP_TYPE (right) == AOP_LIT) &&
6612                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6613                 {
6614                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6615                 }
6616               else
6617                 {
6618                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6619                     emitcode ("xrl", "a,%s",
6620                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6621                   } else {
6622                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6623                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6624                       {
6625                           emitcode("mov", "b,a");
6626                           rOp = "b";
6627                       }
6628                         
6629                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6630                       emitcode ("xrl", "a,%s", rOp);                  
6631                   }
6632                 }
6633               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6634               offset++;
6635             }
6636           if (size)
6637             {
6638               CLRC;
6639               emitcode ("", "!tlabeldef", tlbl->key + 100);
6640               outBitC (result);
6641             }
6642           else if (ifx)
6643             jmpTrueOrFalse (ifx, tlbl);
6644         }
6645       else
6646         {
6647         for (; (size--); offset++)
6648           {
6649             // normal case
6650             // result = left & right
6651             if (AOP_TYPE (right) == AOP_LIT)
6652               {
6653                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6654                   {
6655                     aopPut (AOP (result),
6656                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6657                             offset);
6658                     continue;
6659                   }
6660                 D (emitcode (";", "better literal XOR."););
6661                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6662                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6663                                                   FALSE, FALSE, FALSE));
6664               }
6665             else
6666               {
6667                 // faster than result <- left, anl result,right
6668                 // and better if result is SFR
6669                 if (AOP_TYPE (left) == AOP_ACC)
6670                   {
6671                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6672                                                      FALSE, FALSE, FALSE));
6673                   }
6674                 else
6675                   {
6676                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6677                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6678                       {
6679                           emitcode("mov", "b,a");
6680                           rOp = "b";
6681                       }
6682                         
6683                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6684                       emitcode ("xrl", "a,%s", rOp);
6685                   }
6686               }
6687             aopPut (AOP (result), "a", offset);
6688           }
6689         }
6690         
6691     }
6692
6693 release:
6694   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6695   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6696   freeAsmop (result, NULL, ic, TRUE);
6697 }
6698
6699 /*-----------------------------------------------------------------*/
6700 /* genInline - write the inline code out                           */
6701 /*-----------------------------------------------------------------*/
6702 static void
6703 genInline (iCode * ic)
6704 {
6705   char *buffer, *bp, *bp1;
6706
6707   D (emitcode (";", "genInline ");
6708     );
6709
6710   _G.inLine += (!options.asmpeep);
6711
6712   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6713   strcpy (buffer, IC_INLINE (ic));
6714
6715   /* emit each line as a code */
6716   while (*bp)
6717     {
6718       if (*bp == '\n')
6719         {
6720           *bp++ = '\0';
6721           emitcode (bp1, "");
6722           bp1 = bp;
6723         }
6724       else
6725         {
6726           if (*bp == ':')
6727             {
6728               bp++;
6729               *bp = '\0';
6730               bp++;
6731               emitcode (bp1, "");
6732               bp1 = bp;
6733             }
6734           else
6735             bp++;
6736         }
6737     }
6738   if (bp1 != bp)
6739     emitcode (bp1, "");
6740   /*     emitcode("",buffer); */
6741   _G.inLine -= (!options.asmpeep);
6742 }
6743
6744 /*-----------------------------------------------------------------*/
6745 /* genRRC - rotate right with carry                                */
6746 /*-----------------------------------------------------------------*/
6747 static void
6748 genRRC (iCode * ic)
6749 {
6750   operand *left, *result;
6751   int size, offset = 0;
6752   char *l;
6753
6754   D (emitcode (";", "genRRC ");
6755     );
6756
6757   /* rotate right with carry */
6758   left = IC_LEFT (ic);
6759   result = IC_RESULT (ic);
6760   aopOp (left, ic, FALSE, FALSE);
6761   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6762
6763   /* move it to the result */
6764   size = AOP_SIZE (result);
6765   offset = size - 1;
6766   CLRC;
6767
6768   _startLazyDPSEvaluation ();
6769   while (size--)
6770     {
6771       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6772       MOVA (l);
6773       emitcode ("rrc", "a");
6774       if (AOP_SIZE (result) > 1)
6775         aopPut (AOP (result), "a", offset--);
6776     }
6777   _endLazyDPSEvaluation ();
6778
6779   /* now we need to put the carry into the
6780      highest order byte of the result */
6781   if (AOP_SIZE (result) > 1)
6782     {
6783       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6784       MOVA (l);
6785     }
6786   emitcode ("mov", "acc.7,c");
6787   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6788   freeAsmop (left, NULL, ic, TRUE);
6789   freeAsmop (result, NULL, ic, TRUE);
6790 }
6791
6792 /*-----------------------------------------------------------------*/
6793 /* genRLC - generate code for rotate left with carry               */
6794 /*-----------------------------------------------------------------*/
6795 static void
6796 genRLC (iCode * ic)
6797 {
6798   operand *left, *result;
6799   int size, offset = 0;
6800   char *l;
6801
6802   D (emitcode (";", "genRLC ");
6803     );
6804
6805   /* rotate right with carry */
6806   left = IC_LEFT (ic);
6807   result = IC_RESULT (ic);
6808   aopOp (left, ic, FALSE, FALSE);
6809   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6810
6811   /* move it to the result */
6812   size = AOP_SIZE (result);
6813   offset = 0;
6814   if (size--)
6815     {
6816       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6817       MOVA (l);
6818       emitcode ("add", "a,acc");
6819       if (AOP_SIZE (result) > 1)
6820         {
6821           aopPut (AOP (result), "a", offset++);
6822         }
6823
6824       _startLazyDPSEvaluation ();
6825       while (size--)
6826         {
6827           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6828           MOVA (l);
6829           emitcode ("rlc", "a");
6830           if (AOP_SIZE (result) > 1)
6831             aopPut (AOP (result), "a", offset++);
6832         }
6833       _endLazyDPSEvaluation ();
6834     }
6835   /* now we need to put the carry into the
6836      highest order byte of the result */
6837   if (AOP_SIZE (result) > 1)
6838     {
6839       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6840       MOVA (l);
6841     }
6842   emitcode ("mov", "acc.0,c");
6843   aopPut (AOP (result), "a", 0);
6844   freeAsmop (left, NULL, ic, TRUE);
6845   freeAsmop (result, NULL, ic, TRUE);
6846 }
6847
6848 /*-----------------------------------------------------------------*/
6849 /* genGetHbit - generates code get highest order bit               */
6850 /*-----------------------------------------------------------------*/
6851 static void
6852 genGetHbit (iCode * ic)
6853 {
6854   operand *left, *result;
6855   left = IC_LEFT (ic);
6856   result = IC_RESULT (ic);
6857   aopOp (left, ic, FALSE, FALSE);
6858   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6859
6860   D (emitcode (";", "genGetHbit ");
6861     );
6862
6863   /* get the highest order byte into a */
6864   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6865   if (AOP_TYPE (result) == AOP_CRY)
6866     {
6867       emitcode ("rlc", "a");
6868       outBitC (result);
6869     }
6870   else
6871     {
6872       emitcode ("rl", "a");
6873       emitcode ("anl", "a,#0x01");
6874       outAcc (result);
6875     }
6876
6877
6878   freeAsmop (left, NULL, ic, TRUE);
6879   freeAsmop (result, NULL, ic, TRUE);
6880 }
6881
6882 /*-----------------------------------------------------------------*/
6883 /* AccRol - rotate left accumulator by known count                 */
6884 /*-----------------------------------------------------------------*/
6885 static void
6886 AccRol (int shCount)
6887 {
6888   shCount &= 0x0007;            // shCount : 0..7
6889
6890   switch (shCount)
6891     {
6892     case 0:
6893       break;
6894     case 1:
6895       emitcode ("rl", "a");
6896       break;
6897     case 2:
6898       emitcode ("rl", "a");
6899       emitcode ("rl", "a");
6900       break;
6901     case 3:
6902       emitcode ("swap", "a");
6903       emitcode ("rr", "a");
6904       break;
6905     case 4:
6906       emitcode ("swap", "a");
6907       break;
6908     case 5:
6909       emitcode ("swap", "a");
6910       emitcode ("rl", "a");
6911       break;
6912     case 6:
6913       emitcode ("rr", "a");
6914       emitcode ("rr", "a");
6915       break;
6916     case 7:
6917       emitcode ("rr", "a");
6918       break;
6919     }
6920 }
6921
6922 /*-----------------------------------------------------------------*/
6923 /* AccLsh - left shift accumulator by known count                  */
6924 /*-----------------------------------------------------------------*/
6925 static void
6926 AccLsh (int shCount)
6927 {
6928   if (shCount != 0)
6929     {
6930       if (shCount == 1)
6931         emitcode ("add", "a,acc");
6932       else if (shCount == 2)
6933         {
6934           emitcode ("add", "a,acc");
6935           emitcode ("add", "a,acc");
6936         }
6937       else
6938         {
6939           /* rotate left accumulator */
6940           AccRol (shCount);
6941           /* and kill the lower order bits */
6942           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
6943         }
6944     }
6945 }
6946
6947 /*-----------------------------------------------------------------*/
6948 /* AccRsh - right shift accumulator by known count                 */
6949 /*-----------------------------------------------------------------*/
6950 static void
6951 AccRsh (int shCount)
6952 {
6953   if (shCount != 0)
6954     {
6955       if (shCount == 1)
6956         {
6957           CLRC;
6958           emitcode ("rrc", "a");
6959         }
6960       else
6961         {
6962           /* rotate right accumulator */
6963           AccRol (8 - shCount);
6964           /* and kill the higher order bits */
6965           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6966         }
6967     }
6968 }
6969
6970 #ifdef BETTER_LITERAL_SHIFT
6971 /*-----------------------------------------------------------------*/
6972 /* AccSRsh - signed right shift accumulator by known count                 */
6973 /*-----------------------------------------------------------------*/
6974 static void
6975 AccSRsh (int shCount)
6976 {
6977   symbol *tlbl;
6978   if (shCount != 0)
6979     {
6980       if (shCount == 1)
6981         {
6982           emitcode ("mov", "c,acc.7");
6983           emitcode ("rrc", "a");
6984         }
6985       else if (shCount == 2)
6986         {
6987           emitcode ("mov", "c,acc.7");
6988           emitcode ("rrc", "a");
6989           emitcode ("mov", "c,acc.7");
6990           emitcode ("rrc", "a");
6991         }
6992       else
6993         {
6994           tlbl = newiTempLabel (NULL);
6995           /* rotate right accumulator */
6996           AccRol (8 - shCount);
6997           /* and kill the higher order bits */
6998           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6999           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7000           emitcode ("orl", "a,#!constbyte",
7001                     (unsigned char) ~SRMask[shCount]);
7002           emitcode ("", "!tlabeldef", tlbl->key + 100);
7003         }
7004     }
7005 }
7006 #endif
7007
7008 #ifdef BETTER_LITERAL_SHIFT
7009 /*-----------------------------------------------------------------*/
7010 /* shiftR1Left2Result - shift right one byte from left to result   */
7011 /*-----------------------------------------------------------------*/
7012 static void
7013 shiftR1Left2Result (operand * left, int offl,
7014                     operand * result, int offr,
7015                     int shCount, int sign)
7016 {
7017   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7018   /* shift right accumulator */
7019   if (sign)
7020     AccSRsh (shCount);
7021   else
7022     AccRsh (shCount);
7023   aopPut (AOP (result), "a", offr);
7024 }
7025 #endif
7026
7027 #ifdef BETTER_LITERAL_SHIFT
7028 /*-----------------------------------------------------------------*/
7029 /* shiftL1Left2Result - shift left one byte from left to result    */
7030 /*-----------------------------------------------------------------*/
7031 static void
7032 shiftL1Left2Result (operand * left, int offl,
7033                     operand * result, int offr, int shCount)
7034 {
7035   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7036   /* shift left accumulator */
7037   AccLsh (shCount);
7038   aopPut (AOP (result), "a", offr);
7039 }
7040 #endif
7041
7042 #ifdef BETTER_LITERAL_SHIFT
7043 /*-----------------------------------------------------------------*/
7044 /* movLeft2Result - move byte from left to result                  */
7045 /*-----------------------------------------------------------------*/
7046 static void
7047 movLeft2Result (operand * left, int offl,
7048                 operand * result, int offr, int sign)
7049 {
7050   char *l;
7051   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7052   {
7053       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7054
7055       if (*l == '@' && (IS_AOP_PREG (result)))
7056       {
7057           emitcode ("mov", "a,%s", l);
7058           aopPut (AOP (result), "a", offr);
7059       }
7060       else
7061       {
7062           if (!sign)
7063           {
7064             aopPut (AOP (result), l, offr);
7065           }
7066           else
7067             {
7068               /* MSB sign in acc.7 ! */
7069               if (getDataSize (left) == offl + 1)
7070                 {
7071                   emitcode ("mov", "a,%s", l);
7072                   aopPut (AOP (result), "a", offr);
7073                 }
7074             }
7075       }
7076   }
7077 }
7078 #endif
7079
7080 #ifdef BETTER_LITERAL_SHIFT
7081 /*-----------------------------------------------------------------*/
7082 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7083 /*-----------------------------------------------------------------*/
7084 static void
7085 AccAXRrl1 (char *x)
7086 {
7087   emitcode ("rrc", "a");
7088   emitcode ("xch", "a,%s", x);
7089   emitcode ("rrc", "a");
7090   emitcode ("xch", "a,%s", x);
7091 }
7092 #endif
7093
7094 #ifdef BETTER_LITERAL_SHIFT
7095 //REMOVE ME!!!
7096 /*-----------------------------------------------------------------*/
7097 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7098 /*-----------------------------------------------------------------*/
7099 static void
7100 AccAXLrl1 (char *x)
7101 {
7102   emitcode ("xch", "a,%s", x);
7103   emitcode ("rlc", "a");
7104   emitcode ("xch", "a,%s", x);
7105   emitcode ("rlc", "a");
7106 }
7107 #endif
7108
7109 #ifdef BETTER_LITERAL_SHIFT
7110 /*-----------------------------------------------------------------*/
7111 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7112 /*-----------------------------------------------------------------*/
7113 static void
7114 AccAXLsh1 (char *x)
7115 {
7116   emitcode ("xch", "a,%s", x);
7117   emitcode ("add", "a,acc");
7118   emitcode ("xch", "a,%s", x);
7119   emitcode ("rlc", "a");
7120 }
7121 #endif
7122
7123 #ifdef BETTER_LITERAL_SHIFT
7124 /*-----------------------------------------------------------------*/
7125 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7126 /*-----------------------------------------------------------------*/
7127 static void
7128 AccAXLsh (char *x, int shCount)
7129 {
7130   switch (shCount)
7131     {
7132     case 0:
7133       break;
7134     case 1:
7135       AccAXLsh1 (x);
7136       break;
7137     case 2:
7138       AccAXLsh1 (x);
7139       AccAXLsh1 (x);
7140       break;
7141     case 3:
7142     case 4:
7143     case 5:                     // AAAAABBB:CCCCCDDD
7144
7145       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7146
7147       emitcode ("anl", "a,#!constbyte",
7148                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7149
7150       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7151
7152       AccRol (shCount);         // DDDCCCCC:BBB00000
7153
7154       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7155
7156       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7157
7158       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7159
7160       emitcode ("anl", "a,#!constbyte",
7161                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7162
7163       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7164
7165       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7166
7167       break;
7168     case 6:                     // AAAAAABB:CCCCCCDD
7169       emitcode ("anl", "a,#!constbyte",
7170                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7171       emitcode ("mov", "c,acc.0");      // c = B
7172       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7173 #if 0
7174       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7175       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7176 #else
7177       emitcode("rrc","a"); 
7178       emitcode("xch","a,%s", x); 
7179       emitcode("rrc","a"); 
7180       emitcode("mov","c,acc.0"); //<< get correct bit 
7181       emitcode("xch","a,%s", x); 
7182
7183       emitcode("rrc","a"); 
7184       emitcode("xch","a,%s", x); 
7185       emitcode("rrc","a"); 
7186       emitcode("xch","a,%s", x); 
7187 #endif
7188       break;
7189     case 7:                     // a:x <<= 7
7190
7191       emitcode ("anl", "a,#!constbyte",
7192                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7193
7194       emitcode ("mov", "c,acc.0");      // c = B
7195
7196       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7197
7198       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7199
7200       break;
7201     default:
7202       break;
7203     }
7204 }
7205 #endif
7206
7207 #ifdef BETTER_LITERAL_SHIFT
7208 //REMOVE ME!!!
7209 /*-----------------------------------------------------------------*/
7210 /* AccAXRsh - right shift a:x known count (0..7)                   */
7211 /*-----------------------------------------------------------------*/
7212 static void
7213 AccAXRsh (char *x, int shCount)
7214 {
7215   switch (shCount)
7216     {
7217     case 0:
7218       break;
7219     case 1:
7220       CLRC;
7221       AccAXRrl1 (x);            // 0->a:x
7222
7223       break;
7224     case 2:
7225       CLRC;
7226       AccAXRrl1 (x);            // 0->a:x
7227
7228       CLRC;
7229       AccAXRrl1 (x);            // 0->a:x
7230
7231       break;
7232     case 3:
7233     case 4:
7234     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7235
7236       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7237
7238       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7239
7240       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7241
7242       emitcode ("anl", "a,#!constbyte",
7243                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7244
7245       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7246
7247       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7248
7249       emitcode ("anl", "a,#!constbyte",
7250                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7251
7252       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7253
7254       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7255
7256       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7257
7258       break;
7259     case 6:                     // AABBBBBB:CCDDDDDD
7260
7261       emitcode ("mov", "c,acc.7");
7262       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7263
7264       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7265
7266       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7267
7268       emitcode ("anl", "a,#!constbyte",
7269                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7270
7271       break;
7272     case 7:                     // ABBBBBBB:CDDDDDDD
7273
7274       emitcode ("mov", "c,acc.7");      // c = A
7275
7276       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7277
7278       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7279
7280       emitcode ("anl", "a,#!constbyte",
7281                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7282
7283       break;
7284     default:
7285       break;
7286     }
7287 }
7288 #endif
7289
7290 #ifdef BETTER_LITERAL_SHIFT
7291 /*-----------------------------------------------------------------*/
7292 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7293 /*-----------------------------------------------------------------*/
7294 static void
7295 AccAXRshS (char *x, int shCount)
7296 {
7297   symbol *tlbl;
7298   switch (shCount)
7299     {
7300     case 0:
7301       break;
7302     case 1:
7303       emitcode ("mov", "c,acc.7");
7304       AccAXRrl1 (x);            // s->a:x
7305
7306       break;
7307     case 2:
7308       emitcode ("mov", "c,acc.7");
7309       AccAXRrl1 (x);            // s->a:x
7310
7311       emitcode ("mov", "c,acc.7");
7312       AccAXRrl1 (x);            // s->a:x
7313
7314       break;
7315     case 3:
7316     case 4:
7317     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7318
7319       tlbl = newiTempLabel (NULL);
7320       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7321
7322       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7323
7324       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7325
7326       emitcode ("anl", "a,#!constbyte",
7327                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7328
7329       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7330
7331       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7332
7333       emitcode ("anl", "a,#!constbyte",
7334                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7335
7336       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7337
7338       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7339
7340       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7341
7342       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7343       emitcode ("orl", "a,#!constbyte",
7344                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7345
7346       emitcode ("", "!tlabeldef", tlbl->key + 100);
7347       break;                    // SSSSAAAA:BBBCCCCC
7348
7349     case 6:                     // AABBBBBB:CCDDDDDD
7350
7351       tlbl = newiTempLabel (NULL);
7352       emitcode ("mov", "c,acc.7");
7353       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7354
7355       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7356
7357       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7358
7359       emitcode ("anl", "a,#!constbyte",
7360                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7361
7362       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7363       emitcode ("orl", "a,#!constbyte",
7364                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7365
7366       emitcode ("", "!tlabeldef", tlbl->key + 100);
7367       break;
7368     case 7:                     // ABBBBBBB:CDDDDDDD
7369
7370       tlbl = newiTempLabel (NULL);
7371       emitcode ("mov", "c,acc.7");      // c = A
7372
7373       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7374
7375       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7376
7377       emitcode ("anl", "a,#!constbyte",
7378                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7379
7380       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7381       emitcode ("orl", "a,#!constbyte",
7382                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7383
7384       emitcode ("", "!tlabeldef", tlbl->key + 100);
7385       break;
7386     default:
7387       break;
7388     }
7389 }
7390 #endif
7391
7392 #ifdef BETTER_LITERAL_SHIFT
7393 static void
7394 _loadLeftIntoAx(char    **lsb, 
7395                 operand *left, 
7396                 operand *result,
7397                 int     offl,
7398                 int     offr)
7399 {
7400   // Get the initial value from left into a pair of registers.
7401   // MSB must be in A, LSB can be any register.
7402   //
7403   // If the result is held in registers, it is an optimization
7404   // if the LSB can be held in the register which will hold the,
7405   // result LSB since this saves us from having to copy it into
7406   // the result following AccAXLsh.
7407   //
7408   // If the result is addressed indirectly, this is not a gain.
7409   if (AOP_NEEDSACC(result))
7410   {
7411        char *leftByte;
7412        
7413        _startLazyDPSEvaluation();
7414       if (AOP_TYPE(left) == AOP_DPTR2)
7415        {
7416            // Get MSB in A.
7417            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7418            // get LSB in DP2_RESULT_REG.
7419            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7420            assert(!strcmp(leftByte, DP2_RESULT_REG));
7421        }
7422        else
7423        {
7424            // get LSB into DP2_RESULT_REG
7425            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7426            if (strcmp(leftByte, DP2_RESULT_REG))
7427            {
7428                TR_AP("#7");
7429                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7430            }
7431            // And MSB in A.
7432            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7433            assert(strcmp(leftByte, DP2_RESULT_REG));
7434            MOVA(leftByte);
7435        }
7436        _endLazyDPSEvaluation();
7437        *lsb = DP2_RESULT_REG;
7438   }
7439   else
7440   {
7441       if (sameRegs (AOP (result), AOP (left)) &&
7442         ((offl + MSB16) == offr))
7443       {
7444           /* don't crash result[offr] */
7445           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7446           emitcode ("xch", "a,%s", 
7447                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7448       }
7449       else
7450       {
7451           movLeft2Result (left, offl, result, offr, 0);
7452           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7453       }
7454       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7455       assert(strcmp(*lsb,"a"));      
7456   }
7457 }
7458
7459 static void
7460 _storeAxResults(char    *lsb,
7461                 operand *result,
7462                 int     offr)
7463 {
7464   _startLazyDPSEvaluation();
7465   if (AOP_NEEDSACC(result))
7466   {
7467       /* We have to explicitly update the result LSB.
7468        */
7469       emitcode("xch","a,%s", lsb);
7470       aopPut(AOP(result), "a", offr);
7471       emitcode("mov","a,%s", lsb);
7472   }
7473   if (getDataSize (result) > 1)
7474   {
7475       aopPut (AOP (result), "a", offr + MSB16);
7476   }
7477   _endLazyDPSEvaluation();
7478 }
7479
7480 /*-----------------------------------------------------------------*/
7481 /* shiftL2Left2Result - shift left two bytes from left to result   */
7482 /*-----------------------------------------------------------------*/
7483 static void
7484 shiftL2Left2Result (operand * left, int offl,
7485                     operand * result, int offr, int shCount)
7486 {
7487   char *lsb;
7488
7489   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7490   
7491   AccAXLsh (lsb, shCount);
7492   
7493   _storeAxResults(lsb, result, offr);
7494 }
7495 #endif
7496
7497 #ifdef BETTER_LITERAL_SHIFT
7498 /*-----------------------------------------------------------------*/
7499 /* shiftR2Left2Result - shift right two bytes from left to result  */
7500 /*-----------------------------------------------------------------*/
7501 static void
7502 shiftR2Left2Result (operand * left, int offl,
7503                     operand * result, int offr,
7504                     int shCount, int sign)
7505 {
7506   char *lsb;
7507   
7508   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7509   
7510   /* a:x >> shCount (x = lsb(result)) */
7511   if (sign)
7512   {
7513      AccAXRshS(lsb, shCount);
7514   }
7515   else
7516   {
7517     AccAXRsh(lsb, shCount);
7518   }
7519   
7520   _storeAxResults(lsb, result, offr);
7521 }
7522 #endif
7523
7524 #if 0
7525 //REMOVE ME!!!
7526 /*-----------------------------------------------------------------*/
7527 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7528 /*-----------------------------------------------------------------*/
7529 static void
7530 shiftLLeftOrResult (operand * left, int offl,
7531                     operand * result, int offr, int shCount)
7532 {
7533   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7534   /* shift left accumulator */
7535   AccLsh (shCount);
7536   /* or with result */
7537   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7538   /* back to result */
7539   aopPut (AOP (result), "a", offr);
7540 }
7541 #endif
7542
7543 #if 0
7544 //REMOVE ME!!!
7545 /*-----------------------------------------------------------------*/
7546 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7547 /*-----------------------------------------------------------------*/
7548 static void
7549 shiftRLeftOrResult (operand * left, int offl,
7550                     operand * result, int offr, int shCount)
7551 {
7552   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7553   /* shift right accumulator */
7554   AccRsh (shCount);
7555   /* or with result */
7556   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7557   /* back to result */
7558   aopPut (AOP (result), "a", offr);
7559 }
7560 #endif
7561
7562 #ifdef BETTER_LITERAL_SHIFT
7563 /*-----------------------------------------------------------------*/
7564 /* genlshOne - left shift a one byte quantity by known count       */
7565 /*-----------------------------------------------------------------*/
7566 static void
7567 genlshOne (operand * result, operand * left, int shCount)
7568 {
7569   D (emitcode (";", "genlshOne "););
7570   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7571 }
7572 #endif
7573
7574 #ifdef BETTER_LITERAL_SHIFT
7575 /*-----------------------------------------------------------------*/
7576 /* genlshTwo - left shift two bytes by known amount != 0           */
7577 /*-----------------------------------------------------------------*/
7578 static void
7579 genlshTwo (operand * result, operand * left, int shCount)
7580 {
7581   int size;
7582
7583   D (emitcode (";", "genlshTwo "););
7584
7585   size = getDataSize (result);
7586
7587   /* if shCount >= 8 */
7588   if (shCount >= 8)
7589   {
7590       shCount -= 8;
7591
7592       _startLazyDPSEvaluation();
7593
7594       if (size > 1)
7595         {
7596           if (shCount)
7597           {
7598             _endLazyDPSEvaluation();
7599             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7600             aopPut (AOP (result), zero, LSB);       
7601           }
7602           else
7603           {
7604             movLeft2Result (left, LSB, result, MSB16, 0);
7605             aopPut (AOP (result), zero, LSB);
7606             _endLazyDPSEvaluation();
7607           }
7608         }
7609         else
7610         {
7611           aopPut (AOP (result), zero, LSB);
7612           _endLazyDPSEvaluation();
7613         }
7614   }
7615
7616   /*  1 <= shCount <= 7 */
7617   else
7618     {
7619       if (size == 1)
7620       {
7621         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7622       }
7623       else
7624       {
7625         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7626       }
7627     }
7628 }
7629 #endif
7630
7631 #if 0
7632 //REMOVE ME!!!
7633 /*-----------------------------------------------------------------*/
7634 /* shiftLLong - shift left one long from left to result            */
7635 /* offl = LSB or MSB16                                             */
7636 /*-----------------------------------------------------------------*/
7637 static void
7638 shiftLLong (operand * left, operand * result, int offr)
7639 {
7640   char *l;
7641   int size = AOP_SIZE (result);
7642
7643   if (size >= LSB + offr)
7644     {
7645       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7646       MOVA (l);
7647       emitcode ("add", "a,acc");
7648       if (sameRegs (AOP (left), AOP (result)) &&
7649           size >= MSB16 + offr && offr != LSB)
7650         emitcode ("xch", "a,%s",
7651                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7652       else
7653         aopPut (AOP (result), "a", LSB + offr);
7654     }
7655
7656   if (size >= MSB16 + offr)
7657     {
7658       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7659         {
7660           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7661           MOVA (l);
7662         }
7663       emitcode ("rlc", "a");
7664       if (sameRegs (AOP (left), AOP (result)) &&
7665           size >= MSB24 + offr && offr != LSB)
7666         emitcode ("xch", "a,%s",
7667                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7668       else
7669         aopPut (AOP (result), "a", MSB16 + offr);
7670     }
7671
7672   if (size >= MSB24 + offr)
7673     {
7674       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7675         {
7676           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7677           MOVA (l);
7678         }
7679       emitcode ("rlc", "a");
7680       if (sameRegs (AOP (left), AOP (result)) &&
7681           size >= MSB32 + offr && offr != LSB)
7682         emitcode ("xch", "a,%s",
7683                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7684       else
7685         aopPut (AOP (result), "a", MSB24 + offr);
7686     }
7687
7688   if (size > MSB32 + offr)
7689     {
7690       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7691         {
7692           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7693           MOVA (l);
7694         }
7695       emitcode ("rlc", "a");
7696       aopPut (AOP (result), "a", MSB32 + offr);
7697     }
7698   if (offr != LSB)
7699     aopPut (AOP (result), zero, LSB);
7700 }
7701 #endif
7702
7703 #if 0
7704 //REMOVE ME!!!
7705 /*-----------------------------------------------------------------*/
7706 /* genlshFour - shift four byte by a known amount != 0             */
7707 /*-----------------------------------------------------------------*/
7708 static void
7709 genlshFour (operand * result, operand * left, int shCount)
7710 {
7711   int size;
7712
7713   D (emitcode (";", "genlshFour ");
7714     );
7715
7716   size = AOP_SIZE (result);
7717
7718   /* if shifting more that 3 bytes */
7719   if (shCount >= 24)
7720     {
7721       shCount -= 24;
7722       if (shCount)
7723         /* lowest order of left goes to the highest
7724            order of the destination */
7725         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7726       else
7727         movLeft2Result (left, LSB, result, MSB32, 0);
7728       aopPut (AOP (result), zero, LSB);
7729       aopPut (AOP (result), zero, MSB16);
7730       aopPut (AOP (result), zero, MSB24);
7731       return;
7732     }
7733
7734   /* more than two bytes */
7735   else if (shCount >= 16)
7736     {
7737       /* lower order two bytes goes to higher order two bytes */
7738       shCount -= 16;
7739       /* if some more remaining */
7740       if (shCount)
7741         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7742       else
7743         {
7744           movLeft2Result (left, MSB16, result, MSB32, 0);
7745           movLeft2Result (left, LSB, result, MSB24, 0);
7746         }
7747       aopPut (AOP (result), zero, MSB16);
7748       aopPut (AOP (result), zero, LSB);
7749       return;
7750     }
7751
7752   /* if more than 1 byte */
7753   else if (shCount >= 8)
7754     {
7755       /* lower order three bytes goes to higher order  three bytes */
7756       shCount -= 8;
7757       if (size == 2)
7758         {
7759           if (shCount)
7760             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7761           else
7762             movLeft2Result (left, LSB, result, MSB16, 0);
7763         }
7764       else
7765         {                       /* size = 4 */
7766           if (shCount == 0)
7767             {
7768               movLeft2Result (left, MSB24, result, MSB32, 0);
7769               movLeft2Result (left, MSB16, result, MSB24, 0);
7770               movLeft2Result (left, LSB, result, MSB16, 0);
7771               aopPut (AOP (result), zero, LSB);
7772             }
7773           else if (shCount == 1)
7774             shiftLLong (left, result, MSB16);
7775           else
7776             {
7777               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7778               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7779               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7780               aopPut (AOP (result), zero, LSB);
7781             }
7782         }
7783     }
7784
7785   /* 1 <= shCount <= 7 */
7786   else if (shCount <= 2)
7787     {
7788       shiftLLong (left, result, LSB);
7789       if (shCount == 2)
7790         shiftLLong (result, result, LSB);
7791     }
7792   /* 3 <= shCount <= 7, optimize */
7793   else
7794     {
7795       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7796       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7797       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7798     }
7799 }
7800 #endif
7801
7802 #ifdef BETTER_LITERAL_SHIFT
7803 /*-----------------------------------------------------------------*/
7804 /* genLeftShiftLiteral - left shifting by known count              */
7805 /*-----------------------------------------------------------------*/
7806 static bool
7807 genLeftShiftLiteral (operand * left,
7808                      operand * right,
7809                      operand * result,
7810                      iCode * ic)
7811 {
7812   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7813   int size;
7814
7815   size = getSize (operandType (result));
7816
7817   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7818
7819   /* We only handle certain easy cases so far. */
7820   if ((shCount != 0)
7821    && (shCount < (size * 8))
7822    && (size != 1)
7823    && (size != 2))
7824   {
7825       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7826       return FALSE;
7827   }
7828
7829   freeAsmop (right, NULL, ic, TRUE);
7830
7831   aopOp(left, ic, FALSE, FALSE);
7832   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7833
7834 #if 0 // debug spew
7835   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7836   {
7837         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7838         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7839         {
7840            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7841         }
7842   }
7843   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7844   {
7845         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7846         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7847         {
7848            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7849         }       
7850   }  
7851 #endif
7852   
7853 #if VIEW_SIZE
7854   emitcode ("; shift left ", "result %d, left %d", size,
7855             AOP_SIZE (left));
7856 #endif
7857
7858   /* I suppose that the left size >= result size */
7859   if (shCount == 0)
7860   {
7861         _startLazyDPSEvaluation();
7862         while (size--)
7863         {
7864           movLeft2Result (left, size, result, size, 0);
7865         }
7866         _endLazyDPSEvaluation();
7867   }
7868   else if (shCount >= (size * 8))
7869   {
7870     _startLazyDPSEvaluation();
7871     while (size--)
7872     {
7873       aopPut (AOP (result), zero, size);
7874     }
7875     _endLazyDPSEvaluation();
7876   }
7877   else
7878   {
7879       switch (size)
7880         {
7881         case 1:
7882           genlshOne (result, left, shCount);
7883           break;
7884
7885         case 2:
7886           genlshTwo (result, left, shCount);
7887           break;
7888 #if 0
7889         case 4:
7890           genlshFour (result, left, shCount);
7891           break;
7892 #endif
7893         default:
7894           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7895           break;
7896         }
7897     }
7898   freeAsmop (left, NULL, ic, TRUE);
7899   freeAsmop (result, NULL, ic, TRUE);
7900   return TRUE;
7901 }
7902 #endif
7903
7904 /*-----------------------------------------------------------------*/
7905 /* genLeftShift - generates code for left shifting                 */
7906 /*-----------------------------------------------------------------*/
7907 static void
7908 genLeftShift (iCode * ic)
7909 {
7910   operand *left, *right, *result;
7911   int size, offset;
7912   char *l;
7913   symbol *tlbl, *tlbl1;
7914
7915   D (emitcode (";", "genLeftShift "););
7916
7917   right = IC_RIGHT (ic);
7918   left = IC_LEFT (ic);
7919   result = IC_RESULT (ic);
7920
7921   aopOp (right, ic, FALSE, FALSE);
7922
7923
7924 #ifdef BETTER_LITERAL_SHIFT
7925   /* if the shift count is known then do it
7926      as efficiently as possible */
7927   if (AOP_TYPE (right) == AOP_LIT)
7928     {
7929       if (genLeftShiftLiteral (left, right, result, ic))
7930       {
7931         return;
7932       }
7933     }
7934 #endif
7935
7936   /* shift count is unknown then we have to form
7937      a loop get the loop count in B : Note: we take
7938      only the lower order byte since shifting
7939      more that 32 bits make no sense anyway, ( the
7940      largest size of an object can be only 32 bits ) */
7941
7942   if (AOP_TYPE (right) == AOP_LIT)
7943   {
7944       /* Really should be handled by genLeftShiftLiteral,
7945        * but since I'm too lazy to fix that today, at least we can make
7946        * some small improvement.
7947        */
7948        emitcode("mov", "b,#!constbyte",
7949                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7950   }
7951   else
7952   {
7953         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7954         emitcode ("inc", "b");
7955   }
7956   freeAsmop (right, NULL, ic, TRUE);
7957   aopOp (left, ic, FALSE, FALSE);
7958   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7959
7960   /* now move the left to the result if they are not the
7961      same */
7962   if (!sameRegs (AOP (left), AOP (result)) &&
7963       AOP_SIZE (result) > 1)
7964     {
7965
7966       size = AOP_SIZE (result);
7967       offset = 0;
7968       _startLazyDPSEvaluation ();
7969       while (size--)
7970         {
7971           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7972           if (*l == '@' && (IS_AOP_PREG (result)))
7973             {
7974
7975               emitcode ("mov", "a,%s", l);
7976               aopPut (AOP (result), "a", offset);
7977             }
7978           else
7979             aopPut (AOP (result), l, offset);
7980           offset++;
7981         }
7982       _endLazyDPSEvaluation ();
7983     }
7984
7985   tlbl = newiTempLabel (NULL);
7986   size = AOP_SIZE (result);
7987   offset = 0;
7988   tlbl1 = newiTempLabel (NULL);
7989
7990   /* if it is only one byte then */
7991   if (size == 1)
7992     {
7993       symbol *tlbl1 = newiTempLabel (NULL);
7994
7995       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7996       MOVA (l);
7997       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
7998       emitcode ("", "!tlabeldef", tlbl->key + 100);
7999       emitcode ("add", "a,acc");
8000       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8001       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8002       aopPut (AOP (result), "a", 0);
8003       goto release;
8004     }
8005
8006   reAdjustPreg (AOP (result));
8007
8008   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8009   emitcode ("", "!tlabeldef", tlbl->key + 100);
8010   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8011   MOVA (l);
8012   emitcode ("add", "a,acc");
8013   aopPut (AOP (result), "a", offset++);
8014   _startLazyDPSEvaluation ();
8015   while (--size)
8016     {
8017       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8018       MOVA (l);
8019       emitcode ("rlc", "a");
8020       aopPut (AOP (result), "a", offset++);
8021     }
8022   _endLazyDPSEvaluation ();
8023   reAdjustPreg (AOP (result));
8024
8025   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8026   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8027 release:
8028   freeAsmop (left, NULL, ic, TRUE);
8029   freeAsmop (result, NULL, ic, TRUE);
8030 }
8031
8032 #ifdef BETTER_LITERAL_SHIFT
8033 /*-----------------------------------------------------------------*/
8034 /* genrshOne - right shift a one byte quantity by known count      */
8035 /*-----------------------------------------------------------------*/
8036 static void
8037 genrshOne (operand * result, operand * left,
8038            int shCount, int sign)
8039 {
8040   D (emitcode (";", "genrshOne"););
8041   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8042 }
8043 #endif
8044
8045 #ifdef BETTER_LITERAL_SHIFT
8046 /*-----------------------------------------------------------------*/
8047 /* genrshTwo - right shift two bytes by known amount != 0          */
8048 /*-----------------------------------------------------------------*/
8049 static void
8050 genrshTwo (operand * result, operand * left,
8051            int shCount, int sign)
8052 {
8053   D (emitcode (";", "genrshTwo"););
8054
8055   /* if shCount >= 8 */
8056   if (shCount >= 8)
8057     {
8058       shCount -= 8;
8059       _startLazyDPSEvaluation();
8060       if (shCount)
8061       {
8062         shiftR1Left2Result (left, MSB16, result, LSB,
8063                             shCount, sign);
8064       }                     
8065       else
8066       {
8067         movLeft2Result (left, MSB16, result, LSB, sign);
8068       }
8069       addSign (result, MSB16, sign);
8070       _endLazyDPSEvaluation();
8071     }
8072
8073   /*  1 <= shCount <= 7 */
8074   else
8075   {
8076     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8077   }
8078 }
8079 #endif
8080
8081 #if 0
8082 //REMOVE ME!!!
8083 /*-----------------------------------------------------------------*/
8084 /* shiftRLong - shift right one long from left to result           */
8085 /* offl = LSB or MSB16                                             */
8086 /*-----------------------------------------------------------------*/
8087 static void
8088 shiftRLong (operand * left, int offl,
8089             operand * result, int sign)
8090 {
8091   int isSameRegs=sameRegs(AOP(left),AOP(result));
8092
8093   if (isSameRegs && offl>1) {
8094     // we are in big trouble, but this shouldn't happen
8095     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8096   }
8097
8098   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8099   
8100   if (offl==MSB16) {
8101     // shift is > 8
8102     if (sign) {
8103       emitcode ("rlc", "a");
8104       emitcode ("subb", "a,acc");
8105       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8106     } else {
8107       aopPut (AOP(result), zero, MSB32);
8108     }
8109   }
8110
8111   if (!sign) {
8112     emitcode ("clr", "c");
8113   } else {
8114     emitcode ("mov", "c,acc.7");
8115   }
8116
8117   emitcode ("rrc", "a");
8118
8119   if (isSameRegs && offl==MSB16) {
8120     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8121   } else {
8122     aopPut (AOP (result), "a", MSB32);
8123     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8124   }
8125
8126   emitcode ("rrc", "a");
8127   if (isSameRegs && offl==1) {
8128     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8129   } else {
8130     aopPut (AOP (result), "a", MSB24);
8131     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8132   }
8133   emitcode ("rrc", "a");
8134   aopPut (AOP (result), "a", MSB16 - offl);
8135
8136   if (offl == LSB)
8137     {
8138       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8139       emitcode ("rrc", "a");
8140       aopPut (AOP (result), "a", LSB);
8141     }
8142 }
8143 #endif
8144
8145 #if 0
8146 //REMOVE ME!!!
8147 /*-----------------------------------------------------------------*/
8148 /* genrshFour - shift four byte by a known amount != 0             */
8149 /*-----------------------------------------------------------------*/
8150 static void
8151 genrshFour (operand * result, operand * left,
8152             int shCount, int sign)
8153 {
8154   D (emitcode (";", "genrshFour");
8155     );
8156
8157   /* if shifting more that 3 bytes */
8158   if (shCount >= 24)
8159     {
8160       shCount -= 24;
8161       if (shCount)
8162         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8163       else
8164         movLeft2Result (left, MSB32, result, LSB, sign);
8165       addSign (result, MSB16, sign);
8166     }
8167   else if (shCount >= 16)
8168     {
8169       shCount -= 16;
8170       if (shCount)
8171         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8172       else
8173         {
8174           movLeft2Result (left, MSB24, result, LSB, 0);
8175           movLeft2Result (left, MSB32, result, MSB16, sign);
8176         }
8177       addSign (result, MSB24, sign);
8178     }
8179   else if (shCount >= 8)
8180     {
8181       shCount -= 8;
8182       if (shCount == 1)
8183         shiftRLong (left, MSB16, result, sign);
8184       else if (shCount == 0)
8185         {
8186           movLeft2Result (left, MSB16, result, LSB, 0);
8187           movLeft2Result (left, MSB24, result, MSB16, 0);
8188           movLeft2Result (left, MSB32, result, MSB24, sign);
8189           addSign (result, MSB32, sign);
8190         }
8191       else
8192         {
8193           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8194           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8195           /* the last shift is signed */
8196           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8197           addSign (result, MSB32, sign);
8198         }
8199     }
8200   else
8201     {                           /* 1 <= shCount <= 7 */
8202       if (shCount <= 2)
8203         {
8204           shiftRLong (left, LSB, result, sign);
8205           if (shCount == 2)
8206             shiftRLong (result, LSB, result, sign);
8207         }
8208       else
8209         {
8210           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8211           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8212           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8213         }
8214     }
8215 }
8216 #endif
8217
8218 #ifdef BETTER_LITERAL_SHIFT
8219 /*-----------------------------------------------------------------*/
8220 /* genRightShiftLiteral - right shifting by known count            */
8221 /*-----------------------------------------------------------------*/
8222 static bool
8223 genRightShiftLiteral (operand * left,
8224                       operand * right,
8225                       operand * result,
8226                       iCode * ic,
8227                       int sign)
8228 {
8229   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8230   int size;
8231
8232   size = getSize (operandType (result));
8233
8234   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8235
8236   /* We only handle certain easy cases so far. */
8237   if ((shCount != 0)
8238    && (shCount < (size * 8))
8239    && (size != 1)
8240    && (size != 2))
8241   {
8242       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8243       return FALSE;
8244   }
8245
8246   freeAsmop (right, NULL, ic, TRUE);
8247
8248   aopOp (left, ic, FALSE, FALSE);
8249   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8250
8251 #if VIEW_SIZE
8252   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8253             AOP_SIZE (left));
8254 #endif
8255
8256   /* test the LEFT size !!! */
8257
8258   /* I suppose that the left size >= result size */
8259   if (shCount == 0)
8260   {
8261       size = getDataSize (result);
8262       _startLazyDPSEvaluation();
8263       while (size--)
8264       {
8265         movLeft2Result (left, size, result, size, 0);
8266       }
8267       _endLazyDPSEvaluation();
8268   }
8269   else if (shCount >= (size * 8))
8270     {
8271       if (sign)
8272       {
8273         /* get sign in acc.7 */
8274         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8275       }
8276       addSign (result, LSB, sign);
8277     }
8278   else
8279     {
8280       switch (size)
8281         {
8282         case 1:
8283           genrshOne (result, left, shCount, sign);
8284           break;
8285
8286         case 2:
8287           genrshTwo (result, left, shCount, sign);
8288           break;
8289 #if 0
8290         case 4:
8291           genrshFour (result, left, shCount, sign);
8292           break;
8293 #endif    
8294         default:
8295           break;
8296         }
8297
8298       freeAsmop (left, NULL, ic, TRUE);
8299       freeAsmop (result, NULL, ic, TRUE);
8300     }
8301     return TRUE;
8302 }
8303 #endif
8304
8305 /*-----------------------------------------------------------------*/
8306 /* genSignedRightShift - right shift of signed number              */
8307 /*-----------------------------------------------------------------*/
8308 static void
8309 genSignedRightShift (iCode * ic)
8310 {
8311   operand *right, *left, *result;
8312   int size, offset;
8313   char *l;
8314   symbol *tlbl, *tlbl1;
8315
8316   D (emitcode (";", "genSignedRightShift "););
8317
8318   /* we do it the hard way put the shift count in b
8319      and loop thru preserving the sign */
8320
8321   right = IC_RIGHT (ic);
8322   left = IC_LEFT (ic);
8323   result = IC_RESULT (ic);
8324
8325   aopOp (right, ic, FALSE, FALSE);
8326
8327 #ifdef BETTER_LITERAL_SHIFT
8328   if (AOP_TYPE (right) == AOP_LIT)
8329     {
8330       if (genRightShiftLiteral (left, right, result, ic, 1))
8331       {
8332         return;
8333       }
8334     }
8335 #endif
8336   /* shift count is unknown then we have to form
8337      a loop get the loop count in B : Note: we take
8338      only the lower order byte since shifting
8339      more that 32 bits make no sense anyway, ( the
8340      largest size of an object can be only 32 bits ) */
8341
8342   if (AOP_TYPE (right) == AOP_LIT)
8343   {
8344       /* Really should be handled by genRightShiftLiteral,
8345        * but since I'm too lazy to fix that today, at least we can make
8346        * some small improvement.
8347        */
8348        emitcode("mov", "b,#!constbyte",
8349                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8350   }
8351   else
8352   {
8353         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8354         emitcode ("inc", "b");
8355   }
8356   freeAsmop (right, NULL, ic, TRUE);
8357   aopOp (left, ic, FALSE, FALSE);
8358   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8359
8360   /* now move the left to the result if they are not the
8361      same */
8362   if (!sameRegs (AOP (left), AOP (result)) &&
8363       AOP_SIZE (result) > 1)
8364     {
8365
8366       size = AOP_SIZE (result);
8367       offset = 0;
8368       _startLazyDPSEvaluation ();
8369       while (size--)
8370         {
8371           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8372           if (*l == '@' && IS_AOP_PREG (result))
8373             {
8374
8375               emitcode ("mov", "a,%s", l);
8376               aopPut (AOP (result), "a", offset);
8377             }
8378           else
8379             aopPut (AOP (result), l, offset);
8380           offset++;
8381         }
8382       _endLazyDPSEvaluation ();
8383     }
8384
8385   /* mov the highest order bit to OVR */
8386   tlbl = newiTempLabel (NULL);
8387   tlbl1 = newiTempLabel (NULL);
8388
8389   size = AOP_SIZE (result);
8390   offset = size - 1;
8391   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8392   emitcode ("rlc", "a");
8393   emitcode ("mov", "ov,c");
8394   /* if it is only one byte then */
8395   if (size == 1)
8396     {
8397       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8398       MOVA (l);
8399       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8400       emitcode ("", "!tlabeldef", tlbl->key + 100);
8401       emitcode ("mov", "c,ov");
8402       emitcode ("rrc", "a");
8403       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8404       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8405       aopPut (AOP (result), "a", 0);
8406       goto release;
8407     }
8408
8409   reAdjustPreg (AOP (result));
8410   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8411   emitcode ("", "!tlabeldef", tlbl->key + 100);
8412   emitcode ("mov", "c,ov");
8413   _startLazyDPSEvaluation ();
8414   while (size--)
8415     {
8416       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8417       MOVA (l);
8418       emitcode ("rrc", "a");
8419       aopPut (AOP (result), "a", offset--);
8420     }
8421   _endLazyDPSEvaluation ();
8422   reAdjustPreg (AOP (result));
8423   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8424   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8425
8426 release:
8427   freeAsmop (left, NULL, ic, TRUE);
8428   freeAsmop (result, NULL, ic, TRUE);
8429 }
8430
8431 /*-----------------------------------------------------------------*/
8432 /* genRightShift - generate code for right shifting                */
8433 /*-----------------------------------------------------------------*/
8434 static void
8435 genRightShift (iCode * ic)
8436 {
8437   operand *right, *left, *result;
8438   sym_link *retype;
8439   int size, offset;
8440   char *l;
8441   symbol *tlbl, *tlbl1;
8442
8443   D (emitcode (";", "genRightShift "););
8444
8445   /* if signed then we do it the hard way preserve the
8446      sign bit moving it inwards */
8447   retype = getSpec (operandType (IC_RESULT (ic)));
8448
8449   if (!SPEC_USIGN (retype))
8450     {
8451       genSignedRightShift (ic);
8452       return;
8453     }
8454
8455   /* signed & unsigned types are treated the same : i.e. the
8456      signed is NOT propagated inwards : quoting from the
8457      ANSI - standard : "for E1 >> E2, is equivalent to division
8458      by 2**E2 if unsigned or if it has a non-negative value,
8459      otherwise the result is implementation defined ", MY definition
8460      is that the sign does not get propagated */
8461
8462   right = IC_RIGHT (ic);
8463   left = IC_LEFT (ic);
8464   result = IC_RESULT (ic);
8465
8466   aopOp (right, ic, FALSE, FALSE);
8467
8468 #ifdef BETTER_LITERAL_SHIFT
8469   /* if the shift count is known then do it
8470      as efficiently as possible */
8471   if (AOP_TYPE (right) == AOP_LIT)
8472     {
8473       if (genRightShiftLiteral (left, right, result, ic, 0))
8474       {
8475         return;
8476       }
8477     }
8478 #endif
8479
8480   /* shift count is unknown then we have to form
8481      a loop get the loop count in B : Note: we take
8482      only the lower order byte since shifting
8483      more that 32 bits make no sense anyway, ( the
8484      largest size of an object can be only 32 bits ) */
8485   
8486   if (AOP_TYPE (right) == AOP_LIT)
8487   {
8488       /* Really should be handled by genRightShiftLiteral,
8489        * but since I'm too lazy to fix that today, at least we can make
8490        * some small improvement.
8491        */
8492        emitcode("mov", "b,#!constbyte",
8493                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8494   }
8495   else
8496   {
8497         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8498         emitcode ("inc", "b");
8499   }
8500   freeAsmop (right, NULL, ic, TRUE);
8501   aopOp (left, ic, FALSE, FALSE);
8502   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8503
8504   /* now move the left to the result if they are not the
8505      same */
8506   if (!sameRegs (AOP (left), AOP (result)) &&
8507       AOP_SIZE (result) > 1)
8508     {
8509
8510       size = AOP_SIZE (result);
8511       offset = 0;
8512       _startLazyDPSEvaluation ();
8513       while (size--)
8514         {
8515           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8516           if (*l == '@' && IS_AOP_PREG (result))
8517             {
8518
8519               emitcode ("mov", "a,%s", l);
8520               aopPut (AOP (result), "a", offset);
8521             }
8522           else
8523             aopPut (AOP (result), l, offset);
8524           offset++;
8525         }
8526       _endLazyDPSEvaluation ();
8527     }
8528
8529   tlbl = newiTempLabel (NULL);
8530   tlbl1 = newiTempLabel (NULL);
8531   size = AOP_SIZE (result);
8532   offset = size - 1;
8533
8534   /* if it is only one byte then */
8535   if (size == 1)
8536     {
8537       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8538       MOVA (l);
8539       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8540       emitcode ("", "!tlabeldef", tlbl->key + 100);
8541       CLRC;
8542       emitcode ("rrc", "a");
8543       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8544       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8545       aopPut (AOP (result), "a", 0);
8546       goto release;
8547     }
8548
8549   reAdjustPreg (AOP (result));
8550   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8551   emitcode ("", "!tlabeldef", tlbl->key + 100);
8552   CLRC;
8553   _startLazyDPSEvaluation ();
8554   while (size--)
8555     {
8556       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8557       MOVA (l);
8558       emitcode ("rrc", "a");
8559       aopPut (AOP (result), "a", offset--);
8560     }
8561   _endLazyDPSEvaluation ();
8562   reAdjustPreg (AOP (result));
8563
8564   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8565   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8566
8567 release:
8568   freeAsmop (left, NULL, ic, TRUE);
8569   freeAsmop (result, NULL, ic, TRUE);
8570 }
8571
8572 /*-----------------------------------------------------------------*/
8573 /* genUnpackBits - generates code for unpacking bits               */
8574 /*-----------------------------------------------------------------*/
8575 static void
8576 genUnpackBits (operand * result, char *rname, int ptype)
8577 {
8578   int shCnt;
8579   int rlen = 0;
8580   sym_link *etype;
8581   int offset = 0;
8582
8583   D (emitcode (";", "genUnpackBits ");
8584     );
8585
8586   etype = getSpec (operandType (result));
8587
8588   /* read the first byte  */
8589   switch (ptype)
8590     {
8591
8592     case POINTER:
8593     case IPOINTER:
8594       emitcode ("mov", "a,@%s", rname);
8595       break;
8596
8597     case PPOINTER:
8598       emitcode ("movx", "a,@%s", rname);
8599       break;
8600
8601     case FPOINTER:
8602       emitcode ("movx", "a,@dptr");
8603       break;
8604
8605     case CPOINTER:
8606       emitcode ("clr", "a");
8607       emitcode ("movc", "a,@a+dptr");
8608       break;
8609
8610     case GPOINTER:
8611       emitcode ("lcall", "__gptrget");
8612       break;
8613     }
8614
8615   /* if we have bitdisplacement then it fits   */
8616   /* into this byte completely or if length is */
8617   /* less than a byte                          */
8618   if ((shCnt = SPEC_BSTR (etype)) ||
8619       (SPEC_BLEN (etype) <= 8))
8620     {
8621
8622       /* shift right acc */
8623       AccRsh (shCnt);
8624
8625       emitcode ("anl", "a,#!constbyte",
8626                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8627       aopPut (AOP (result), "a", offset);
8628       return;
8629     }
8630
8631   /* bit field did not fit in a byte  */
8632   rlen = SPEC_BLEN (etype) - 8;
8633   aopPut (AOP (result), "a", offset++);
8634
8635   while (1)
8636     {
8637
8638       switch (ptype)
8639         {
8640         case POINTER:
8641         case IPOINTER:
8642           emitcode ("inc", "%s", rname);
8643           emitcode ("mov", "a,@%s", rname);
8644           break;
8645
8646         case PPOINTER:
8647           emitcode ("inc", "%s", rname);
8648           emitcode ("movx", "a,@%s", rname);
8649           break;
8650
8651         case FPOINTER:
8652           emitcode ("inc", "dptr");
8653           emitcode ("movx", "a,@dptr");
8654           break;
8655
8656         case CPOINTER:
8657           emitcode ("clr", "a");
8658           emitcode ("inc", "dptr");
8659           emitcode ("movc", "a,@a+dptr");
8660           break;
8661
8662         case GPOINTER:
8663           emitcode ("inc", "dptr");
8664           emitcode ("lcall", "__gptrget");
8665           break;
8666         }
8667
8668       rlen -= 8;
8669       /* if we are done */
8670       if (rlen < 8)
8671         break;
8672
8673       aopPut (AOP (result), "a", offset++);
8674
8675     }
8676
8677   if (rlen)
8678     {
8679       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8680       aopPut (AOP (result), "a", offset);
8681     }
8682
8683   return;
8684 }
8685
8686
8687 /*-----------------------------------------------------------------*/
8688 /* genDataPointerGet - generates code when ptr offset is known     */
8689 /*-----------------------------------------------------------------*/
8690 static void
8691 genDataPointerGet (operand * left,
8692                    operand * result,
8693                    iCode * ic)
8694 {
8695   char *l;
8696   char buffer[256];
8697   int size, offset = 0;
8698   aopOp (result, ic, TRUE, FALSE);
8699
8700   /* get the string representation of the name */
8701   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8702   size = AOP_SIZE (result);
8703   _startLazyDPSEvaluation ();
8704   while (size--)
8705     {
8706       if (offset)
8707         sprintf (buffer, "(%s + %d)", l + 1, offset);
8708       else
8709         sprintf (buffer, "%s", l + 1);
8710       aopPut (AOP (result), buffer, offset++);
8711     }
8712   _endLazyDPSEvaluation ();
8713
8714   freeAsmop (left, NULL, ic, TRUE);
8715   freeAsmop (result, NULL, ic, TRUE);
8716 }
8717
8718 /*-----------------------------------------------------------------*/
8719 /* genNearPointerGet - emitcode for near pointer fetch             */
8720 /*-----------------------------------------------------------------*/
8721 static void
8722 genNearPointerGet (operand * left,
8723                    operand * result,
8724                    iCode * ic,
8725                    iCode *pi)
8726 {
8727   asmop *aop = NULL;
8728   regs *preg = NULL;
8729   char *rname;
8730   sym_link *rtype, *retype, *letype;
8731   sym_link *ltype = operandType (left);
8732   char buffer[80];
8733
8734   rtype = operandType (result);
8735   retype = getSpec (rtype);
8736   letype = getSpec (ltype);
8737
8738   aopOp (left, ic, FALSE, FALSE);
8739
8740   /* if left is rematerialisable and
8741      result is not bit variable type and
8742      the left is pointer to data space i.e
8743      lower 128 bytes of space */
8744   if (AOP_TYPE (left) == AOP_IMMD &&
8745       !IS_BITVAR (retype) &&
8746       !IS_BITVAR (letype) &&
8747       DCL_TYPE (ltype) == POINTER)
8748     {
8749       genDataPointerGet (left, result, ic);
8750       return;
8751     }
8752
8753   /* if the value is already in a pointer register
8754      then don't need anything more */
8755   if (!AOP_INPREG (AOP (left)))
8756     {
8757       /* otherwise get a free pointer register */
8758       aop = newAsmop (0);
8759       preg = getFreePtr (ic, &aop, FALSE);
8760       emitcode ("mov", "%s,%s",
8761                 preg->name,
8762                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8763       rname = preg->name;
8764     }
8765   else
8766     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8767
8768   freeAsmop (left, NULL, ic, TRUE);
8769   aopOp (result, ic, FALSE, FALSE);
8770
8771   /* if bitfield then unpack the bits */
8772   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8773     genUnpackBits (result, rname, POINTER);
8774   else
8775     {
8776       /* we have can just get the values */
8777       int size = AOP_SIZE (result);
8778       int offset = 0;
8779
8780       while (size--)
8781         {
8782           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8783             {
8784
8785               emitcode ("mov", "a,@%s", rname);
8786               aopPut (AOP (result), "a", offset);
8787             }
8788           else
8789             {
8790               sprintf (buffer, "@%s", rname);
8791               aopPut (AOP (result), buffer, offset);
8792             }
8793           offset++;
8794           if (size || pi)
8795             emitcode ("inc", "%s", rname);
8796         }
8797     }
8798
8799   /* now some housekeeping stuff */
8800   if (aop)
8801     {
8802       /* we had to allocate for this iCode */
8803       if (pi) { /* post increment present */
8804         aopPut(AOP ( left ),rname,0);
8805       }
8806       freeAsmop (NULL, aop, ic, TRUE);
8807     }
8808   else
8809     {
8810       /* we did not allocate which means left
8811          already in a pointer register, then
8812          if size > 0 && this could be used again
8813          we have to point it back to where it
8814          belongs */
8815       if (AOP_SIZE (result) > 1 &&
8816           !OP_SYMBOL (left)->remat &&
8817           (OP_SYMBOL (left)->liveTo > ic->seq ||
8818            ic->depth) &&
8819           !pi)
8820         {
8821           int size = AOP_SIZE (result) - 1;
8822           while (size--)
8823             emitcode ("dec", "%s", rname);
8824         }
8825     }
8826
8827   /* done */
8828   freeAsmop (result, NULL, ic, TRUE);
8829   if (pi) pi->generated = 1;
8830 }
8831
8832 /*-----------------------------------------------------------------*/
8833 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8834 /*-----------------------------------------------------------------*/
8835 static void
8836 genPagedPointerGet (operand * left,
8837                     operand * result,
8838                     iCode * ic,
8839                     iCode * pi)
8840 {
8841   asmop *aop = NULL;
8842   regs *preg = NULL;
8843   char *rname;
8844   sym_link *rtype, *retype, *letype;
8845
8846   rtype = operandType (result);
8847   retype = getSpec (rtype);
8848   letype = getSpec (operandType (left));
8849   aopOp (left, ic, FALSE, FALSE);
8850
8851   /* if the value is already in a pointer register
8852      then don't need anything more */
8853   if (!AOP_INPREG (AOP (left)))
8854     {
8855       /* otherwise get a free pointer register */
8856       aop = newAsmop (0);
8857       preg = getFreePtr (ic, &aop, FALSE);
8858       emitcode ("mov", "%s,%s",
8859                 preg->name,
8860                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8861       rname = preg->name;
8862     }
8863   else
8864     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8865
8866   freeAsmop (left, NULL, ic, TRUE);
8867   aopOp (result, ic, FALSE, FALSE);
8868
8869   /* if bitfield then unpack the bits */
8870   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8871     genUnpackBits (result, rname, PPOINTER);
8872   else
8873     {
8874       /* we have can just get the values */
8875       int size = AOP_SIZE (result);
8876       int offset = 0;
8877
8878       while (size--)
8879         {
8880
8881           emitcode ("movx", "a,@%s", rname);
8882           aopPut (AOP (result), "a", offset);
8883
8884           offset++;
8885
8886           if (size || pi)
8887             emitcode ("inc", "%s", rname);
8888         }
8889     }
8890
8891   /* now some housekeeping stuff */
8892   if (aop)
8893     {
8894       /* we had to allocate for this iCode */
8895       if (pi) aopPut ( AOP (left), rname, 0);
8896       freeAsmop (NULL, aop, ic, TRUE);
8897     }
8898   else
8899     {
8900       /* we did not allocate which means left
8901          already in a pointer register, then
8902          if size > 0 && this could be used again
8903          we have to point it back to where it
8904          belongs */
8905       if (AOP_SIZE (result) > 1 &&
8906           !OP_SYMBOL (left)->remat &&
8907           (OP_SYMBOL (left)->liveTo > ic->seq ||
8908            ic->depth) &&
8909           !pi)
8910         {
8911           int size = AOP_SIZE (result) - 1;
8912           while (size--)
8913             emitcode ("dec", "%s", rname);
8914         }
8915     }
8916
8917   /* done */
8918   freeAsmop (result, NULL, ic, TRUE);
8919   if (pi) pi->generated = 1;
8920 }
8921
8922 /*-----------------------------------------------------------------*/
8923 /* genFarPointerGet - gget value from far space                    */
8924 /*-----------------------------------------------------------------*/
8925 static void
8926 genFarPointerGet (operand * left,
8927                   operand * result, iCode * ic, iCode *pi)
8928 {
8929     int size, offset, dopi=1;
8930   sym_link *retype = getSpec (operandType (result));
8931   sym_link *letype = getSpec (operandType (left));
8932   D (emitcode (";", "genFarPointerGet");
8933     );
8934
8935   aopOp (left, ic, FALSE, FALSE);
8936
8937   /* if the operand is already in dptr
8938      then we do nothing else we move the value to dptr */
8939   if (AOP_TYPE (left) != AOP_STR)
8940     {
8941       /* if this is remateriazable */
8942       if (AOP_TYPE (left) == AOP_IMMD)
8943         {
8944           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8945         }
8946       else
8947         {
8948           /* we need to get it byte by byte */
8949           _startLazyDPSEvaluation ();
8950           if (AOP_TYPE (left) != AOP_DPTR)
8951             {
8952               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8953               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8954               if (options.model == MODEL_FLAT24)
8955                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8956             }
8957           else
8958             {
8959               /* We need to generate a load to DPTR indirect through DPTR. */
8960               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8961                 );
8962               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8963               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8964               if (options.model == MODEL_FLAT24)
8965                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8966               emitcode ("pop", "dph");
8967               emitcode ("pop", "dpl");
8968               dopi =0;
8969             }
8970           _endLazyDPSEvaluation ();
8971         }
8972     }
8973   /* so dptr know contains the address */
8974   aopOp (result, ic, FALSE, TRUE);
8975
8976   /* if bit then unpack */
8977   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8978     genUnpackBits (result, "dptr", FPOINTER);
8979   else
8980     {
8981       size = AOP_SIZE (result);
8982       offset = 0;
8983
8984       _startLazyDPSEvaluation ();
8985       while (size--)
8986         {
8987
8988           genSetDPTR (0);
8989           _flushLazyDPS ();
8990
8991           emitcode ("movx", "a,@dptr");
8992           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
8993             emitcode ("inc", "dptr");
8994
8995           aopPut (AOP (result), "a", offset++);
8996         }
8997       _endLazyDPSEvaluation ();
8998     }
8999   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9000     aopPut ( AOP (left), "dpl", 0);
9001     aopPut ( AOP (left), "dph", 1);
9002     if (options.model == MODEL_FLAT24)
9003             aopPut ( AOP (left), "dpx", 2);
9004     pi->generated = 1;
9005   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9006              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9007       
9008       size = AOP_SIZE (result) - 1;
9009       while (size--) emitcode ("lcall","__decdptr");
9010   }
9011
9012   freeAsmop (left, NULL, ic, TRUE);
9013   freeAsmop (result, NULL, ic, TRUE);
9014 }
9015
9016 /*-----------------------------------------------------------------*/
9017 /* emitcodePointerGet - gget value from code space                  */
9018 /*-----------------------------------------------------------------*/
9019 static void
9020 emitcodePointerGet (operand * left,
9021                     operand * result, iCode * ic, iCode *pi)
9022 {
9023   int size, offset, dopi=1;
9024   sym_link *retype = getSpec (operandType (result));
9025
9026   aopOp (left, ic, FALSE, FALSE);
9027
9028   /* if the operand is already in dptr
9029      then we do nothing else we move the value to dptr */
9030   if (AOP_TYPE (left) != AOP_STR)
9031     {
9032       /* if this is remateriazable */
9033       if (AOP_TYPE (left) == AOP_IMMD)
9034         {
9035           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9036         }
9037       else
9038         {                       /* we need to get it byte by byte */
9039           _startLazyDPSEvaluation ();
9040           if (AOP_TYPE (left) != AOP_DPTR)
9041             {
9042               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9043               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9044               if (options.model == MODEL_FLAT24)
9045                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9046             }
9047           else
9048             {
9049               /* We need to generate a load to DPTR indirect through DPTR. */
9050               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9051                 );
9052               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9053               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9054               if (options.model == MODEL_FLAT24)
9055                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9056               emitcode ("pop", "dph");
9057               emitcode ("pop", "dpl");
9058               dopi=0;
9059             }
9060           _endLazyDPSEvaluation ();
9061         }
9062     }
9063   /* so dptr know contains the address */
9064   aopOp (result, ic, FALSE, TRUE);
9065
9066   /* if bit then unpack */
9067   if (IS_BITVAR (retype))
9068     genUnpackBits (result, "dptr", CPOINTER);
9069   else
9070     {
9071       size = AOP_SIZE (result);
9072       offset = 0;
9073
9074       _startLazyDPSEvaluation ();
9075       while (size--)
9076         {
9077           genSetDPTR (0);
9078           _flushLazyDPS ();
9079
9080           emitcode ("clr", "a");
9081           emitcode ("movc", "a,@a+dptr");
9082           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9083             emitcode ("inc", "dptr");
9084           aopPut (AOP (result), "a", offset++);
9085         }
9086       _endLazyDPSEvaluation ();
9087     }
9088   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9089       aopPut ( AOP (left), "dpl", 0);
9090       aopPut ( AOP (left), "dph", 1);
9091       if (options.model == MODEL_FLAT24)
9092           aopPut ( AOP (left), "dpx", 2);
9093       pi->generated = 1;
9094   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9095              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9096       
9097       size = AOP_SIZE (result) - 1;
9098       while (size--) emitcode ("lcall","__decdptr");
9099   }
9100   
9101   freeAsmop (left, NULL, ic, TRUE);
9102   freeAsmop (result, NULL, ic, TRUE);
9103 }
9104
9105 /*-----------------------------------------------------------------*/
9106 /* genGenPointerGet - gget value from generic pointer space        */
9107 /*-----------------------------------------------------------------*/
9108 static void
9109 genGenPointerGet (operand * left,
9110                   operand * result, iCode * ic, iCode * pi)
9111 {
9112   int size, offset;
9113   sym_link *retype = getSpec (operandType (result));
9114   sym_link *letype = getSpec (operandType (left));
9115
9116   D (emitcode (";", "genGenPointerGet "); );
9117
9118   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9119
9120   /* if the operand is already in dptr
9121      then we do nothing else we move the value to dptr */
9122   if (AOP_TYPE (left) != AOP_STR)
9123     {
9124       /* if this is remateriazable */
9125       if (AOP_TYPE (left) == AOP_IMMD)
9126         {
9127           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9128           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9129                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9130           else
9131                   emitcode ("mov", "b,#%d", pointerCode (retype));
9132         }
9133       else
9134         {                       /* we need to get it byte by byte */
9135           _startLazyDPSEvaluation ();
9136           if (AOP(left)->type==AOP_DPTR2) {
9137             char *l;
9138             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9139             genSetDPTR(0);
9140             _flushLazyDPS();
9141             emitcode ("mov", "dpl,%s", l);
9142             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9143             genSetDPTR(0);
9144             _flushLazyDPS();
9145             emitcode ("mov", "dph,%s", l);
9146             if (options.model == MODEL_FLAT24) {
9147               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9148               genSetDPTR(0);
9149               _flushLazyDPS();
9150               emitcode ("mov", "dpx,%s", l);
9151               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9152             } else {
9153               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9154             }
9155           } else {
9156             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9157             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9158             if (options.model == MODEL_FLAT24) {
9159               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9160               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9161             } else {
9162               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9163             }
9164           }
9165           _endLazyDPSEvaluation ();
9166         }
9167     }
9168   /* so dptr know contains the address */
9169   aopOp (result, ic, FALSE, TRUE);
9170
9171   /* if bit then unpack */
9172   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9173     genUnpackBits (result, "dptr", GPOINTER);
9174   else
9175     {
9176       size = AOP_SIZE (result);
9177       offset = 0;
9178
9179       while (size--)
9180         {
9181           emitcode ("lcall", "__gptrget");
9182           aopPut (AOP (result), "a", offset++);
9183           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9184             emitcode ("inc", "dptr");
9185         }
9186     }
9187
9188   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9189     aopPut ( AOP (left), "dpl", 0);
9190     aopPut ( AOP (left), "dph", 1);
9191     if (options.model == MODEL_FLAT24) {
9192         aopPut ( AOP (left), "dpx", 2);
9193         aopPut ( AOP (left), "b", 3);   
9194     } else  aopPut ( AOP (left), "b", 2);       
9195     pi->generated = 1;
9196   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9197              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9198       
9199       size = AOP_SIZE (result) - 1;
9200       while (size--) emitcode ("lcall","__decdptr");
9201   }
9202
9203   freeAsmop (left, NULL, ic, TRUE);
9204   freeAsmop (result, NULL, ic, TRUE);
9205 }
9206
9207 /*-----------------------------------------------------------------*/
9208 /* genPointerGet - generate code for pointer get                   */
9209 /*-----------------------------------------------------------------*/
9210 static void
9211 genPointerGet (iCode * ic, iCode *pi)
9212 {
9213   operand *left, *result;
9214   sym_link *type, *etype;
9215   int p_type;
9216
9217   D (emitcode (";", "genPointerGet ");
9218     );
9219
9220   left = IC_LEFT (ic);
9221   result = IC_RESULT (ic);
9222
9223   /* depending on the type of pointer we need to
9224      move it to the correct pointer register */
9225   type = operandType (left);
9226   etype = getSpec (type);
9227   /* if left is of type of pointer then it is simple */
9228   if (IS_PTR (type) && !IS_FUNC (type->next))
9229     p_type = DCL_TYPE (type);
9230   else
9231     {
9232       /* we have to go by the storage class */
9233       p_type = PTR_TYPE (SPEC_OCLS (etype));
9234     }
9235   /* special case when cast remat */
9236   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9237       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9238           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9239           type =   type = operandType (left);
9240           p_type = DCL_TYPE (type);
9241   }
9242   /* now that we have the pointer type we assign
9243      the pointer values */
9244   switch (p_type)
9245     {
9246
9247     case POINTER:
9248     case IPOINTER:
9249       genNearPointerGet (left, result, ic, pi);
9250       break;
9251
9252     case PPOINTER:
9253       genPagedPointerGet (left, result, ic, pi);
9254       break;
9255
9256     case FPOINTER:
9257       genFarPointerGet (left, result, ic, pi);
9258       break;
9259
9260     case CPOINTER:
9261       emitcodePointerGet (left, result, ic, pi);
9262       break;
9263
9264     case GPOINTER:
9265       genGenPointerGet (left, result, ic, pi);
9266       break;
9267     }
9268
9269 }
9270
9271 /*-----------------------------------------------------------------*/
9272 /* genPackBits - generates code for packed bit storage             */
9273 /*-----------------------------------------------------------------*/
9274 static void
9275 genPackBits (sym_link * etype,
9276              operand * right,
9277              char *rname, int p_type)
9278 {
9279   int shCount = 0;
9280   int offset = 0;
9281   int rLen = 0;
9282   int blen, bstr;
9283   char *l;
9284
9285   blen = SPEC_BLEN (etype);
9286   bstr = SPEC_BSTR (etype);
9287
9288   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9289   MOVA (l);
9290
9291   /* if the bit lenth is less than or    */
9292   /* it exactly fits a byte then         */
9293   if (SPEC_BLEN (etype) <= 8)
9294     {
9295       shCount = SPEC_BSTR (etype);
9296
9297       /* shift left acc */
9298       AccLsh (shCount);
9299
9300       if (SPEC_BLEN (etype) < 8)
9301         {                       /* if smaller than a byte */
9302
9303
9304           switch (p_type)
9305             {
9306             case POINTER:
9307               emitcode ("mov", "b,a");
9308               emitcode ("mov", "a,@%s", rname);
9309               break;
9310
9311             case FPOINTER:
9312               emitcode ("mov", "b,a");
9313               emitcode ("movx", "a,@dptr");
9314               break;
9315
9316             case GPOINTER:
9317               emitcode ("push", "b");
9318               emitcode ("push", "acc");
9319               emitcode ("lcall", "__gptrget");
9320               emitcode ("pop", "b");
9321               break;
9322             }
9323
9324           emitcode ("anl", "a,#!constbyte", (unsigned char)
9325                     ((unsigned char) (0xFF << (blen + bstr)) |
9326                      (unsigned char) (0xFF >> (8 - bstr))));
9327           emitcode ("orl", "a,b");
9328           if (p_type == GPOINTER)
9329             emitcode ("pop", "b");
9330         }
9331     }
9332
9333   switch (p_type)
9334     {
9335     case POINTER:
9336       emitcode ("mov", "@%s,a", rname);
9337       break;
9338
9339     case FPOINTER:
9340       emitcode ("movx", "@dptr,a");
9341       break;
9342
9343     case GPOINTER:
9344       emitcode ("lcall", "__gptrput");
9345       break;
9346     }
9347
9348   /* if we r done */
9349   if (SPEC_BLEN (etype) <= 8)
9350     return;
9351
9352   emitcode ("inc", "%s", rname);
9353   rLen = SPEC_BLEN (etype);
9354
9355   /* now generate for lengths greater than one byte */
9356   while (1)
9357     {
9358
9359       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9360
9361       rLen -= 8;
9362       if (rLen < 8)
9363         break;
9364
9365       switch (p_type)
9366         {
9367         case POINTER:
9368           if (*l == '@')
9369             {
9370               MOVA (l);
9371               emitcode ("mov", "@%s,a", rname);
9372             }
9373           else
9374             emitcode ("mov", "@%s,%s", rname, l);
9375           break;
9376
9377         case FPOINTER:
9378           MOVA (l);
9379           emitcode ("movx", "@dptr,a");
9380           break;
9381
9382         case GPOINTER:
9383           MOVA (l);
9384           emitcode ("lcall", "__gptrput");
9385           break;
9386         }
9387       emitcode ("inc", "%s", rname);
9388     }
9389
9390   MOVA (l);
9391
9392   /* last last was not complete */
9393   if (rLen)
9394     {
9395       /* save the byte & read byte */
9396       switch (p_type)
9397         {
9398         case POINTER:
9399           emitcode ("mov", "b,a");
9400           emitcode ("mov", "a,@%s", rname);
9401           break;
9402
9403         case FPOINTER:
9404           emitcode ("mov", "b,a");
9405           emitcode ("movx", "a,@dptr");
9406           break;
9407
9408         case GPOINTER:
9409           emitcode ("push", "b");
9410           emitcode ("push", "acc");
9411           emitcode ("lcall", "__gptrget");
9412           emitcode ("pop", "b");
9413           break;
9414         }
9415
9416       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9417       emitcode ("orl", "a,b");
9418     }
9419
9420   if (p_type == GPOINTER)
9421     emitcode ("pop", "b");
9422
9423   switch (p_type)
9424     {
9425
9426     case POINTER:
9427       emitcode ("mov", "@%s,a", rname);
9428       break;
9429
9430     case FPOINTER:
9431       emitcode ("movx", "@dptr,a");
9432       break;
9433
9434     case GPOINTER:
9435       emitcode ("lcall", "__gptrput");
9436       break;
9437     }
9438 }
9439 /*-----------------------------------------------------------------*/
9440 /* genDataPointerSet - remat pointer to data space                 */
9441 /*-----------------------------------------------------------------*/
9442 static void
9443 genDataPointerSet (operand * right,
9444                    operand * result,
9445                    iCode * ic)
9446 {
9447   int size, offset = 0;
9448   char *l, buffer[256];
9449
9450   aopOp (right, ic, FALSE, FALSE);
9451
9452   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9453   size = AOP_SIZE (right);
9454   while (size--)
9455     {
9456       if (offset)
9457         sprintf (buffer, "(%s + %d)", l + 1, offset);
9458       else
9459         sprintf (buffer, "%s", l + 1);
9460       emitcode ("mov", "%s,%s", buffer,
9461                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9462     }
9463
9464   freeAsmop (right, NULL, ic, TRUE);
9465   freeAsmop (result, NULL, ic, TRUE);
9466 }
9467
9468 /*-----------------------------------------------------------------*/
9469 /* genNearPointerSet - emitcode for near pointer put                */
9470 /*-----------------------------------------------------------------*/
9471 static void
9472 genNearPointerSet (operand * right,
9473                    operand * result,
9474                    iCode * ic,
9475                    iCode * pi)
9476 {
9477   asmop *aop = NULL;
9478   regs *preg = NULL;
9479   char *rname, *l;
9480   sym_link *retype, *letype;
9481   sym_link *ptype = operandType (result);
9482
9483   retype = getSpec (operandType (right));
9484   letype = getSpec (ptype);
9485
9486   aopOp (result, ic, FALSE, FALSE);
9487
9488   /* if the result is rematerializable &
9489      in data space & not a bit variable */
9490   if (AOP_TYPE (result) == AOP_IMMD &&
9491       DCL_TYPE (ptype) == POINTER &&
9492       !IS_BITVAR (retype) &&
9493       !IS_BITVAR (letype))
9494     {
9495       genDataPointerSet (right, result, ic);
9496       return;
9497     }
9498
9499   /* if the value is already in a pointer register
9500      then don't need anything more */
9501   if (!AOP_INPREG (AOP (result)))
9502     {
9503       /* otherwise get a free pointer register */
9504       aop = newAsmop (0);
9505       preg = getFreePtr (ic, &aop, FALSE);
9506       emitcode ("mov", "%s,%s",
9507                 preg->name,
9508                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9509       rname = preg->name;
9510     }
9511   else
9512     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9513
9514   aopOp (right, ic, FALSE, FALSE);
9515
9516   /* if bitfield then unpack the bits */
9517   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9518     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9519   else
9520     {
9521       /* we have can just get the values */
9522       int size = AOP_SIZE (right);
9523       int offset = 0;
9524
9525       while (size--)
9526         {
9527           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9528           if (*l == '@')
9529             {
9530               MOVA (l);
9531               emitcode ("mov", "@%s,a", rname);
9532             }
9533           else
9534             emitcode ("mov", "@%s,%s", rname, l);
9535           if (size || pi)
9536             emitcode ("inc", "%s", rname);
9537           offset++;
9538         }
9539     }
9540
9541   /* now some housekeeping stuff */
9542   if (aop)
9543     {
9544       /* we had to allocate for this iCode */
9545       if (pi) aopPut (AOP (result),rname,0);
9546       freeAsmop (NULL, aop, ic, TRUE);
9547     }
9548   else
9549     {
9550       /* we did not allocate which means left
9551          already in a pointer register, then
9552          if size > 0 && this could be used again
9553          we have to point it back to where it
9554          belongs */
9555       if (AOP_SIZE (right) > 1 &&
9556           !OP_SYMBOL (result)->remat &&
9557           (OP_SYMBOL (result)->liveTo > ic->seq ||
9558            ic->depth) &&
9559           !pi)
9560         {
9561           int size = AOP_SIZE (right) - 1;
9562           while (size--)
9563             emitcode ("dec", "%s", rname);
9564         }
9565     }
9566
9567   /* done */
9568   if (pi) pi->generated = 1;
9569   freeAsmop (result, NULL, ic, TRUE);
9570   freeAsmop (right, NULL, ic, TRUE);
9571
9572
9573 }
9574
9575 /*-----------------------------------------------------------------*/
9576 /* genPagedPointerSet - emitcode for Paged pointer put             */
9577 /*-----------------------------------------------------------------*/
9578 static void
9579 genPagedPointerSet (operand * right,
9580                     operand * result,
9581                     iCode * ic,
9582                     iCode *pi)
9583 {
9584   asmop *aop = NULL;
9585   regs *preg = NULL;
9586   char *rname, *l;
9587   sym_link *retype, *letype;
9588
9589   retype = getSpec (operandType (right));
9590   letype = getSpec (operandType (result));
9591
9592   aopOp (result, ic, FALSE, FALSE);
9593
9594   /* if the value is already in a pointer register
9595      then don't need anything more */
9596   if (!AOP_INPREG (AOP (result)))
9597     {
9598       /* otherwise get a free pointer register */
9599       aop = newAsmop (0);
9600       preg = getFreePtr (ic, &aop, FALSE);
9601       emitcode ("mov", "%s,%s",
9602                 preg->name,
9603                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9604       rname = preg->name;
9605     }
9606   else
9607     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9608
9609   aopOp (right, ic, FALSE, FALSE);
9610
9611   /* if bitfield then unpack the bits */
9612   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9613     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9614   else
9615     {
9616       /* we have can just get the values */
9617       int size = AOP_SIZE (right);
9618       int offset = 0;
9619
9620       while (size--)
9621         {
9622           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9623
9624           MOVA (l);
9625           emitcode ("movx", "@%s,a", rname);
9626
9627           if (size || pi)
9628             emitcode ("inc", "%s", rname);
9629
9630           offset++;
9631         }
9632     }
9633
9634   /* now some housekeeping stuff */
9635   if (aop)
9636     {
9637       if (pi) aopPut (AOP (result),rname,0);
9638       /* we had to allocate for this iCode */
9639       freeAsmop (NULL, aop, ic, TRUE);
9640     }
9641   else
9642     {
9643       /* we did not allocate which means left
9644          already in a pointer register, then
9645          if size > 0 && this could be used again
9646          we have to point it back to where it
9647          belongs */
9648       if (AOP_SIZE (right) > 1 &&
9649           !OP_SYMBOL (result)->remat &&
9650           (OP_SYMBOL (result)->liveTo > ic->seq ||
9651            ic->depth) &&
9652           !pi)
9653         {
9654           int size = AOP_SIZE (right) - 1;
9655           while (size--)
9656             emitcode ("dec", "%s", rname);
9657         }
9658     }
9659
9660   /* done */
9661   if (pi) pi->generated = 1;
9662   freeAsmop (result, NULL, ic, TRUE);
9663   freeAsmop (right, NULL, ic, TRUE);
9664
9665
9666 }
9667
9668 /*-----------------------------------------------------------------*/
9669 /* genFarPointerSet - set value from far space                     */
9670 /*-----------------------------------------------------------------*/
9671 static void
9672 genFarPointerSet (operand * right,
9673                   operand * result, iCode * ic, iCode *pi)
9674 {
9675   int size, offset, dopi=1;
9676   sym_link *retype = getSpec (operandType (right));
9677   sym_link *letype = getSpec (operandType (result));
9678
9679   aopOp (result, ic, FALSE, FALSE);
9680
9681   /* if the operand is already in dptr
9682      then we do nothing else we move the value to dptr */
9683   if (AOP_TYPE (result) != AOP_STR)
9684     {
9685       /* if this is remateriazable */
9686       if (AOP_TYPE (result) == AOP_IMMD)
9687         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9688       else
9689         {
9690           /* we need to get it byte by byte */
9691           _startLazyDPSEvaluation ();
9692           if (AOP_TYPE (result) != AOP_DPTR)
9693             {
9694               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9695               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9696               if (options.model == MODEL_FLAT24)
9697                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9698             }
9699           else
9700             {
9701               /* We need to generate a load to DPTR indirect through DPTR. */
9702               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9703                 );
9704               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9705               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9706               if (options.model == MODEL_FLAT24)
9707                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9708               emitcode ("pop", "dph");
9709               emitcode ("pop", "dpl");
9710               dopi=0;
9711             }
9712           _endLazyDPSEvaluation ();
9713         }
9714     }
9715   /* so dptr know contains the address */
9716   aopOp (right, ic, FALSE, TRUE);
9717
9718   /* if bit then unpack */
9719   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9720     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9721   else
9722     {
9723       size = AOP_SIZE (right);
9724       offset = 0;
9725
9726       _startLazyDPSEvaluation ();
9727       while (size--)
9728         {
9729           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9730           MOVA (l);
9731
9732           genSetDPTR (0);
9733           _flushLazyDPS ();
9734
9735           emitcode ("movx", "@dptr,a");
9736           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9737             emitcode ("inc", "dptr");
9738         }
9739       _endLazyDPSEvaluation ();
9740     }
9741
9742   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9743       aopPut (AOP(result),"dpl",0);
9744       aopPut (AOP(result),"dph",1);
9745       if (options.model == MODEL_FLAT24)
9746           aopPut (AOP(result),"dpx",2);
9747       pi->generated=1;
9748   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9749              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9750       
9751       size = AOP_SIZE (right) - 1;
9752       while (size--) emitcode ("lcall","__decdptr");
9753   }
9754   freeAsmop (result, NULL, ic, TRUE);
9755   freeAsmop (right, NULL, ic, TRUE);
9756 }
9757
9758 /*-----------------------------------------------------------------*/
9759 /* genGenPointerSet - set value from generic pointer space         */
9760 /*-----------------------------------------------------------------*/
9761 static void
9762 genGenPointerSet (operand * right,
9763                   operand * result, iCode * ic, iCode *pi)
9764 {
9765   int size, offset;
9766   sym_link *retype = getSpec (operandType (right));
9767   sym_link *letype = getSpec (operandType (result));
9768
9769   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9770
9771   /* if the operand is already in dptr
9772      then we do nothing else we move the value to dptr */
9773   if (AOP_TYPE (result) != AOP_STR)
9774     {
9775       _startLazyDPSEvaluation ();
9776       /* if this is remateriazable */
9777       if (AOP_TYPE (result) == AOP_IMMD)
9778         {
9779           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9780           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9781                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9782           else
9783                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9784         }
9785       else
9786         {                       /* we need to get it byte by byte */
9787           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9788           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9789           if (options.model == MODEL_FLAT24) {
9790             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9791             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9792           } else {
9793             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9794           }
9795         }
9796       _endLazyDPSEvaluation ();
9797     }
9798   /* so dptr know contains the address */
9799   aopOp (right, ic, FALSE, TRUE);
9800
9801   /* if bit then unpack */
9802   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9803     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9804   else
9805     {
9806       size = AOP_SIZE (right);
9807       offset = 0;
9808
9809       _startLazyDPSEvaluation ();
9810       while (size--)
9811         {
9812           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9813           MOVA (l);
9814
9815           genSetDPTR (0);
9816           _flushLazyDPS ();
9817
9818           emitcode ("lcall", "__gptrput");
9819           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9820             emitcode ("inc", "dptr");
9821         }
9822       _endLazyDPSEvaluation ();
9823     }
9824
9825   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9826       aopPut (AOP(result),"dpl",0);
9827       aopPut (AOP(result),"dph",1);
9828       if (options.model == MODEL_FLAT24) {
9829           aopPut (AOP(result),"dpx",2);
9830           aopPut (AOP(result),"b",3);
9831       } else {
9832           aopPut (AOP(result),"b",2);
9833       }
9834       pi->generated=1;
9835   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9836              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9837       
9838       size = AOP_SIZE (right) - 1;
9839       while (size--) emitcode ("lcall","__decdptr");
9840   }
9841   freeAsmop (result, NULL, ic, TRUE);
9842   freeAsmop (right, NULL, ic, TRUE);
9843 }
9844
9845 /*-----------------------------------------------------------------*/
9846 /* genPointerSet - stores the value into a pointer location        */
9847 /*-----------------------------------------------------------------*/
9848 static void
9849 genPointerSet (iCode * ic, iCode *pi)
9850 {
9851   operand *right, *result;
9852   sym_link *type, *etype;
9853   int p_type;
9854
9855   D (emitcode (";", "genPointerSet ");
9856     );
9857
9858   right = IC_RIGHT (ic);
9859   result = IC_RESULT (ic);
9860
9861   /* depending on the type of pointer we need to
9862      move it to the correct pointer register */
9863   type = operandType (result);
9864   etype = getSpec (type);
9865   /* if left is of type of pointer then it is simple */
9866   if (IS_PTR (type) && !IS_FUNC (type->next))
9867     {
9868       p_type = DCL_TYPE (type);
9869     }
9870   else
9871     {
9872       /* we have to go by the storage class */
9873       p_type = PTR_TYPE (SPEC_OCLS (etype));
9874     }
9875   /* special case when cast remat */
9876   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9877       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9878           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9879           type =   type = operandType (result);
9880           p_type = DCL_TYPE (type);
9881   }
9882
9883   /* now that we have the pointer type we assign
9884      the pointer values */
9885   switch (p_type)
9886     {
9887
9888     case POINTER:
9889     case IPOINTER:
9890       genNearPointerSet (right, result, ic, pi);
9891       break;
9892
9893     case PPOINTER:
9894       genPagedPointerSet (right, result, ic, pi);
9895       break;
9896
9897     case FPOINTER:
9898       genFarPointerSet (right, result, ic, pi);
9899       break;
9900
9901     case GPOINTER:
9902       genGenPointerSet (right, result, ic, pi);
9903       break;
9904     }
9905
9906 }
9907
9908 /*-----------------------------------------------------------------*/
9909 /* genIfx - generate code for Ifx statement                        */
9910 /*-----------------------------------------------------------------*/
9911 static void
9912 genIfx (iCode * ic, iCode * popIc)
9913 {
9914   operand *cond = IC_COND (ic);
9915   int isbit = 0;
9916
9917   D (emitcode (";", "genIfx "););
9918
9919   aopOp (cond, ic, FALSE, FALSE);
9920
9921   /* get the value into acc */
9922   if (AOP_TYPE (cond) != AOP_CRY)
9923     toBoolean (cond);
9924   else
9925     isbit = 1;
9926   /* the result is now in the accumulator */
9927   freeAsmop (cond, NULL, ic, TRUE);
9928
9929   /* if there was something to be popped then do it */
9930   if (popIc)
9931     genIpop (popIc);
9932
9933   /* if the condition is  a bit variable */
9934   if (isbit && IS_ITEMP (cond) &&
9935       SPIL_LOC (cond))
9936     genIfxJump (ic, SPIL_LOC (cond)->rname);
9937   else if (isbit && !IS_ITEMP (cond))
9938     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9939   else
9940     genIfxJump (ic, "a");
9941
9942   ic->generated = 1;
9943 }
9944
9945 /*-----------------------------------------------------------------*/
9946 /* genAddrOf - generates code for address of                       */
9947 /*-----------------------------------------------------------------*/
9948 static void
9949 genAddrOf (iCode * ic)
9950 {
9951   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9952   int size, offset;
9953
9954   D (emitcode (";", "genAddrOf ");
9955     );
9956
9957   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9958
9959   /* if the operand is on the stack then we
9960      need to get the stack offset of this
9961      variable */
9962   if (sym->onStack) {
9963       
9964       /* if 10 bit stack */
9965       if (options.stack10bit) {
9966           char buff[10];
9967           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
9968           /* if it has an offset then we need to compute it */
9969           emitcode ("subb", "a,#!constbyte",
9970                     -((sym->stack < 0) ?
9971                       ((short) (sym->stack - _G.nRegsSaved)) :
9972                       ((short) sym->stack)) & 0xff);
9973           emitcode ("mov","b,a");
9974           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
9975                                          ((short) (sym->stack - _G.nRegsSaved)) :
9976                                          ((short) sym->stack)) >> 8) & 0xff);
9977           if (sym->stack) {
9978               emitcode ("mov", "a,_bpx");
9979               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
9980                                              ((char) (sym->stack - _G.nRegsSaved)) :
9981                                              ((char) sym->stack )) & 0xff);
9982               emitcode ("mov", "b,a");
9983               emitcode ("mov", "a,_bpx+1");
9984               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
9985                                               ((short) (sym->stack - _G.nRegsSaved)) :
9986                                               ((short) sym->stack )) >> 8) & 0xff);
9987               aopPut (AOP (IC_RESULT (ic)), "b", 0);
9988               aopPut (AOP (IC_RESULT (ic)), "a", 1);
9989               aopPut (AOP (IC_RESULT (ic)), buff, 2);
9990           } else {
9991               /* we can just move _bp */
9992               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9993               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9994               aopPut (AOP (IC_RESULT (ic)), buff, 2);
9995           }       
9996       } else {
9997           /* if it has an offset then we need to compute it */
9998           if (sym->stack) {
9999               emitcode ("mov", "a,_bp");
10000               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10001               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10002           } else {
10003               /* we can just move _bp */
10004               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10005           }
10006           /* fill the result with zero */
10007           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10008           
10009           
10010           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10011               fprintf (stderr,
10012                        "*** warning: pointer to stack var truncated.\n");
10013           }
10014
10015           offset = 1;
10016           while (size--) {
10017               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10018           }      
10019       }
10020       goto release;
10021   }
10022
10023   /* object not on stack then we need the name */
10024   size = AOP_SIZE (IC_RESULT (ic));
10025   offset = 0;
10026
10027   while (size--)
10028     {
10029       char s[SDCC_NAME_MAX];
10030       if (offset) {
10031           switch (offset) {
10032           case 1:
10033               tsprintf(s,"!his",sym->rname);
10034               break;
10035           case 2:
10036               tsprintf(s,"!hihis",sym->rname);
10037               break;
10038           case 3:
10039               tsprintf(s,"!hihihis",sym->rname);
10040               break;
10041           default: /* should not need this (just in case) */
10042               sprintf (s, "#(%s >> %d)",
10043                        sym->rname,
10044                        offset * 8);
10045           }
10046       } else
10047           sprintf (s, "#%s", sym->rname);
10048       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10049     }
10050
10051 release:
10052   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10053
10054 }
10055
10056 /*-----------------------------------------------------------------*/
10057 /* genArrayInit - generates code for address of                       */
10058 /*-----------------------------------------------------------------*/
10059 static void
10060 genArrayInit (iCode * ic)
10061 {
10062     literalList *iLoop;
10063     int         ix, count;
10064     int         elementSize = 0, eIndex;
10065     unsigned    val, lastVal;
10066     sym_link    *type;
10067     operand     *left=IC_LEFT(ic);
10068     
10069     D (emitcode (";", "genArrayInit "););
10070
10071     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10072     
10073     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10074     {
10075         // Load immediate value into DPTR.
10076         emitcode("mov", "dptr, %s",
10077              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10078     }
10079     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10080     {
10081 #if 0
10082       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10083               "Unexpected operand to genArrayInit.\n");
10084       exit(1);
10085 #else
10086       // a regression because of SDCCcse.c:1.52
10087       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10088       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10089       if (options.model == MODEL_FLAT24)
10090         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10091 #endif
10092     }
10093     
10094     type = operandType(IC_LEFT(ic));
10095     
10096     if (type && type->next)
10097     {
10098         elementSize = getSize(type->next);
10099     }
10100     else
10101     {
10102         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10103                                 "can't determine element size in genArrayInit.\n");
10104         exit(1);
10105     }
10106     
10107     iLoop = IC_ARRAYILIST(ic);
10108     lastVal = 0xffff;
10109     
10110     while (iLoop)
10111     {
10112         bool firstpass = TRUE;
10113         
10114         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10115                  iLoop->count, (int)iLoop->literalValue, elementSize);
10116         
10117         ix = iLoop->count;
10118         
10119         while (ix)
10120         {
10121             symbol *tlbl = NULL;
10122             
10123             count = ix > 256 ? 256 : ix;
10124             
10125             if (count > 1)
10126             {
10127                 tlbl = newiTempLabel (NULL);
10128                 if (firstpass || (count & 0xff))
10129                 {
10130                     emitcode("mov", "b, #!constbyte", count & 0xff);
10131                 }
10132                 
10133                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10134             }
10135             
10136             firstpass = FALSE;
10137                 
10138             for (eIndex = 0; eIndex < elementSize; eIndex++)
10139             {
10140                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10141                 if (val != lastVal)
10142                 {
10143                     emitcode("mov", "a, #!constbyte", val);
10144                     lastVal = val;
10145                 }
10146                 
10147                 emitcode("movx", "@dptr, a");
10148                 emitcode("inc", "dptr");
10149             }
10150             
10151             if (count > 1)
10152             {
10153                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10154             }
10155             
10156             ix -= count;
10157         }
10158         
10159         iLoop = iLoop->next;
10160     }
10161     
10162     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10163 }
10164
10165 /*-----------------------------------------------------------------*/
10166 /* genFarFarAssign - assignment when both are in far space         */
10167 /*-----------------------------------------------------------------*/
10168 static void
10169 genFarFarAssign (operand * result, operand * right, iCode * ic)
10170 {
10171   int size = AOP_SIZE (right);
10172   int offset = 0;
10173   symbol *rSym = NULL;
10174
10175   if (size == 1)
10176   {
10177       /* quick & easy case. */
10178       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10179       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10180       freeAsmop (right, NULL, ic, FALSE);
10181       /* now assign DPTR to result */
10182       _G.accInUse++;
10183       aopOp(result, ic, FALSE, FALSE);
10184       _G.accInUse--;
10185       aopPut(AOP(result), "a", 0);
10186       freeAsmop(result, NULL, ic, FALSE);
10187       return;
10188   }
10189   
10190   /* See if we've got an underlying symbol to abuse. */
10191   if (IS_SYMOP(result) && OP_SYMBOL(result))
10192   {
10193       if (IS_TRUE_SYMOP(result))
10194       {
10195           rSym = OP_SYMBOL(result);
10196       }
10197       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10198       {
10199           rSym = OP_SYMBOL(result)->usl.spillLoc;
10200       }
10201   }
10202              
10203   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10204   {
10205       /* We can use the '390 auto-toggle feature to good effect here. */
10206       
10207       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10208       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
10209       emitcode ("mov", "dptr,#%s", rSym->rname); 
10210       /* DP2 = result, DP1 = right, DP1 is current. */
10211       while (size)
10212       {
10213           emitcode("movx", "a,@dptr");
10214           emitcode("movx", "@dptr,a");
10215           if (--size)
10216           {
10217                emitcode("inc", "dptr");
10218                emitcode("inc", "dptr");
10219           }
10220       }
10221       emitcode("mov", "dps, #0");
10222       freeAsmop (right, NULL, ic, FALSE);
10223 #if 0
10224 some alternative code for processors without auto-toggle
10225 no time to test now, so later well put in...kpb
10226         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10227         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
10228         emitcode ("mov", "dptr,#%s", rSym->rname); 
10229         /* DP2 = result, DP1 = right, DP1 is current. */
10230         while (size)
10231         {
10232           --size;
10233           emitcode("movx", "a,@dptr");
10234           if (size)
10235             emitcode("inc", "dptr");
10236           emitcode("inc", "dps");
10237           emitcode("movx", "@dptr,a");
10238           if (size)
10239             emitcode("inc", "dptr");
10240           emitcode("inc", "dps");
10241         }
10242         emitcode("mov", "dps, #0");
10243         freeAsmop (right, NULL, ic, FALSE);
10244 #endif
10245   }
10246   else
10247   {
10248       D (emitcode (";", "genFarFarAssign"););
10249       aopOp (result, ic, TRUE, TRUE);
10250
10251       _startLazyDPSEvaluation ();
10252       
10253       while (size--)
10254         {
10255           aopPut (AOP (result),
10256                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10257           offset++;
10258         }
10259       _endLazyDPSEvaluation ();
10260       freeAsmop (result, NULL, ic, FALSE);
10261       freeAsmop (right, NULL, ic, FALSE);
10262   }
10263 }
10264
10265 /*-----------------------------------------------------------------*/
10266 /* genAssign - generate code for assignment                        */
10267 /*-----------------------------------------------------------------*/
10268 static void
10269 genAssign (iCode * ic)
10270 {
10271   operand *result, *right;
10272   int size, offset;
10273   unsigned long lit = 0L;
10274
10275   D (emitcode (";", "genAssign ");
10276     );
10277
10278   result = IC_RESULT (ic);
10279   right = IC_RIGHT (ic);
10280
10281   /* if they are the same */
10282   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10283     return;
10284
10285   aopOp (right, ic, FALSE, FALSE);
10286
10287   emitcode (";", "genAssign: resultIsFar = %s",
10288             isOperandInFarSpace (result) ?
10289             "TRUE" : "FALSE");
10290
10291   /* special case both in far space */
10292   if ((AOP_TYPE (right) == AOP_DPTR ||
10293        AOP_TYPE (right) == AOP_DPTR2) &&
10294   /* IS_TRUE_SYMOP(result)       && */
10295       isOperandInFarSpace (result))
10296     {
10297       genFarFarAssign (result, right, ic);
10298       return;
10299     }
10300
10301   aopOp (result, ic, TRUE, FALSE);
10302
10303   /* if they are the same registers */
10304   if (sameRegs (AOP (right), AOP (result)))
10305     goto release;
10306
10307   /* if the result is a bit */
10308   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10309     {
10310       /* if the right size is a literal then
10311          we know what the value is */
10312       if (AOP_TYPE (right) == AOP_LIT)
10313         {
10314           if (((int) operandLitValue (right)))
10315             aopPut (AOP (result), one, 0);
10316           else
10317             aopPut (AOP (result), zero, 0);
10318           goto release;
10319         }
10320
10321       /* the right is also a bit variable */
10322       if (AOP_TYPE (right) == AOP_CRY)
10323         {
10324           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10325           aopPut (AOP (result), "c", 0);
10326           goto release;
10327         }
10328
10329       /* we need to or */
10330       toBoolean (right);
10331       aopPut (AOP (result), "a", 0);
10332       goto release;
10333     }
10334
10335   /* bit variables done */
10336   /* general case */
10337   size = AOP_SIZE (result);
10338   offset = 0;
10339   if (AOP_TYPE (right) == AOP_LIT)
10340     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10341
10342   if ((size > 1) &&
10343       (AOP_TYPE (result) != AOP_REG) &&
10344       (AOP_TYPE (right) == AOP_LIT) &&
10345       !IS_FLOAT (operandType (right)))
10346     {
10347       _startLazyDPSEvaluation ();
10348       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10349         {
10350           aopPut (AOP (result),
10351                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10352                   offset);
10353           offset++;
10354           size--;
10355         }
10356       /* And now fill the rest with zeros. */
10357       if (size)
10358         {
10359           emitcode ("clr", "a");
10360         }
10361       while (size--)
10362         {
10363           aopPut (AOP (result), "a", offset++);
10364         }
10365       _endLazyDPSEvaluation ();
10366     }
10367   else
10368     {
10369       _startLazyDPSEvaluation ();
10370       while (size--)
10371         {
10372           aopPut (AOP (result),
10373                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10374                   offset);
10375           offset++;
10376         }
10377       _endLazyDPSEvaluation ();
10378     }
10379
10380 release:
10381   freeAsmop (right, NULL, ic, FALSE);
10382   freeAsmop (result, NULL, ic, TRUE);
10383 }
10384
10385 /*-----------------------------------------------------------------*/
10386 /* genJumpTab - generates code for jump table                      */
10387 /*-----------------------------------------------------------------*/
10388 static void
10389 genJumpTab (iCode * ic)
10390 {
10391   symbol *jtab;
10392   char *l;
10393
10394   D (emitcode (";", "genJumpTab ");
10395     );
10396
10397   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10398   /* get the condition into accumulator */
10399   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10400   MOVA (l);
10401   /* multiply by four! */
10402   emitcode ("add", "a,acc");
10403   emitcode ("add", "a,acc");
10404   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10405
10406   jtab = newiTempLabel (NULL);
10407   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10408   emitcode ("jmp", "@a+dptr");
10409   emitcode ("", "!tlabeldef", jtab->key + 100);
10410   /* now generate the jump labels */
10411   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10412        jtab = setNextItem (IC_JTLABELS (ic)))
10413     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10414
10415 }
10416
10417 /*-----------------------------------------------------------------*/
10418 /* genCast - gen code for casting                                  */
10419 /*-----------------------------------------------------------------*/
10420 static void
10421 genCast (iCode * ic)
10422 {
10423   operand *result = IC_RESULT (ic);
10424   sym_link *ctype = operandType (IC_LEFT (ic));
10425   sym_link *rtype = operandType (IC_RIGHT (ic));
10426   operand *right = IC_RIGHT (ic);
10427   int size, offset;
10428
10429   D (emitcode (";", "genCast ");
10430     );
10431
10432   /* if they are equivalent then do nothing */
10433   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10434     return;
10435
10436   aopOp (right, ic, FALSE, FALSE);
10437   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10438
10439   /* if the result is a bit */
10440   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10441   if (IS_BITVAR(OP_SYMBOL(result)->type))
10442     {
10443       /* if the right size is a literal then
10444          we know what the value is */
10445       if (AOP_TYPE (right) == AOP_LIT)
10446         {
10447           if (((int) operandLitValue (right)))
10448             aopPut (AOP (result), one, 0);
10449           else
10450             aopPut (AOP (result), zero, 0);
10451
10452           goto release;
10453         }
10454
10455       /* the right is also a bit variable */
10456       if (AOP_TYPE (right) == AOP_CRY)
10457         {
10458           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10459           aopPut (AOP (result), "c", 0);
10460           goto release;
10461         }
10462
10463       /* we need to or */
10464       toBoolean (right);
10465       aopPut (AOP (result), "a", 0);
10466       goto release;
10467     }
10468
10469   /* if they are the same size : or less */
10470   if (AOP_SIZE (result) <= AOP_SIZE (right))
10471     {
10472
10473       /* if they are in the same place */
10474       if (sameRegs (AOP (right), AOP (result)))
10475         goto release;
10476
10477       /* if they in different places then copy */
10478       size = AOP_SIZE (result);
10479       offset = 0;
10480       _startLazyDPSEvaluation ();
10481       while (size--)
10482         {
10483           aopPut (AOP (result),
10484                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10485                   offset);
10486           offset++;
10487         }
10488       _endLazyDPSEvaluation ();
10489       goto release;
10490     }
10491
10492
10493   /* if the result is of type pointer */
10494   if (IS_PTR (ctype))
10495     {
10496
10497       int p_type;
10498       sym_link *type = operandType (right);
10499
10500       /* pointer to generic pointer */
10501       if (IS_GENPTR (ctype))
10502         {
10503           char *l = zero;
10504
10505           if (IS_PTR (type))
10506             {
10507               p_type = DCL_TYPE (type);
10508             }
10509           else
10510             {
10511 #if OLD_CAST_BEHAVIOR
10512               /* KV: we are converting a non-pointer type to
10513                * a generic pointer. This (ifdef'd out) code
10514                * says that the resulting generic pointer
10515                * should have the same class as the storage
10516                * location of the non-pointer variable.
10517                *
10518                * For example, converting an int (which happens
10519                * to be stored in DATA space) to a pointer results
10520                * in a DATA generic pointer; if the original int
10521                * in XDATA space, so will be the resulting pointer.
10522                *
10523                * I don't like that behavior, and thus this change:
10524                * all such conversions will be forced to XDATA and
10525                * throw a warning. If you want some non-XDATA
10526                * type, or you want to suppress the warning, you
10527                * must go through an intermediate cast, like so:
10528                *
10529                * char _generic *gp = (char _xdata *)(intVar);
10530                */
10531               sym_link *etype = getSpec (type);
10532
10533               /* we have to go by the storage class */
10534               if (SPEC_OCLS (etype) != generic)
10535                 {
10536                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10537                 }
10538               else
10539 #endif
10540                 {
10541                   /* Converting unknown class (i.e. register variable)
10542                    * to generic pointer. This is not good, but
10543                    * we'll make a guess (and throw a warning).
10544                    */
10545                   p_type = FPOINTER;
10546                   werror (W_INT_TO_GEN_PTR_CAST);
10547                 }
10548             }
10549
10550           /* the first two bytes are known */
10551           size = GPTRSIZE - 1;
10552           offset = 0;
10553           _startLazyDPSEvaluation ();
10554           while (size--)
10555             {
10556               aopPut (AOP (result),
10557                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10558                       offset);
10559               offset++;
10560             }
10561           _endLazyDPSEvaluation ();
10562
10563           /* the last byte depending on type */
10564           switch (p_type)
10565             {
10566             case IPOINTER:
10567             case POINTER:
10568               l = zero;
10569               break;
10570             case FPOINTER:
10571               l = one;
10572               break;
10573             case CPOINTER:
10574               l = "#0x02";
10575               break;
10576             case PPOINTER:
10577               l = "#0x03";
10578               break;
10579
10580             default:
10581               /* this should never happen */
10582               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10583                       "got unknown pointer type");
10584               exit (1);
10585             }
10586           aopPut (AOP (result), l, GPTRSIZE - 1);
10587           goto release;
10588         }
10589
10590       /* just copy the pointers */
10591       size = AOP_SIZE (result);
10592       offset = 0;
10593       _startLazyDPSEvaluation ();
10594       while (size--)
10595         {
10596           aopPut (AOP (result),
10597                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10598                   offset);
10599           offset++;
10600         }
10601       _endLazyDPSEvaluation ();
10602       goto release;
10603     }
10604
10605   /* so we now know that the size of destination is greater
10606      than the size of the source */
10607   /* we move to result for the size of source */
10608   size = AOP_SIZE (right);
10609   offset = 0;
10610   _startLazyDPSEvaluation ();
10611   while (size--)
10612     {
10613       aopPut (AOP (result),
10614               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10615               offset);
10616       offset++;
10617     }
10618   _endLazyDPSEvaluation ();
10619
10620   /* now depending on the sign of the source && destination */
10621   size = AOP_SIZE (result) - AOP_SIZE (right);
10622   /* if unsigned or not an integral type */
10623   /* also, if the source is a bit, we don't need to sign extend, because
10624    * it can't possibly have set the sign bit.
10625    */
10626   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10627     {
10628       while (size--)
10629         {
10630           aopPut (AOP (result), zero, offset++);
10631         }
10632     }
10633   else
10634     {
10635       /* we need to extend the sign :{ */
10636       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10637                         FALSE, FALSE, TRUE);
10638       MOVA (l);
10639       emitcode ("rlc", "a");
10640       emitcode ("subb", "a,acc");
10641       while (size--)
10642         aopPut (AOP (result), "a", offset++);
10643     }
10644
10645   /* we are done hurray !!!! */
10646
10647 release:
10648   freeAsmop (right, NULL, ic, TRUE);
10649   freeAsmop (result, NULL, ic, TRUE);
10650
10651 }
10652
10653 /*-----------------------------------------------------------------*/
10654 /* genDjnz - generate decrement & jump if not zero instrucion      */
10655 /*-----------------------------------------------------------------*/
10656 static int
10657 genDjnz (iCode * ic, iCode * ifx)
10658 {
10659   symbol *lbl, *lbl1;
10660   if (!ifx)
10661     return 0;
10662
10663   /* if the if condition has a false label
10664      then we cannot save */
10665   if (IC_FALSE (ifx))
10666     return 0;
10667
10668   /* if the minus is not of the form
10669      a = a - 1 */
10670   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10671       !IS_OP_LITERAL (IC_RIGHT (ic)))
10672     return 0;
10673
10674   if (operandLitValue (IC_RIGHT (ic)) != 1)
10675     return 0;
10676
10677   /* if the size of this greater than one then no
10678      saving */
10679   if (getSize (operandType (IC_RESULT (ic))) > 1)
10680     return 0;
10681
10682   /* otherwise we can save BIG */
10683   D(emitcode(";", "genDjnz"););
10684
10685   lbl = newiTempLabel (NULL);
10686   lbl1 = newiTempLabel (NULL);
10687
10688   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10689
10690   if (AOP_NEEDSACC(IC_RESULT(ic)))
10691   {
10692       /* If the result is accessed indirectly via
10693        * the accumulator, we must explicitly write
10694        * it back after the decrement.
10695        */
10696       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10697       
10698       if (strcmp(rByte, "a"))
10699       {
10700            /* Something is hopelessly wrong */
10701            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10702                    __FILE__, __LINE__);
10703            /* We can just give up; the generated code will be inefficient,
10704             * but what the hey.
10705             */
10706            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10707            return 0;
10708       }
10709       emitcode ("dec", "%s", rByte);
10710       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10711       emitcode ("jnz", "!tlabel", lbl->key + 100);
10712   }
10713   else if (IS_AOP_PREG (IC_RESULT (ic)))
10714     {
10715       emitcode ("dec", "%s",
10716                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10717       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10718       emitcode ("jnz", "!tlabel", lbl->key + 100);
10719     }
10720   else
10721     {
10722       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10723                 lbl->key + 100);
10724     }
10725   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10726   emitcode ("", "!tlabeldef", lbl->key + 100);
10727   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10728   emitcode ("", "!tlabeldef", lbl1->key + 100);
10729
10730   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10731   ifx->generated = 1;
10732   return 1;
10733 }
10734
10735 /*-----------------------------------------------------------------*/
10736 /* genReceive - generate code for a receive iCode                  */
10737 /*-----------------------------------------------------------------*/
10738 static void
10739 genReceive (iCode * ic)
10740 {
10741
10742   D (emitcode (";", "genReceive ");
10743     );
10744
10745   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10746       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10747        IS_TRUE_SYMOP (IC_RESULT (ic))))
10748     {
10749       int size = getSize (operandType (IC_RESULT (ic)));
10750       int offset = fReturnSizeDS390 - size;
10751       while (size--)
10752         {
10753           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10754                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10755           offset++;
10756         }
10757       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10758       size = AOP_SIZE (IC_RESULT (ic));
10759       offset = 0;
10760       while (size--)
10761         {
10762           emitcode ("pop", "acc");
10763           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10764         }
10765
10766     }
10767   else
10768     {
10769       _G.accInUse++;
10770       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10771       _G.accInUse--;
10772       assignResultValue (IC_RESULT (ic));
10773     }
10774
10775   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10776 }
10777
10778 /*-----------------------------------------------------------------*/
10779 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10780 /*-----------------------------------------------------------------*/
10781 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10782 {
10783     operand *from , *to , *count;
10784     symbol *lbl;
10785
10786     /* we know it has to be 3 parameters */
10787     assert (nparms == 3);
10788     
10789     to = parms[0];
10790     from = parms[1];
10791     count = parms[2];
10792
10793     aopOp (from, ic->next, FALSE, FALSE);
10794
10795     /* get from into DPTR1 */
10796     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10797     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10798     if (options.model == MODEL_FLAT24) {
10799         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10800     }
10801
10802     freeAsmop (from, NULL, ic, FALSE);
10803     aopOp (to, ic, FALSE, FALSE);
10804     /* get "to" into DPTR */
10805     /* if the operand is already in dptr
10806        then we do nothing else we move the value to dptr */
10807     if (AOP_TYPE (to) != AOP_STR) {
10808         /* if already in DPTR then we need to push */
10809         if (AOP_TYPE(to) == AOP_DPTR) {
10810             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10811             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10812             if (options.model == MODEL_FLAT24)
10813                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10814             emitcode ("pop", "dph");
10815             emitcode ("pop", "dpl");        
10816         } else {
10817             _startLazyDPSEvaluation ();
10818             /* if this is remateriazable */
10819             if (AOP_TYPE (to) == AOP_IMMD) {
10820                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10821             } else {                    /* we need to get it byte by byte */
10822                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10823                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10824                 if (options.model == MODEL_FLAT24) {
10825                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10826                 }
10827             }
10828             _endLazyDPSEvaluation ();
10829         }
10830     }
10831     freeAsmop (to, NULL, ic, FALSE);
10832
10833     aopOp (count, ic->next->next, FALSE,FALSE);
10834     lbl =newiTempLabel(NULL);
10835
10836     /* now for the actual copy */
10837     if (AOP_TYPE(count) == AOP_LIT && 
10838         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10839         emitcode (";","OH! JOY auto increment with djnz (very fast)");
10840         emitcode ("mov", "dps, #0x21");         /* Select DPTR2 & auto-toggle. */
10841         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10842         emitcode ("","!tlabeldef",lbl->key+100);
10843         if (fromc) {
10844             emitcode ("clr","a");
10845             emitcode ("movc", "a,@a+dptr");
10846         } else 
10847             emitcode ("movx", "a,@dptr");
10848         emitcode ("movx", "@dptr,a");
10849         emitcode ("inc", "dptr");
10850         emitcode ("inc", "dptr");
10851         emitcode ("djnz","b,!tlabel",lbl->key+100);
10852     } else {
10853         symbol *lbl1 = newiTempLabel(NULL);
10854         
10855         emitcode (";"," Auto increment but no djnz");
10856         emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10857         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10858         emitcode ("mov", "dps, #0x21");         /* Select DPTR2 & auto-toggle. */
10859         emitcode ("","!tlabeldef",lbl->key+100);
10860         if (fromc) {
10861             emitcode ("clr","a");
10862             emitcode ("movc", "a,@a+dptr");
10863         } else 
10864             emitcode ("movx", "a,@dptr");
10865         emitcode ("movx", "@dptr,a");
10866         emitcode ("inc", "dptr");
10867         emitcode ("inc", "dptr");
10868         emitcode ("mov","a,b");
10869         emitcode ("orl","a,ap");
10870         emitcode ("jz","!tlabel",lbl1->key+100);
10871         emitcode ("mov","a,ap");
10872         emitcode ("add","a,#0xFF");
10873         emitcode ("mov","ap,a");
10874         emitcode ("mov","a,b");
10875         emitcode ("addc","a,#0xFF");
10876         emitcode ("mov","b,a");
10877         emitcode ("sjmp","!tlabel",lbl->key+100);
10878         emitcode ("","!tlabeldef",lbl1->key+100);
10879     }
10880     emitcode ("mov", "dps, #0"); 
10881     freeAsmop (count, NULL, ic, FALSE);
10882
10883 }
10884
10885 /*-----------------------------------------------------------------*/
10886 /* genMemsetX - gencode for memSetX data                           */
10887 /*-----------------------------------------------------------------*/
10888 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10889 {
10890     operand *to , *val , *count;
10891     symbol *lbl;
10892     char *l;
10893     /* we know it has to be 3 parameters */
10894     assert (nparms == 3);
10895     
10896     to = parms[0];
10897     val = parms[1];
10898     count = parms[2];
10899
10900     aopOp (to, ic, FALSE, FALSE);
10901     /* get "to" into DPTR */
10902     /* if the operand is already in dptr
10903        then we do nothing else we move the value to dptr */
10904     if (AOP_TYPE (to) != AOP_STR) {
10905         /* if already in DPTR then we need to push */
10906         if (AOP_TYPE(to) == AOP_DPTR) {
10907             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10908             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10909             if (options.model == MODEL_FLAT24)
10910                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10911             emitcode ("pop", "dph");
10912             emitcode ("pop", "dpl");        
10913         } else {
10914             _startLazyDPSEvaluation ();
10915             /* if this is remateriazable */
10916             if (AOP_TYPE (to) == AOP_IMMD) {
10917                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10918             } else {                    /* we need to get it byte by byte */
10919                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10920                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10921                 if (options.model == MODEL_FLAT24) {
10922                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10923                 }
10924             }
10925             _endLazyDPSEvaluation ();
10926         }
10927     }
10928     freeAsmop (to, NULL, ic, FALSE);
10929
10930     aopOp (val, ic->next->next, FALSE,FALSE);
10931     aopOp (count, ic->next->next, FALSE,FALSE);    
10932     lbl =newiTempLabel(NULL);
10933     /* now for the actual copy */
10934     if (AOP_TYPE(count) == AOP_LIT && 
10935         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10936         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10937         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10938         MOVA(l);
10939         emitcode ("","!tlabeldef",lbl->key+100);
10940         emitcode ("movx", "@dptr,a");
10941         emitcode ("inc", "dptr");
10942         emitcode ("djnz","b,!tlabel",lbl->key+100);
10943     } else {
10944         symbol *lbl1 = newiTempLabel(NULL);
10945         
10946         emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10947         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10948         emitcode ("","!tlabeldef",lbl->key+100);
10949         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10950         MOVA(l);
10951         emitcode ("movx", "a,@dptr");
10952         emitcode ("inc", "dptr");
10953         emitcode ("mov","a,b");
10954         emitcode ("orl","a,ap");
10955         emitcode ("jz","!tlabel",lbl1->key+100);
10956         emitcode ("mov","a,ap");
10957         emitcode ("add","a,#0xFF");
10958         emitcode ("mov","ap,a");
10959         emitcode ("mov","a,b");
10960         emitcode ("addc","a,#0xFF");
10961         emitcode ("mov","b,a");
10962         emitcode ("sjmp","!tlabel",lbl->key+100);
10963         emitcode ("","!tlabeldef",lbl1->key+100);
10964     }
10965     freeAsmop (count, NULL, ic, FALSE);
10966 }
10967
10968 /*-----------------------------------------------------------------*/
10969 /* genBuiltIn - calls the appropriate function to  generating code */
10970 /* for a built in function                                         */
10971 /*-----------------------------------------------------------------*/
10972 static void genBuiltIn (iCode *ic)
10973 {
10974     operand *bi_parms[MAX_BUILTIN_ARGS];
10975     int nbi_parms;
10976     iCode *bi_iCode;
10977     symbol *bif;
10978
10979     /* get all the arguments for a built in function */
10980     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
10981
10982     /* which function is it */
10983     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
10984     if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
10985         genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
10986     } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
10987         genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
10988     } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
10989         genMemsetX(bi_iCode,nbi_parms,bi_parms);
10990     } else {
10991         werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n");
10992         return ;
10993     }
10994     return ;    
10995 }
10996
10997 /*-----------------------------------------------------------------*/
10998 /* gen390Code - generate code for Dallas 390 based controllers     */
10999 /*-----------------------------------------------------------------*/
11000 void
11001 gen390Code (iCode * lic)
11002 {
11003   iCode *ic;
11004   int cln = 0;
11005
11006   lineHead = lineCurr = NULL;
11007
11008   if (options.model == MODEL_FLAT24) {
11009     fReturnSizeDS390 = 5;
11010     fReturn = fReturn24;
11011   } else {
11012     fReturnSizeDS390 = 4;
11013     fReturn = fReturn16;
11014     options.stack10bit=0;
11015   }
11016 #if 0
11017   //REMOVE ME!!!
11018   /* print the allocation information */
11019   if (allocInfo)
11020     printAllocInfo (currFunc, codeOutFile);
11021 #endif
11022   /* if debug information required */
11023   if (options.debug && currFunc)
11024     {
11025       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11026       _G.debugLine = 1;
11027       if (IS_STATIC (currFunc->etype))
11028         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11029       else
11030         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11031       _G.debugLine = 0;
11032     }
11033   /* stack pointer name */
11034   if (options.useXstack)
11035     spname = "_spx";
11036   else
11037     spname = "sp";
11038
11039
11040   for (ic = lic; ic; ic = ic->next)
11041     {
11042
11043       if (cln != ic->lineno)
11044         {
11045           if (options.debug)
11046             {
11047               _G.debugLine = 1;
11048               emitcode ("", "C$%s$%d$%d$%d ==.",
11049                         FileBaseName (ic->filename), ic->lineno,
11050                         ic->level, ic->block);
11051               _G.debugLine = 0;
11052             }
11053           emitcode (";", "%s %d", ic->filename, ic->lineno);
11054           cln = ic->lineno;
11055         }
11056       /* if the result is marked as
11057          spilt and rematerializable or code for
11058          this has already been generated then
11059          do nothing */
11060       if (resultRemat (ic) || ic->generated)
11061         continue;
11062
11063       /* depending on the operation */
11064       switch (ic->op)
11065         {
11066         case '!':
11067           genNot (ic);
11068           break;
11069
11070         case '~':
11071           genCpl (ic);
11072           break;
11073
11074         case UNARYMINUS:
11075           genUminus (ic);
11076           break;
11077
11078         case IPUSH:
11079           genIpush (ic);
11080           break;
11081
11082         case IPOP:
11083           /* IPOP happens only when trying to restore a
11084              spilt live range, if there is an ifx statement
11085              following this pop then the if statement might
11086              be using some of the registers being popped which
11087              would destory the contents of the register so
11088              we need to check for this condition and handle it */
11089           if (ic->next &&
11090               ic->next->op == IFX &&
11091               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11092             genIfx (ic->next, ic);
11093           else
11094             genIpop (ic);
11095           break;
11096
11097         case CALL:
11098           genCall (ic);
11099           break;
11100
11101         case PCALL:
11102           genPcall (ic);
11103           break;
11104
11105         case FUNCTION:
11106           genFunction (ic);
11107           break;
11108
11109         case ENDFUNCTION:
11110           genEndFunction (ic);
11111           break;
11112
11113         case RETURN:
11114           genRet (ic);
11115           break;
11116
11117         case LABEL:
11118           genLabel (ic);
11119           break;
11120
11121         case GOTO:
11122           genGoto (ic);
11123           break;
11124
11125         case '+':
11126           genPlus (ic);
11127           break;
11128
11129         case '-':
11130           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11131             genMinus (ic);
11132           break;
11133
11134         case '*':
11135           genMult (ic);
11136           break;
11137
11138         case '/':
11139           genDiv (ic);
11140           break;
11141
11142         case '%':
11143           genMod (ic);
11144           break;
11145
11146         case '>':
11147           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11148           break;
11149
11150         case '<':
11151           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11152           break;
11153
11154         case LE_OP:
11155         case GE_OP:
11156         case NE_OP:
11157
11158           /* note these two are xlated by algebraic equivalence
11159              during parsing SDCC.y */
11160           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11161                   "got '>=' or '<=' shouldn't have come here");
11162           break;
11163
11164         case EQ_OP:
11165           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11166           break;
11167
11168         case AND_OP:
11169           genAndOp (ic);
11170           break;
11171
11172         case OR_OP:
11173           genOrOp (ic);
11174           break;
11175
11176         case '^':
11177           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11178           break;
11179
11180         case '|':
11181           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11182           break;
11183
11184         case BITWISEAND:
11185           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11186           break;
11187
11188         case INLINEASM:
11189           genInline (ic);
11190           break;
11191
11192         case RRC:
11193           genRRC (ic);
11194           break;
11195
11196         case RLC:
11197           genRLC (ic);
11198           break;
11199
11200         case GETHBIT:
11201           genGetHbit (ic);
11202           break;
11203
11204         case LEFT_OP:
11205           genLeftShift (ic);
11206           break;
11207
11208         case RIGHT_OP:
11209           genRightShift (ic);
11210           break;
11211
11212         case GET_VALUE_AT_ADDRESS:
11213           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11214           break;
11215
11216         case '=':
11217           if (POINTER_SET (ic))
11218             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11219           else
11220             genAssign (ic);
11221           break;
11222
11223         case IFX:
11224           genIfx (ic, NULL);
11225           break;
11226
11227         case ADDRESS_OF:
11228           genAddrOf (ic);
11229           break;
11230
11231         case JUMPTABLE:
11232           genJumpTab (ic);
11233           break;
11234
11235         case CAST:
11236           genCast (ic);
11237           break;
11238
11239         case RECEIVE:
11240           genReceive (ic);
11241           break;
11242
11243         case SEND:
11244           if (ic->builtinSEND) genBuiltIn(ic);
11245           else addSet (&_G.sendSet, ic);
11246           break;
11247
11248         case ARRAYINIT:
11249             genArrayInit(ic);
11250             break;
11251             
11252         default:
11253           ic = ic;
11254         }
11255     }
11256
11257
11258   /* now we are ready to call the
11259      peep hole optimizer */
11260   if (!options.nopeep)
11261     peepHole (&lineHead);
11262
11263   /* now do the actual printing */
11264   printLine (lineHead, codeOutFile);
11265   return;
11266 }