Made it assembler agnostic everything assembler specific now handled in asm.c
[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       sym->aop = op->aop = aop =
831         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
832       aop->size = getSize (sym->type);
833       return;
834     }
835
836   /* must be in a register */
837   sym->aop = op->aop = aop = newAsmop (AOP_REG);
838   aop->size = sym->nRegs;
839   for (i = 0; i < sym->nRegs; i++)
840     aop->aopu.aop_reg[i] = sym->regs[i];
841 }
842
843 /*-----------------------------------------------------------------*/
844 /* freeAsmop - free up the asmop given to an operand               */
845 /*----------------------------------------------------------------*/
846 static void
847 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
848 {
849   asmop *aop;
850
851   if (!op)
852     aop = aaop;
853   else
854     aop = op->aop;
855
856   if (!aop)
857     return;
858
859   if (aop->freed)
860     goto dealloc;
861
862   aop->freed = 1;
863
864   /* depending on the asmop type only three cases need work AOP_RO
865      , AOP_R1 && AOP_STK */
866   switch (aop->type)
867     {
868     case AOP_R0:
869       if (_G.r0Pushed)
870         {
871           if (pop)
872             {
873               emitcode ("pop", "ar0");
874               _G.r0Pushed--;
875             }
876         }
877       bitVectUnSetBit (ic->rUsed, R0_IDX);
878       break;
879
880     case AOP_R1:
881       if (_G.r1Pushed)
882         {
883           if (pop)
884             {
885               emitcode ("pop", "ar1");
886               _G.r1Pushed--;
887             }
888         }
889       bitVectUnSetBit (ic->rUsed, R1_IDX);
890       break;
891
892     case AOP_STK:
893       {
894         int sz = aop->size;
895         int stk = aop->aopu.aop_stk + aop->size;
896         bitVectUnSetBit (ic->rUsed, R0_IDX);
897         bitVectUnSetBit (ic->rUsed, R1_IDX);
898
899         getFreePtr (ic, &aop, FALSE);
900
901         if (options.stack10bit)
902           {
903             /* I'm not sure what to do here yet... */
904             /* #STUB */
905             fprintf (stderr,
906                      "*** Warning: probably generating bad code for "
907                      "10 bit stack mode.\n");
908           }
909
910         if (stk)
911           {
912             emitcode ("mov", "a,_bp");
913             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
914             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
915           }
916         else
917           {
918             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
919           }
920
921         while (sz--)
922           {
923             emitcode ("pop", "acc");
924             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
925             if (!sz)
926               break;
927             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
928           }
929         op->aop = aop;
930         freeAsmop (op, NULL, ic, TRUE);
931         if (_G.r0Pushed)
932           {
933             emitcode ("pop", "ar0");
934             _G.r0Pushed--;
935           }
936
937         if (_G.r1Pushed)
938           {
939             emitcode ("pop", "ar1");
940             _G.r1Pushed--;
941           }
942       }
943     }
944
945 dealloc:
946   /* all other cases just dealloc */
947   if (op)
948     {
949       op->aop = NULL;
950       if (IS_SYMOP (op))
951         {
952           OP_SYMBOL (op)->aop = NULL;
953           /* if the symbol has a spill */
954           if (SPIL_LOC (op))
955             SPIL_LOC (op)->aop = NULL;
956         }
957     }
958 }
959
960 /*------------------------------------------------------------------*/
961 /* aopGet - for fetching value of the aop                           */
962 /*                    */
963 /* Set canClobberACC if you are sure it is OK to clobber the value  */
964 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
965 /* just less efficient.               */
966 /*------------------------------------------------------------------*/
967
968 static char *
969 aopGet (asmop * aop,
970         int offset,
971         bool bit16,
972         bool dname,
973         bool canClobberACC)
974 {
975   char *s = buffer;
976   char *rs;
977
978   /* offset is greater than
979      size then zero */
980   if (offset > (aop->size - 1) &&
981       aop->type != AOP_LIT)
982     return zero;
983
984   /* depending on type */
985   switch (aop->type)
986     {
987
988     case AOP_R0:
989     case AOP_R1:
990       /* if we need to increment it */
991       while (offset > aop->coff)
992         {
993           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
994           aop->coff++;
995         }
996
997       while (offset < aop->coff)
998         {
999           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1000           aop->coff--;
1001         }
1002
1003       aop->coff = offset;
1004       if (aop->paged)
1005         {
1006           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1007           return (dname ? "acc" : "a");
1008         }
1009       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1010       rs = Safe_calloc (1, strlen (s) + 1);
1011       strcpy (rs, s);
1012       return rs;
1013
1014     case AOP_DPTR:
1015     case AOP_DPTR2:
1016
1017       if (aop->type == AOP_DPTR2)
1018         {
1019           genSetDPTR (1);
1020           if (!canClobberACC)
1021             {
1022                     TR_AP("#1");
1023                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1024             }
1025         }
1026
1027       _flushLazyDPS ();
1028
1029       while (offset > aop->coff)
1030         {
1031           emitcode ("inc", "dptr");
1032           aop->coff++;
1033         }
1034
1035       while (offset < aop->coff)
1036         {
1037           emitcode ("lcall", "__decdptr");
1038           aop->coff--;
1039         }
1040
1041       aop->coff = offset;
1042       if (aop->code)
1043         {
1044           emitcode ("clr", "a");
1045           emitcode ("movc", "a,@a+dptr");
1046         }
1047       else
1048         {
1049           emitcode ("movx", "a,@dptr");
1050         }
1051
1052       if (aop->type == AOP_DPTR2)
1053         {
1054           genSetDPTR (0);
1055           if (!canClobberACC)
1056             {
1057        TR_AP("#2");
1058               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1059               return DP2_RESULT_REG;
1060             }
1061         }
1062       return (dname ? "acc" : "a");
1063
1064     case AOP_IMMD:
1065       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1066               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1067       } else if (bit16)
1068         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1069       else if (offset) {
1070           switch (offset) {
1071           case 1:
1072               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1073               break;
1074           case 2:
1075               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1076               break;
1077           case 3:
1078               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1079               break;
1080           default: /* should not need this (just in case) */
1081               sprintf (s, "#(%s >> %d)",
1082                        aop->aopu.aop_immd.aop_immd1,
1083                        offset * 8);
1084           }
1085       }
1086       else
1087         sprintf (s, "#%s",
1088                  aop->aopu.aop_immd.aop_immd1);
1089       rs = Safe_calloc (1, strlen (s) + 1);
1090       strcpy (rs, s);
1091       return rs;
1092
1093     case AOP_DIR:
1094       if (offset)
1095         sprintf (s, "(%s + %d)",
1096                  aop->aopu.aop_dir,
1097                  offset);
1098       else
1099         sprintf (s, "%s", aop->aopu.aop_dir);
1100       rs = Safe_calloc (1, strlen (s) + 1);
1101       strcpy (rs, s);
1102       return rs;
1103
1104     case AOP_REG:
1105       if (dname)
1106         return aop->aopu.aop_reg[offset]->dname;
1107       else
1108         return aop->aopu.aop_reg[offset]->name;
1109
1110     case AOP_CRY:
1111       emitcode ("clr", "a");
1112       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1113       emitcode ("rlc", "a");
1114       return (dname ? "acc" : "a");
1115
1116     case AOP_ACC:
1117       if (!offset && dname)
1118         return "acc";
1119       return aop->aopu.aop_str[offset];
1120
1121     case AOP_LIT:
1122       return aopLiteral (aop->aopu.aop_lit, offset);
1123
1124     case AOP_STR:
1125       aop->coff = offset;
1126       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1127           dname)
1128         return "acc";
1129
1130       return aop->aopu.aop_str[offset];
1131
1132     }
1133
1134   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1135           "aopget got unsupported aop->type");
1136   exit (1);
1137 }
1138 /*-----------------------------------------------------------------*/
1139 /* aopPut - puts a string for a aop                                */
1140 /*-----------------------------------------------------------------*/
1141 static void
1142 aopPut (asmop * aop, char *s, int offset)
1143 {
1144   char *d = buffer;
1145
1146   if (aop->size && offset > (aop->size - 1))
1147     {
1148       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1149               "aopPut got offset > aop->size");
1150       exit (1);
1151     }
1152
1153   /* will assign value to value */
1154   /* depending on where it is ofcourse */
1155   switch (aop->type)
1156     {
1157     case AOP_DIR:
1158       if (offset)
1159         sprintf (d, "(%s + %d)",
1160                  aop->aopu.aop_dir, offset);
1161       else
1162         sprintf (d, "%s", aop->aopu.aop_dir);
1163
1164       if (strcmp (d, s))
1165         emitcode ("mov", "%s,%s", d, s);
1166
1167       break;
1168
1169     case AOP_REG:
1170       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1171           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1172         {
1173           if (*s == '@' ||
1174               strcmp (s, "r0") == 0 ||
1175               strcmp (s, "r1") == 0 ||
1176               strcmp (s, "r2") == 0 ||
1177               strcmp (s, "r3") == 0 ||
1178               strcmp (s, "r4") == 0 ||
1179               strcmp (s, "r5") == 0 ||
1180               strcmp (s, "r6") == 0 ||
1181               strcmp (s, "r7") == 0)
1182             emitcode ("mov", "%s,%s",
1183                       aop->aopu.aop_reg[offset]->dname, s);
1184           else
1185             emitcode ("mov", "%s,%s",
1186                       aop->aopu.aop_reg[offset]->name, s);
1187         }
1188       break;
1189
1190     case AOP_DPTR:
1191     case AOP_DPTR2:
1192
1193       if (aop->type == AOP_DPTR2)
1194         {
1195           genSetDPTR (1);
1196         }
1197       _flushLazyDPS ();
1198
1199       if (aop->code)
1200         {
1201           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1202                   "aopPut writting to code space");
1203           exit (1);
1204         }
1205
1206       while (offset > aop->coff)
1207         {
1208           aop->coff++;
1209           emitcode ("inc", "dptr");
1210         }
1211
1212       while (offset < aop->coff)
1213         {
1214           aop->coff--;
1215           emitcode ("lcall", "__decdptr");
1216         }
1217
1218       aop->coff = offset;
1219
1220       /* if not in accumulater */
1221       MOVA (s);
1222
1223       emitcode ("movx", "@dptr,a");
1224
1225       if (aop->type == AOP_DPTR2)
1226         {
1227           genSetDPTR (0);
1228         }
1229       break;
1230
1231     case AOP_R0:
1232     case AOP_R1:
1233       while (offset > aop->coff)
1234         {
1235           aop->coff++;
1236           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1237         }
1238       while (offset < aop->coff)
1239         {
1240           aop->coff--;
1241           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1242         }
1243       aop->coff = offset;
1244
1245       if (aop->paged)
1246         {
1247           MOVA (s);
1248           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1249
1250         }
1251       else if (*s == '@')
1252         {
1253           MOVA (s);
1254           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1255         }
1256       else if (strcmp (s, "r0") == 0 ||
1257                strcmp (s, "r1") == 0 ||
1258                strcmp (s, "r2") == 0 ||
1259                strcmp (s, "r3") == 0 ||
1260                strcmp (s, "r4") == 0 ||
1261                strcmp (s, "r5") == 0 ||
1262                strcmp (s, "r6") == 0 ||
1263                strcmp (s, "r7") == 0)
1264         {
1265           char buffer[10];
1266           sprintf (buffer, "a%s", s);
1267           emitcode ("mov", "@%s,%s",
1268                     aop->aopu.aop_ptr->name, buffer);
1269         }
1270       else
1271         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1272
1273       break;
1274
1275     case AOP_STK:
1276       if (strcmp (s, "a") == 0)
1277         emitcode ("push", "acc");
1278       else
1279         if (*s=='@') {
1280           MOVA(s);
1281           emitcode ("push", "acc");
1282         } else {
1283           emitcode ("push", s);
1284         }
1285
1286       break;
1287
1288     case AOP_CRY:
1289       /* if bit variable */
1290       if (!aop->aopu.aop_dir)
1291         {
1292           emitcode ("clr", "a");
1293           emitcode ("rlc", "a");
1294         }
1295       else
1296         {
1297           if (s == zero)
1298             emitcode ("clr", "%s", aop->aopu.aop_dir);
1299           else if (s == one)
1300             emitcode ("setb", "%s", aop->aopu.aop_dir);
1301           else if (!strcmp (s, "c"))
1302             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1303           else
1304             {
1305               if (strcmp (s, "a"))
1306                 {
1307                   MOVA (s);
1308                 }
1309               {
1310                 symbol *lbl = newiTempLabel (NULL);
1311                 emitcode ("clr", "c");
1312                 emitcode ("jz", "!tlabel", lbl->key + 100);
1313                 emitcode ("cpl", "c");
1314                 emitcode ("", "!tlabeldef", lbl->key + 100);
1315                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1316               }
1317             }
1318         }
1319       break;
1320
1321     case AOP_STR:
1322       aop->coff = offset;
1323       if (strcmp (aop->aopu.aop_str[offset], s))
1324         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1325       break;
1326
1327     case AOP_ACC:
1328       aop->coff = offset;
1329       if (!offset && (strcmp (s, "acc") == 0))
1330         break;
1331
1332       if (strcmp (aop->aopu.aop_str[offset], s))
1333         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1334       break;
1335
1336     default:
1337       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1338               "aopPut got unsupported aop->type");
1339       exit (1);
1340     }
1341
1342 }
1343
1344
1345 /*--------------------------------------------------------------------*/
1346 /* reAdjustPreg - points a register back to where it should (coff==0) */
1347 /*--------------------------------------------------------------------*/
1348 static void
1349 reAdjustPreg (asmop * aop)
1350 {
1351   if ((aop->coff==0) || (aop->size <= 1)) {
1352     return;
1353   }
1354
1355   switch (aop->type)
1356     {
1357     case AOP_R0:
1358     case AOP_R1:
1359       while (aop->coff--)
1360         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1361       break;
1362     case AOP_DPTR:
1363     case AOP_DPTR2:
1364       if (aop->type == AOP_DPTR2)
1365         {
1366           genSetDPTR (1);
1367           _flushLazyDPS ();
1368         }
1369       while (aop->coff--)
1370         {
1371           emitcode ("lcall", "__decdptr");
1372         }
1373
1374       if (aop->type == AOP_DPTR2)
1375         {
1376           genSetDPTR (0);
1377         }
1378       break;
1379
1380     }
1381   aop->coff=0;
1382 }
1383
1384 #define AOP(op) op->aop
1385 #define AOP_TYPE(op) AOP(op)->type
1386 #define AOP_SIZE(op) AOP(op)->size
1387 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1388                        AOP_TYPE(x) == AOP_R0))
1389
1390 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1391                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1392                          AOP(x)->paged))
1393
1394 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1395                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1396                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1397
1398 /* Workaround for DS80C390 bug: div ab may return bogus results
1399  * if A is accessed in instruction immediately before the div.
1400  *
1401  * Will be fixed in B4 rev of processor, Dallas claims.
1402  */
1403
1404 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1405     if (!AOP_NEEDSACC(RIGHT))         \
1406     {               \
1407       /* We can load A first, then B, since     \
1408        * B (the RIGHT operand) won't clobber A,   \
1409        * thus avoiding touching A right before the div. \
1410        */             \
1411       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1412       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1413       MOVA(L);            \
1414       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1415     }               \
1416     else              \
1417     {               \
1418       /* Just stuff in a nop after loading A. */    \
1419       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1420       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1421       MOVA(L);            \
1422       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1423     }
1424
1425 /*-----------------------------------------------------------------*/
1426 /* genNotFloat - generates not for float operations              */
1427 /*-----------------------------------------------------------------*/
1428 static void
1429 genNotFloat (operand * op, operand * res)
1430 {
1431   int size, offset;
1432   char *l;
1433   symbol *tlbl;
1434
1435   D (emitcode (";", "genNotFloat ");
1436     );
1437
1438   /* we will put 127 in the first byte of
1439      the result */
1440   aopPut (AOP (res), "#127", 0);
1441   size = AOP_SIZE (op) - 1;
1442   offset = 1;
1443
1444   _startLazyDPSEvaluation ();
1445   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1446   MOVA (l);
1447
1448   while (size--)
1449     {
1450       emitcode ("orl", "a,%s",
1451                 aopGet (op->aop,
1452                         offset++, FALSE, FALSE, FALSE));
1453     }
1454   _endLazyDPSEvaluation ();
1455
1456   tlbl = newiTempLabel (NULL);
1457   aopPut (res->aop, one, 1);
1458   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1459   aopPut (res->aop, zero, 1);
1460   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1461
1462   size = res->aop->size - 2;
1463   offset = 2;
1464   /* put zeros in the rest */
1465   while (size--)
1466     aopPut (res->aop, zero, offset++);
1467 }
1468
1469 /*-----------------------------------------------------------------*/
1470 /* opIsGptr: returns non-zero if the passed operand is       */
1471 /* a generic pointer type.             */
1472 /*-----------------------------------------------------------------*/
1473 static int
1474 opIsGptr (operand * op)
1475 {
1476   sym_link *type = operandType (op);
1477
1478   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1479     {
1480       return 1;
1481     }
1482   return 0;
1483 }
1484
1485 /*-----------------------------------------------------------------*/
1486 /* getDataSize - get the operand data size                         */
1487 /*-----------------------------------------------------------------*/
1488 static int
1489 getDataSize (operand * op)
1490 {
1491   int size;
1492   size = AOP_SIZE (op);
1493   if (size == GPTRSIZE)
1494     {
1495       sym_link *type = operandType (op);
1496       if (IS_GENPTR (type))
1497         {
1498           /* generic pointer; arithmetic operations
1499            * should ignore the high byte (pointer type).
1500            */
1501           size--;
1502         }
1503     }
1504   return size;
1505 }
1506
1507 /*-----------------------------------------------------------------*/
1508 /* outAcc - output Acc                                             */
1509 /*-----------------------------------------------------------------*/
1510 static void
1511 outAcc (operand * result)
1512 {
1513   int size, offset;
1514   size = getDataSize (result);
1515   if (size)
1516     {
1517       aopPut (AOP (result), "a", 0);
1518       size--;
1519       offset = 1;
1520       /* unsigned or positive */
1521       while (size--)
1522         {
1523           aopPut (AOP (result), zero, offset++);
1524         }
1525     }
1526 }
1527
1528 /*-----------------------------------------------------------------*/
1529 /* outBitC - output a bit C                                        */
1530 /*-----------------------------------------------------------------*/
1531 static void
1532 outBitC (operand * result)
1533 {
1534   /* if the result is bit */
1535   if (AOP_TYPE (result) == AOP_CRY)
1536     {
1537       aopPut (AOP (result), "c", 0);
1538     }
1539   else
1540     {
1541       emitcode ("clr", "a");
1542       emitcode ("rlc", "a");
1543       outAcc (result);
1544     }
1545 }
1546
1547 /*-----------------------------------------------------------------*/
1548 /* toBoolean - emit code for orl a,operator(sizeop)                */
1549 /*-----------------------------------------------------------------*/
1550 static void
1551 toBoolean (operand * oper)
1552 {
1553   int   size = AOP_SIZE (oper) - 1;
1554   int   offset = 1;
1555   bool usedB = FALSE;
1556
1557   /* The generic part of a generic pointer should
1558    * not participate in it's truth value.
1559    *
1560    * i.e. 0x10000000 is zero.
1561    */
1562   if (opIsGptr (oper))
1563     {
1564       D (emitcode (";", "toBoolean: generic ptr special case.");
1565         );
1566       size--;
1567     }
1568
1569   _startLazyDPSEvaluation ();
1570   if (AOP_NEEDSACC (oper) && size)
1571     {
1572       usedB = TRUE;
1573       emitcode ("push", "b");
1574       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1575     }
1576   else
1577     {
1578       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1579     }
1580   while (size--)
1581     {
1582       if (usedB)
1583         {
1584           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1585         }
1586       else
1587         {
1588           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1589         }
1590     }
1591   _endLazyDPSEvaluation ();
1592
1593   if (usedB)
1594     {
1595       emitcode ("mov", "a,b");
1596       emitcode ("pop", "b");
1597     }
1598 }
1599
1600
1601 /*-----------------------------------------------------------------*/
1602 /* genNot - generate code for ! operation                          */
1603 /*-----------------------------------------------------------------*/
1604 static void
1605 genNot (iCode * ic)
1606 {
1607   symbol *tlbl;
1608   sym_link *optype = operandType (IC_LEFT (ic));
1609
1610   D (emitcode (";", "genNot ");
1611     );
1612
1613   /* assign asmOps to operand & result */
1614   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1615   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1616
1617   /* if in bit space then a special case */
1618   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1619     {
1620       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1621       emitcode ("cpl", "c");
1622       outBitC (IC_RESULT (ic));
1623       goto release;
1624     }
1625
1626   /* if type float then do float */
1627   if (IS_FLOAT (optype))
1628     {
1629       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1630       goto release;
1631     }
1632
1633   toBoolean (IC_LEFT (ic));
1634
1635   tlbl = newiTempLabel (NULL);
1636   emitcode ("cjne", "a,#0x01,!tlabel", tlbl->key + 100);
1637   emitcode ("", "!tlabeldef", tlbl->key + 100);
1638   outBitC (IC_RESULT (ic));
1639
1640 release:
1641   /* release the aops */
1642   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1643   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1644 }
1645
1646
1647 /*-----------------------------------------------------------------*/
1648 /* genCpl - generate code for complement                           */
1649 /*-----------------------------------------------------------------*/
1650 static void
1651 genCpl (iCode * ic)
1652 {
1653   int offset = 0;
1654   int size;
1655
1656   D (emitcode (";", "genCpl ");
1657     );
1658
1659
1660   /* assign asmOps to operand & result */
1661   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1662   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1663
1664   /* if both are in bit space then
1665      a special case */
1666   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1667       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1668     {
1669
1670       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1671       emitcode ("cpl", "c");
1672       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1673       goto release;
1674     }
1675
1676   size = AOP_SIZE (IC_RESULT (ic));
1677   _startLazyDPSEvaluation ();
1678   while (size--)
1679     {
1680       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1681       MOVA (l);
1682       emitcode ("cpl", "a");
1683       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1684     }
1685   _endLazyDPSEvaluation ();
1686
1687
1688 release:
1689   /* release the aops */
1690   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1691   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1692 }
1693
1694 /*-----------------------------------------------------------------*/
1695 /* genUminusFloat - unary minus for floating points                */
1696 /*-----------------------------------------------------------------*/
1697 static void
1698 genUminusFloat (operand * op, operand * result)
1699 {
1700   int size, offset = 0;
1701   char *l;
1702   /* for this we just need to flip the
1703      first it then copy the rest in place */
1704   D (emitcode (";", "genUminusFloat");
1705     );
1706
1707   _startLazyDPSEvaluation ();
1708   size = AOP_SIZE (op) - 1;
1709   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1710   MOVA (l);
1711
1712   emitcode ("cpl", "acc.7");
1713   aopPut (AOP (result), "a", 3);
1714
1715   while (size--)
1716     {
1717       aopPut (AOP (result),
1718               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1719               offset);
1720       offset++;
1721     }
1722   _endLazyDPSEvaluation ();
1723 }
1724
1725 /*-----------------------------------------------------------------*/
1726 /* genUminus - unary minus code generation                         */
1727 /*-----------------------------------------------------------------*/
1728 static void
1729 genUminus (iCode * ic)
1730 {
1731   int offset, size;
1732   sym_link *optype, *rtype;
1733
1734   D (emitcode (";", "genUminus ");
1735     );
1736
1737
1738   /* assign asmops */
1739   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1740   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1741
1742   /* if both in bit space then special
1743      case */
1744   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1745       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1746     {
1747
1748       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1749       emitcode ("cpl", "c");
1750       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1751       goto release;
1752     }
1753
1754   optype = operandType (IC_LEFT (ic));
1755   rtype = operandType (IC_RESULT (ic));
1756
1757   /* if float then do float stuff */
1758   if (IS_FLOAT (optype))
1759     {
1760       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1761       goto release;
1762     }
1763
1764   /* otherwise subtract from zero */
1765   size = AOP_SIZE (IC_LEFT (ic));
1766   offset = 0;
1767   _startLazyDPSEvaluation ();
1768   while (size--)
1769     {
1770       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1771       if (!strcmp (l, "a"))
1772         {
1773           if (offset == 0)
1774             SETC;
1775           emitcode ("cpl", "a");
1776           emitcode ("addc", "a,#0");
1777         }
1778       else
1779         {
1780           if (offset == 0)
1781             CLRC;
1782           emitcode ("clr", "a");
1783           emitcode ("subb", "a,%s", l);
1784         }
1785       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1786     }
1787   _endLazyDPSEvaluation ();
1788
1789   /* if any remaining bytes in the result */
1790   /* we just need to propagate the sign   */
1791   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1792     {
1793       emitcode ("rlc", "a");
1794       emitcode ("subb", "a,acc");
1795       while (size--)
1796         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1797     }
1798
1799 release:
1800   /* release the aops */
1801   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1802   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1803 }
1804
1805 /*-----------------------------------------------------------------*/
1806 /* saveRegisters - will look for a call and save the registers     */
1807 /*-----------------------------------------------------------------*/
1808 static void
1809 saveRegisters (iCode * lic)
1810 {
1811   int i;
1812   iCode *ic;
1813   bitVect *rsave;
1814   sym_link *detype;
1815
1816   /* look for call */
1817   for (ic = lic; ic; ic = ic->next)
1818     if (ic->op == CALL || ic->op == PCALL)
1819       break;
1820
1821   if (!ic)
1822     {
1823       fprintf (stderr, "found parameter push with no function call\n");
1824       return;
1825     }
1826
1827   /* if the registers have been saved already then
1828      do nothing */
1829   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1830
1831   /* special case if DPTR alive across a function call then must save it 
1832      even though callee saves */
1833   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1834       int i =0;
1835       rsave = newBitVect(ic->rMask->size);
1836       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1837           if (bitVectBitValue(ic->rMask,i))
1838               rsave = bitVectSetBit(rsave,i);
1839       }
1840   } else {
1841       /* find the registers in use at this time
1842          and push them away to safety */
1843       rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1844                              ic->rUsed);
1845   }
1846   ic->regsSaved = 1;
1847   if (options.useXstack)
1848     {
1849       if (bitVectBitValue (rsave, R0_IDX))
1850         emitcode ("mov", "b,r0");
1851       emitcode ("mov", "r0,%s", spname);
1852       for (i = 0; i < ds390_nRegs; i++)
1853         {
1854           if (bitVectBitValue (rsave, i))
1855             {
1856               if (i == R0_IDX)
1857                 emitcode ("mov", "a,b");
1858               else
1859                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1860               emitcode ("movx", "@r0,a");
1861               emitcode ("inc", "r0");
1862             }
1863         }
1864       emitcode ("mov", "%s,r0", spname);
1865       if (bitVectBitValue (rsave, R0_IDX))
1866         emitcode ("mov", "r0,b");
1867     }
1868   else
1869     for (i = 0; i < ds390_nRegs; i++)
1870       {
1871         if (bitVectBitValue (rsave, i))
1872           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1873       }
1874
1875   detype = getSpec (operandType (IC_LEFT (ic)));
1876 }
1877
1878 /*-----------------------------------------------------------------*/
1879 /* unsaveRegisters - pop the pushed registers                      */
1880 /*-----------------------------------------------------------------*/
1881 static void
1882 unsaveRegisters (iCode * ic)
1883 {
1884   int i;
1885   bitVect *rsave;
1886
1887   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1888       int i =0;
1889       rsave = newBitVect(ic->rMask->size);
1890       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1891           if (bitVectBitValue(ic->rMask,i))
1892               rsave = bitVectSetBit(rsave,i);
1893       }
1894   } else {
1895       /* find the registers in use at this time
1896          and push them away to safety */
1897       rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1898                              ic->rUsed);
1899   }
1900   if (options.useXstack)
1901     {
1902       emitcode ("mov", "r0,%s", spname);
1903       for (i = ds390_nRegs; i >= 0; i--)
1904         {
1905           if (bitVectBitValue (rsave, i))
1906             {
1907               emitcode ("dec", "r0");
1908               emitcode ("movx", "a,@r0");
1909               if (i == R0_IDX)
1910                 emitcode ("mov", "b,a");
1911               else
1912                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1913             }
1914
1915         }
1916       emitcode ("mov", "%s,r0", spname);
1917       if (bitVectBitValue (rsave, R0_IDX))
1918         emitcode ("mov", "r0,b");
1919     }
1920   else
1921     for (i = ds390_nRegs; i >= 0; i--)
1922       {
1923         if (bitVectBitValue (rsave, i))
1924           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1925       }
1926
1927 }
1928
1929
1930 /*-----------------------------------------------------------------*/
1931 /* pushSide -                */
1932 /*-----------------------------------------------------------------*/
1933 static void
1934 pushSide (operand * oper, int size)
1935 {
1936   int offset = 0;
1937   _startLazyDPSEvaluation ();
1938   while (size--)
1939     {
1940       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1941       if (AOP_TYPE (oper) != AOP_REG &&
1942           AOP_TYPE (oper) != AOP_DIR &&
1943           strcmp (l, "a"))
1944         {
1945           emitcode ("mov", "a,%s", l);
1946           emitcode ("push", "acc");
1947         }
1948       else
1949         emitcode ("push", "%s", l);
1950     }
1951   _endLazyDPSEvaluation ();
1952 }
1953
1954 /*-----------------------------------------------------------------*/
1955 /* assignResultValue -               */
1956 /*-----------------------------------------------------------------*/
1957 static void
1958 assignResultValue (operand * oper)
1959 {
1960   int offset = 0;
1961   int size = AOP_SIZE (oper);
1962
1963   _startLazyDPSEvaluation ();
1964   while (size--)
1965     {
1966       aopPut (AOP (oper), fReturn[offset], offset);
1967       offset++;
1968     }
1969   _endLazyDPSEvaluation ();
1970 }
1971
1972
1973 /*-----------------------------------------------------------------*/
1974 /* genXpush - pushes onto the external stack                       */
1975 /*-----------------------------------------------------------------*/
1976 static void
1977 genXpush (iCode * ic)
1978 {
1979   asmop *aop = newAsmop (0);
1980   regs *r;
1981   int size, offset = 0;
1982
1983   D (emitcode (";", "genXpush ");
1984     );
1985
1986   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1987   r = getFreePtr (ic, &aop, FALSE);
1988
1989
1990   emitcode ("mov", "%s,_spx", r->name);
1991
1992   size = AOP_SIZE (IC_LEFT (ic));
1993   _startLazyDPSEvaluation ();
1994   while (size--)
1995     {
1996
1997       char *l = aopGet (AOP (IC_LEFT (ic)),
1998                         offset++, FALSE, FALSE, TRUE);
1999       MOVA (l);
2000       emitcode ("movx", "@%s,a", r->name);
2001       emitcode ("inc", "%s", r->name);
2002
2003     }
2004   _endLazyDPSEvaluation ();
2005
2006
2007   emitcode ("mov", "_spx,%s", r->name);
2008
2009   freeAsmop (NULL, aop, ic, TRUE);
2010   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2011 }
2012
2013 /*-----------------------------------------------------------------*/
2014 /* genIpush - genrate code for pushing this gets a little complex  */
2015 /*-----------------------------------------------------------------*/
2016 static void
2017 genIpush (iCode * ic)
2018 {
2019   int size, offset = 0;
2020   char *l;
2021
2022   D (emitcode (";", "genIpush ");
2023     );
2024
2025   /* if this is not a parm push : ie. it is spill push
2026      and spill push is always done on the local stack */
2027   if (!ic->parmPush)
2028     {
2029
2030       /* and the item is spilt then do nothing */
2031       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2032         return;
2033
2034       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2035       size = AOP_SIZE (IC_LEFT (ic));
2036       /* push it on the stack */
2037       _startLazyDPSEvaluation ();
2038       while (size--)
2039         {
2040           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2041           if (*l == '#')
2042             {
2043               MOVA (l);
2044               l = "acc";
2045             }
2046           emitcode ("push", "%s", l);
2047         }
2048       _endLazyDPSEvaluation ();
2049       return;
2050     }
2051
2052   /* this is a paramter push: in this case we call
2053      the routine to find the call and save those
2054      registers that need to be saved */
2055   saveRegisters (ic);
2056
2057   /* if use external stack then call the external
2058      stack pushing routine */
2059   if (options.useXstack)
2060     {
2061       genXpush (ic);
2062       return;
2063     }
2064
2065   /* then do the push */
2066   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2067
2068   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2069   size = AOP_SIZE (IC_LEFT (ic));
2070
2071   _startLazyDPSEvaluation ();
2072   while (size--)
2073     {
2074       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2075       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2076           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2077           strcmp (l, "a"))
2078         {
2079           emitcode ("mov", "a,%s", l);
2080           emitcode ("push", "acc");
2081         }
2082       else
2083         emitcode ("push", "%s", l);
2084     }
2085   _endLazyDPSEvaluation ();
2086
2087   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2088 }
2089
2090 /*-----------------------------------------------------------------*/
2091 /* genIpop - recover the registers: can happen only for spilling   */
2092 /*-----------------------------------------------------------------*/
2093 static void
2094 genIpop (iCode * ic)
2095 {
2096   int size, offset;
2097
2098   D (emitcode (";", "genIpop ");
2099     );
2100
2101
2102   /* if the temp was not pushed then */
2103   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2104     return;
2105
2106   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2107   size = AOP_SIZE (IC_LEFT (ic));
2108   offset = (size - 1);
2109   _startLazyDPSEvaluation ();
2110   while (size--)
2111     {
2112       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2113                                      FALSE, TRUE, TRUE));
2114     }
2115   _endLazyDPSEvaluation ();
2116
2117   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2118 }
2119
2120 /*-----------------------------------------------------------------*/
2121 /* unsaveRBank - restores the resgister bank from stack            */
2122 /*-----------------------------------------------------------------*/
2123 static void
2124 unsaveRBank (int bank, iCode * ic, bool popPsw)
2125 {
2126   int i;
2127   asmop *aop = NULL;
2128   regs *r = NULL;
2129
2130   if (options.useXstack)
2131   {
2132       if (!ic)
2133       {
2134           /* Assume r0 is available for use. */
2135           r = ds390_regWithIdx (R0_IDX);;          
2136       } 
2137       else
2138       {
2139           aop = newAsmop (0);
2140           r = getFreePtr (ic, &aop, FALSE);
2141       }
2142       emitcode ("mov", "%s,_spx", r->name);      
2143   }
2144   
2145   if (popPsw)
2146     {
2147       if (options.useXstack)
2148       {
2149           emitcode ("movx", "a,@%s", r->name);
2150           emitcode ("mov", "psw,a");
2151           emitcode ("dec", "%s", r->name);
2152         }
2153       else
2154       {
2155         emitcode ("pop", "psw");
2156       }
2157     }
2158
2159   for (i = (ds390_nRegs - 1); i >= 0; i--)
2160     {
2161       if (options.useXstack)
2162         {
2163           emitcode ("movx", "a,@%s", r->name);
2164           emitcode ("mov", "(%s+%d),a",
2165                     regs390[i].base, 8 * bank + regs390[i].offset);
2166           emitcode ("dec", "%s", r->name);
2167
2168         }
2169       else
2170         emitcode ("pop", "(%s+%d)",
2171                   regs390[i].base, 8 * bank + regs390[i].offset);
2172     }
2173
2174   if (options.useXstack)
2175     {
2176       emitcode ("mov", "_spx,%s", r->name);
2177     }
2178     
2179   if (aop)
2180   {
2181       freeAsmop (NULL, aop, ic, TRUE);  
2182   }    
2183 }
2184
2185 /*-----------------------------------------------------------------*/
2186 /* saveRBank - saves an entire register bank on the stack          */
2187 /*-----------------------------------------------------------------*/
2188 static void
2189 saveRBank (int bank, iCode * ic, bool pushPsw)
2190 {
2191   int i;
2192   asmop *aop = NULL;
2193   regs *r = NULL;
2194
2195   if (options.useXstack)
2196     {
2197         if (!ic)
2198         {
2199           /* Assume r0 is available for use. */
2200                   r = ds390_regWithIdx (R0_IDX);;
2201         }
2202         else
2203         {
2204           aop = newAsmop (0);
2205           r = getFreePtr (ic, &aop, FALSE);
2206         }
2207         emitcode ("mov", "%s,_spx", r->name);    
2208     }
2209
2210   for (i = 0; i < ds390_nRegs; i++)
2211     {
2212       if (options.useXstack)
2213         {
2214           emitcode ("inc", "%s", r->name);
2215           emitcode ("mov", "a,(%s+%d)",
2216                     regs390[i].base, 8 * bank + regs390[i].offset);
2217           emitcode ("movx", "@%s,a", r->name);
2218         }
2219       else
2220         emitcode ("push", "(%s+%d)",
2221                   regs390[i].base, 8 * bank + regs390[i].offset);
2222     }
2223
2224   if (pushPsw)
2225     {
2226       if (options.useXstack)
2227         {
2228           emitcode ("mov", "a,psw");
2229           emitcode ("movx", "@%s,a", r->name);
2230           emitcode ("inc", "%s", r->name);
2231           emitcode ("mov", "_spx,%s", r->name);
2232         }
2233       else
2234       {
2235         emitcode ("push", "psw");
2236       }
2237
2238       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2239     }
2240   
2241   if (aop)
2242   {
2243        freeAsmop (NULL, aop, ic, TRUE);
2244   }    
2245     
2246   if (ic)
2247   {  
2248       ic->bankSaved = 1;
2249   }
2250 }
2251
2252 /*-----------------------------------------------------------------*/
2253 /* genCall - generates a call statement                            */
2254 /*-----------------------------------------------------------------*/
2255 static void
2256 genCall (iCode * ic)
2257 {
2258   sym_link *dtype;
2259   bool restoreBank = FALSE;
2260   bool swapBanks = FALSE;
2261
2262   D (emitcode (";", "genCall "););
2263
2264   /* if we are calling a not _naked function that is not using
2265      the same register bank then we need to save the
2266      destination registers on the stack */
2267   dtype = operandType (IC_LEFT (ic));
2268   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2269       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2270       IFFUNC_ISISR (currFunc->type))
2271   {
2272       if (!ic->bankSaved) 
2273       {
2274            /* This is unexpected; the bank should have been saved in
2275             * genFunction.
2276             */
2277            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2278            restoreBank = TRUE;
2279       }
2280       swapBanks = TRUE;
2281   }
2282   
2283     /* if caller saves & we have not saved then */
2284     if (!ic->regsSaved)
2285       saveRegisters (ic);
2286   
2287   /* if send set is not empty the assign */
2288   /* We've saved all the registers we care about;
2289   * therefore, we may clobber any register not used
2290   * in the calling convention (i.e. anything not in
2291   * fReturn.
2292   */
2293   if (_G.sendSet)
2294     {
2295       iCode *sic;
2296
2297       for (sic = setFirstItem (_G.sendSet); sic;
2298            sic = setNextItem (_G.sendSet))
2299         {
2300           int size, offset = 0;
2301
2302 #if 0
2303           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2304           size = AOP_SIZE (IC_LEFT (sic));
2305
2306           _startLazyDPSEvaluation ();
2307           while (size--)
2308             {
2309               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2310                                 FALSE, FALSE, TRUE);
2311                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2312                 {
2313                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2314                 }
2315                 else if (strcmp (l, fReturn[offset]))
2316                 {
2317                     emitcode ("mov", "%s,%s",
2318                               fReturn[offset],
2319                               l);
2320                 }
2321               offset++;
2322             }
2323           _endLazyDPSEvaluation ();
2324           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2325           {
2326               size = AOP_SIZE (IC_LEFT (sic));
2327               if (size)
2328               {
2329                  size--;
2330               }
2331               while (size)
2332               {
2333                    size--;
2334                    emitcode("mov", "%s,%s",
2335                                     fReturn[size], regs390[size].name);
2336               }
2337           }
2338 #else
2339           // we know that dpl(hxb) is the result, so
2340           _startLazyDPSEvaluation ();
2341           size=getSize(operandType(IC_LEFT(sic)));
2342           if (size>1) {
2343             aopOp (IC_LEFT (sic), sic, FALSE, 
2344                    (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2345           } else {
2346             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2347           }
2348           while (size--)
2349             {
2350               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2351                                 FALSE, FALSE, TRUE);
2352               if (strcmp (l, fReturn[offset]))
2353                 {
2354                   emitcode ("mov", "%s,%s",
2355                             fReturn[offset],
2356                             l);
2357                 }
2358               offset++;
2359             }
2360           _endLazyDPSEvaluation ();
2361 #endif
2362           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2363         }
2364       _G.sendSet = NULL;
2365     }  
2366     
2367   if (swapBanks)
2368   {
2369         emitcode ("mov", "psw,#!constbyte", 
2370            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2371   }
2372
2373   /* make the call */
2374   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2375                             OP_SYMBOL (IC_LEFT (ic))->rname :
2376                             OP_SYMBOL (IC_LEFT (ic))->name));
2377
2378   if (swapBanks)
2379   {
2380        emitcode ("mov", "psw,#!constbyte", 
2381           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2382   }
2383
2384   /* if we need assign a result value */
2385   if ((IS_ITEMP (IC_RESULT (ic)) &&
2386        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2387         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2388         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2389       IS_TRUE_SYMOP (IC_RESULT (ic)))
2390     {
2391       if (isOperandInFarSpace (IC_RESULT (ic))
2392           && getSize (operandType (IC_RESULT (ic))) <= 2)
2393         {
2394           int size = getSize (operandType (IC_RESULT (ic)));
2395
2396           /* Special case for 1 or 2 byte return in far space. */
2397           MOVA (fReturn[0]);
2398           if (size > 1)
2399             {
2400               emitcode ("mov", "b,%s", fReturn[1]);
2401             }
2402
2403           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2404           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2405
2406           if (size > 1)
2407             {
2408               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2409             }
2410           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2411         }
2412       else
2413         {
2414           _G.accInUse++;
2415           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2416           _G.accInUse--;
2417
2418           assignResultValue (IC_RESULT (ic));
2419
2420           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2421         }
2422     }
2423
2424   /* adjust the stack for parameters if
2425      required */
2426   if (ic->parmBytes) {
2427       if (options.stack10bit) {
2428           emitcode ("clr","c");
2429           emitcode ("mov","a,sp");
2430           emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2431           emitcode ("mov","sp,a");
2432           emitcode ("mov","a,esp");
2433           emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2434           emitcode ("mov","esp,a");       
2435       } else {
2436           int i;
2437           if (ic->parmBytes > 3) {
2438               emitcode ("mov", "a,%s", spname);
2439               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2440               emitcode ("mov", "%s,a", spname);
2441           } else
2442               for (i = 0; i < ic->parmBytes; i++)
2443                   emitcode ("dec", "%s", spname);
2444       }
2445   }
2446
2447   /* if we hade saved some registers then unsave them */
2448   if (ic->regsSaved)
2449     unsaveRegisters (ic);
2450
2451   /* if register bank was saved then pop them */
2452   if (restoreBank)
2453     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2454 }
2455
2456 /*-----------------------------------------------------------------*/
2457 /* genPcall - generates a call by pointer statement                */
2458 /*-----------------------------------------------------------------*/
2459 static void
2460 genPcall (iCode * ic)
2461 {
2462   sym_link *dtype;
2463   symbol *rlbl = newiTempLabel (NULL);
2464   bool restoreBank=FALSE;
2465
2466   D (emitcode (";", "genPcall ");
2467     );
2468
2469
2470   /* if caller saves & we have not saved then */
2471   if (!ic->regsSaved)
2472     saveRegisters (ic);
2473
2474   /* if we are calling a function that is not using
2475      the same register bank then we need to save the
2476      destination registers on the stack */
2477   dtype = operandType (IC_LEFT (ic));
2478   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2479       IFFUNC_ISISR (currFunc->type) &&
2480       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2481     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2482     restoreBank=TRUE;
2483   }
2484
2485   /* push the return address on to the stack */
2486   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2487   emitcode ("push", "acc");
2488   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2489   emitcode ("push", "acc");
2490
2491   if (options.model == MODEL_FLAT24)
2492     {
2493       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2494       emitcode ("push", "acc");
2495     }
2496
2497   /* now push the calling address */
2498   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2499
2500   pushSide (IC_LEFT (ic), FPTRSIZE);
2501
2502   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2503
2504   /* if send set is not empty the assign */
2505   if (_G.sendSet)
2506     {
2507       iCode *sic;
2508
2509       for (sic = setFirstItem (_G.sendSet); sic;
2510            sic = setNextItem (_G.sendSet))
2511         {
2512           int size, offset = 0;
2513
2514           // we know that dpl(hxb) is the result, so
2515           _startLazyDPSEvaluation ();
2516           size=getSize(operandType(IC_LEFT(sic)));
2517           if (size>1) {
2518             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2519           } else {
2520             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2521           }
2522           while (size--)
2523             {
2524               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2525                                 FALSE, FALSE, TRUE);
2526               if (strcmp (l, fReturn[offset]))
2527                 {
2528                   emitcode ("mov", "%s,%s",
2529                             fReturn[offset],
2530                             l);
2531                 }
2532               offset++;
2533             }
2534           _endLazyDPSEvaluation ();
2535           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2536         }
2537       _G.sendSet = NULL;
2538     }
2539
2540   emitcode ("ret", "");
2541   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2542
2543
2544   /* if we need assign a result value */
2545   if ((IS_ITEMP (IC_RESULT (ic)) &&
2546        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2547         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2548       IS_TRUE_SYMOP (IC_RESULT (ic)))
2549     {
2550
2551       _G.accInUse++;
2552       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2553       _G.accInUse--;
2554
2555       assignResultValue (IC_RESULT (ic));
2556
2557       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2558     }
2559
2560   /* adjust the stack for parameters if
2561      required */
2562   if (ic->parmBytes)
2563     {
2564       int i;
2565       if (ic->parmBytes > 3)
2566         {
2567           emitcode ("mov", "a,%s", spname);
2568           emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2569           emitcode ("mov", "%s,a", spname);
2570         }
2571       else
2572         for (i = 0; i < ic->parmBytes; i++)
2573           emitcode ("dec", "%s", spname);
2574
2575     }
2576
2577   /* if register bank was saved then unsave them */
2578   if (restoreBank)
2579     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2580   
2581   /* if we hade saved some registers then
2582      unsave them */
2583   if (ic->regsSaved)
2584     unsaveRegisters (ic);
2585
2586 }
2587
2588 /*-----------------------------------------------------------------*/
2589 /* resultRemat - result  is rematerializable                       */
2590 /*-----------------------------------------------------------------*/
2591 static int
2592 resultRemat (iCode * ic)
2593 {
2594   if (SKIP_IC (ic) || ic->op == IFX)
2595     return 0;
2596
2597   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2598     {
2599       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2600       if (sym->remat && !POINTER_SET (ic))
2601         return 1;
2602     }
2603
2604   return 0;
2605 }
2606
2607 #if defined(__BORLANDC__) || defined(_MSC_VER)
2608 #define STRCASECMP stricmp
2609 #else
2610 #define STRCASECMP strcasecmp
2611 #endif
2612
2613 /*-----------------------------------------------------------------*/
2614 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2615 /*-----------------------------------------------------------------*/
2616 static bool
2617 inExcludeList (char *s)
2618 {
2619   int i = 0;
2620
2621   if (options.excludeRegs[i] &&
2622       STRCASECMP (options.excludeRegs[i], "none") == 0)
2623     return FALSE;
2624
2625   for (i = 0; options.excludeRegs[i]; i++)
2626     {
2627       if (options.excludeRegs[i] &&
2628           STRCASECMP (s, options.excludeRegs[i]) == 0)
2629         return TRUE;
2630     }
2631   return FALSE;
2632 }
2633
2634 /*-----------------------------------------------------------------*/
2635 /* genFunction - generated code for function entry                 */
2636 /*-----------------------------------------------------------------*/
2637 static void
2638 genFunction (iCode * ic)
2639 {
2640   symbol *sym;
2641   sym_link *ftype;
2642   bool   switchedPSW = FALSE;
2643
2644   D (emitcode (";", "genFunction "););
2645
2646   _G.nRegsSaved = 0;
2647   /* create the function header */
2648   emitcode (";", "-----------------------------------------");
2649   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2650   emitcode (";", "-----------------------------------------");
2651
2652   emitcode ("", "%s:", sym->rname);
2653   ftype = operandType (IC_LEFT (ic));
2654
2655   if (IFFUNC_ISNAKED(ftype))
2656   {
2657       emitcode(";", "naked function: no prologue.");
2658       return;
2659   }
2660   
2661   if (options.stack_probe) 
2662       emitcode ("lcall","__stack_probe");
2663   /* if critical function then turn interrupts off */
2664   if (IFFUNC_ISCRITICAL (ftype))
2665     emitcode ("clr", "ea");
2666
2667   /* here we need to generate the equates for the
2668      register bank if required */
2669   if (FUNC_REGBANK (ftype) != rbank)
2670     {
2671       int i;
2672
2673       rbank = FUNC_REGBANK (ftype);
2674       for (i = 0; i < ds390_nRegs; i++)
2675         {
2676           if (regs390[i].print) {
2677               if (strcmp (regs390[i].base, "0") == 0)
2678                   emitcode ("", "%s = !constbyte",
2679                             regs390[i].dname,
2680                             8 * rbank + regs390[i].offset);
2681               else
2682                   emitcode ("", "%s = %s + !constbyte",
2683                             regs390[i].dname,
2684                             regs390[i].base,
2685                             8 * rbank + regs390[i].offset);
2686           }
2687         }
2688     }
2689
2690   /* if this is an interrupt service routine then
2691      save acc, b, dpl, dph  */
2692   if (IFFUNC_ISISR (sym->type))
2693     {
2694
2695       if (!inExcludeList ("acc"))
2696         emitcode ("push", "acc");
2697       if (!inExcludeList ("b"))
2698         emitcode ("push", "b");
2699       if (!inExcludeList ("dpl"))
2700         emitcode ("push", "dpl");
2701       if (!inExcludeList ("dph"))
2702         emitcode ("push", "dph");
2703       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2704         {
2705           emitcode ("push", "dpx");
2706           /* Make sure we're using standard DPTR */
2707           emitcode ("push", "dps");
2708           emitcode ("mov", "dps, #0x00");
2709           if (options.stack10bit)
2710             {
2711               /* This ISR could conceivably use DPTR2. Better save it. */
2712               emitcode ("push", "dpl1");
2713               emitcode ("push", "dph1");
2714               emitcode ("push", "dpx1");
2715               emitcode ("push",  DP2_RESULT_REG);
2716             }
2717         }
2718       /* if this isr has no bank i.e. is going to
2719          run with bank 0 , then we need to save more
2720          registers :-) */
2721       if (!FUNC_REGBANK (sym->type))
2722         {
2723
2724           /* if this function does not call any other
2725              function then we can be economical and
2726              save only those registers that are used */
2727           if (!IFFUNC_HASFCALL(sym->type))
2728             {
2729               int i;
2730
2731               /* if any registers used */
2732               if (sym->regsUsed)
2733                 {
2734                   /* save the registers used */
2735                   for (i = 0; i < sym->regsUsed->size; i++)
2736                     {
2737                       if (bitVectBitValue (sym->regsUsed, i) ||
2738                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2739                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2740                     }
2741                 }
2742
2743             }
2744           else
2745             {
2746               /* this function has  a function call cannot
2747                  determines register usage so we will have to push the
2748                  entire bank */
2749               saveRBank (0, ic, FALSE);
2750             }
2751         }
2752         else
2753         {
2754             /* This ISR uses a non-zero bank.
2755              *
2756              * We assume that the bank is available for our
2757              * exclusive use.
2758              *
2759              * However, if this ISR calls a function which uses some
2760              * other bank, we must save that bank entirely.
2761              */
2762             unsigned long banksToSave = 0;
2763             
2764             if (IFFUNC_HASFCALL(sym->type))
2765             {
2766
2767 #define MAX_REGISTER_BANKS 4
2768
2769                 iCode *i;
2770                 int ix;
2771
2772                 for (i = ic; i; i = i->next)
2773                 {
2774                     if (i->op == ENDFUNCTION)
2775                     {
2776                         /* we got to the end OK. */
2777                         break;
2778                     }
2779                     
2780                     if (i->op == CALL)
2781                     {
2782                         sym_link *dtype;
2783                         
2784                         dtype = operandType (IC_LEFT(i));
2785                         if (dtype 
2786                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2787                         {
2788                              /* Mark this bank for saving. */
2789                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2790                              {
2791                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2792                              }
2793                              else
2794                              {
2795                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2796                              }
2797                              
2798                              /* And note that we don't need to do it in 
2799                               * genCall.
2800                               */
2801                              i->bankSaved = 1;
2802                         }
2803                     }
2804                     if (i->op == PCALL)
2805                     {
2806                         /* This is a mess; we have no idea what
2807                          * register bank the called function might
2808                          * use.
2809                          *
2810                          * The only thing I can think of to do is
2811                          * throw a warning and hope.
2812                          */
2813                         werror(W_FUNCPTR_IN_USING_ISR);   
2814                     }
2815                 }
2816
2817                 if (banksToSave && options.useXstack)
2818                 {
2819                     /* Since we aren't passing it an ic, 
2820                      * saveRBank will assume r0 is available to abuse.
2821                      *
2822                      * So switch to our (trashable) bank now, so
2823                      * the caller's R0 isn't trashed.
2824                      */
2825                     emitcode ("push", "psw");
2826                     emitcode ("mov", "psw,#!constbyte", 
2827                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2828                     switchedPSW = TRUE;
2829                 }
2830                 
2831                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2832                 {
2833                      if (banksToSave & (1 << ix))
2834                      {
2835                          saveRBank(ix, NULL, FALSE);
2836                      }
2837                 }
2838             }
2839             // jwk: this needs a closer look
2840             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2841         }
2842     }
2843   else
2844     {
2845       /* if callee-save to be used for this function
2846          then save the registers being used in this function */
2847       if (IFFUNC_CALLEESAVES(sym->type))
2848         {
2849           int i;
2850
2851           /* if any registers used */
2852           if (sym->regsUsed)
2853             {
2854               /* save the registers used */
2855               for (i = 0; i < sym->regsUsed->size; i++)
2856                 {
2857                   if (bitVectBitValue (sym->regsUsed, i) ||
2858                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2859                     {
2860                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2861                       _G.nRegsSaved++;
2862                     }
2863                 }
2864             }
2865         }
2866     }
2867
2868   /* set the register bank to the desired value */
2869   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2870    && !switchedPSW)
2871     {
2872       emitcode ("push", "psw");
2873       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2874     }
2875
2876   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2877       if (options.stack10bit) {
2878           emitcode ("push","_bpx");
2879           emitcode ("push","_bpx+1");
2880           emitcode ("mov","_bpx,%s",spname);
2881           emitcode ("mov","_bpx+1,esp");
2882           emitcode ("anl","_bpx+1,#3");
2883       } else {
2884           if (options.useXstack) {
2885               emitcode ("mov", "r0,%s", spname);
2886               emitcode ("mov", "a,_bp");
2887               emitcode ("movx", "@r0,a");
2888               emitcode ("inc", "%s", spname);
2889           } else {
2890               /* set up the stack */
2891               emitcode ("push", "_bp"); /* save the callers stack  */
2892           }
2893           emitcode ("mov", "_bp,%s", spname);
2894       }
2895   }
2896
2897   /* adjust the stack for the function */
2898   if (sym->stack) {
2899       int i = sym->stack;
2900       if (options.stack10bit) {
2901           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2902           assert (sym->recvSize <= 4);
2903           emitcode ("mov","a,sp");
2904           emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2905           emitcode ("mov","sp,a");
2906           emitcode ("mov","a,esp");
2907           emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2908           emitcode ("mov","esp,a");
2909       } else {
2910           if (i > 256)
2911               werror (W_STACK_OVERFLOW, sym->name);
2912           
2913           if (i > 3 && sym->recvSize < 4) {
2914               
2915               emitcode ("mov", "a,sp");
2916               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2917               emitcode ("mov", "sp,a");
2918               
2919           } else
2920               while (i--)
2921                   emitcode ("inc", "sp");
2922       }
2923   }
2924
2925   if (sym->xstack)
2926     {
2927
2928       emitcode ("mov", "a,_spx");
2929       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2930       emitcode ("mov", "_spx,a");
2931     }
2932
2933 }
2934
2935 /*-----------------------------------------------------------------*/
2936 /* genEndFunction - generates epilogue for functions               */
2937 /*-----------------------------------------------------------------*/
2938 static void
2939 genEndFunction (iCode * ic)
2940 {
2941   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2942
2943   D (emitcode (";", "genEndFunction "););
2944
2945   if (IFFUNC_ISNAKED(sym->type))
2946   {
2947       emitcode(";", "naked function: no epilogue.");
2948       return;
2949   }
2950
2951   if (IFFUNC_ISREENT (sym->type) || options.stackAuto) {
2952       if (options.stack10bit) {
2953           emitcode ("mov", "sp,_bpx", spname);
2954           emitcode ("mov", "esp,_bpx+1", spname);
2955       } else {
2956           emitcode ("mov", "%s,_bp", spname);
2957       }
2958   }
2959
2960   /* if use external stack but some variables were
2961      added to the local stack then decrement the
2962      local stack */
2963   if (options.useXstack && sym->stack) {
2964       emitcode ("mov", "a,sp");
2965       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2966       emitcode ("mov", "sp,a");
2967   }
2968
2969
2970   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) {
2971       if (options.useXstack) {
2972           emitcode ("mov", "r0,%s", spname);
2973           emitcode ("movx", "a,@r0");
2974           emitcode ("mov", "_bp,a");
2975           emitcode ("dec", "%s", spname);
2976       } else {
2977           if (options.stack10bit) {
2978               emitcode ("pop", "_bpx+1");
2979               emitcode ("pop", "_bpx");
2980           } else {
2981               emitcode ("pop", "_bp");
2982           }
2983       }
2984   }
2985
2986   /* restore the register bank  */
2987   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2988   {
2989     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2990      || !options.useXstack)
2991     {
2992         /* Special case of ISR using non-zero bank with useXstack
2993          * is handled below.
2994          */
2995         emitcode ("pop", "psw");
2996     }
2997   }
2998
2999   if (IFFUNC_ISISR (sym->type))
3000     {
3001
3002       /* now we need to restore the registers */
3003       /* if this isr has no bank i.e. is going to
3004          run with bank 0 , then we need to save more
3005          registers :-) */
3006       if (!FUNC_REGBANK (sym->type))
3007         {
3008           /* if this function does not call any other
3009              function then we can be economical and
3010              save only those registers that are used */
3011           if (!IFFUNC_HASFCALL(sym->type))
3012             {
3013               int i;
3014
3015               /* if any registers used */
3016               if (sym->regsUsed)
3017                 {
3018                   /* save the registers used */
3019                   for (i = sym->regsUsed->size; i >= 0; i--)
3020                     {
3021                       if (bitVectBitValue (sym->regsUsed, i) ||
3022                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3023                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3024                     }
3025                 }
3026
3027             }
3028           else
3029             {
3030               /* this function has  a function call cannot
3031                  determines register usage so we will have to pop the
3032                  entire bank */
3033               unsaveRBank (0, ic, FALSE);
3034             }
3035         }
3036         else
3037         {
3038             /* This ISR uses a non-zero bank.
3039              *
3040              * Restore any register banks saved by genFunction
3041              * in reverse order.
3042              */
3043           // jwk: this needs a closer look
3044             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3045             int ix;
3046           
3047             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3048             {
3049                 if (savedBanks & (1 << ix))
3050                 {
3051                     unsaveRBank(ix, NULL, FALSE);
3052                 }
3053             }
3054             
3055             if (options.useXstack)
3056             {
3057                 /* Restore bank AFTER calling unsaveRBank,
3058                  * since it can trash r0.
3059                  */
3060                 emitcode ("pop", "psw");
3061             }
3062         }
3063
3064       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3065         {
3066           if (options.stack10bit)
3067             {
3068               emitcode ("pop", DP2_RESULT_REG);
3069               emitcode ("pop", "dpx1");
3070               emitcode ("pop", "dph1");
3071               emitcode ("pop", "dpl1");
3072             }
3073           emitcode ("pop", "dps");
3074           emitcode ("pop", "dpx");
3075         }
3076       if (!inExcludeList ("dph"))
3077         emitcode ("pop", "dph");
3078       if (!inExcludeList ("dpl"))
3079         emitcode ("pop", "dpl");
3080       if (!inExcludeList ("b"))
3081         emitcode ("pop", "b");
3082       if (!inExcludeList ("acc"))
3083         emitcode ("pop", "acc");
3084
3085       if (IFFUNC_ISCRITICAL (sym->type))
3086         emitcode ("setb", "ea");
3087
3088       /* if debug then send end of function */
3089       if (options.debug && currFunc) {
3090           _G.debugLine = 1;
3091           emitcode ("", "C$%s$%d$%d$%d ==.",
3092                     FileBaseName (ic->filename), currFunc->lastLine,
3093                     ic->level, ic->block);
3094           if (IS_STATIC (currFunc->etype))
3095             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3096           else
3097             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3098           _G.debugLine = 0;
3099         }
3100
3101       emitcode ("reti", "");
3102     }
3103   else
3104     {
3105       if (IFFUNC_ISCRITICAL (sym->type))
3106         emitcode ("setb", "ea");
3107
3108       if (IFFUNC_CALLEESAVES(sym->type))
3109         {
3110           int i;
3111
3112           /* if any registers used */
3113           if (sym->regsUsed)
3114             {
3115               /* save the registers used */
3116               for (i = sym->regsUsed->size; i >= 0; i--)
3117                 {
3118                   if (bitVectBitValue (sym->regsUsed, i) ||
3119                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3120                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3121                 }
3122             }
3123
3124         }
3125
3126       /* if debug then send end of function */
3127       if (options.debug && currFunc)
3128         {
3129           _G.debugLine = 1;
3130           emitcode ("", "C$%s$%d$%d$%d ==.",
3131                     FileBaseName (ic->filename), currFunc->lastLine,
3132                     ic->level, ic->block);
3133           if (IS_STATIC (currFunc->etype))
3134             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3135           else
3136             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3137           _G.debugLine = 0;
3138         }
3139
3140       emitcode ("ret", "");
3141     }
3142
3143 }
3144
3145 /*-----------------------------------------------------------------*/
3146 /* genRet - generate code for return statement                     */
3147 /*-----------------------------------------------------------------*/
3148 static void
3149 genRet (iCode * ic)
3150 {
3151   int size, offset = 0, pushed = 0;
3152
3153   D (emitcode (";", "genRet ");
3154     );
3155
3156   /* if we have no return value then
3157      just generate the "ret" */
3158   if (!IC_LEFT (ic))
3159     goto jumpret;
3160
3161   /* we have something to return then
3162      move the return value into place */
3163   aopOp (IC_LEFT (ic), ic, FALSE, 
3164          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3165   size = AOP_SIZE (IC_LEFT (ic));
3166
3167   _startLazyDPSEvaluation ();
3168   while (size--)
3169     {
3170       char *l;
3171       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3172         {
3173           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3174                       FALSE, TRUE, FALSE);
3175           emitcode ("push", "%s", l);
3176           pushed++;
3177         }
3178       else
3179         {
3180           /* Since A is the last element of fReturn,
3181            * is is OK to clobber it in the aopGet.
3182            */
3183           l = aopGet (AOP (IC_LEFT (ic)), offset,
3184                       FALSE, FALSE, TRUE);
3185           if (strcmp (fReturn[offset], l))
3186             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3187         }
3188     }
3189   _endLazyDPSEvaluation ();
3190
3191   if (pushed)
3192     {
3193       while (pushed)
3194         {
3195           pushed--;
3196           if (strcmp (fReturn[pushed], "a"))
3197             emitcode ("pop", fReturn[pushed]);
3198           else
3199             emitcode ("pop", "acc");
3200         }
3201     }
3202   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3203
3204 jumpret:
3205   /* generate a jump to the return label
3206      if the next is not the return statement */
3207   if (!(ic->next && ic->next->op == LABEL &&
3208         IC_LABEL (ic->next) == returnLabel))
3209
3210     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3211
3212 }
3213
3214 /*-----------------------------------------------------------------*/
3215 /* genLabel - generates a label                                    */
3216 /*-----------------------------------------------------------------*/
3217 static void
3218 genLabel (iCode * ic)
3219 {
3220   /* special case never generate */
3221   if (IC_LABEL (ic) == entryLabel)
3222     return;
3223
3224   D (emitcode (";", "genLabel ");
3225     );
3226
3227   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3228 }
3229
3230 /*-----------------------------------------------------------------*/
3231 /* genGoto - generates a ljmp                                      */
3232 /*-----------------------------------------------------------------*/
3233 static void
3234 genGoto (iCode * ic)
3235 {
3236   D (emitcode (";", "genGoto ");
3237     );
3238   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3239 }
3240
3241 /*-----------------------------------------------------------------*/
3242 /* findLabelBackwards: walks back through the iCode chain looking  */
3243 /* for the given label. Returns number of iCode instructions     */
3244 /* between that label and given ic.          */
3245 /* Returns zero if label not found.          */
3246 /*-----------------------------------------------------------------*/
3247 static int
3248 findLabelBackwards (iCode * ic, int key)
3249 {
3250   int count = 0;
3251
3252   while (ic->prev)
3253     {
3254       ic = ic->prev;
3255       count++;
3256
3257       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3258         {
3259           /* printf("findLabelBackwards = %d\n", count); */
3260           return count;
3261         }
3262     }
3263
3264   return 0;
3265 }
3266
3267 /*-----------------------------------------------------------------*/
3268 /* genPlusIncr :- does addition with increment if possible         */
3269 /*-----------------------------------------------------------------*/
3270 static bool
3271 genPlusIncr (iCode * ic)
3272 {
3273   unsigned int icount;
3274   unsigned int size = getDataSize (IC_RESULT (ic));
3275
3276   /* will try to generate an increment */
3277   /* if the right side is not a literal
3278      we cannot */
3279   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3280     return FALSE;
3281
3282   /* if the literal value of the right hand side
3283      is greater than 4 then it is not worth it */
3284   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3285     return FALSE;
3286
3287   /* if increment 16 bits in register */
3288   if (
3289        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3290        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3291        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3292        (size > 1) &&
3293        (icount == 1))
3294     {
3295       symbol *tlbl;
3296       int emitTlbl;
3297       int labelRange;
3298
3299       /* If the next instruction is a goto and the goto target
3300        * is <= 5 instructions previous to this, we can generate
3301        * jumps straight to that target.
3302        */
3303       if (ic->next && ic->next->op == GOTO
3304           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3305           && labelRange <= 5)
3306         {
3307           emitcode (";", "tail increment optimized (range %d)", labelRange);
3308           tlbl = IC_LABEL (ic->next);
3309           emitTlbl = 0;
3310         }
3311       else
3312         {
3313           tlbl = newiTempLabel (NULL);
3314           emitTlbl = 1;
3315         }
3316       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3317       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3318           IS_AOP_PREG (IC_RESULT (ic)))
3319         emitcode ("cjne", "%s,#0x00,!tlabel"
3320                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3321                   ,tlbl->key + 100);
3322       else
3323         {
3324           emitcode ("clr", "a");
3325           emitcode ("cjne", "a,%s,!tlabel"
3326                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3327                     ,tlbl->key + 100);
3328         }
3329
3330       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3331       if (size > 2)
3332         {
3333           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3334               IS_AOP_PREG (IC_RESULT (ic)))
3335             emitcode ("cjne", "%s,#0x00,!tlabel"
3336                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3337                       ,tlbl->key + 100);
3338           else
3339             emitcode ("cjne", "a,%s,!tlabel"
3340                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3341                       ,tlbl->key + 100);
3342
3343           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3344         }
3345       if (size > 3)
3346         {
3347           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3348               IS_AOP_PREG (IC_RESULT (ic)))
3349             emitcode ("cjne", "%s,#0x00,!tlabel"
3350                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3351                       ,tlbl->key + 100);
3352           else
3353             {
3354               emitcode ("cjne", "a,%s,!tlabel"
3355                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3356                         ,tlbl->key + 100);
3357             }
3358           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3359         }
3360
3361       if (emitTlbl)
3362         {
3363           emitcode ("", "!tlabeldef", tlbl->key + 100);
3364         }
3365       return TRUE;
3366     }
3367
3368   /* if the sizes are greater than 1 then we cannot */
3369   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3370       AOP_SIZE (IC_LEFT (ic)) > 1)
3371     return FALSE;
3372
3373   /* we can if the aops of the left & result match or
3374      if they are in registers and the registers are the
3375      same */
3376   if (
3377        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3378        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3379        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3380     {
3381
3382       if (icount > 3)
3383         {
3384           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3385           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3386           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3387         }
3388       else
3389         {
3390
3391           _startLazyDPSEvaluation ();
3392           while (icount--)
3393             {
3394               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3395             }
3396           _endLazyDPSEvaluation ();
3397         }
3398
3399       return TRUE;
3400     }
3401
3402   return FALSE;
3403 }
3404
3405 /*-----------------------------------------------------------------*/
3406 /* outBitAcc - output a bit in acc                                 */
3407 /*-----------------------------------------------------------------*/
3408 static void
3409 outBitAcc (operand * result)
3410 {
3411   symbol *tlbl = newiTempLabel (NULL);
3412   /* if the result is a bit */
3413   if (AOP_TYPE (result) == AOP_CRY)
3414     {
3415       aopPut (AOP (result), "a", 0);
3416     }
3417   else
3418     {
3419       emitcode ("jz", "!tlabel", tlbl->key + 100);
3420       emitcode ("mov", "a,%s", one);
3421       emitcode ("", "!tlabeldef", tlbl->key + 100);
3422       outAcc (result);
3423     }
3424 }
3425
3426 /*-----------------------------------------------------------------*/
3427 /* genPlusBits - generates code for addition of two bits           */
3428 /*-----------------------------------------------------------------*/
3429 static void
3430 genPlusBits (iCode * ic)
3431 {
3432   D (emitcode (";", "genPlusBits ");
3433     );
3434   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3435     {
3436       symbol *lbl = newiTempLabel (NULL);
3437       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3438       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3439       emitcode ("cpl", "c");
3440       emitcode ("", "!tlabeldef", (lbl->key + 100));
3441       outBitC (IC_RESULT (ic));
3442     }
3443   else
3444     {
3445       emitcode ("clr", "a");
3446       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3447       emitcode ("rlc", "a");
3448       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3449       emitcode ("addc", "a,#0x00");
3450       outAcc (IC_RESULT (ic));
3451     }
3452 }
3453
3454 static void
3455 adjustArithmeticResult (iCode * ic)
3456 {
3457   if (opIsGptr (IC_RESULT (ic)) &&
3458       opIsGptr (IC_LEFT (ic)) &&
3459       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3460     {
3461       aopPut (AOP (IC_RESULT (ic)),
3462               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3463               GPTRSIZE - 1);
3464     }
3465
3466   if (opIsGptr (IC_RESULT (ic)) &&
3467       opIsGptr (IC_RIGHT (ic)) &&
3468       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3469     {
3470       aopPut (AOP (IC_RESULT (ic)),
3471             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3472               GPTRSIZE - 1);
3473     }
3474
3475   if (opIsGptr (IC_RESULT (ic)) &&
3476       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3477       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3478       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3479       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3480     {
3481       char buffer[5];
3482       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3483       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3484     }
3485 }
3486
3487 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3488       // Please don't bring it back without a really good reason.
3489 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3490 // (because all three operands are in far space).
3491 #define AOP_OP_3(ic) \
3492     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3493     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3494     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3495               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3496     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3497         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3498     { \
3499         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3500         fprintf(stderr,                                  \
3501                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3502     }
3503 #endif
3504
3505 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3506 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3507 // will be set TRUE. The caller must then handle the case specially, noting
3508 // that the IC_RESULT operand is not aopOp'd.
3509 #define AOP_OP_3_NOFATAL(ic, rc) \
3510     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3511     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3512                                   (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \
3513     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3514         (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \
3515     { \
3516        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3517        rc = TRUE; \
3518     }  \
3519     else \
3520     { \
3521        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3522                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3523        rc = FALSE; \
3524        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3525            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3526        { \
3527             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3528             fprintf(stderr,                                  \
3529                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3530        } \
3531     }
3532
3533 // aopOp the left & right operands of an ic.
3534 #define AOP_OP_2(ic) \
3535     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3536     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3537
3538 // convienience macro.
3539 #define AOP_SET_LOCALS(ic) \
3540     left = IC_LEFT(ic); \
3541     right = IC_RIGHT(ic); \
3542     result = IC_RESULT(ic);
3543
3544
3545 // Given an integer value of pushedSize bytes on the stack,
3546 // adjust it to be resultSize bytes, either by discarding
3547 // the most significant bytes or by zero-padding.
3548 //
3549 // On exit from this macro, pushedSize will have been adjusted to
3550 // equal resultSize, and ACC may be trashed.
3551 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3552       /* If the pushed data is bigger than the result,          \
3553        * simply discard unused bytes. Icky, but works.          \
3554        */                                                       \
3555       while (pushedSize > resultSize)                           \
3556       {                                                         \
3557           D (emitcode (";", "discarding unused result byte."););\
3558           emitcode ("pop", "acc");                              \
3559           pushedSize--;                                         \
3560       }                                                         \
3561       if (pushedSize < resultSize)                              \
3562       {                                                         \
3563           emitcode ("clr", "a");                                \
3564           /* Conversly, we haven't pushed enough here.          \
3565            * just zero-pad, and all is well.                    \
3566            */                                                   \
3567           while (pushedSize < resultSize)                       \
3568           {                                                     \
3569               emitcode("push", "acc");                          \
3570               pushedSize++;                                     \
3571           }                                                     \
3572       }                                                         \
3573       assert(pushedSize == resultSize);
3574
3575 /*-----------------------------------------------------------------*/
3576 /* genPlus - generates code for addition                           */
3577 /*-----------------------------------------------------------------*/
3578 static void
3579 genPlus (iCode * ic)
3580 {
3581   int size, offset = 0;
3582   bool pushResult = FALSE;
3583   int rSize;
3584
3585   D (emitcode (";", "genPlus "););
3586
3587   /* special cases :- */
3588   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3589       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3590       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3591       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3592       if (size <= 9) {
3593           while (size--) emitcode ("inc","dptr");
3594       } else {
3595           emitcode ("mov","a,dpl");
3596           emitcode ("add","a,#!constbyte",size & 0xff);
3597           emitcode ("mov","dpl,a");
3598           emitcode ("mov","a,dph");
3599           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3600           emitcode ("mov","dph,a");
3601           emitcode ("mov","a,dpx");
3602           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3603           emitcode ("mov","dpx,a");
3604       }
3605       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3606       return ;
3607   }
3608   if ( IS_SYMOP(IC_LEFT(ic)) && 
3609        OP_SYMBOL(IC_LEFT(ic))->remat &&
3610        isOperandInFarSpace(IC_RIGHT(ic))) {
3611       operand *op = IC_RIGHT(ic);
3612       IC_RIGHT(ic) = IC_LEFT(ic);
3613       IC_LEFT(ic) = op;
3614   }
3615                 
3616   AOP_OP_3_NOFATAL (ic, pushResult);
3617   if (pushResult)
3618     {
3619       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3620     }
3621
3622   if (!pushResult)
3623     {
3624       /* if literal, literal on the right or
3625          if left requires ACC or right is already
3626          in ACC */
3627       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3628        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3629           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3630         {
3631           operand *t = IC_RIGHT (ic);
3632           IC_RIGHT (ic) = IC_LEFT (ic);
3633           IC_LEFT (ic) = t;
3634           emitcode (";", "Swapped plus args.");
3635         }
3636
3637       /* if both left & right are in bit
3638          space */
3639       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3640           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3641         {
3642           genPlusBits (ic);
3643           goto release;
3644         }
3645
3646       /* if left in bit space & right literal */
3647       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3648           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3649         {
3650           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3651           /* if result in bit space */
3652           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3653             {
3654               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3655                 emitcode ("cpl", "c");
3656               outBitC (IC_RESULT (ic));
3657             }
3658           else
3659             {
3660               size = getDataSize (IC_RESULT (ic));
3661               _startLazyDPSEvaluation ();
3662               while (size--)
3663                 {
3664                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3665                   emitcode ("addc", "a,#00");
3666                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3667                 }
3668               _endLazyDPSEvaluation ();
3669             }
3670           goto release;
3671         }
3672
3673       /* if I can do an increment instead
3674          of add then GOOD for ME */
3675       if (genPlusIncr (ic) == TRUE)
3676         {
3677           emitcode (";", "did genPlusIncr");
3678           goto release;
3679         }
3680
3681     }
3682   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3683
3684   _startLazyDPSEvaluation ();
3685   while (size--)
3686     {
3687       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3688         {
3689           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3690           if (offset == 0)
3691             emitcode ("add", "a,%s",
3692                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3693           else
3694             emitcode ("addc", "a,%s",
3695                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3696         }
3697       else
3698         {
3699           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3700           {
3701               /* right is going to use ACC or we would have taken the
3702                * above branch.
3703                */
3704               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3705        TR_AP("#3");
3706               D(emitcode(";", "+ AOP_ACC special case."););
3707               emitcode("xch", "a, %s", DP2_RESULT_REG);
3708           }
3709           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3710           if (offset == 0)
3711           {
3712             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3713             {
3714          TR_AP("#4");
3715                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3716             }
3717             else
3718             {
3719                 emitcode ("add", "a,%s",
3720                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3721             }
3722           }
3723           else
3724           {
3725             emitcode ("addc", "a,%s",
3726                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3727           }
3728         }
3729       if (!pushResult)
3730         {
3731           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3732         }
3733       else
3734         {
3735           emitcode ("push", "acc");
3736         }
3737       offset++;
3738     }
3739   _endLazyDPSEvaluation ();
3740
3741   if (pushResult)
3742     {
3743       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3744
3745       size = getDataSize (IC_LEFT (ic));
3746       rSize = getDataSize (IC_RESULT (ic));
3747
3748       ADJUST_PUSHED_RESULT(size, rSize);
3749
3750       _startLazyDPSEvaluation ();
3751       while (size--)
3752         {
3753           emitcode ("pop", "acc");
3754           aopPut (AOP (IC_RESULT (ic)), "a", size);
3755         }
3756       _endLazyDPSEvaluation ();
3757     }
3758
3759   adjustArithmeticResult (ic);
3760
3761 release:
3762   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3763   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3764   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3765 }
3766
3767 /*-----------------------------------------------------------------*/
3768 /* genMinusDec :- does subtraction with deccrement if possible     */
3769 /*-----------------------------------------------------------------*/
3770 static bool
3771 genMinusDec (iCode * ic)
3772 {
3773   unsigned int icount;
3774   unsigned int size = getDataSize (IC_RESULT (ic));
3775
3776   /* will try to generate an increment */
3777   /* if the right side is not a literal
3778      we cannot */
3779   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3780     return FALSE;
3781
3782   /* if the literal value of the right hand side
3783      is greater than 4 then it is not worth it */
3784   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3785     return FALSE;
3786
3787   /* if decrement 16 bits in register */
3788   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3789       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3790       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3791       (size > 1) &&
3792       (icount == 1))
3793     {
3794       symbol *tlbl;
3795       int emitTlbl;
3796       int labelRange;
3797
3798       /* If the next instruction is a goto and the goto target
3799          * is <= 5 instructions previous to this, we can generate
3800          * jumps straight to that target.
3801        */
3802       if (ic->next && ic->next->op == GOTO
3803           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3804           && labelRange <= 5)
3805         {
3806           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3807           tlbl = IC_LABEL (ic->next);
3808           emitTlbl = 0;
3809         }
3810       else
3811         {
3812           tlbl = newiTempLabel (NULL);
3813           emitTlbl = 1;
3814         }
3815
3816       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3817       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3818           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3819           IS_AOP_PREG (IC_RESULT (ic)))
3820         emitcode ("cjne", "%s,#0xff,!tlabel"
3821                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3822                   ,tlbl->key + 100);
3823       else
3824         {
3825           emitcode ("mov", "a,#0xff");
3826           emitcode ("cjne", "a,%s,!tlabel"
3827                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3828                     ,tlbl->key + 100);
3829         }
3830       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3831       if (size > 2)
3832         {
3833           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3834               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3835               IS_AOP_PREG (IC_RESULT (ic)))
3836             emitcode ("cjne", "%s,#0xff,!tlabel"
3837                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3838                       ,tlbl->key + 100);
3839           else
3840             {
3841               emitcode ("cjne", "a,%s,!tlabel"
3842                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3843                         ,tlbl->key + 100);
3844             }
3845           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3846         }
3847       if (size > 3)
3848         {
3849           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3850               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3851               IS_AOP_PREG (IC_RESULT (ic)))
3852             emitcode ("cjne", "%s,#0xff,!tlabel"
3853                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3854                       ,tlbl->key + 100);
3855           else
3856             {
3857               emitcode ("cjne", "a,%s,!tlabel"
3858                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3859                         ,tlbl->key + 100);
3860             }
3861           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3862         }
3863       if (emitTlbl)
3864         {
3865           emitcode ("", "!tlabeldef", tlbl->key + 100);
3866         }
3867       return TRUE;
3868     }
3869
3870   /* if the sizes are greater than 1 then we cannot */
3871   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3872       AOP_SIZE (IC_LEFT (ic)) > 1)
3873     return FALSE;
3874
3875   /* we can if the aops of the left & result match or
3876      if they are in registers and the registers are the
3877      same */
3878   if (
3879        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3880        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3881        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3882     {
3883
3884       _startLazyDPSEvaluation ();
3885       while (icount--)
3886         {
3887           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3888         }
3889       _endLazyDPSEvaluation ();
3890
3891       return TRUE;
3892     }
3893
3894   return FALSE;
3895 }
3896
3897 /*-----------------------------------------------------------------*/
3898 /* addSign - complete with sign                                    */
3899 /*-----------------------------------------------------------------*/
3900 static void
3901 addSign (operand * result, int offset, int sign)
3902 {
3903   int size = (getDataSize (result) - offset);
3904   if (size > 0)
3905     {
3906       _startLazyDPSEvaluation();
3907       if (sign)
3908         {
3909           emitcode ("rlc", "a");
3910           emitcode ("subb", "a,acc");
3911           while (size--)
3912           {
3913             aopPut (AOP (result), "a", offset++);
3914           }
3915         }
3916       else
3917       {
3918         while (size--)
3919         {
3920           aopPut (AOP (result), zero, offset++);
3921         }
3922       }
3923       _endLazyDPSEvaluation();
3924     }
3925 }
3926
3927 /*-----------------------------------------------------------------*/
3928 /* genMinusBits - generates code for subtraction  of two bits      */
3929 /*-----------------------------------------------------------------*/
3930 static void
3931 genMinusBits (iCode * ic)
3932 {
3933   symbol *lbl = newiTempLabel (NULL);
3934
3935   D (emitcode (";", "genMinusBits "););
3936
3937   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3938     {
3939       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3940       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3941       emitcode ("cpl", "c");
3942       emitcode ("", "!tlabeldef", (lbl->key + 100));
3943       outBitC (IC_RESULT (ic));
3944     }
3945   else
3946     {
3947       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3948       emitcode ("subb", "a,acc");
3949       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3950       emitcode ("inc", "a");
3951       emitcode ("", "!tlabeldef", (lbl->key + 100));
3952       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3953       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3954     }
3955 }
3956
3957 /*-----------------------------------------------------------------*/
3958 /* genMinus - generates code for subtraction                       */
3959 /*-----------------------------------------------------------------*/
3960 static void
3961 genMinus (iCode * ic)
3962 {
3963   int size, offset = 0;
3964   int rSize;
3965   unsigned long lit = 0L;
3966   bool pushResult = FALSE;
3967
3968   D (emitcode (";", "genMinus "););
3969
3970   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3971   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3972   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3973       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3974     {
3975       pushResult = TRUE;
3976     }
3977   else
3978     {
3979       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3980
3981       /* special cases :- */
3982       /* if both left & right are in bit space */
3983       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3984           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3985         {
3986           genMinusBits (ic);
3987           goto release;
3988         }
3989
3990       /* if I can do an decrement instead
3991          of subtract then GOOD for ME */
3992       if (genMinusDec (ic) == TRUE)
3993         goto release;
3994
3995     }
3996
3997   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3998
3999   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4000     {
4001       CLRC;
4002     }
4003   else
4004     {
4005       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4006       lit = -(long) lit;
4007     }
4008
4009
4010   /* if literal, add a,#-lit, else normal subb */
4011   _startLazyDPSEvaluation ();
4012   while (size--)
4013     {
4014       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4015       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4016         emitcode ("subb", "a,%s",
4017                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4018       else
4019         {
4020           /* first add without previous c */
4021           if (!offset) {
4022             if (!size && lit==-1) {
4023               emitcode ("dec", "a");
4024             } else {
4025               emitcode ("add", "a,#!constbyte",
4026                         (unsigned int) (lit & 0x0FFL));
4027             }
4028           } else {
4029             emitcode ("addc", "a,#!constbyte",
4030                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4031           }
4032         }
4033
4034       if (pushResult)
4035         {
4036           emitcode ("push", "acc");
4037         }
4038       else
4039         {
4040           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4041         }
4042       offset++;
4043     }
4044   _endLazyDPSEvaluation ();
4045
4046   if (pushResult)
4047     {
4048       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4049
4050       size = getDataSize (IC_LEFT (ic));
4051       rSize = getDataSize (IC_RESULT (ic));
4052
4053       ADJUST_PUSHED_RESULT(size, rSize);
4054
4055       _startLazyDPSEvaluation ();
4056       while (size--)
4057         {
4058           emitcode ("pop", "acc");
4059           aopPut (AOP (IC_RESULT (ic)), "a", size);
4060         }
4061       _endLazyDPSEvaluation ();
4062     }
4063
4064   adjustArithmeticResult (ic);
4065
4066 release:
4067   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4068   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4069   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4070 }
4071
4072
4073 /*-----------------------------------------------------------------*/
4074 /* genMultbits :- multiplication of bits                           */
4075 /*-----------------------------------------------------------------*/
4076 static void
4077 genMultbits (operand * left,
4078              operand * right,
4079              operand * result,
4080              iCode   * ic)
4081 {
4082   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4083   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4084   aopOp(result, ic, TRUE, FALSE);
4085   outBitC (result);
4086 }
4087
4088
4089 /*-----------------------------------------------------------------*/
4090 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4091 /*-----------------------------------------------------------------*/
4092 static void
4093 genMultOneByte (operand * left,
4094                 operand * right,
4095                 operand * result,
4096                 iCode   * ic)
4097 {
4098   sym_link *opetype = operandType (result);
4099   symbol *lbl;
4100
4101
4102   /* (if two literals: the value is computed before) */
4103   /* if one literal, literal on the right */
4104   if (AOP_TYPE (left) == AOP_LIT)
4105     {
4106       operand *t = right;
4107       right = left;
4108       left = t;
4109       emitcode (";", "swapped left and right");
4110     }
4111
4112   if (SPEC_USIGN(opetype)
4113       // ignore the sign of left and right, what else can we do?
4114       || (SPEC_USIGN(operandType(left)) && 
4115           SPEC_USIGN(operandType(right)))) {
4116     // just an unsigned 8*8=8/16 multiply
4117     //emitcode (";","unsigned");
4118     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4119     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4120     emitcode ("mul", "ab");
4121    
4122     _G.accInUse++; _G.bInUse++;
4123     aopOp(result, ic, TRUE, FALSE);
4124       
4125       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4126       {
4127           // this should never happen
4128           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4129                    AOP_SIZE(result), __FILE__, lineno);
4130           exit (1);
4131       }      
4132       
4133     aopPut (AOP (result), "a", 0);
4134     _G.accInUse--; _G.bInUse--;
4135     if (AOP_SIZE(result)==2) 
4136     {
4137       aopPut (AOP (result), "b", 1);
4138     }
4139     return;
4140   }
4141
4142   // we have to do a signed multiply
4143
4144   emitcode (";", "signed");
4145   emitcode ("clr", "F0"); // reset sign flag
4146   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4147
4148   lbl=newiTempLabel(NULL);
4149   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4150   // left side is negative, 8-bit two's complement, this fails for -128
4151   emitcode ("setb", "F0"); // set sign flag
4152   emitcode ("cpl", "a");
4153   emitcode ("inc", "a");
4154
4155   emitcode ("", "!tlabeldef", lbl->key+100);
4156
4157   /* if literal */
4158   if (AOP_TYPE(right)==AOP_LIT) {
4159     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4160     /* AND literal negative */
4161     if ((int) val < 0) {
4162       emitcode ("cpl", "F0"); // complement sign flag
4163       emitcode ("mov", "b,#!constbyte", -val);
4164     } else {
4165       emitcode ("mov", "b,#!constbyte", val);
4166     }
4167   } else {
4168     lbl=newiTempLabel(NULL);
4169     emitcode ("mov", "b,a");
4170     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4171     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4172     // right side is negative, 8-bit two's complement
4173     emitcode ("cpl", "F0"); // complement sign flag
4174     emitcode ("cpl", "a");
4175     emitcode ("inc", "a");
4176     emitcode ("", "!tlabeldef", lbl->key+100);
4177   }
4178   emitcode ("mul", "ab");
4179     
4180   _G.accInUse++;_G.bInUse++;
4181   aopOp(result, ic, TRUE, FALSE);
4182     
4183   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4184   {
4185     // this should never happen
4186       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4187                AOP_SIZE(result), __FILE__, lineno);
4188       exit (1);
4189   }    
4190     
4191   lbl=newiTempLabel(NULL);
4192   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4193   // only ONE op was negative, we have to do a 8/16-bit two's complement
4194   emitcode ("cpl", "a"); // lsb
4195   if (AOP_SIZE(result)==1) {
4196     emitcode ("inc", "a");
4197   } else {
4198     emitcode ("add", "a,#1");
4199     emitcode ("xch", "a,b");
4200     emitcode ("cpl", "a"); // msb
4201     emitcode ("addc", "a,#0");
4202     emitcode ("xch", "a,b");
4203   }
4204
4205   emitcode ("", "!tlabeldef", lbl->key+100);
4206   aopPut (AOP (result), "a", 0);
4207   _G.accInUse--;_G.bInUse--;
4208   if (AOP_SIZE(result)==2) {
4209     aopPut (AOP (result), "b", 1);
4210   }
4211 }
4212
4213 /*-----------------------------------------------------------------*/
4214 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4215 /*-----------------------------------------------------------------*/
4216 static void genMultTwoByte (operand *left, operand *right, 
4217                             operand *result, iCode *ic)
4218 {
4219         sym_link *retype = getSpec(operandType(right));
4220         sym_link *letype = getSpec(operandType(left));
4221         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4222         symbol *lbl;
4223
4224         if (AOP_TYPE (left) == AOP_LIT) {
4225                 operand *t = right;
4226                 right = left;
4227                 left = t;
4228         }
4229         /* save EA bit in F1 */
4230         lbl = newiTempLabel(NULL);
4231         emitcode ("setb","F1");
4232         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4233         emitcode ("clr","F1");
4234         emitcode("","!tlabeldef",lbl->key+100);
4235
4236         /* load up MB with right */
4237         if (!umult) {
4238                 emitcode("clr","F0");
4239                 if (AOP_TYPE(right) == AOP_LIT) {
4240                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4241                         if (val < 0) {
4242                                 emitcode("setb","F0");
4243                                 val = -val;
4244                         }
4245                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4246                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4247                 } else {
4248                         lbl = newiTempLabel(NULL);
4249                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4250                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4251                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4252                         emitcode ("xch", "a,b");
4253                         emitcode ("cpl","a");
4254                         emitcode ("add", "a,#1");
4255                         emitcode ("xch", "a,b");
4256                         emitcode ("cpl", "a"); // msb
4257                         emitcode ("addc", "a,#0");
4258                         emitcode ("setb","F0");
4259                         emitcode ("","!tlabeldef",lbl->key+100);
4260                         emitcode ("mov","mb,b");
4261                         emitcode ("mov","mb,a");
4262                 }
4263         } else {
4264                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4265                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4266         }
4267         /* load up MA with left */
4268         if (!umult) {
4269                 lbl = newiTempLabel(NULL);
4270                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4271                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4272                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4273                 emitcode ("xch", "a,b");
4274                 emitcode ("cpl","a");
4275                 emitcode ("add", "a,#1");
4276                 emitcode ("xch", "a,b");
4277                 emitcode ("cpl", "a"); // msb
4278                 emitcode ("addc","a,#0");
4279                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4280                 emitcode ("setb","F0");
4281                 emitcode ("","!tlabeldef",lbl->key+100);
4282                 emitcode ("mov","ma,b");
4283                 emitcode ("mov","ma,a");
4284         } else {
4285                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4286                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4287         }
4288         /* wait for multiplication to finish */
4289         lbl = newiTempLabel(NULL);
4290         emitcode("","!tlabeldef", lbl->key+100);
4291         emitcode("mov","a,mcnt1");
4292         emitcode("anl","a,#0x80");
4293         emitcode("jnz","!tlabel",lbl->key+100);
4294         
4295         freeAsmop (left, NULL, ic, TRUE);
4296         freeAsmop (right, NULL, ic,TRUE);
4297         aopOp(result, ic, TRUE, FALSE);
4298
4299         /* if unsigned then simple */   
4300         if (umult) {
4301                 emitcode ("mov","a,ma");
4302                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4303                 emitcode ("mov","a,ma");
4304                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4305                 aopPut(AOP(result),"ma",1);
4306                 aopPut(AOP(result),"ma",0);
4307         } else {
4308                 emitcode("push","ma");
4309                 emitcode("push","ma");
4310                 emitcode("push","ma");
4311                 MOVA("ma");
4312                 /* negate result if needed */
4313                 lbl = newiTempLabel(NULL);      
4314                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4315                 emitcode("cpl","a");
4316                 emitcode("add","a,#1");
4317                 emitcode("","!tlabeldef", lbl->key+100);
4318                 if (AOP_TYPE(result) == AOP_ACC)
4319                 {
4320                     D(emitcode(";", "ACC special case."););
4321                     /* We know result is the only live aop, and 
4322                      * it's obviously not a DPTR2, so AP is available.
4323                      */
4324                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4325                 }
4326                 else
4327                 {
4328                     aopPut(AOP(result),"a",0);
4329                 }
4330             
4331                 emitcode("pop","acc");
4332                 lbl = newiTempLabel(NULL);      
4333                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4334                 emitcode("cpl","a");
4335                 emitcode("addc","a,#0");
4336                 emitcode("","!tlabeldef", lbl->key+100);
4337                 aopPut(AOP(result),"a",1);
4338                 emitcode("pop","acc");
4339                 if (AOP_SIZE(result) >= 3) {
4340                         lbl = newiTempLabel(NULL);      
4341                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4342                         emitcode("cpl","a");
4343                         emitcode("addc","a,#0");                        
4344                         emitcode("","!tlabeldef", lbl->key+100);
4345                         aopPut(AOP(result),"a",2);
4346                 }
4347                 emitcode("pop","acc");
4348                 if (AOP_SIZE(result) >= 4) {
4349                         lbl = newiTempLabel(NULL);      
4350                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4351                         emitcode("cpl","a");
4352                         emitcode("addc","a,#0");                        
4353                         emitcode("","!tlabeldef", lbl->key+100);
4354                         aopPut(AOP(result),"a",3);
4355                 }
4356                 if (AOP_TYPE(result) == AOP_ACC)
4357                 {
4358                     /* We stashed the result away above. */
4359                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4360                 }           
4361                 
4362         }
4363         freeAsmop (result, NULL, ic, TRUE);
4364
4365         /* restore EA bit in F1 */
4366         lbl = newiTempLabel(NULL);
4367         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4368         emitcode ("setb","EA");
4369         emitcode("","!tlabeldef",lbl->key+100);
4370         return ;
4371 }
4372
4373 /*-----------------------------------------------------------------*/
4374 /* genMult - generates code for multiplication                     */
4375 /*-----------------------------------------------------------------*/
4376 static void
4377 genMult (iCode * ic)
4378 {
4379   operand *left = IC_LEFT (ic);
4380   operand *right = IC_RIGHT (ic);
4381   operand *result = IC_RESULT (ic);
4382
4383   D (emitcode (";", "genMult "););
4384
4385   /* assign the amsops */
4386   AOP_OP_2 (ic);
4387
4388   /* special cases first */
4389   /* both are bits */
4390   if (AOP_TYPE (left) == AOP_CRY &&
4391       AOP_TYPE (right) == AOP_CRY)
4392     {
4393       genMultbits (left, right, result, ic);
4394       goto release;
4395     }
4396
4397   /* if both are of size == 1 */
4398   if (AOP_SIZE (left) == 1 &&
4399       AOP_SIZE (right) == 1)
4400     {
4401       genMultOneByte (left, right, result, ic);
4402       goto release;
4403     }
4404
4405   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4406           /* use the ds390 ARITHMETIC accel UNIT */
4407           genMultTwoByte (left, right, result, ic);
4408           return ;
4409   }
4410   /* should have been converted to function call */
4411   assert (0);
4412
4413 release:
4414   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4415   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4416   freeAsmop (result, NULL, ic, TRUE);
4417 }
4418
4419 /*-----------------------------------------------------------------*/
4420 /* genDivbits :- division of bits                                  */
4421 /*-----------------------------------------------------------------*/
4422 static void
4423 genDivbits (operand * left,
4424             operand * right,
4425             operand * result,
4426             iCode   * ic)
4427 {
4428
4429   char *l;
4430
4431   /* the result must be bit */
4432   LOAD_AB_FOR_DIV (left, right, l);
4433   emitcode ("div", "ab");
4434   emitcode ("rrc", "a");
4435   aopOp(result, ic, TRUE, FALSE);
4436     
4437   aopPut (AOP (result), "c", 0);
4438 }
4439
4440 /*-----------------------------------------------------------------*/
4441 /* genDivOneByte : 8 bit division                                  */
4442 /*-----------------------------------------------------------------*/
4443 static void
4444 genDivOneByte (operand * left,
4445                operand * right,
4446                operand * result,
4447                iCode   * ic)
4448 {
4449   sym_link *opetype = operandType (result);
4450   char *l;
4451   symbol *lbl;
4452   int size, offset;
4453
4454   offset = 1;
4455   /* signed or unsigned */
4456   if (SPEC_USIGN (opetype))
4457     {
4458         /* unsigned is easy */
4459         LOAD_AB_FOR_DIV (left, right, l);
4460         emitcode ("div", "ab");
4461
4462         _G.accInUse++;
4463         aopOp(result, ic, TRUE, FALSE);
4464         aopPut (AOP (result), "a", 0);
4465         _G.accInUse--;
4466
4467         size = AOP_SIZE (result) - 1;
4468         
4469         while (size--)
4470         {
4471             aopPut (AOP (result), zero, offset++);
4472         }
4473       return;
4474     }
4475
4476   /* signed is a little bit more difficult */
4477
4478   /* save the signs of the operands */
4479   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4480   MOVA (l);
4481   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4482   emitcode ("push", "acc");     /* save it on the stack */
4483
4484   /* now sign adjust for both left & right */
4485   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4486   MOVA (l);
4487   lbl = newiTempLabel (NULL);
4488   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4489   emitcode ("cpl", "a");
4490   emitcode ("inc", "a");
4491   emitcode ("", "!tlabeldef", (lbl->key + 100));
4492   emitcode ("mov", "b,a");
4493
4494   /* sign adjust left side */
4495   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4496   MOVA (l);
4497
4498   lbl = newiTempLabel (NULL);
4499   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4500   emitcode ("cpl", "a");
4501   emitcode ("inc", "a");
4502   emitcode ("", "!tlabeldef", (lbl->key + 100));
4503
4504   /* now the division */
4505   emitcode ("nop", "; workaround for DS80C390 div bug.");
4506   emitcode ("div", "ab");
4507   /* we are interested in the lower order
4508      only */
4509   emitcode ("mov", "b,a");
4510   lbl = newiTempLabel (NULL);
4511   emitcode ("pop", "acc");
4512   /* if there was an over flow we don't
4513      adjust the sign of the result */
4514   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4515   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4516   CLRC;
4517   emitcode ("clr", "a");
4518   emitcode ("subb", "a,b");
4519   emitcode ("mov", "b,a");
4520   emitcode ("", "!tlabeldef", (lbl->key + 100));
4521
4522   /* now we are done */
4523   _G.accInUse++;     _G.bInUse++;
4524     aopOp(result, ic, TRUE, FALSE);
4525     
4526     aopPut (AOP (result), "b", 0);
4527     
4528     size = AOP_SIZE (result) - 1;
4529     
4530     if (size > 0)
4531     {
4532       emitcode ("mov", "c,b.7");
4533       emitcode ("subb", "a,acc");
4534     }
4535     while (size--)
4536     {
4537         aopPut (AOP (result), "a", offset++);
4538     }
4539     _G.accInUse--;     _G.bInUse--;
4540
4541 }
4542
4543 /*-----------------------------------------------------------------*/
4544 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4545 /*-----------------------------------------------------------------*/
4546 static void genDivTwoByte (operand *left, operand *right, 
4547                             operand *result, iCode *ic)
4548 {
4549         sym_link *retype = getSpec(operandType(right));
4550         sym_link *letype = getSpec(operandType(left));
4551         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4552         symbol *lbl;
4553
4554         /* save EA bit in F1 */
4555         lbl = newiTempLabel(NULL);
4556         emitcode ("setb","F1");
4557         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4558         emitcode ("clr","F1");
4559         emitcode("","!tlabeldef",lbl->key+100);
4560
4561         /* load up MA with left */
4562         if (!umult) {
4563                 emitcode("clr","F0");
4564                 lbl = newiTempLabel(NULL);
4565                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4566                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4567                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4568                 emitcode ("xch", "a,b");
4569                 emitcode ("cpl","a");
4570                 emitcode ("add", "a,#1");
4571                 emitcode ("xch", "a,b");
4572                 emitcode ("cpl", "a"); // msb
4573                 emitcode ("addc","a,#0");
4574                 emitcode ("setb","F0");
4575                 emitcode ("","!tlabeldef",lbl->key+100);
4576                 emitcode ("mov","ma,b");
4577                 emitcode ("mov","ma,a");
4578         } else {
4579                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4580                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4581         }
4582
4583         /* load up MB with right */
4584         if (!umult) {
4585                 if (AOP_TYPE(right) == AOP_LIT) {
4586                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4587                         if (val < 0) {
4588                                 lbl = newiTempLabel(NULL);
4589                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4590                                 emitcode("setb","F0");
4591                                 emitcode ("","!tlabeldef",lbl->key+100);
4592                                 val = -val;
4593                         } 
4594                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4595                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4596                 } else {
4597                         lbl = newiTempLabel(NULL);
4598                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4599                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4600                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4601                         emitcode ("xch", "a,b");
4602                         emitcode ("cpl","a");
4603                         emitcode ("add", "a,#1");
4604                         emitcode ("xch", "a,b");
4605                         emitcode ("cpl", "a"); // msb
4606                         emitcode ("addc", "a,#0");
4607                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4608                         emitcode ("setb","F0");
4609                         emitcode ("","!tlabeldef",lbl->key+100);
4610                         emitcode ("mov","mb,b");
4611                         emitcode ("mov","mb,a");
4612                 }
4613         } else {
4614                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4615                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4616         }
4617
4618         /* wait for multiplication to finish */
4619         lbl = newiTempLabel(NULL);
4620         emitcode("","!tlabeldef", lbl->key+100);
4621         emitcode("mov","a,mcnt1");
4622         emitcode("anl","a,#0x80");
4623         emitcode("jnz","!tlabel",lbl->key+100);
4624         
4625         freeAsmop (left, NULL, ic, TRUE);
4626         freeAsmop (right, NULL, ic,TRUE);
4627         aopOp(result, ic, TRUE, FALSE);
4628
4629         /* if unsigned then simple */   
4630         if (umult) {
4631                 aopPut(AOP(result),"ma",1);
4632                 aopPut(AOP(result),"ma",0);
4633         } else {
4634                 emitcode("push","ma");
4635                 MOVA("ma");
4636                 /* negate result if needed */
4637                 lbl = newiTempLabel(NULL);      
4638                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4639                 emitcode("cpl","a");
4640                 emitcode("add","a,#1");
4641                 emitcode("","!tlabeldef", lbl->key+100);
4642                 aopPut(AOP(result),"a",0);
4643                 emitcode("pop","acc");
4644                 lbl = newiTempLabel(NULL);      
4645                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4646                 emitcode("cpl","a");
4647                 emitcode("addc","a,#0");
4648                 emitcode("","!tlabeldef", lbl->key+100);
4649                 aopPut(AOP(result),"a",1);
4650         }
4651         freeAsmop (result, NULL, ic, TRUE);
4652         /* restore EA bit in F1 */
4653         lbl = newiTempLabel(NULL);
4654         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4655         emitcode ("setb","EA");
4656         emitcode("","!tlabeldef",lbl->key+100);
4657         return ;
4658 }
4659
4660 /*-----------------------------------------------------------------*/
4661 /* genDiv - generates code for division                            */
4662 /*-----------------------------------------------------------------*/
4663 static void
4664 genDiv (iCode * ic)
4665 {
4666   operand *left = IC_LEFT (ic);
4667   operand *right = IC_RIGHT (ic);
4668   operand *result = IC_RESULT (ic);
4669
4670   D (emitcode (";", "genDiv "););
4671
4672   /* assign the amsops */
4673   AOP_OP_2 (ic);
4674
4675   /* special cases first */
4676   /* both are bits */
4677   if (AOP_TYPE (left) == AOP_CRY &&
4678       AOP_TYPE (right) == AOP_CRY)
4679     {
4680       genDivbits (left, right, result, ic);
4681       goto release;
4682     }
4683
4684   /* if both are of size == 1 */
4685   if (AOP_SIZE (left) == 1 &&
4686       AOP_SIZE (right) == 1)
4687     {
4688       genDivOneByte (left, right, result, ic);
4689       goto release;
4690     }
4691
4692   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4693           /* use the ds390 ARITHMETIC accel UNIT */
4694           genDivTwoByte (left, right, result, ic);
4695           return ;
4696   }
4697   /* should have been converted to function call */
4698   assert (0);
4699 release:
4700   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4701   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4702   freeAsmop (result, NULL, ic, TRUE);
4703 }
4704
4705 /*-----------------------------------------------------------------*/
4706 /* genModbits :- modulus of bits                                   */
4707 /*-----------------------------------------------------------------*/
4708 static void
4709 genModbits (operand * left,
4710             operand * right,
4711             operand * result,
4712             iCode   * ic)
4713 {
4714
4715   char *l;
4716
4717   /* the result must be bit */
4718   LOAD_AB_FOR_DIV (left, right, l);
4719   emitcode ("div", "ab");
4720   emitcode ("mov", "a,b");
4721   emitcode ("rrc", "a");
4722   aopOp(result, ic, TRUE, FALSE);
4723   aopPut (AOP (result), "c", 0);
4724 }
4725
4726 /*-----------------------------------------------------------------*/
4727 /* genModOneByte : 8 bit modulus                                   */
4728 /*-----------------------------------------------------------------*/
4729 static void
4730 genModOneByte (operand * left,
4731                operand * right,
4732                operand * result,
4733                iCode   * ic)
4734 {
4735   sym_link *opetype = operandType (result);
4736   char *l;
4737   symbol *lbl;
4738
4739   /* signed or unsigned */
4740   if (SPEC_USIGN (opetype))
4741     {
4742       /* unsigned is easy */
4743       LOAD_AB_FOR_DIV (left, right, l);
4744       emitcode ("div", "ab");
4745       aopOp(result, ic, TRUE, FALSE);   
4746       aopPut (AOP (result), "b", 0);
4747       return;
4748     }
4749
4750   /* signed is a little bit more difficult */
4751
4752   /* save the signs of the operands */
4753   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4754   MOVA (l);
4755
4756   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4757   emitcode ("push", "acc");     /* save it on the stack */
4758
4759   /* now sign adjust for both left & right */
4760   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4761   MOVA (l);
4762
4763   lbl = newiTempLabel (NULL);
4764   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4765   emitcode ("cpl", "a");
4766   emitcode ("inc", "a");
4767   emitcode ("", "!tlabeldef", (lbl->key + 100));
4768   emitcode ("mov", "b,a");
4769
4770   /* sign adjust left side */
4771   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4772   MOVA (l);
4773
4774   lbl = newiTempLabel (NULL);
4775   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4776   emitcode ("cpl", "a");
4777   emitcode ("inc", "a");
4778   emitcode ("", "!tlabeldef", (lbl->key + 100));
4779
4780   /* now the multiplication */
4781   emitcode ("nop", "; workaround for DS80C390 div bug.");
4782   emitcode ("div", "ab");
4783   /* we are interested in the lower order
4784      only */
4785   lbl = newiTempLabel (NULL);
4786   emitcode ("pop", "acc");
4787   /* if there was an over flow we don't
4788      adjust the sign of the result */
4789   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4790   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4791   CLRC;
4792   emitcode ("clr", "a");
4793   emitcode ("subb", "a,b");
4794   emitcode ("mov", "b,a");
4795   emitcode ("", "!tlabeldef", (lbl->key + 100));
4796   
4797   _G.bInUse++;
4798   /* now we are done */
4799   aopOp(result, ic, TRUE, FALSE);    
4800   aopPut (AOP (result), "b", 0);
4801   _G.bInUse--;
4802
4803 }
4804
4805 /*-----------------------------------------------------------------*/
4806 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4807 /*-----------------------------------------------------------------*/
4808 static void genModTwoByte (operand *left, operand *right, 
4809                             operand *result, iCode *ic)
4810 {
4811         sym_link *retype = getSpec(operandType(right));
4812         sym_link *letype = getSpec(operandType(left));
4813         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4814         symbol *lbl;
4815
4816         /* load up MA with left */
4817         /* save EA bit in F1 */
4818         lbl = newiTempLabel(NULL);
4819         emitcode ("setb","F1");
4820         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4821         emitcode ("clr","F1");
4822         emitcode("","!tlabeldef",lbl->key+100);
4823
4824         if (!umult) {
4825                 lbl = newiTempLabel(NULL);
4826                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4827                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4828                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4829                 emitcode ("xch", "a,b");
4830                 emitcode ("cpl","a");
4831                 emitcode ("add", "a,#1");
4832                 emitcode ("xch", "a,b");
4833                 emitcode ("cpl", "a"); // msb
4834                 emitcode ("addc","a,#0");
4835                 emitcode ("","!tlabeldef",lbl->key+100);
4836                 emitcode ("mov","ma,b");
4837                 emitcode ("mov","ma,a");
4838         } else {
4839                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4840                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4841         }
4842
4843         /* load up MB with right */
4844         if (!umult) {
4845                 if (AOP_TYPE(right) == AOP_LIT) {
4846                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4847                         if (val < 0) {
4848                                 val = -val;
4849                         } 
4850                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4851                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4852                 } else {
4853                         lbl = newiTempLabel(NULL);
4854                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4855                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4856                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4857                         emitcode ("xch", "a,b");
4858                         emitcode ("cpl","a");
4859                         emitcode ("add", "a,#1");
4860                         emitcode ("xch", "a,b");
4861                         emitcode ("cpl", "a"); // msb
4862                         emitcode ("addc", "a,#0");
4863                         emitcode ("","!tlabeldef",lbl->key+100);
4864                         emitcode ("mov","mb,b");
4865                         emitcode ("mov","mb,a");
4866                 }
4867         } else {
4868                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4869                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4870         }
4871
4872         /* wait for multiplication to finish */
4873         lbl = newiTempLabel(NULL);
4874         emitcode("","!tlabeldef", lbl->key+100);
4875         emitcode("mov","a,mcnt1");
4876         emitcode("anl","a,#0x80");
4877         emitcode("jnz","!tlabel",lbl->key+100);
4878         
4879         freeAsmop (left, NULL, ic, TRUE);
4880         freeAsmop (right, NULL, ic,TRUE);
4881         aopOp(result, ic, TRUE, FALSE);
4882
4883         aopPut(AOP(result),"mb",1);
4884         aopPut(AOP(result),"mb",0);
4885         freeAsmop (result, NULL, ic, TRUE);
4886
4887         /* restore EA bit in F1 */
4888         lbl = newiTempLabel(NULL);
4889         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4890         emitcode ("setb","EA");
4891         emitcode("","!tlabeldef",lbl->key+100);
4892         return ;
4893 }
4894
4895 /*-----------------------------------------------------------------*/
4896 /* genMod - generates code for division                            */
4897 /*-----------------------------------------------------------------*/
4898 static void
4899 genMod (iCode * ic)
4900 {
4901   operand *left = IC_LEFT (ic);
4902   operand *right = IC_RIGHT (ic);
4903   operand *result = IC_RESULT (ic);
4904
4905   D (emitcode (";", "genMod "); );
4906
4907   /* assign the amsops */
4908   AOP_OP_2 (ic);
4909
4910   /* special cases first */
4911   /* both are bits */
4912   if (AOP_TYPE (left) == AOP_CRY &&
4913       AOP_TYPE (right) == AOP_CRY)
4914     {
4915       genModbits (left, right, result, ic);
4916       goto release;
4917     }
4918
4919   /* if both are of size == 1 */
4920   if (AOP_SIZE (left) == 1 &&
4921       AOP_SIZE (right) == 1)
4922     {
4923       genModOneByte (left, right, result, ic);
4924       goto release;
4925     }
4926
4927   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4928           /* use the ds390 ARITHMETIC accel UNIT */
4929           genModTwoByte (left, right, result, ic);
4930           return ;
4931   }
4932
4933   /* should have been converted to function call */
4934   assert (0);
4935
4936 release:
4937   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4939   freeAsmop (result, NULL, ic, TRUE);
4940 }
4941
4942 /*-----------------------------------------------------------------*/
4943 /* genIfxJump :- will create a jump depending on the ifx           */
4944 /*-----------------------------------------------------------------*/
4945 static void
4946 genIfxJump (iCode * ic, char *jval)
4947 {
4948   symbol *jlbl;
4949   symbol *tlbl = newiTempLabel (NULL);
4950   char *inst;
4951
4952   D (emitcode (";", "genIfxJump ");
4953     );
4954
4955   /* if true label then we jump if condition
4956      supplied is true */
4957   if (IC_TRUE (ic))
4958     {
4959       jlbl = IC_TRUE (ic);
4960       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4961                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4962     }
4963   else
4964     {
4965       /* false label is present */
4966       jlbl = IC_FALSE (ic);
4967       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4968                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4969     }
4970   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4971     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
4972   else
4973     emitcode (inst, "!tlabel", tlbl->key + 100);
4974   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
4975   emitcode ("", "!tlabeldef", tlbl->key + 100);
4976
4977   /* mark the icode as generated */
4978   ic->generated = 1;
4979 }
4980
4981 /*-----------------------------------------------------------------*/
4982 /* genCmp :- greater or less than comparison                       */
4983 /*-----------------------------------------------------------------*/
4984 static void
4985 genCmp (operand * left, operand * right,
4986         iCode * ic, iCode * ifx, int sign)
4987 {
4988   int size, offset = 0;
4989   unsigned long lit = 0L;
4990   operand *result;
4991
4992   D (emitcode (";", "genCmp");
4993     );
4994
4995   result = IC_RESULT (ic);
4996
4997   /* if left & right are bit variables */
4998   if (AOP_TYPE (left) == AOP_CRY &&
4999       AOP_TYPE (right) == AOP_CRY)
5000     {
5001       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5002       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5003     }
5004   else
5005     {
5006       /* subtract right from left if at the
5007          end the carry flag is set then we know that
5008          left is greater than right */
5009       size = max (AOP_SIZE (left), AOP_SIZE (right));
5010
5011       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5012       if ((size == 1) && !sign &&
5013           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5014         {
5015           symbol *lbl = newiTempLabel (NULL);
5016           emitcode ("cjne", "%s,%s,!tlabel",
5017                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5018                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5019                     lbl->key + 100);
5020           emitcode ("", "!tlabeldef", lbl->key + 100);
5021         }
5022       else
5023         {
5024           if (AOP_TYPE (right) == AOP_LIT)
5025             {
5026               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5027               /* optimize if(x < 0) or if(x >= 0) */
5028               if (lit == 0L)
5029                 {
5030                   if (!sign)
5031                     {
5032                       CLRC;
5033                     }
5034                   else
5035                     {
5036                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5037
5038                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5039                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5040
5041                       aopOp (result, ic, FALSE, FALSE);
5042
5043                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5044                         {
5045                           freeAsmop (result, NULL, ic, TRUE);
5046                           genIfxJump (ifx, "acc.7");
5047                           return;
5048                         }
5049                       else
5050                         {
5051                           emitcode ("rlc", "a");
5052                         }
5053                       goto release_freedLR;
5054                     }
5055                   goto release;
5056                 }
5057             }
5058           CLRC;
5059           while (size--)
5060             {
5061               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5062               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5063               emitcode (";", "genCmp #2");
5064               if (sign && (size == 0))
5065                 {
5066                   emitcode (";", "genCmp #3");
5067                   emitcode ("xrl", "a,#0x80");
5068                   if (AOP_TYPE (right) == AOP_LIT)
5069                     {
5070                       unsigned long lit = (unsigned long)
5071                       floatFromVal (AOP (right)->aopu.aop_lit);
5072                       emitcode (";", "genCmp #3.1");
5073                       emitcode ("subb", "a,#!constbyte",
5074                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5075                     }
5076                   else
5077                     {
5078                       emitcode (";", "genCmp #3.2");
5079                       if (AOP_NEEDSACC (right))
5080                         {
5081                           emitcode ("push", "acc");
5082                         }
5083                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5084                                                        FALSE, FALSE, FALSE));
5085                       emitcode ("xrl", "b,#0x80");
5086                       if (AOP_NEEDSACC (right))
5087                         {
5088                           emitcode ("pop", "acc");
5089                         }
5090                       emitcode ("subb", "a,b");
5091                     }
5092                 }
5093               else
5094                 {
5095                   const char *s;
5096
5097                   emitcode (";", "genCmp #4");
5098                   if (AOP_NEEDSACC (right))
5099                     {
5100                       /* Yuck!! */
5101                       emitcode (";", "genCmp #4.1");
5102                       emitcode ("xch", "a, b");
5103                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5104                       emitcode ("xch", "a, b");
5105                       s = "b";
5106                     }
5107                   else
5108                     {
5109                       emitcode (";", "genCmp #4.2");
5110                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5111                     }
5112
5113                   emitcode ("subb", "a,%s", s);
5114                 }
5115             }
5116         }
5117     }
5118
5119 release:
5120 /* Don't need the left & right operands any more; do need the result. */
5121   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5123
5124   aopOp (result, ic, FALSE, FALSE);
5125
5126 release_freedLR:
5127
5128   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5129     {
5130       outBitC (result);
5131     }
5132   else
5133     {
5134       /* if the result is used in the next
5135          ifx conditional branch then generate
5136          code a little differently */
5137       if (ifx)
5138         {
5139           genIfxJump (ifx, "c");
5140         }
5141       else
5142         {
5143           outBitC (result);
5144         }
5145       /* leave the result in acc */
5146     }
5147   freeAsmop (result, NULL, ic, TRUE);
5148 }
5149
5150 /*-----------------------------------------------------------------*/
5151 /* genCmpGt :- greater than comparison                             */
5152 /*-----------------------------------------------------------------*/
5153 static void
5154 genCmpGt (iCode * ic, iCode * ifx)
5155 {
5156   operand *left, *right;
5157   sym_link *letype, *retype;
5158   int sign;
5159
5160   D (emitcode (";", "genCmpGt ");
5161     );
5162
5163   left = IC_LEFT (ic);
5164   right = IC_RIGHT (ic);
5165
5166   letype = getSpec (operandType (left));
5167   retype = getSpec (operandType (right));
5168   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5169
5170   /* assign the left & right amsops */
5171   AOP_OP_2 (ic);
5172
5173   genCmp (right, left, ic, ifx, sign);
5174 }
5175
5176 /*-----------------------------------------------------------------*/
5177 /* genCmpLt - less than comparisons                                */
5178 /*-----------------------------------------------------------------*/
5179 static void
5180 genCmpLt (iCode * ic, iCode * ifx)
5181 {
5182   operand *left, *right;
5183   sym_link *letype, *retype;
5184   int sign;
5185
5186   D (emitcode (";", "genCmpLt "););
5187
5188   left = IC_LEFT (ic);
5189   right = IC_RIGHT (ic);
5190
5191   letype = getSpec (operandType (left));
5192   retype = getSpec (operandType (right));
5193   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5194
5195   /* assign the left & right amsops */
5196   AOP_OP_2 (ic);
5197
5198   genCmp (left, right, ic, ifx, sign);
5199 }
5200
5201 /*-----------------------------------------------------------------*/
5202 /* gencjneshort - compare and jump if not equal                    */
5203 /*-----------------------------------------------------------------*/
5204 static void
5205 gencjneshort (operand * left, operand * right, symbol * lbl)
5206 {
5207   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5208   int offset = 0;
5209   unsigned long lit = 0L;
5210
5211   D (emitcode (";", "gencjneshort");
5212     );
5213
5214   /* if the left side is a literal or
5215      if the right is in a pointer register and left
5216      is not */
5217   if ((AOP_TYPE (left) == AOP_LIT) ||
5218       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5219     {
5220       operand *t = right;
5221       right = left;
5222       left = t;
5223     }
5224
5225   if (AOP_TYPE (right) == AOP_LIT)
5226     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5227
5228   if (opIsGptr (left) || opIsGptr (right))
5229     {
5230       /* We are comparing a generic pointer to something.
5231        * Exclude the generic type byte from the comparison.
5232        */
5233       size--;
5234       D (emitcode (";", "cjneshort: generic ptr special case.");
5235         )
5236     }
5237
5238
5239   /* if the right side is a literal then anything goes */
5240   if (AOP_TYPE (right) == AOP_LIT &&
5241       AOP_TYPE (left) != AOP_DIR)
5242     {
5243       while (size--)
5244         {
5245           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5246           MOVA (l);
5247           emitcode ("cjne", "a,%s,!tlabel",
5248                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5249                     lbl->key + 100);
5250           offset++;
5251         }
5252     }
5253
5254   /* if the right side is in a register or in direct space or
5255      if the left is a pointer register & right is not */
5256   else if (AOP_TYPE (right) == AOP_REG ||
5257            AOP_TYPE (right) == AOP_DIR ||
5258            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5259            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5260     {
5261       while (size--)
5262         {
5263           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5264           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5265               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5266             emitcode ("jnz", "!tlabel", lbl->key + 100);
5267           else
5268             emitcode ("cjne", "a,%s,!tlabel",
5269                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5270                       lbl->key + 100);
5271           offset++;
5272         }
5273     }
5274   else
5275     {
5276       /* right is a pointer reg need both a & b */
5277       while (size--)
5278         {
5279           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5280           if (strcmp (l, "b"))
5281             emitcode ("mov", "b,%s", l);
5282           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5283           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5284           offset++;
5285         }
5286     }
5287 }
5288
5289 /*-----------------------------------------------------------------*/
5290 /* gencjne - compare and jump if not equal                         */
5291 /*-----------------------------------------------------------------*/
5292 static void
5293 gencjne (operand * left, operand * right, symbol * lbl)
5294 {
5295   symbol *tlbl = newiTempLabel (NULL);
5296
5297   D (emitcode (";", "gencjne");
5298     );
5299
5300   gencjneshort (left, right, lbl);
5301
5302   emitcode ("mov", "a,%s", one);
5303   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5304   emitcode ("", "!tlabeldef", lbl->key + 100);
5305   emitcode ("clr", "a");
5306   emitcode ("", "!tlabeldef", tlbl->key + 100);
5307 }
5308
5309 /*-----------------------------------------------------------------*/
5310 /* genCmpEq - generates code for equal to                          */
5311 /*-----------------------------------------------------------------*/
5312 static void
5313 genCmpEq (iCode * ic, iCode * ifx)
5314 {
5315   operand *left, *right, *result;
5316
5317   D (emitcode (";", "genCmpEq ");
5318     );
5319
5320   AOP_OP_2 (ic);
5321   AOP_SET_LOCALS (ic);
5322
5323   /* if literal, literal on the right or
5324      if the right is in a pointer register and left
5325      is not */
5326   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5327       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5328     {
5329       operand *t = IC_RIGHT (ic);
5330       IC_RIGHT (ic) = IC_LEFT (ic);
5331       IC_LEFT (ic) = t;
5332     }
5333
5334   if (ifx &&                    /* !AOP_SIZE(result) */
5335       OP_SYMBOL (result) &&
5336       OP_SYMBOL (result)->regType == REG_CND)
5337     {
5338       symbol *tlbl;
5339       /* if they are both bit variables */
5340       if (AOP_TYPE (left) == AOP_CRY &&
5341           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5342         {
5343           if (AOP_TYPE (right) == AOP_LIT)
5344             {
5345               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5346               if (lit == 0L)
5347                 {
5348                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5349                   emitcode ("cpl", "c");
5350                 }
5351               else if (lit == 1L)
5352                 {
5353                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5354                 }
5355               else
5356                 {
5357                   emitcode ("clr", "c");
5358                 }
5359               /* AOP_TYPE(right) == AOP_CRY */
5360             }
5361           else
5362             {
5363               symbol *lbl = newiTempLabel (NULL);
5364               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5365               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5366               emitcode ("cpl", "c");
5367               emitcode ("", "!tlabeldef", (lbl->key + 100));
5368             }
5369           /* if true label then we jump if condition
5370              supplied is true */
5371           tlbl = newiTempLabel (NULL);
5372           if (IC_TRUE (ifx))
5373             {
5374               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5375               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5376             }
5377           else
5378             {
5379               emitcode ("jc", "!tlabel", tlbl->key + 100);
5380               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5381             }
5382           emitcode ("", "!tlabeldef", tlbl->key + 100);
5383         }
5384       else
5385         {
5386           tlbl = newiTempLabel (NULL);
5387           gencjneshort (left, right, tlbl);
5388           if (IC_TRUE (ifx))
5389             {
5390               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5391               emitcode ("", "!tlabeldef", tlbl->key + 100);
5392             }
5393           else
5394             {
5395               symbol *lbl = newiTempLabel (NULL);
5396               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5397               emitcode ("", "!tlabeldef", tlbl->key + 100);
5398               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5399               emitcode ("", "!tlabeldef", lbl->key + 100);
5400             }
5401         }
5402       /* mark the icode as generated */
5403       ifx->generated = 1;
5404
5405       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5406       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5407       return;
5408     }
5409
5410   /* if they are both bit variables */
5411   if (AOP_TYPE (left) == AOP_CRY &&
5412       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5413     {
5414       if (AOP_TYPE (right) == AOP_LIT)
5415         {
5416           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5417           if (lit == 0L)
5418             {
5419               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5420               emitcode ("cpl", "c");
5421             }
5422           else if (lit == 1L)
5423             {
5424               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5425             }
5426           else
5427             {
5428               emitcode ("clr", "c");
5429             }
5430           /* AOP_TYPE(right) == AOP_CRY */
5431         }
5432       else
5433         {
5434           symbol *lbl = newiTempLabel (NULL);
5435           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5436           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5437           emitcode ("cpl", "c");
5438           emitcode ("", "!tlabeldef", (lbl->key + 100));
5439         }
5440
5441       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5442       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5443
5444       aopOp (result, ic, TRUE, FALSE);
5445
5446       /* c = 1 if egal */
5447       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5448         {
5449           outBitC (result);
5450           goto release;
5451         }
5452       if (ifx)
5453         {
5454           genIfxJump (ifx, "c");
5455           goto release;
5456         }
5457       /* if the result is used in an arithmetic operation
5458          then put the result in place */
5459       outBitC (result);
5460     }
5461   else
5462     {
5463       gencjne (left, right, newiTempLabel (NULL));
5464
5465       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5466       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5467
5468       aopOp (result, ic, TRUE, FALSE);
5469
5470       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5471         {
5472           aopPut (AOP (result), "a", 0);
5473           goto release;
5474         }
5475       if (ifx)
5476         {
5477           genIfxJump (ifx, "a");
5478           goto release;
5479         }
5480       /* if the result is used in an arithmetic operation
5481          then put the result in place */
5482       if (AOP_TYPE (result) != AOP_CRY)
5483         outAcc (result);
5484       /* leave the result in acc */
5485     }
5486
5487 release:
5488   freeAsmop (result, NULL, ic, TRUE);
5489 }
5490
5491 /*-----------------------------------------------------------------*/
5492 /* ifxForOp - returns the icode containing the ifx for operand     */
5493 /*-----------------------------------------------------------------*/
5494 static iCode *
5495 ifxForOp (operand * op, iCode * ic)
5496 {
5497   /* if true symbol then needs to be assigned */
5498   if (IS_TRUE_SYMOP (op))
5499     return NULL;
5500
5501   /* if this has register type condition and
5502      the next instruction is ifx with the same operand
5503      and live to of the operand is upto the ifx only then */
5504   if (ic->next &&
5505       ic->next->op == IFX &&
5506       IC_COND (ic->next)->key == op->key &&
5507       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5508     return ic->next;
5509
5510   return NULL;
5511 }
5512 /*-----------------------------------------------------------------*/
5513 /* hasInc - operand is incremented before any other use            */
5514 /*-----------------------------------------------------------------*/
5515 static iCode *
5516 hasInc (operand *op, iCode *ic)
5517 {
5518   sym_link *type = operandType(op);
5519   sym_link *retype = getSpec (type);
5520   iCode *lic = ic->next;
5521   int isize ;
5522   
5523   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5524   if (!IS_SYMOP(op)) return NULL;
5525
5526   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5527   isize = getSize(type->next);
5528   while (lic) {
5529       /* if operand of the form op = op + <sizeof *op> */
5530       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5531           isOperandEqual(IC_RESULT(lic),op) && 
5532           isOperandLiteral(IC_RIGHT(lic)) &&
5533           operandLitValue(IC_RIGHT(lic)) == isize) {
5534           return lic;
5535       }
5536       /* if the operand used or deffed */
5537       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5538           return NULL;
5539       }
5540       /* if GOTO or IFX */
5541       if (lic->op == IFX || lic->op == GOTO) break;
5542       lic = lic->next;
5543   }
5544   return NULL;
5545 }
5546
5547 /*-----------------------------------------------------------------*/
5548 /* genAndOp - for && operation                                     */
5549 /*-----------------------------------------------------------------*/
5550 static void
5551 genAndOp (iCode * ic)
5552 {
5553   operand *left, *right, *result;
5554   symbol *tlbl;
5555
5556   D (emitcode (";", "genAndOp "););
5557
5558   /* note here that && operations that are in an
5559      if statement are taken away by backPatchLabels
5560      only those used in arthmetic operations remain */
5561   AOP_OP_2 (ic);
5562   AOP_SET_LOCALS (ic);
5563
5564   /* if both are bit variables */
5565   if (AOP_TYPE (left) == AOP_CRY &&
5566       AOP_TYPE (right) == AOP_CRY)
5567     {
5568       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5569       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5570       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5571       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5572   
5573       aopOp (result,ic,FALSE, FALSE);
5574       outBitC (result);
5575     }
5576   else
5577     {
5578       tlbl = newiTempLabel (NULL);
5579       toBoolean (left);
5580       emitcode ("jz", "!tlabel", tlbl->key + 100);
5581       toBoolean (right);
5582       emitcode ("", "!tlabeldef", tlbl->key + 100);
5583       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5584       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5585   
5586       aopOp (result,ic,FALSE, FALSE);
5587       outBitAcc (result);
5588     }
5589     freeAsmop (result, NULL, ic, TRUE);
5590 }
5591
5592
5593 /*-----------------------------------------------------------------*/
5594 /* genOrOp - for || operation                                      */
5595 /*-----------------------------------------------------------------*/
5596 static void
5597 genOrOp (iCode * ic)
5598 {
5599   operand *left, *right, *result;
5600   symbol *tlbl;
5601
5602   D (emitcode (";", "genOrOp "););
5603
5604   /* note here that || operations that are in an
5605      if statement are taken away by backPatchLabels
5606      only those used in arthmetic operations remain */
5607   AOP_OP_2 (ic);
5608   AOP_SET_LOCALS (ic);
5609
5610   /* if both are bit variables */
5611   if (AOP_TYPE (left) == AOP_CRY &&
5612       AOP_TYPE (right) == AOP_CRY)
5613     {
5614       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5615       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5616       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5617       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5618   
5619       aopOp (result,ic,FALSE, FALSE);
5620       
5621       outBitC (result);
5622     }
5623   else
5624     {
5625       tlbl = newiTempLabel (NULL);
5626       toBoolean (left);
5627       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5628       toBoolean (right);
5629       emitcode ("", "!tlabeldef", tlbl->key + 100);
5630       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5631       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5632   
5633       aopOp (result,ic,FALSE, FALSE);
5634       
5635       outBitAcc (result);
5636     }
5637
5638   freeAsmop (result, NULL, ic, TRUE);
5639 }
5640
5641 /*-----------------------------------------------------------------*/
5642 /* isLiteralBit - test if lit == 2^n                               */
5643 /*-----------------------------------------------------------------*/
5644 static int
5645 isLiteralBit (unsigned long lit)
5646 {
5647   unsigned long pw[32] =
5648   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5649    0x100L, 0x200L, 0x400L, 0x800L,
5650    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5651    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5652    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5653    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5654    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5655   int idx;
5656
5657   for (idx = 0; idx < 32; idx++)
5658     if (lit == pw[idx])
5659       return idx + 1;
5660   return 0;
5661 }
5662
5663 /*-----------------------------------------------------------------*/
5664 /* continueIfTrue -                                                */
5665 /*-----------------------------------------------------------------*/
5666 static void
5667 continueIfTrue (iCode * ic)
5668 {
5669   if (IC_TRUE (ic))
5670     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5671   ic->generated = 1;
5672 }
5673
5674 /*-----------------------------------------------------------------*/
5675 /* jmpIfTrue -                                                     */
5676 /*-----------------------------------------------------------------*/
5677 static void
5678 jumpIfTrue (iCode * ic)
5679 {
5680   if (!IC_TRUE (ic))
5681     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5682   ic->generated = 1;
5683 }
5684
5685 /*-----------------------------------------------------------------*/
5686 /* jmpTrueOrFalse -                                                */
5687 /*-----------------------------------------------------------------*/
5688 static void
5689 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5690 {
5691   // ugly but optimized by peephole
5692   if (IC_TRUE (ic))
5693     {
5694       symbol *nlbl = newiTempLabel (NULL);
5695       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5696       emitcode ("", "!tlabeldef", tlbl->key + 100);
5697       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5698       emitcode ("", "!tlabeldef", nlbl->key + 100);
5699     }
5700   else
5701     {
5702       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5703       emitcode ("", "!tlabeldef", tlbl->key + 100);
5704     }
5705   ic->generated = 1;
5706 }
5707
5708 // Generate code to perform a bit-wise logic operation
5709 // on two operands in far space (assumed to already have been 
5710 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5711 // in far space. This requires pushing the result on the stack
5712 // then popping it into the result.
5713 static void
5714 genFarFarLogicOp(iCode *ic, char *logicOp)
5715 {
5716       int size, resultSize, compSize;
5717       int offset = 0;
5718       
5719       TR_AP("#5");
5720       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5721       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5722                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5723       
5724       _startLazyDPSEvaluation();
5725       for (size = compSize; (size--); offset++)
5726       {
5727           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5728           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5729           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5730           
5731           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5732           emitcode ("push", "acc");
5733       }
5734       _endLazyDPSEvaluation();
5735      
5736       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5737       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5738       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5739      
5740       resultSize = AOP_SIZE(IC_RESULT(ic));
5741
5742       ADJUST_PUSHED_RESULT(compSize, resultSize);
5743
5744       _startLazyDPSEvaluation();
5745       while (compSize--)
5746       {
5747           emitcode ("pop", "acc");
5748           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5749       }
5750       _endLazyDPSEvaluation();
5751       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5752 }
5753
5754
5755 /*-----------------------------------------------------------------*/
5756 /* genAnd  - code for and                                          */
5757 /*-----------------------------------------------------------------*/
5758 static void
5759 genAnd (iCode * ic, iCode * ifx)
5760 {
5761   operand *left, *right, *result;
5762   int size, offset = 0;
5763   unsigned long lit = 0L;
5764   int bytelit = 0;
5765   char buffer[10];
5766   bool pushResult;
5767
5768   D (emitcode (";", "genAnd "););
5769
5770   AOP_OP_3_NOFATAL (ic, pushResult);
5771   AOP_SET_LOCALS (ic);
5772
5773   if (pushResult)
5774   {
5775       genFarFarLogicOp(ic, "anl");
5776       return;
5777   }  
5778
5779 #ifdef DEBUG_TYPE
5780   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5781             AOP_TYPE (result),
5782             AOP_TYPE (left), AOP_TYPE (right));
5783   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5784             AOP_SIZE (result),
5785             AOP_SIZE (left), AOP_SIZE (right));
5786 #endif
5787
5788   /* if left is a literal & right is not then exchange them */
5789   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5790 #ifdef LOGIC_OPS_BROKEN      
5791     ||  AOP_NEEDSACC (left)
5792 #endif
5793     )
5794     {
5795       operand *tmp = right;
5796       right = left;
5797       left = tmp;
5798     }
5799
5800   /* if result = right then exchange them */
5801   if (sameRegs (AOP (result), AOP (right)))
5802     {
5803       operand *tmp = right;
5804       right = left;
5805       left = tmp;
5806     }
5807
5808   /* if right is bit then exchange them */
5809   if (AOP_TYPE (right) == AOP_CRY &&
5810       AOP_TYPE (left) != AOP_CRY)
5811     {
5812       operand *tmp = right;
5813       right = left;
5814       left = tmp;
5815     }
5816   if (AOP_TYPE (right) == AOP_LIT)
5817     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5818
5819   size = AOP_SIZE (result);
5820
5821   // if(bit & yy)
5822   // result = bit & yy;
5823   if (AOP_TYPE (left) == AOP_CRY)
5824     {
5825       // c = bit & literal;
5826       if (AOP_TYPE (right) == AOP_LIT)
5827         {
5828           if (lit & 1)
5829             {
5830               if (size && sameRegs (AOP (result), AOP (left)))
5831                 // no change
5832                 goto release;
5833               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5834             }
5835           else
5836             {
5837               // bit(result) = 0;
5838               if (size && (AOP_TYPE (result) == AOP_CRY))
5839                 {
5840                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5841                   goto release;
5842                 }
5843               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5844                 {
5845                   jumpIfTrue (ifx);
5846                   goto release;
5847                 }
5848               emitcode ("clr", "c");
5849             }
5850         }
5851       else
5852         {
5853           if (AOP_TYPE (right) == AOP_CRY)
5854             {
5855               // c = bit & bit;
5856               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5857               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5858             }
5859           else
5860             {
5861               // c = bit & val;
5862               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5863               // c = lsb
5864               emitcode ("rrc", "a");
5865               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5866             }
5867         }
5868       // bit = c
5869       // val = c
5870       if (size)
5871         outBitC (result);
5872       // if(bit & ...)
5873       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5874         genIfxJump (ifx, "c");
5875       goto release;
5876     }
5877
5878   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5879   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5880   if ((AOP_TYPE (right) == AOP_LIT) &&
5881       (AOP_TYPE (result) == AOP_CRY) &&
5882       (AOP_TYPE (left) != AOP_CRY))
5883     {
5884       int posbit = isLiteralBit (lit);
5885       /* left &  2^n */
5886       if (posbit)
5887         {
5888           posbit--;
5889           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5890           // bit = left & 2^n
5891           if (size)
5892             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5893           // if(left &  2^n)
5894           else
5895             {
5896               if (ifx)
5897                 {
5898                   sprintf (buffer, "acc.%d", posbit & 0x07);
5899                   genIfxJump (ifx, buffer);
5900                 }
5901               goto release;
5902             }
5903         }
5904       else
5905         {
5906           symbol *tlbl = newiTempLabel (NULL);
5907           int sizel = AOP_SIZE (left);
5908           if (size)
5909             emitcode ("setb", "c");
5910           while (sizel--)
5911             {
5912               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5913                 {
5914                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5915                   // byte ==  2^n ?
5916                   if ((posbit = isLiteralBit (bytelit)) != 0)
5917                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5918                   else
5919                     {
5920                       if (bytelit != 0x0FFL)
5921                         emitcode ("anl", "a,%s",
5922                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5923                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5924                     }
5925                 }
5926               offset++;
5927             }
5928           // bit = left & literal
5929           if (size)
5930             {
5931               emitcode ("clr", "c");
5932               emitcode ("", "!tlabeldef", tlbl->key + 100);
5933             }
5934           // if(left & literal)
5935           else
5936             {
5937               if (ifx)
5938                 jmpTrueOrFalse (ifx, tlbl);
5939               goto release;
5940             }
5941         }
5942       outBitC (result);
5943       goto release;
5944     }
5945
5946   /* if left is same as result */
5947   if (sameRegs (AOP (result), AOP (left)))
5948     {
5949       for (; size--; offset++)
5950         {
5951           if (AOP_TYPE (right) == AOP_LIT)
5952             {
5953               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5954                 continue;
5955               else if (bytelit == 0)
5956                 aopPut (AOP (result), zero, offset);
5957               else if (IS_AOP_PREG (result))
5958                 {
5959                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5960                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5961                   aopPut (AOP (result), "a", offset);
5962                 }
5963               else
5964                 emitcode ("anl", "%s,%s",
5965                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5966                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5967             }
5968           else
5969             {
5970               if (AOP_TYPE (left) == AOP_ACC)
5971                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5972               else
5973                 {
5974                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5975                   if (IS_AOP_PREG (result))
5976                     {
5977                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5978                       aopPut (AOP (result), "a", offset);
5979
5980                     }
5981                   else
5982                     emitcode ("anl", "%s,a",
5983                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5984                 }
5985             }
5986         }
5987     }
5988   else
5989     {
5990       // left & result in different registers
5991       if (AOP_TYPE (result) == AOP_CRY)
5992         {
5993           // result = bit
5994           // if(size), result in bit
5995           // if(!size && ifx), conditional oper: if(left & right)
5996           symbol *tlbl = newiTempLabel (NULL);
5997           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5998           if (size)
5999             emitcode ("setb", "c");
6000           while (sizer--)
6001             {
6002               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6003                 emitcode ("anl", "a,%s",
6004                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6005               } else {
6006                 if (AOP_TYPE(left)==AOP_ACC) {
6007                   emitcode("mov", "b,a");
6008                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6009                   emitcode("anl", "a,b");
6010                 }else {
6011                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6012                   emitcode ("anl", "a,%s",
6013                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6014                 }
6015               }
6016               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6017               offset++;
6018             }
6019           if (size)
6020             {
6021               CLRC;
6022               emitcode ("", "!tlabeldef", tlbl->key + 100);
6023               outBitC (result);
6024             }
6025           else if (ifx)
6026             jmpTrueOrFalse (ifx, tlbl);
6027         }
6028       else
6029         {
6030           for (; (size--); offset++)
6031             {
6032               // normal case
6033               // result = left & right
6034               if (AOP_TYPE (right) == AOP_LIT)
6035                 {
6036                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6037                     {
6038                       aopPut (AOP (result),
6039                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6040                               offset);
6041                       continue;
6042                     }
6043                   else if (bytelit == 0)
6044                     {
6045                       aopPut (AOP (result), zero, offset);
6046                       continue;
6047                     }
6048                   D (emitcode (";", "better literal AND."););
6049                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6050                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6051                                                     FALSE, FALSE, FALSE));
6052
6053                 }
6054               else
6055                 {
6056                   // faster than result <- left, anl result,right
6057                   // and better if result is SFR
6058                   if (AOP_TYPE (left) == AOP_ACC)
6059                     {
6060                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6061                                                        FALSE, FALSE, FALSE));
6062                     }
6063                   else
6064                     {
6065                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6066                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6067                       {
6068                           emitcode("mov", "b,a");
6069                           rOp = "b";
6070                       }
6071                         
6072                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6073                       emitcode ("anl", "a,%s", rOp);
6074                     }                   
6075                 }
6076               aopPut (AOP (result), "a", offset);
6077             }
6078         }
6079     }
6080
6081 release:
6082   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6083   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6084   freeAsmop (result, NULL, ic, TRUE);
6085 }
6086
6087
6088 /*-----------------------------------------------------------------*/
6089 /* genOr  - code for or                                            */
6090 /*-----------------------------------------------------------------*/
6091 static void
6092 genOr (iCode * ic, iCode * ifx)
6093 {
6094   operand *left, *right, *result;
6095   int size, offset = 0;
6096   unsigned long lit = 0L;
6097   bool     pushResult;
6098
6099   D (emitcode (";", "genOr "););
6100
6101   AOP_OP_3_NOFATAL (ic, pushResult);
6102   AOP_SET_LOCALS (ic);
6103
6104   if (pushResult)
6105   {
6106       genFarFarLogicOp(ic, "orl");
6107       return;
6108   }
6109
6110
6111 #ifdef DEBUG_TYPE
6112   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6113             AOP_TYPE (result),
6114             AOP_TYPE (left), AOP_TYPE (right));
6115   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6116             AOP_SIZE (result),
6117             AOP_SIZE (left), AOP_SIZE (right));
6118 #endif
6119
6120   /* if left is a literal & right is not then exchange them */
6121   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6122 #ifdef LOGIC_OPS_BROKEN
6123    || AOP_NEEDSACC (left) // I think this is a net loss now.
6124 #endif      
6125       )
6126     {
6127       operand *tmp = right;
6128       right = left;
6129       left = tmp;
6130     }
6131
6132   /* if result = right then exchange them */
6133   if (sameRegs (AOP (result), AOP (right)))
6134     {
6135       operand *tmp = right;
6136       right = left;
6137       left = tmp;
6138     }
6139
6140   /* if right is bit then exchange them */
6141   if (AOP_TYPE (right) == AOP_CRY &&
6142       AOP_TYPE (left) != AOP_CRY)
6143     {
6144       operand *tmp = right;
6145       right = left;
6146       left = tmp;
6147     }
6148   if (AOP_TYPE (right) == AOP_LIT)
6149     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6150
6151   size = AOP_SIZE (result);
6152
6153   // if(bit | yy)
6154   // xx = bit | yy;
6155   if (AOP_TYPE (left) == AOP_CRY)
6156     {
6157       if (AOP_TYPE (right) == AOP_LIT)
6158         {
6159           // c = bit & literal;
6160           if (lit)
6161             {
6162               // lit != 0 => result = 1
6163               if (AOP_TYPE (result) == AOP_CRY)
6164                 {
6165                   if (size)
6166                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6167                   else if (ifx)
6168                     continueIfTrue (ifx);
6169                   goto release;
6170                 }
6171               emitcode ("setb", "c");
6172             }
6173           else
6174             {
6175               // lit == 0 => result = left
6176               if (size && sameRegs (AOP (result), AOP (left)))
6177                 goto release;
6178               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6179             }
6180         }
6181       else
6182         {
6183           if (AOP_TYPE (right) == AOP_CRY)
6184             {
6185               // c = bit | bit;
6186               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6187               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6188             }
6189           else
6190             {
6191               // c = bit | val;
6192               symbol *tlbl = newiTempLabel (NULL);
6193               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6194                 emitcode ("setb", "c");
6195               emitcode ("jb", "%s,!tlabel",
6196                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6197               toBoolean (right);
6198               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6199               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6200                 {
6201                   jmpTrueOrFalse (ifx, tlbl);
6202                   goto release;
6203                 }
6204               else
6205                 {
6206                   CLRC;
6207                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6208                 }
6209             }
6210         }
6211       // bit = c
6212       // val = c
6213       if (size)
6214         outBitC (result);
6215       // if(bit | ...)
6216       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6217         genIfxJump (ifx, "c");
6218       goto release;
6219     }
6220
6221   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6222   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6223   if ((AOP_TYPE (right) == AOP_LIT) &&
6224       (AOP_TYPE (result) == AOP_CRY) &&
6225       (AOP_TYPE (left) != AOP_CRY))
6226     {
6227       if (lit)
6228         {
6229           // result = 1
6230           if (size)
6231             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6232           else
6233             continueIfTrue (ifx);
6234           goto release;
6235         }
6236       else
6237         {
6238           // lit = 0, result = boolean(left)
6239           if (size)
6240             emitcode ("setb", "c");
6241           toBoolean (right);
6242           if (size)
6243             {
6244               symbol *tlbl = newiTempLabel (NULL);
6245               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6246               CLRC;
6247               emitcode ("", "!tlabeldef", tlbl->key + 100);
6248             }
6249           else
6250             {
6251               genIfxJump (ifx, "a");
6252               goto release;
6253             }
6254         }
6255       outBitC (result);
6256       goto release;
6257     }
6258
6259   /* if left is same as result */
6260   if (sameRegs (AOP (result), AOP (left)))
6261     {
6262       for (; size--; offset++)
6263         {
6264           if (AOP_TYPE (right) == AOP_LIT)
6265             {
6266               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6267                 {
6268                   continue;
6269                 }
6270               else
6271                 {
6272                   if (IS_AOP_PREG (left))
6273                     {
6274                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6275                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6276                       aopPut (AOP (result), "a", offset);
6277                     }
6278                   else
6279                     {
6280                       emitcode ("orl", "%s,%s",
6281                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6282                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6283                     }
6284                 }
6285             }
6286           else
6287             {
6288               if (AOP_TYPE (left) == AOP_ACC)
6289                 {
6290                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6291                 }
6292               else
6293                 {
6294                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6295                   if (IS_AOP_PREG (left))
6296                     {
6297                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6298                       aopPut (AOP (result), "a", offset);
6299                     }
6300                   else
6301                     {
6302                       emitcode ("orl", "%s,a",
6303                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6304                     }
6305                 }
6306             }
6307         }
6308     }
6309   else
6310     {
6311       // left & result in different registers
6312       if (AOP_TYPE (result) == AOP_CRY)
6313         {
6314           // result = bit
6315           // if(size), result in bit
6316           // if(!size && ifx), conditional oper: if(left | right)
6317           symbol *tlbl = newiTempLabel (NULL);
6318           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6319           if (size)
6320             emitcode ("setb", "c");
6321           while (sizer--)
6322             {
6323               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6324                 emitcode ("orl", "a,%s",
6325                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6326               } else {
6327                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6328                 emitcode ("orl", "a,%s",
6329                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6330               }
6331               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6332               offset++;
6333             }
6334           if (size)
6335             {
6336               CLRC;
6337               emitcode ("", "!tlabeldef", tlbl->key + 100);
6338               outBitC (result);
6339             }
6340           else if (ifx)
6341             jmpTrueOrFalse (ifx, tlbl);
6342         }
6343       else
6344         {
6345             _startLazyDPSEvaluation();
6346           for (; (size--); offset++)
6347             {
6348               // normal case
6349               // result = left & right
6350               if (AOP_TYPE (right) == AOP_LIT)
6351                 {
6352                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6353                     {
6354                       aopPut (AOP (result),
6355                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6356                               offset);
6357                       continue;
6358                     }
6359                   D (emitcode (";", "better literal OR."););
6360                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6361                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6362                                                     FALSE, FALSE, FALSE));
6363
6364                 }
6365               else
6366                 {
6367                   // faster than result <- left, anl result,right
6368                   // and better if result is SFR
6369                   if (AOP_TYPE (left) == AOP_ACC)
6370                     {
6371                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6372                                                        FALSE, FALSE, FALSE));
6373                     }
6374                   else
6375                     {
6376                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6377                         
6378                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6379                       {
6380                           emitcode("mov", "b,a");
6381                           rOp = "b";
6382                       }
6383                         
6384                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6385                       emitcode ("orl", "a,%s", rOp);
6386                     }
6387                 }
6388               aopPut (AOP (result), "a", offset);
6389             }
6390             _endLazyDPSEvaluation();
6391         }
6392     }
6393
6394 release:
6395   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6396   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6397   freeAsmop (result, NULL, ic, TRUE);
6398 }
6399
6400 /*-----------------------------------------------------------------*/
6401 /* genXor - code for xclusive or                                   */
6402 /*-----------------------------------------------------------------*/
6403 static void
6404 genXor (iCode * ic, iCode * ifx)
6405 {
6406   operand *left, *right, *result;
6407   int size, offset = 0;
6408   unsigned long lit = 0L;
6409   bool pushResult;
6410
6411   D (emitcode (";", "genXor "););
6412
6413   AOP_OP_3_NOFATAL (ic, pushResult);
6414   AOP_SET_LOCALS (ic);
6415
6416   if (pushResult)
6417   {
6418       genFarFarLogicOp(ic, "xrl");
6419       return;
6420   }  
6421
6422 #ifdef DEBUG_TYPE
6423   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6424             AOP_TYPE (result),
6425             AOP_TYPE (left), AOP_TYPE (right));
6426   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6427             AOP_SIZE (result),
6428             AOP_SIZE (left), AOP_SIZE (right));
6429 #endif
6430
6431   /* if left is a literal & right is not ||
6432      if left needs acc & right does not */
6433   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6434 #ifdef LOGIC_OPS_BROKEN      
6435       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6436 #endif
6437      )
6438     {
6439       operand *tmp = right;
6440       right = left;
6441       left = tmp;
6442     }
6443
6444   /* if result = right then exchange them */
6445   if (sameRegs (AOP (result), AOP (right)))
6446     {
6447       operand *tmp = right;
6448       right = left;
6449       left = tmp;
6450     }
6451
6452   /* if right is bit then exchange them */
6453   if (AOP_TYPE (right) == AOP_CRY &&
6454       AOP_TYPE (left) != AOP_CRY)
6455     {
6456       operand *tmp = right;
6457       right = left;
6458       left = tmp;
6459     }
6460   if (AOP_TYPE (right) == AOP_LIT)
6461     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6462
6463   size = AOP_SIZE (result);
6464
6465   // if(bit ^ yy)
6466   // xx = bit ^ yy;
6467   if (AOP_TYPE (left) == AOP_CRY)
6468     {
6469       if (AOP_TYPE (right) == AOP_LIT)
6470         {
6471           // c = bit & literal;
6472           if (lit >> 1)
6473             {
6474               // lit>>1  != 0 => result = 1
6475               if (AOP_TYPE (result) == AOP_CRY)
6476                 {
6477                   if (size)
6478                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6479                   else if (ifx)
6480                     continueIfTrue (ifx);
6481                   goto release;
6482                 }
6483               emitcode ("setb", "c");
6484             }
6485           else
6486             {
6487               // lit == (0 or 1)
6488               if (lit == 0)
6489                 {
6490                   // lit == 0, result = left
6491                   if (size && sameRegs (AOP (result), AOP (left)))
6492                     goto release;
6493                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6494                 }
6495               else
6496                 {
6497                   // lit == 1, result = not(left)
6498                   if (size && sameRegs (AOP (result), AOP (left)))
6499                     {
6500                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6501                       goto release;
6502                     }
6503                   else
6504                     {
6505                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6506                       emitcode ("cpl", "c");
6507                     }
6508                 }
6509             }
6510
6511         }
6512       else
6513         {
6514           // right != literal
6515           symbol *tlbl = newiTempLabel (NULL);
6516           if (AOP_TYPE (right) == AOP_CRY)
6517             {
6518               // c = bit ^ bit;
6519               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6520             }
6521           else
6522             {
6523               int sizer = AOP_SIZE (right);
6524               // c = bit ^ val
6525               // if val>>1 != 0, result = 1
6526               emitcode ("setb", "c");
6527               while (sizer)
6528                 {
6529                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6530                   if (sizer == 1)
6531                     // test the msb of the lsb
6532                     emitcode ("anl", "a,#0xfe");
6533                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6534                   sizer--;
6535                 }
6536               // val = (0,1)
6537               emitcode ("rrc", "a");
6538             }
6539           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6540           emitcode ("cpl", "c");
6541           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6542         }
6543       // bit = c
6544       // val = c
6545       if (size)
6546         outBitC (result);
6547       // if(bit | ...)
6548       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6549         genIfxJump (ifx, "c");
6550       goto release;
6551     }
6552
6553   if (sameRegs (AOP (result), AOP (left)))
6554     {
6555       /* if left is same as result */
6556       for (; size--; offset++)
6557         {
6558           if (AOP_TYPE (right) == AOP_LIT)
6559             {
6560               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6561                 continue;
6562               else if (IS_AOP_PREG (left))
6563                 {
6564                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6565                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6566                   aopPut (AOP (result), "a", offset);
6567                 }
6568               else
6569                 emitcode ("xrl", "%s,%s",
6570                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6571                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6572             }
6573           else
6574             {
6575               if (AOP_TYPE (left) == AOP_ACC)
6576                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6577               else
6578                 {
6579                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6580                   if (IS_AOP_PREG (left))
6581                     {
6582                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6583                       aopPut (AOP (result), "a", offset);
6584                     }
6585                   else
6586                     emitcode ("xrl", "%s,a",
6587                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6588                 }
6589             }
6590         }
6591     }
6592   else
6593     {
6594       // left & result in different registers
6595       if (AOP_TYPE (result) == AOP_CRY)
6596         {
6597           // result = bit
6598           // if(size), result in bit
6599           // if(!size && ifx), conditional oper: if(left ^ right)
6600           symbol *tlbl = newiTempLabel (NULL);
6601           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6602                   
6603           if (size)
6604             emitcode ("setb", "c");
6605           while (sizer--)
6606             {
6607               if ((AOP_TYPE (right) == AOP_LIT) &&
6608                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6609                 {
6610                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6611                 }
6612               else
6613                 {
6614                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6615                     emitcode ("xrl", "a,%s",
6616                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6617                   } else {
6618                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6619                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6620                       {
6621                           emitcode("mov", "b,a");
6622                           rOp = "b";
6623                       }
6624                         
6625                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6626                       emitcode ("xrl", "a,%s", rOp);                  
6627                   }
6628                 }
6629               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6630               offset++;
6631             }
6632           if (size)
6633             {
6634               CLRC;
6635               emitcode ("", "!tlabeldef", tlbl->key + 100);
6636               outBitC (result);
6637             }
6638           else if (ifx)
6639             jmpTrueOrFalse (ifx, tlbl);
6640         }
6641       else
6642         {
6643         for (; (size--); offset++)
6644           {
6645             // normal case
6646             // result = left & right
6647             if (AOP_TYPE (right) == AOP_LIT)
6648               {
6649                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6650                   {
6651                     aopPut (AOP (result),
6652                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6653                             offset);
6654                     continue;
6655                   }
6656                 D (emitcode (";", "better literal XOR."););
6657                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6658                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6659                                                   FALSE, FALSE, FALSE));
6660               }
6661             else
6662               {
6663                 // faster than result <- left, anl result,right
6664                 // and better if result is SFR
6665                 if (AOP_TYPE (left) == AOP_ACC)
6666                   {
6667                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6668                                                      FALSE, FALSE, FALSE));
6669                   }
6670                 else
6671                   {
6672                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6673                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6674                       {
6675                           emitcode("mov", "b,a");
6676                           rOp = "b";
6677                       }
6678                         
6679                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6680                       emitcode ("xrl", "a,%s", rOp);
6681                   }
6682               }
6683             aopPut (AOP (result), "a", offset);
6684           }
6685         }
6686         
6687     }
6688
6689 release:
6690   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6691   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6692   freeAsmop (result, NULL, ic, TRUE);
6693 }
6694
6695 /*-----------------------------------------------------------------*/
6696 /* genInline - write the inline code out                           */
6697 /*-----------------------------------------------------------------*/
6698 static void
6699 genInline (iCode * ic)
6700 {
6701   char *buffer, *bp, *bp1;
6702
6703   D (emitcode (";", "genInline ");
6704     );
6705
6706   _G.inLine += (!options.asmpeep);
6707
6708   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6709   strcpy (buffer, IC_INLINE (ic));
6710
6711   /* emit each line as a code */
6712   while (*bp)
6713     {
6714       if (*bp == '\n')
6715         {
6716           *bp++ = '\0';
6717           emitcode (bp1, "");
6718           bp1 = bp;
6719         }
6720       else
6721         {
6722           if (*bp == ':')
6723             {
6724               bp++;
6725               *bp = '\0';
6726               bp++;
6727               emitcode (bp1, "");
6728               bp1 = bp;
6729             }
6730           else
6731             bp++;
6732         }
6733     }
6734   if (bp1 != bp)
6735     emitcode (bp1, "");
6736   /*     emitcode("",buffer); */
6737   _G.inLine -= (!options.asmpeep);
6738 }
6739
6740 /*-----------------------------------------------------------------*/
6741 /* genRRC - rotate right with carry                                */
6742 /*-----------------------------------------------------------------*/
6743 static void
6744 genRRC (iCode * ic)
6745 {
6746   operand *left, *result;
6747   int size, offset = 0;
6748   char *l;
6749
6750   D (emitcode (";", "genRRC ");
6751     );
6752
6753   /* rotate right with carry */
6754   left = IC_LEFT (ic);
6755   result = IC_RESULT (ic);
6756   aopOp (left, ic, FALSE, FALSE);
6757   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6758
6759   /* move it to the result */
6760   size = AOP_SIZE (result);
6761   offset = size - 1;
6762   CLRC;
6763
6764   _startLazyDPSEvaluation ();
6765   while (size--)
6766     {
6767       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6768       MOVA (l);
6769       emitcode ("rrc", "a");
6770       if (AOP_SIZE (result) > 1)
6771         aopPut (AOP (result), "a", offset--);
6772     }
6773   _endLazyDPSEvaluation ();
6774
6775   /* now we need to put the carry into the
6776      highest order byte of the result */
6777   if (AOP_SIZE (result) > 1)
6778     {
6779       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6780       MOVA (l);
6781     }
6782   emitcode ("mov", "acc.7,c");
6783   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6784   freeAsmop (left, NULL, ic, TRUE);
6785   freeAsmop (result, NULL, ic, TRUE);
6786 }
6787
6788 /*-----------------------------------------------------------------*/
6789 /* genRLC - generate code for rotate left with carry               */
6790 /*-----------------------------------------------------------------*/
6791 static void
6792 genRLC (iCode * ic)
6793 {
6794   operand *left, *result;
6795   int size, offset = 0;
6796   char *l;
6797
6798   D (emitcode (";", "genRLC ");
6799     );
6800
6801   /* rotate right with carry */
6802   left = IC_LEFT (ic);
6803   result = IC_RESULT (ic);
6804   aopOp (left, ic, FALSE, FALSE);
6805   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6806
6807   /* move it to the result */
6808   size = AOP_SIZE (result);
6809   offset = 0;
6810   if (size--)
6811     {
6812       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6813       MOVA (l);
6814       emitcode ("add", "a,acc");
6815       if (AOP_SIZE (result) > 1)
6816         {
6817           aopPut (AOP (result), "a", offset++);
6818         }
6819
6820       _startLazyDPSEvaluation ();
6821       while (size--)
6822         {
6823           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6824           MOVA (l);
6825           emitcode ("rlc", "a");
6826           if (AOP_SIZE (result) > 1)
6827             aopPut (AOP (result), "a", offset++);
6828         }
6829       _endLazyDPSEvaluation ();
6830     }
6831   /* now we need to put the carry into the
6832      highest order byte of the result */
6833   if (AOP_SIZE (result) > 1)
6834     {
6835       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6836       MOVA (l);
6837     }
6838   emitcode ("mov", "acc.0,c");
6839   aopPut (AOP (result), "a", 0);
6840   freeAsmop (left, NULL, ic, TRUE);
6841   freeAsmop (result, NULL, ic, TRUE);
6842 }
6843
6844 /*-----------------------------------------------------------------*/
6845 /* genGetHbit - generates code get highest order bit               */
6846 /*-----------------------------------------------------------------*/
6847 static void
6848 genGetHbit (iCode * ic)
6849 {
6850   operand *left, *result;
6851   left = IC_LEFT (ic);
6852   result = IC_RESULT (ic);
6853   aopOp (left, ic, FALSE, FALSE);
6854   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6855
6856   D (emitcode (";", "genGetHbit ");
6857     );
6858
6859   /* get the highest order byte into a */
6860   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6861   if (AOP_TYPE (result) == AOP_CRY)
6862     {
6863       emitcode ("rlc", "a");
6864       outBitC (result);
6865     }
6866   else
6867     {
6868       emitcode ("rl", "a");
6869       emitcode ("anl", "a,#0x01");
6870       outAcc (result);
6871     }
6872
6873
6874   freeAsmop (left, NULL, ic, TRUE);
6875   freeAsmop (result, NULL, ic, TRUE);
6876 }
6877
6878 /*-----------------------------------------------------------------*/
6879 /* AccRol - rotate left accumulator by known count                 */
6880 /*-----------------------------------------------------------------*/
6881 static void
6882 AccRol (int shCount)
6883 {
6884   shCount &= 0x0007;            // shCount : 0..7
6885
6886   switch (shCount)
6887     {
6888     case 0:
6889       break;
6890     case 1:
6891       emitcode ("rl", "a");
6892       break;
6893     case 2:
6894       emitcode ("rl", "a");
6895       emitcode ("rl", "a");
6896       break;
6897     case 3:
6898       emitcode ("swap", "a");
6899       emitcode ("rr", "a");
6900       break;
6901     case 4:
6902       emitcode ("swap", "a");
6903       break;
6904     case 5:
6905       emitcode ("swap", "a");
6906       emitcode ("rl", "a");
6907       break;
6908     case 6:
6909       emitcode ("rr", "a");
6910       emitcode ("rr", "a");
6911       break;
6912     case 7:
6913       emitcode ("rr", "a");
6914       break;
6915     }
6916 }
6917
6918 /*-----------------------------------------------------------------*/
6919 /* AccLsh - left shift accumulator by known count                  */
6920 /*-----------------------------------------------------------------*/
6921 static void
6922 AccLsh (int shCount)
6923 {
6924   if (shCount != 0)
6925     {
6926       if (shCount == 1)
6927         emitcode ("add", "a,acc");
6928       else if (shCount == 2)
6929         {
6930           emitcode ("add", "a,acc");
6931           emitcode ("add", "a,acc");
6932         }
6933       else
6934         {
6935           /* rotate left accumulator */
6936           AccRol (shCount);
6937           /* and kill the lower order bits */
6938           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
6939         }
6940     }
6941 }
6942
6943 /*-----------------------------------------------------------------*/
6944 /* AccRsh - right shift accumulator by known count                 */
6945 /*-----------------------------------------------------------------*/
6946 static void
6947 AccRsh (int shCount)
6948 {
6949   if (shCount != 0)
6950     {
6951       if (shCount == 1)
6952         {
6953           CLRC;
6954           emitcode ("rrc", "a");
6955         }
6956       else
6957         {
6958           /* rotate right accumulator */
6959           AccRol (8 - shCount);
6960           /* and kill the higher order bits */
6961           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6962         }
6963     }
6964 }
6965
6966 #ifdef BETTER_LITERAL_SHIFT
6967 /*-----------------------------------------------------------------*/
6968 /* AccSRsh - signed right shift accumulator by known count                 */
6969 /*-----------------------------------------------------------------*/
6970 static void
6971 AccSRsh (int shCount)
6972 {
6973   symbol *tlbl;
6974   if (shCount != 0)
6975     {
6976       if (shCount == 1)
6977         {
6978           emitcode ("mov", "c,acc.7");
6979           emitcode ("rrc", "a");
6980         }
6981       else if (shCount == 2)
6982         {
6983           emitcode ("mov", "c,acc.7");
6984           emitcode ("rrc", "a");
6985           emitcode ("mov", "c,acc.7");
6986           emitcode ("rrc", "a");
6987         }
6988       else
6989         {
6990           tlbl = newiTempLabel (NULL);
6991           /* rotate right accumulator */
6992           AccRol (8 - shCount);
6993           /* and kill the higher order bits */
6994           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
6995           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
6996           emitcode ("orl", "a,#!constbyte",
6997                     (unsigned char) ~SRMask[shCount]);
6998           emitcode ("", "!tlabeldef", tlbl->key + 100);
6999         }
7000     }
7001 }
7002 #endif
7003
7004 #ifdef BETTER_LITERAL_SHIFT
7005 /*-----------------------------------------------------------------*/
7006 /* shiftR1Left2Result - shift right one byte from left to result   */
7007 /*-----------------------------------------------------------------*/
7008 static void
7009 shiftR1Left2Result (operand * left, int offl,
7010                     operand * result, int offr,
7011                     int shCount, int sign)
7012 {
7013   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7014   /* shift right accumulator */
7015   if (sign)
7016     AccSRsh (shCount);
7017   else
7018     AccRsh (shCount);
7019   aopPut (AOP (result), "a", offr);
7020 }
7021 #endif
7022
7023 #ifdef BETTER_LITERAL_SHIFT
7024 /*-----------------------------------------------------------------*/
7025 /* shiftL1Left2Result - shift left one byte from left to result    */
7026 /*-----------------------------------------------------------------*/
7027 static void
7028 shiftL1Left2Result (operand * left, int offl,
7029                     operand * result, int offr, int shCount)
7030 {
7031   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7032   /* shift left accumulator */
7033   AccLsh (shCount);
7034   aopPut (AOP (result), "a", offr);
7035 }
7036 #endif
7037
7038 #ifdef BETTER_LITERAL_SHIFT
7039 /*-----------------------------------------------------------------*/
7040 /* movLeft2Result - move byte from left to result                  */
7041 /*-----------------------------------------------------------------*/
7042 static void
7043 movLeft2Result (operand * left, int offl,
7044                 operand * result, int offr, int sign)
7045 {
7046   char *l;
7047   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7048   {
7049       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7050
7051       if (*l == '@' && (IS_AOP_PREG (result)))
7052       {
7053           emitcode ("mov", "a,%s", l);
7054           aopPut (AOP (result), "a", offr);
7055       }
7056       else
7057       {
7058           if (!sign)
7059           {
7060             aopPut (AOP (result), l, offr);
7061           }
7062           else
7063             {
7064               /* MSB sign in acc.7 ! */
7065               if (getDataSize (left) == offl + 1)
7066                 {
7067                   emitcode ("mov", "a,%s", l);
7068                   aopPut (AOP (result), "a", offr);
7069                 }
7070             }
7071       }
7072   }
7073 }
7074 #endif
7075
7076 #ifdef BETTER_LITERAL_SHIFT
7077 /*-----------------------------------------------------------------*/
7078 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7079 /*-----------------------------------------------------------------*/
7080 static void
7081 AccAXRrl1 (char *x)
7082 {
7083   emitcode ("rrc", "a");
7084   emitcode ("xch", "a,%s", x);
7085   emitcode ("rrc", "a");
7086   emitcode ("xch", "a,%s", x);
7087 }
7088 #endif
7089
7090 #ifdef BETTER_LITERAL_SHIFT
7091 //REMOVE ME!!!
7092 /*-----------------------------------------------------------------*/
7093 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7094 /*-----------------------------------------------------------------*/
7095 static void
7096 AccAXLrl1 (char *x)
7097 {
7098   emitcode ("xch", "a,%s", x);
7099   emitcode ("rlc", "a");
7100   emitcode ("xch", "a,%s", x);
7101   emitcode ("rlc", "a");
7102 }
7103 #endif
7104
7105 #ifdef BETTER_LITERAL_SHIFT
7106 /*-----------------------------------------------------------------*/
7107 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7108 /*-----------------------------------------------------------------*/
7109 static void
7110 AccAXLsh1 (char *x)
7111 {
7112   emitcode ("xch", "a,%s", x);
7113   emitcode ("add", "a,acc");
7114   emitcode ("xch", "a,%s", x);
7115   emitcode ("rlc", "a");
7116 }
7117 #endif
7118
7119 #ifdef BETTER_LITERAL_SHIFT
7120 /*-----------------------------------------------------------------*/
7121 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7122 /*-----------------------------------------------------------------*/
7123 static void
7124 AccAXLsh (char *x, int shCount)
7125 {
7126   switch (shCount)
7127     {
7128     case 0:
7129       break;
7130     case 1:
7131       AccAXLsh1 (x);
7132       break;
7133     case 2:
7134       AccAXLsh1 (x);
7135       AccAXLsh1 (x);
7136       break;
7137     case 3:
7138     case 4:
7139     case 5:                     // AAAAABBB:CCCCCDDD
7140
7141       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7142
7143       emitcode ("anl", "a,#!constbyte",
7144                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7145
7146       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7147
7148       AccRol (shCount);         // DDDCCCCC:BBB00000
7149
7150       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7151
7152       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7153
7154       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7155
7156       emitcode ("anl", "a,#!constbyte",
7157                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7158
7159       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7160
7161       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7162
7163       break;
7164     case 6:                     // AAAAAABB:CCCCCCDD
7165       emitcode ("anl", "a,#!constbyte",
7166                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7167       emitcode ("mov", "c,acc.0");      // c = B
7168       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7169 #if 0
7170       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7171       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7172 #else
7173       emitcode("rrc","a"); 
7174       emitcode("xch","a,%s", x); 
7175       emitcode("rrc","a"); 
7176       emitcode("mov","c,acc.0"); //<< get correct bit 
7177       emitcode("xch","a,%s", x); 
7178
7179       emitcode("rrc","a"); 
7180       emitcode("xch","a,%s", x); 
7181       emitcode("rrc","a"); 
7182       emitcode("xch","a,%s", x); 
7183 #endif
7184       break;
7185     case 7:                     // a:x <<= 7
7186
7187       emitcode ("anl", "a,#!constbyte",
7188                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7189
7190       emitcode ("mov", "c,acc.0");      // c = B
7191
7192       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7193
7194       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7195
7196       break;
7197     default:
7198       break;
7199     }
7200 }
7201 #endif
7202
7203 #ifdef BETTER_LITERAL_SHIFT
7204 //REMOVE ME!!!
7205 /*-----------------------------------------------------------------*/
7206 /* AccAXRsh - right shift a:x known count (0..7)                   */
7207 /*-----------------------------------------------------------------*/
7208 static void
7209 AccAXRsh (char *x, int shCount)
7210 {
7211   switch (shCount)
7212     {
7213     case 0:
7214       break;
7215     case 1:
7216       CLRC;
7217       AccAXRrl1 (x);            // 0->a:x
7218
7219       break;
7220     case 2:
7221       CLRC;
7222       AccAXRrl1 (x);            // 0->a:x
7223
7224       CLRC;
7225       AccAXRrl1 (x);            // 0->a:x
7226
7227       break;
7228     case 3:
7229     case 4:
7230     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7231
7232       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7233
7234       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7235
7236       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7237
7238       emitcode ("anl", "a,#!constbyte",
7239                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7240
7241       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7242
7243       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7244
7245       emitcode ("anl", "a,#!constbyte",
7246                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7247
7248       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7249
7250       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7251
7252       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7253
7254       break;
7255     case 6:                     // AABBBBBB:CCDDDDDD
7256
7257       emitcode ("mov", "c,acc.7");
7258       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7259
7260       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7261
7262       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7263
7264       emitcode ("anl", "a,#!constbyte",
7265                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7266
7267       break;
7268     case 7:                     // ABBBBBBB:CDDDDDDD
7269
7270       emitcode ("mov", "c,acc.7");      // c = A
7271
7272       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7273
7274       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7275
7276       emitcode ("anl", "a,#!constbyte",
7277                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7278
7279       break;
7280     default:
7281       break;
7282     }
7283 }
7284 #endif
7285
7286 #ifdef BETTER_LITERAL_SHIFT
7287 /*-----------------------------------------------------------------*/
7288 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7289 /*-----------------------------------------------------------------*/
7290 static void
7291 AccAXRshS (char *x, int shCount)
7292 {
7293   symbol *tlbl;
7294   switch (shCount)
7295     {
7296     case 0:
7297       break;
7298     case 1:
7299       emitcode ("mov", "c,acc.7");
7300       AccAXRrl1 (x);            // s->a:x
7301
7302       break;
7303     case 2:
7304       emitcode ("mov", "c,acc.7");
7305       AccAXRrl1 (x);            // s->a:x
7306
7307       emitcode ("mov", "c,acc.7");
7308       AccAXRrl1 (x);            // s->a:x
7309
7310       break;
7311     case 3:
7312     case 4:
7313     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7314
7315       tlbl = newiTempLabel (NULL);
7316       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7317
7318       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7319
7320       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7321
7322       emitcode ("anl", "a,#!constbyte",
7323                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7324
7325       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7326
7327       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7328
7329       emitcode ("anl", "a,#!constbyte",
7330                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7331
7332       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7333
7334       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7335
7336       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7337
7338       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7339       emitcode ("orl", "a,#!constbyte",
7340                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7341
7342       emitcode ("", "!tlabeldef", tlbl->key + 100);
7343       break;                    // SSSSAAAA:BBBCCCCC
7344
7345     case 6:                     // AABBBBBB:CCDDDDDD
7346
7347       tlbl = newiTempLabel (NULL);
7348       emitcode ("mov", "c,acc.7");
7349       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7350
7351       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7352
7353       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7354
7355       emitcode ("anl", "a,#!constbyte",
7356                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7357
7358       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7359       emitcode ("orl", "a,#!constbyte",
7360                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7361
7362       emitcode ("", "!tlabeldef", tlbl->key + 100);
7363       break;
7364     case 7:                     // ABBBBBBB:CDDDDDDD
7365
7366       tlbl = newiTempLabel (NULL);
7367       emitcode ("mov", "c,acc.7");      // c = A
7368
7369       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7370
7371       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7372
7373       emitcode ("anl", "a,#!constbyte",
7374                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7375
7376       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7377       emitcode ("orl", "a,#!constbyte",
7378                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7379
7380       emitcode ("", "!tlabeldef", tlbl->key + 100);
7381       break;
7382     default:
7383       break;
7384     }
7385 }
7386 #endif
7387
7388 #ifdef BETTER_LITERAL_SHIFT
7389 static void
7390 _loadLeftIntoAx(char    **lsb, 
7391                 operand *left, 
7392                 operand *result,
7393                 int     offl,
7394                 int     offr)
7395 {
7396   // Get the initial value from left into a pair of registers.
7397   // MSB must be in A, LSB can be any register.
7398   //
7399   // If the result is held in registers, it is an optimization
7400   // if the LSB can be held in the register which will hold the,
7401   // result LSB since this saves us from having to copy it into
7402   // the result following AccAXLsh.
7403   //
7404   // If the result is addressed indirectly, this is not a gain.
7405   if (AOP_NEEDSACC(result))
7406   {
7407        char *leftByte;
7408        
7409        _startLazyDPSEvaluation();
7410       if (AOP_TYPE(left) == AOP_DPTR2)
7411        {
7412            // Get MSB in A.
7413            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7414            // get LSB in DP2_RESULT_REG.
7415            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7416            assert(!strcmp(leftByte, DP2_RESULT_REG));
7417        }
7418        else
7419        {
7420            // get LSB into DP2_RESULT_REG
7421            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7422            if (strcmp(leftByte, DP2_RESULT_REG))
7423            {
7424                TR_AP("#7");
7425                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7426            }
7427            // And MSB in A.
7428            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7429            assert(strcmp(leftByte, DP2_RESULT_REG));
7430            MOVA(leftByte);
7431        }
7432        _endLazyDPSEvaluation();
7433        *lsb = DP2_RESULT_REG;
7434   }
7435   else
7436   {
7437       if (sameRegs (AOP (result), AOP (left)) &&
7438         ((offl + MSB16) == offr))
7439       {
7440           /* don't crash result[offr] */
7441           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7442           emitcode ("xch", "a,%s", 
7443                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7444       }
7445       else
7446       {
7447           movLeft2Result (left, offl, result, offr, 0);
7448           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7449       }
7450       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7451       assert(strcmp(*lsb,"a"));      
7452   }
7453 }
7454
7455 static void
7456 _storeAxResults(char    *lsb,
7457                 operand *result,
7458                 int     offr)
7459 {
7460   _startLazyDPSEvaluation();
7461   if (AOP_NEEDSACC(result))
7462   {
7463       /* We have to explicitly update the result LSB.
7464        */
7465       emitcode("xch","a,%s", lsb);
7466       aopPut(AOP(result), "a", offr);
7467       emitcode("mov","a,%s", lsb);
7468   }
7469   if (getDataSize (result) > 1)
7470   {
7471       aopPut (AOP (result), "a", offr + MSB16);
7472   }
7473   _endLazyDPSEvaluation();
7474 }
7475
7476 /*-----------------------------------------------------------------*/
7477 /* shiftL2Left2Result - shift left two bytes from left to result   */
7478 /*-----------------------------------------------------------------*/
7479 static void
7480 shiftL2Left2Result (operand * left, int offl,
7481                     operand * result, int offr, int shCount)
7482 {
7483   char *lsb;
7484
7485   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7486   
7487   AccAXLsh (lsb, shCount);
7488   
7489   _storeAxResults(lsb, result, offr);
7490 }
7491 #endif
7492
7493 #ifdef BETTER_LITERAL_SHIFT
7494 /*-----------------------------------------------------------------*/
7495 /* shiftR2Left2Result - shift right two bytes from left to result  */
7496 /*-----------------------------------------------------------------*/
7497 static void
7498 shiftR2Left2Result (operand * left, int offl,
7499                     operand * result, int offr,
7500                     int shCount, int sign)
7501 {
7502   char *lsb;
7503   
7504   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7505   
7506   /* a:x >> shCount (x = lsb(result)) */
7507   if (sign)
7508   {
7509      AccAXRshS(lsb, shCount);
7510   }
7511   else
7512   {
7513     AccAXRsh(lsb, shCount);
7514   }
7515   
7516   _storeAxResults(lsb, result, offr);
7517 }
7518 #endif
7519
7520 #if 0
7521 //REMOVE ME!!!
7522 /*-----------------------------------------------------------------*/
7523 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7524 /*-----------------------------------------------------------------*/
7525 static void
7526 shiftLLeftOrResult (operand * left, int offl,
7527                     operand * result, int offr, int shCount)
7528 {
7529   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7530   /* shift left accumulator */
7531   AccLsh (shCount);
7532   /* or with result */
7533   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7534   /* back to result */
7535   aopPut (AOP (result), "a", offr);
7536 }
7537 #endif
7538
7539 #if 0
7540 //REMOVE ME!!!
7541 /*-----------------------------------------------------------------*/
7542 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7543 /*-----------------------------------------------------------------*/
7544 static void
7545 shiftRLeftOrResult (operand * left, int offl,
7546                     operand * result, int offr, int shCount)
7547 {
7548   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7549   /* shift right accumulator */
7550   AccRsh (shCount);
7551   /* or with result */
7552   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7553   /* back to result */
7554   aopPut (AOP (result), "a", offr);
7555 }
7556 #endif
7557
7558 #ifdef BETTER_LITERAL_SHIFT
7559 /*-----------------------------------------------------------------*/
7560 /* genlshOne - left shift a one byte quantity by known count       */
7561 /*-----------------------------------------------------------------*/
7562 static void
7563 genlshOne (operand * result, operand * left, int shCount)
7564 {
7565   D (emitcode (";", "genlshOne "););
7566   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7567 }
7568 #endif
7569
7570 #ifdef BETTER_LITERAL_SHIFT
7571 /*-----------------------------------------------------------------*/
7572 /* genlshTwo - left shift two bytes by known amount != 0           */
7573 /*-----------------------------------------------------------------*/
7574 static void
7575 genlshTwo (operand * result, operand * left, int shCount)
7576 {
7577   int size;
7578
7579   D (emitcode (";", "genlshTwo "););
7580
7581   size = getDataSize (result);
7582
7583   /* if shCount >= 8 */
7584   if (shCount >= 8)
7585   {
7586       shCount -= 8;
7587
7588       _startLazyDPSEvaluation();
7589
7590       if (size > 1)
7591         {
7592           if (shCount)
7593           {
7594             _endLazyDPSEvaluation();
7595             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7596             aopPut (AOP (result), zero, LSB);       
7597           }
7598           else
7599           {
7600             movLeft2Result (left, LSB, result, MSB16, 0);
7601             aopPut (AOP (result), zero, LSB);
7602             _endLazyDPSEvaluation();
7603           }
7604         }
7605         else
7606         {
7607           aopPut (AOP (result), zero, LSB);
7608           _endLazyDPSEvaluation();
7609         }
7610   }
7611
7612   /*  1 <= shCount <= 7 */
7613   else
7614     {
7615       if (size == 1)
7616       {
7617         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7618       }
7619       else
7620       {
7621         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7622       }
7623     }
7624 }
7625 #endif
7626
7627 #if 0
7628 //REMOVE ME!!!
7629 /*-----------------------------------------------------------------*/
7630 /* shiftLLong - shift left one long from left to result            */
7631 /* offl = LSB or MSB16                                             */
7632 /*-----------------------------------------------------------------*/
7633 static void
7634 shiftLLong (operand * left, operand * result, int offr)
7635 {
7636   char *l;
7637   int size = AOP_SIZE (result);
7638
7639   if (size >= LSB + offr)
7640     {
7641       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7642       MOVA (l);
7643       emitcode ("add", "a,acc");
7644       if (sameRegs (AOP (left), AOP (result)) &&
7645           size >= MSB16 + offr && offr != LSB)
7646         emitcode ("xch", "a,%s",
7647                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7648       else
7649         aopPut (AOP (result), "a", LSB + offr);
7650     }
7651
7652   if (size >= MSB16 + offr)
7653     {
7654       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7655         {
7656           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7657           MOVA (l);
7658         }
7659       emitcode ("rlc", "a");
7660       if (sameRegs (AOP (left), AOP (result)) &&
7661           size >= MSB24 + offr && offr != LSB)
7662         emitcode ("xch", "a,%s",
7663                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7664       else
7665         aopPut (AOP (result), "a", MSB16 + offr);
7666     }
7667
7668   if (size >= MSB24 + offr)
7669     {
7670       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7671         {
7672           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7673           MOVA (l);
7674         }
7675       emitcode ("rlc", "a");
7676       if (sameRegs (AOP (left), AOP (result)) &&
7677           size >= MSB32 + offr && offr != LSB)
7678         emitcode ("xch", "a,%s",
7679                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7680       else
7681         aopPut (AOP (result), "a", MSB24 + offr);
7682     }
7683
7684   if (size > MSB32 + offr)
7685     {
7686       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7687         {
7688           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7689           MOVA (l);
7690         }
7691       emitcode ("rlc", "a");
7692       aopPut (AOP (result), "a", MSB32 + offr);
7693     }
7694   if (offr != LSB)
7695     aopPut (AOP (result), zero, LSB);
7696 }
7697 #endif
7698
7699 #if 0
7700 //REMOVE ME!!!
7701 /*-----------------------------------------------------------------*/
7702 /* genlshFour - shift four byte by a known amount != 0             */
7703 /*-----------------------------------------------------------------*/
7704 static void
7705 genlshFour (operand * result, operand * left, int shCount)
7706 {
7707   int size;
7708
7709   D (emitcode (";", "genlshFour ");
7710     );
7711
7712   size = AOP_SIZE (result);
7713
7714   /* if shifting more that 3 bytes */
7715   if (shCount >= 24)
7716     {
7717       shCount -= 24;
7718       if (shCount)
7719         /* lowest order of left goes to the highest
7720            order of the destination */
7721         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7722       else
7723         movLeft2Result (left, LSB, result, MSB32, 0);
7724       aopPut (AOP (result), zero, LSB);
7725       aopPut (AOP (result), zero, MSB16);
7726       aopPut (AOP (result), zero, MSB24);
7727       return;
7728     }
7729
7730   /* more than two bytes */
7731   else if (shCount >= 16)
7732     {
7733       /* lower order two bytes goes to higher order two bytes */
7734       shCount -= 16;
7735       /* if some more remaining */
7736       if (shCount)
7737         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7738       else
7739         {
7740           movLeft2Result (left, MSB16, result, MSB32, 0);
7741           movLeft2Result (left, LSB, result, MSB24, 0);
7742         }
7743       aopPut (AOP (result), zero, MSB16);
7744       aopPut (AOP (result), zero, LSB);
7745       return;
7746     }
7747
7748   /* if more than 1 byte */
7749   else if (shCount >= 8)
7750     {
7751       /* lower order three bytes goes to higher order  three bytes */
7752       shCount -= 8;
7753       if (size == 2)
7754         {
7755           if (shCount)
7756             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7757           else
7758             movLeft2Result (left, LSB, result, MSB16, 0);
7759         }
7760       else
7761         {                       /* size = 4 */
7762           if (shCount == 0)
7763             {
7764               movLeft2Result (left, MSB24, result, MSB32, 0);
7765               movLeft2Result (left, MSB16, result, MSB24, 0);
7766               movLeft2Result (left, LSB, result, MSB16, 0);
7767               aopPut (AOP (result), zero, LSB);
7768             }
7769           else if (shCount == 1)
7770             shiftLLong (left, result, MSB16);
7771           else
7772             {
7773               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7774               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7775               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7776               aopPut (AOP (result), zero, LSB);
7777             }
7778         }
7779     }
7780
7781   /* 1 <= shCount <= 7 */
7782   else if (shCount <= 2)
7783     {
7784       shiftLLong (left, result, LSB);
7785       if (shCount == 2)
7786         shiftLLong (result, result, LSB);
7787     }
7788   /* 3 <= shCount <= 7, optimize */
7789   else
7790     {
7791       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7792       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7793       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7794     }
7795 }
7796 #endif
7797
7798 #ifdef BETTER_LITERAL_SHIFT
7799 /*-----------------------------------------------------------------*/
7800 /* genLeftShiftLiteral - left shifting by known count              */
7801 /*-----------------------------------------------------------------*/
7802 static bool
7803 genLeftShiftLiteral (operand * left,
7804                      operand * right,
7805                      operand * result,
7806                      iCode * ic)
7807 {
7808   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7809   int size;
7810
7811   size = getSize (operandType (result));
7812
7813   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7814
7815   /* We only handle certain easy cases so far. */
7816   if ((shCount != 0)
7817    && (shCount < (size * 8))
7818    && (size != 1)
7819    && (size != 2))
7820   {
7821       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7822       return FALSE;
7823   }
7824
7825   freeAsmop (right, NULL, ic, TRUE);
7826
7827   aopOp(left, ic, FALSE, FALSE);
7828   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7829
7830 #if 1 // debug spew
7831   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7832   {
7833         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7834         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7835         {
7836            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7837         }
7838   }
7839   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7840   {
7841         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7842         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7843         {
7844            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7845         }       
7846   }  
7847 #endif
7848   
7849 #if VIEW_SIZE
7850   emitcode ("; shift left ", "result %d, left %d", size,
7851             AOP_SIZE (left));
7852 #endif
7853
7854   /* I suppose that the left size >= result size */
7855   if (shCount == 0)
7856   {
7857         _startLazyDPSEvaluation();
7858         while (size--)
7859         {
7860           movLeft2Result (left, size, result, size, 0);
7861         }
7862         _endLazyDPSEvaluation();
7863   }
7864   else if (shCount >= (size * 8))
7865   {
7866     _startLazyDPSEvaluation();
7867     while (size--)
7868     {
7869       aopPut (AOP (result), zero, size);
7870     }
7871     _endLazyDPSEvaluation();
7872   }
7873   else
7874   {
7875       switch (size)
7876         {
7877         case 1:
7878           genlshOne (result, left, shCount);
7879           break;
7880
7881         case 2:
7882           genlshTwo (result, left, shCount);
7883           break;
7884 #if 0
7885         case 4:
7886           genlshFour (result, left, shCount);
7887           break;
7888 #endif
7889         default:
7890           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7891           break;
7892         }
7893     }
7894   freeAsmop (left, NULL, ic, TRUE);
7895   freeAsmop (result, NULL, ic, TRUE);
7896   return TRUE;
7897 }
7898 #endif
7899
7900 /*-----------------------------------------------------------------*/
7901 /* genLeftShift - generates code for left shifting                 */
7902 /*-----------------------------------------------------------------*/
7903 static void
7904 genLeftShift (iCode * ic)
7905 {
7906   operand *left, *right, *result;
7907   int size, offset;
7908   char *l;
7909   symbol *tlbl, *tlbl1;
7910
7911   D (emitcode (";", "genLeftShift "););
7912
7913   right = IC_RIGHT (ic);
7914   left = IC_LEFT (ic);
7915   result = IC_RESULT (ic);
7916
7917   aopOp (right, ic, FALSE, FALSE);
7918
7919
7920 #ifdef BETTER_LITERAL_SHIFT
7921   /* if the shift count is known then do it
7922      as efficiently as possible */
7923   if (AOP_TYPE (right) == AOP_LIT)
7924     {
7925       if (genLeftShiftLiteral (left, right, result, ic))
7926       {
7927         return;
7928       }
7929     }
7930 #endif
7931
7932   /* shift count is unknown then we have to form
7933      a loop get the loop count in B : Note: we take
7934      only the lower order byte since shifting
7935      more that 32 bits make no sense anyway, ( the
7936      largest size of an object can be only 32 bits ) */
7937
7938   if (AOP_TYPE (right) == AOP_LIT)
7939   {
7940       /* Really should be handled by genLeftShiftLiteral,
7941        * but since I'm too lazy to fix that today, at least we can make
7942        * some small improvement.
7943        */
7944        emitcode("mov", "b,#!constbyte",
7945                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7946   }
7947   else
7948   {
7949         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7950         emitcode ("inc", "b");
7951   }
7952   freeAsmop (right, NULL, ic, TRUE);
7953   aopOp (left, ic, FALSE, FALSE);
7954   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7955
7956   /* now move the left to the result if they are not the
7957      same */
7958   if (!sameRegs (AOP (left), AOP (result)) &&
7959       AOP_SIZE (result) > 1)
7960     {
7961
7962       size = AOP_SIZE (result);
7963       offset = 0;
7964       _startLazyDPSEvaluation ();
7965       while (size--)
7966         {
7967           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7968           if (*l == '@' && (IS_AOP_PREG (result)))
7969             {
7970
7971               emitcode ("mov", "a,%s", l);
7972               aopPut (AOP (result), "a", offset);
7973             }
7974           else
7975             aopPut (AOP (result), l, offset);
7976           offset++;
7977         }
7978       _endLazyDPSEvaluation ();
7979     }
7980
7981   tlbl = newiTempLabel (NULL);
7982   size = AOP_SIZE (result);
7983   offset = 0;
7984   tlbl1 = newiTempLabel (NULL);
7985
7986   /* if it is only one byte then */
7987   if (size == 1)
7988     {
7989       symbol *tlbl1 = newiTempLabel (NULL);
7990
7991       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7992       MOVA (l);
7993       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
7994       emitcode ("", "!tlabeldef", tlbl->key + 100);
7995       emitcode ("add", "a,acc");
7996       emitcode ("", "!tlabeldef", tlbl1->key + 100);
7997       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
7998       aopPut (AOP (result), "a", 0);
7999       goto release;
8000     }
8001
8002   reAdjustPreg (AOP (result));
8003
8004   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8005   emitcode ("", "!tlabeldef", tlbl->key + 100);
8006   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8007   MOVA (l);
8008   emitcode ("add", "a,acc");
8009   aopPut (AOP (result), "a", offset++);
8010   _startLazyDPSEvaluation ();
8011   while (--size)
8012     {
8013       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8014       MOVA (l);
8015       emitcode ("rlc", "a");
8016       aopPut (AOP (result), "a", offset++);
8017     }
8018   _endLazyDPSEvaluation ();
8019   reAdjustPreg (AOP (result));
8020
8021   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8022   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8023 release:
8024   freeAsmop (left, NULL, ic, TRUE);
8025   freeAsmop (result, NULL, ic, TRUE);
8026 }
8027
8028 #ifdef BETTER_LITERAL_SHIFT
8029 /*-----------------------------------------------------------------*/
8030 /* genrshOne - right shift a one byte quantity by known count      */
8031 /*-----------------------------------------------------------------*/
8032 static void
8033 genrshOne (operand * result, operand * left,
8034            int shCount, int sign)
8035 {
8036   D (emitcode (";", "genrshOne"););
8037   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8038 }
8039 #endif
8040
8041 #ifdef BETTER_LITERAL_SHIFT
8042 /*-----------------------------------------------------------------*/
8043 /* genrshTwo - right shift two bytes by known amount != 0          */
8044 /*-----------------------------------------------------------------*/
8045 static void
8046 genrshTwo (operand * result, operand * left,
8047            int shCount, int sign)
8048 {
8049   D (emitcode (";", "genrshTwo"););
8050
8051   /* if shCount >= 8 */
8052   if (shCount >= 8)
8053     {
8054       shCount -= 8;
8055       _startLazyDPSEvaluation();
8056       if (shCount)
8057       {
8058         shiftR1Left2Result (left, MSB16, result, LSB,
8059                             shCount, sign);
8060       }                     
8061       else
8062       {
8063         movLeft2Result (left, MSB16, result, LSB, sign);
8064       }
8065       addSign (result, MSB16, sign);
8066       _endLazyDPSEvaluation();
8067     }
8068
8069   /*  1 <= shCount <= 7 */
8070   else
8071   {
8072     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8073   }
8074 }
8075 #endif
8076
8077 #if 0
8078 //REMOVE ME!!!
8079 /*-----------------------------------------------------------------*/
8080 /* shiftRLong - shift right one long from left to result           */
8081 /* offl = LSB or MSB16                                             */
8082 /*-----------------------------------------------------------------*/
8083 static void
8084 shiftRLong (operand * left, int offl,
8085             operand * result, int sign)
8086 {
8087   int isSameRegs=sameRegs(AOP(left),AOP(result));
8088
8089   if (isSameRegs && offl>1) {
8090     // we are in big trouble, but this shouldn't happen
8091     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8092   }
8093
8094   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8095   
8096   if (offl==MSB16) {
8097     // shift is > 8
8098     if (sign) {
8099       emitcode ("rlc", "a");
8100       emitcode ("subb", "a,acc");
8101       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8102     } else {
8103       aopPut (AOP(result), zero, MSB32);
8104     }
8105   }
8106
8107   if (!sign) {
8108     emitcode ("clr", "c");
8109   } else {
8110     emitcode ("mov", "c,acc.7");
8111   }
8112
8113   emitcode ("rrc", "a");
8114
8115   if (isSameRegs && offl==MSB16) {
8116     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8117   } else {
8118     aopPut (AOP (result), "a", MSB32);
8119     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8120   }
8121
8122   emitcode ("rrc", "a");
8123   if (isSameRegs && offl==1) {
8124     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8125   } else {
8126     aopPut (AOP (result), "a", MSB24);
8127     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8128   }
8129   emitcode ("rrc", "a");
8130   aopPut (AOP (result), "a", MSB16 - offl);
8131
8132   if (offl == LSB)
8133     {
8134       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8135       emitcode ("rrc", "a");
8136       aopPut (AOP (result), "a", LSB);
8137     }
8138 }
8139 #endif
8140
8141 #if 0
8142 //REMOVE ME!!!
8143 /*-----------------------------------------------------------------*/
8144 /* genrshFour - shift four byte by a known amount != 0             */
8145 /*-----------------------------------------------------------------*/
8146 static void
8147 genrshFour (operand * result, operand * left,
8148             int shCount, int sign)
8149 {
8150   D (emitcode (";", "genrshFour");
8151     );
8152
8153   /* if shifting more that 3 bytes */
8154   if (shCount >= 24)
8155     {
8156       shCount -= 24;
8157       if (shCount)
8158         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8159       else
8160         movLeft2Result (left, MSB32, result, LSB, sign);
8161       addSign (result, MSB16, sign);
8162     }
8163   else if (shCount >= 16)
8164     {
8165       shCount -= 16;
8166       if (shCount)
8167         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8168       else
8169         {
8170           movLeft2Result (left, MSB24, result, LSB, 0);
8171           movLeft2Result (left, MSB32, result, MSB16, sign);
8172         }
8173       addSign (result, MSB24, sign);
8174     }
8175   else if (shCount >= 8)
8176     {
8177       shCount -= 8;
8178       if (shCount == 1)
8179         shiftRLong (left, MSB16, result, sign);
8180       else if (shCount == 0)
8181         {
8182           movLeft2Result (left, MSB16, result, LSB, 0);
8183           movLeft2Result (left, MSB24, result, MSB16, 0);
8184           movLeft2Result (left, MSB32, result, MSB24, sign);
8185           addSign (result, MSB32, sign);
8186         }
8187       else
8188         {
8189           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8190           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8191           /* the last shift is signed */
8192           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8193           addSign (result, MSB32, sign);
8194         }
8195     }
8196   else
8197     {                           /* 1 <= shCount <= 7 */
8198       if (shCount <= 2)
8199         {
8200           shiftRLong (left, LSB, result, sign);
8201           if (shCount == 2)
8202             shiftRLong (result, LSB, result, sign);
8203         }
8204       else
8205         {
8206           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8207           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8208           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8209         }
8210     }
8211 }
8212 #endif
8213
8214 #ifdef BETTER_LITERAL_SHIFT
8215 /*-----------------------------------------------------------------*/
8216 /* genRightShiftLiteral - right shifting by known count            */
8217 /*-----------------------------------------------------------------*/
8218 static bool
8219 genRightShiftLiteral (operand * left,
8220                       operand * right,
8221                       operand * result,
8222                       iCode * ic,
8223                       int sign)
8224 {
8225   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8226   int size;
8227
8228   size = getSize (operandType (result));
8229
8230   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8231
8232   /* We only handle certain easy cases so far. */
8233   if ((shCount != 0)
8234    && (shCount < (size * 8))
8235    && (size != 1)
8236    && (size != 2))
8237   {
8238       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8239       return FALSE;
8240   }
8241
8242   freeAsmop (right, NULL, ic, TRUE);
8243
8244   aopOp (left, ic, FALSE, FALSE);
8245   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8246
8247 #if VIEW_SIZE
8248   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8249             AOP_SIZE (left));
8250 #endif
8251
8252   /* test the LEFT size !!! */
8253
8254   /* I suppose that the left size >= result size */
8255   if (shCount == 0)
8256   {
8257       size = getDataSize (result);
8258       _startLazyDPSEvaluation();
8259       while (size--)
8260       {
8261         movLeft2Result (left, size, result, size, 0);
8262       }
8263       _endLazyDPSEvaluation();
8264   }
8265   else if (shCount >= (size * 8))
8266     {
8267       if (sign)
8268       {
8269         /* get sign in acc.7 */
8270         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8271       }
8272       addSign (result, LSB, sign);
8273     }
8274   else
8275     {
8276       switch (size)
8277         {
8278         case 1:
8279           genrshOne (result, left, shCount, sign);
8280           break;
8281
8282         case 2:
8283           genrshTwo (result, left, shCount, sign);
8284           break;
8285 #if 0
8286         case 4:
8287           genrshFour (result, left, shCount, sign);
8288           break;
8289 #endif    
8290         default:
8291           break;
8292         }
8293
8294       freeAsmop (left, NULL, ic, TRUE);
8295       freeAsmop (result, NULL, ic, TRUE);
8296     }
8297     return TRUE;
8298 }
8299 #endif
8300
8301 /*-----------------------------------------------------------------*/
8302 /* genSignedRightShift - right shift of signed number              */
8303 /*-----------------------------------------------------------------*/
8304 static void
8305 genSignedRightShift (iCode * ic)
8306 {
8307   operand *right, *left, *result;
8308   int size, offset;
8309   char *l;
8310   symbol *tlbl, *tlbl1;
8311
8312   D (emitcode (";", "genSignedRightShift "););
8313
8314   /* we do it the hard way put the shift count in b
8315      and loop thru preserving the sign */
8316
8317   right = IC_RIGHT (ic);
8318   left = IC_LEFT (ic);
8319   result = IC_RESULT (ic);
8320
8321   aopOp (right, ic, FALSE, FALSE);
8322
8323 #ifdef BETTER_LITERAL_SHIFT
8324   if (AOP_TYPE (right) == AOP_LIT)
8325     {
8326       if (genRightShiftLiteral (left, right, result, ic, 1))
8327       {
8328         return;
8329       }
8330     }
8331 #endif
8332   /* shift count is unknown then we have to form
8333      a loop get the loop count in B : Note: we take
8334      only the lower order byte since shifting
8335      more that 32 bits make no sense anyway, ( the
8336      largest size of an object can be only 32 bits ) */
8337
8338   if (AOP_TYPE (right) == AOP_LIT)
8339   {
8340       /* Really should be handled by genRightShiftLiteral,
8341        * but since I'm too lazy to fix that today, at least we can make
8342        * some small improvement.
8343        */
8344        emitcode("mov", "b,#!constbyte",
8345                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8346   }
8347   else
8348   {
8349         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8350         emitcode ("inc", "b");
8351   }
8352   freeAsmop (right, NULL, ic, TRUE);
8353   aopOp (left, ic, FALSE, FALSE);
8354   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8355
8356   /* now move the left to the result if they are not the
8357      same */
8358   if (!sameRegs (AOP (left), AOP (result)) &&
8359       AOP_SIZE (result) > 1)
8360     {
8361
8362       size = AOP_SIZE (result);
8363       offset = 0;
8364       _startLazyDPSEvaluation ();
8365       while (size--)
8366         {
8367           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8368           if (*l == '@' && IS_AOP_PREG (result))
8369             {
8370
8371               emitcode ("mov", "a,%s", l);
8372               aopPut (AOP (result), "a", offset);
8373             }
8374           else
8375             aopPut (AOP (result), l, offset);
8376           offset++;
8377         }
8378       _endLazyDPSEvaluation ();
8379     }
8380
8381   /* mov the highest order bit to OVR */
8382   tlbl = newiTempLabel (NULL);
8383   tlbl1 = newiTempLabel (NULL);
8384
8385   size = AOP_SIZE (result);
8386   offset = size - 1;
8387   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8388   emitcode ("rlc", "a");
8389   emitcode ("mov", "ov,c");
8390   /* if it is only one byte then */
8391   if (size == 1)
8392     {
8393       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8394       MOVA (l);
8395       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8396       emitcode ("", "!tlabeldef", tlbl->key + 100);
8397       emitcode ("mov", "c,ov");
8398       emitcode ("rrc", "a");
8399       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8400       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8401       aopPut (AOP (result), "a", 0);
8402       goto release;
8403     }
8404
8405   reAdjustPreg (AOP (result));
8406   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8407   emitcode ("", "!tlabeldef", tlbl->key + 100);
8408   emitcode ("mov", "c,ov");
8409   _startLazyDPSEvaluation ();
8410   while (size--)
8411     {
8412       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8413       MOVA (l);
8414       emitcode ("rrc", "a");
8415       aopPut (AOP (result), "a", offset--);
8416     }
8417   _endLazyDPSEvaluation ();
8418   reAdjustPreg (AOP (result));
8419   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8420   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8421
8422 release:
8423   freeAsmop (left, NULL, ic, TRUE);
8424   freeAsmop (result, NULL, ic, TRUE);
8425 }
8426
8427 /*-----------------------------------------------------------------*/
8428 /* genRightShift - generate code for right shifting                */
8429 /*-----------------------------------------------------------------*/
8430 static void
8431 genRightShift (iCode * ic)
8432 {
8433   operand *right, *left, *result;
8434   sym_link *retype;
8435   int size, offset;
8436   char *l;
8437   symbol *tlbl, *tlbl1;
8438
8439   D (emitcode (";", "genRightShift "););
8440
8441   /* if signed then we do it the hard way preserve the
8442      sign bit moving it inwards */
8443   retype = getSpec (operandType (IC_RESULT (ic)));
8444
8445   if (!SPEC_USIGN (retype))
8446     {
8447       genSignedRightShift (ic);
8448       return;
8449     }
8450
8451   /* signed & unsigned types are treated the same : i.e. the
8452      signed is NOT propagated inwards : quoting from the
8453      ANSI - standard : "for E1 >> E2, is equivalent to division
8454      by 2**E2 if unsigned or if it has a non-negative value,
8455      otherwise the result is implementation defined ", MY definition
8456      is that the sign does not get propagated */
8457
8458   right = IC_RIGHT (ic);
8459   left = IC_LEFT (ic);
8460   result = IC_RESULT (ic);
8461
8462   aopOp (right, ic, FALSE, FALSE);
8463
8464 #ifdef BETTER_LITERAL_SHIFT
8465   /* if the shift count is known then do it
8466      as efficiently as possible */
8467   if (AOP_TYPE (right) == AOP_LIT)
8468     {
8469       if (genRightShiftLiteral (left, right, result, ic, 0))
8470       {
8471         return;
8472       }
8473     }
8474 #endif
8475
8476   /* shift count is unknown then we have to form
8477      a loop get the loop count in B : Note: we take
8478      only the lower order byte since shifting
8479      more that 32 bits make no sense anyway, ( the
8480      largest size of an object can be only 32 bits ) */
8481   
8482   if (AOP_TYPE (right) == AOP_LIT)
8483   {
8484       /* Really should be handled by genRightShiftLiteral,
8485        * but since I'm too lazy to fix that today, at least we can make
8486        * some small improvement.
8487        */
8488        emitcode("mov", "b,#!constbyte",
8489                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8490   }
8491   else
8492   {
8493         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8494         emitcode ("inc", "b");
8495   }
8496   freeAsmop (right, NULL, ic, TRUE);
8497   aopOp (left, ic, FALSE, FALSE);
8498   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8499
8500   /* now move the left to the result if they are not the
8501      same */
8502   if (!sameRegs (AOP (left), AOP (result)) &&
8503       AOP_SIZE (result) > 1)
8504     {
8505
8506       size = AOP_SIZE (result);
8507       offset = 0;
8508       _startLazyDPSEvaluation ();
8509       while (size--)
8510         {
8511           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8512           if (*l == '@' && IS_AOP_PREG (result))
8513             {
8514
8515               emitcode ("mov", "a,%s", l);
8516               aopPut (AOP (result), "a", offset);
8517             }
8518           else
8519             aopPut (AOP (result), l, offset);
8520           offset++;
8521         }
8522       _endLazyDPSEvaluation ();
8523     }
8524
8525   tlbl = newiTempLabel (NULL);
8526   tlbl1 = newiTempLabel (NULL);
8527   size = AOP_SIZE (result);
8528   offset = size - 1;
8529
8530   /* if it is only one byte then */
8531   if (size == 1)
8532     {
8533       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8534       MOVA (l);
8535       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8536       emitcode ("", "!tlabeldef", tlbl->key + 100);
8537       CLRC;
8538       emitcode ("rrc", "a");
8539       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8540       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8541       aopPut (AOP (result), "a", 0);
8542       goto release;
8543     }
8544
8545   reAdjustPreg (AOP (result));
8546   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8547   emitcode ("", "!tlabeldef", tlbl->key + 100);
8548   CLRC;
8549   _startLazyDPSEvaluation ();
8550   while (size--)
8551     {
8552       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8553       MOVA (l);
8554       emitcode ("rrc", "a");
8555       aopPut (AOP (result), "a", offset--);
8556     }
8557   _endLazyDPSEvaluation ();
8558   reAdjustPreg (AOP (result));
8559
8560   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8561   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8562
8563 release:
8564   freeAsmop (left, NULL, ic, TRUE);
8565   freeAsmop (result, NULL, ic, TRUE);
8566 }
8567
8568 /*-----------------------------------------------------------------*/
8569 /* genUnpackBits - generates code for unpacking bits               */
8570 /*-----------------------------------------------------------------*/
8571 static void
8572 genUnpackBits (operand * result, char *rname, int ptype)
8573 {
8574   int shCnt;
8575   int rlen = 0;
8576   sym_link *etype;
8577   int offset = 0;
8578
8579   D (emitcode (";", "genUnpackBits ");
8580     );
8581
8582   etype = getSpec (operandType (result));
8583
8584   /* read the first byte  */
8585   switch (ptype)
8586     {
8587
8588     case POINTER:
8589     case IPOINTER:
8590       emitcode ("mov", "a,@%s", rname);
8591       break;
8592
8593     case PPOINTER:
8594       emitcode ("movx", "a,@%s", rname);
8595       break;
8596
8597     case FPOINTER:
8598       emitcode ("movx", "a,@dptr");
8599       break;
8600
8601     case CPOINTER:
8602       emitcode ("clr", "a");
8603       emitcode ("movc", "a,@a+dptr");
8604       break;
8605
8606     case GPOINTER:
8607       emitcode ("lcall", "__gptrget");
8608       break;
8609     }
8610
8611   /* if we have bitdisplacement then it fits   */
8612   /* into this byte completely or if length is */
8613   /* less than a byte                          */
8614   if ((shCnt = SPEC_BSTR (etype)) ||
8615       (SPEC_BLEN (etype) <= 8))
8616     {
8617
8618       /* shift right acc */
8619       AccRsh (shCnt);
8620
8621       emitcode ("anl", "a,#!constbyte",
8622                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8623       aopPut (AOP (result), "a", offset);
8624       return;
8625     }
8626
8627   /* bit field did not fit in a byte  */
8628   rlen = SPEC_BLEN (etype) - 8;
8629   aopPut (AOP (result), "a", offset++);
8630
8631   while (1)
8632     {
8633
8634       switch (ptype)
8635         {
8636         case POINTER:
8637         case IPOINTER:
8638           emitcode ("inc", "%s", rname);
8639           emitcode ("mov", "a,@%s", rname);
8640           break;
8641
8642         case PPOINTER:
8643           emitcode ("inc", "%s", rname);
8644           emitcode ("movx", "a,@%s", rname);
8645           break;
8646
8647         case FPOINTER:
8648           emitcode ("inc", "dptr");
8649           emitcode ("movx", "a,@dptr");
8650           break;
8651
8652         case CPOINTER:
8653           emitcode ("clr", "a");
8654           emitcode ("inc", "dptr");
8655           emitcode ("movc", "a,@a+dptr");
8656           break;
8657
8658         case GPOINTER:
8659           emitcode ("inc", "dptr");
8660           emitcode ("lcall", "__gptrget");
8661           break;
8662         }
8663
8664       rlen -= 8;
8665       /* if we are done */
8666       if (rlen < 8)
8667         break;
8668
8669       aopPut (AOP (result), "a", offset++);
8670
8671     }
8672
8673   if (rlen)
8674     {
8675       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8676       aopPut (AOP (result), "a", offset);
8677     }
8678
8679   return;
8680 }
8681
8682
8683 /*-----------------------------------------------------------------*/
8684 /* genDataPointerGet - generates code when ptr offset is known     */
8685 /*-----------------------------------------------------------------*/
8686 static void
8687 genDataPointerGet (operand * left,
8688                    operand * result,
8689                    iCode * ic)
8690 {
8691   char *l;
8692   char buffer[256];
8693   int size, offset = 0;
8694   aopOp (result, ic, TRUE, FALSE);
8695
8696   /* get the string representation of the name */
8697   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8698   size = AOP_SIZE (result);
8699   _startLazyDPSEvaluation ();
8700   while (size--)
8701     {
8702       if (offset)
8703         sprintf (buffer, "(%s + %d)", l + 1, offset);
8704       else
8705         sprintf (buffer, "%s", l + 1);
8706       aopPut (AOP (result), buffer, offset++);
8707     }
8708   _endLazyDPSEvaluation ();
8709
8710   freeAsmop (left, NULL, ic, TRUE);
8711   freeAsmop (result, NULL, ic, TRUE);
8712 }
8713
8714 /*-----------------------------------------------------------------*/
8715 /* genNearPointerGet - emitcode for near pointer fetch             */
8716 /*-----------------------------------------------------------------*/
8717 static void
8718 genNearPointerGet (operand * left,
8719                    operand * result,
8720                    iCode * ic,
8721                    iCode *pi)
8722 {
8723   asmop *aop = NULL;
8724   regs *preg = NULL;
8725   char *rname;
8726   sym_link *rtype, *retype, *letype;
8727   sym_link *ltype = operandType (left);
8728   char buffer[80];
8729
8730   rtype = operandType (result);
8731   retype = getSpec (rtype);
8732   letype = getSpec (ltype);
8733
8734   aopOp (left, ic, FALSE, FALSE);
8735
8736   /* if left is rematerialisable and
8737      result is not bit variable type and
8738      the left is pointer to data space i.e
8739      lower 128 bytes of space */
8740   if (AOP_TYPE (left) == AOP_IMMD &&
8741       !IS_BITVAR (retype) &&
8742       !IS_BITVAR (letype) &&
8743       DCL_TYPE (ltype) == POINTER)
8744     {
8745       genDataPointerGet (left, result, ic);
8746       return;
8747     }
8748
8749   /* if the value is already in a pointer register
8750      then don't need anything more */
8751   if (!AOP_INPREG (AOP (left)))
8752     {
8753       /* otherwise get a free pointer register */
8754       aop = newAsmop (0);
8755       preg = getFreePtr (ic, &aop, FALSE);
8756       emitcode ("mov", "%s,%s",
8757                 preg->name,
8758                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8759       rname = preg->name;
8760     }
8761   else
8762     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8763
8764   freeAsmop (left, NULL, ic, TRUE);
8765   aopOp (result, ic, FALSE, FALSE);
8766
8767   /* if bitfield then unpack the bits */
8768   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8769     genUnpackBits (result, rname, POINTER);
8770   else
8771     {
8772       /* we have can just get the values */
8773       int size = AOP_SIZE (result);
8774       int offset = 0;
8775
8776       while (size--)
8777         {
8778           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8779             {
8780
8781               emitcode ("mov", "a,@%s", rname);
8782               aopPut (AOP (result), "a", offset);
8783             }
8784           else
8785             {
8786               sprintf (buffer, "@%s", rname);
8787               aopPut (AOP (result), buffer, offset);
8788             }
8789           offset++;
8790           if (size || pi)
8791             emitcode ("inc", "%s", rname);
8792         }
8793     }
8794
8795   /* now some housekeeping stuff */
8796   if (aop)
8797     {
8798       /* we had to allocate for this iCode */
8799       if (pi) { /* post increment present */
8800         aopPut(AOP ( left ),rname,0);
8801       }
8802       freeAsmop (NULL, aop, ic, TRUE);
8803     }
8804   else
8805     {
8806       /* we did not allocate which means left
8807          already in a pointer register, then
8808          if size > 0 && this could be used again
8809          we have to point it back to where it
8810          belongs */
8811       if (AOP_SIZE (result) > 1 &&
8812           !OP_SYMBOL (left)->remat &&
8813           (OP_SYMBOL (left)->liveTo > ic->seq ||
8814            ic->depth) &&
8815           !pi)
8816         {
8817           int size = AOP_SIZE (result) - 1;
8818           while (size--)
8819             emitcode ("dec", "%s", rname);
8820         }
8821     }
8822
8823   /* done */
8824   freeAsmop (result, NULL, ic, TRUE);
8825   if (pi) pi->generated = 1;
8826 }
8827
8828 /*-----------------------------------------------------------------*/
8829 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8830 /*-----------------------------------------------------------------*/
8831 static void
8832 genPagedPointerGet (operand * left,
8833                     operand * result,
8834                     iCode * ic,
8835                     iCode * pi)
8836 {
8837   asmop *aop = NULL;
8838   regs *preg = NULL;
8839   char *rname;
8840   sym_link *rtype, *retype, *letype;
8841
8842   rtype = operandType (result);
8843   retype = getSpec (rtype);
8844   letype = getSpec (operandType (left));
8845   aopOp (left, ic, FALSE, FALSE);
8846
8847   /* if the value is already in a pointer register
8848      then don't need anything more */
8849   if (!AOP_INPREG (AOP (left)))
8850     {
8851       /* otherwise get a free pointer register */
8852       aop = newAsmop (0);
8853       preg = getFreePtr (ic, &aop, FALSE);
8854       emitcode ("mov", "%s,%s",
8855                 preg->name,
8856                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8857       rname = preg->name;
8858     }
8859   else
8860     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8861
8862   freeAsmop (left, NULL, ic, TRUE);
8863   aopOp (result, ic, FALSE, FALSE);
8864
8865   /* if bitfield then unpack the bits */
8866   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8867     genUnpackBits (result, rname, PPOINTER);
8868   else
8869     {
8870       /* we have can just get the values */
8871       int size = AOP_SIZE (result);
8872       int offset = 0;
8873
8874       while (size--)
8875         {
8876
8877           emitcode ("movx", "a,@%s", rname);
8878           aopPut (AOP (result), "a", offset);
8879
8880           offset++;
8881
8882           if (size || pi)
8883             emitcode ("inc", "%s", rname);
8884         }
8885     }
8886
8887   /* now some housekeeping stuff */
8888   if (aop)
8889     {
8890       /* we had to allocate for this iCode */
8891       if (pi) aopPut ( AOP (left), rname, 0);
8892       freeAsmop (NULL, aop, ic, TRUE);
8893     }
8894   else
8895     {
8896       /* we did not allocate which means left
8897          already in a pointer register, then
8898          if size > 0 && this could be used again
8899          we have to point it back to where it
8900          belongs */
8901       if (AOP_SIZE (result) > 1 &&
8902           !OP_SYMBOL (left)->remat &&
8903           (OP_SYMBOL (left)->liveTo > ic->seq ||
8904            ic->depth) &&
8905           !pi)
8906         {
8907           int size = AOP_SIZE (result) - 1;
8908           while (size--)
8909             emitcode ("dec", "%s", rname);
8910         }
8911     }
8912
8913   /* done */
8914   freeAsmop (result, NULL, ic, TRUE);
8915   if (pi) pi->generated = 1;
8916 }
8917
8918 /*-----------------------------------------------------------------*/
8919 /* genFarPointerGet - gget value from far space                    */
8920 /*-----------------------------------------------------------------*/
8921 static void
8922 genFarPointerGet (operand * left,
8923                   operand * result, iCode * ic, iCode *pi)
8924 {
8925     int size, offset, dopi=1;
8926   sym_link *retype = getSpec (operandType (result));
8927   sym_link *letype = getSpec (operandType (left));
8928   D (emitcode (";", "genFarPointerGet");
8929     );
8930
8931   aopOp (left, ic, FALSE, FALSE);
8932
8933   /* if the operand is already in dptr
8934      then we do nothing else we move the value to dptr */
8935   if (AOP_TYPE (left) != AOP_STR)
8936     {
8937       /* if this is remateriazable */
8938       if (AOP_TYPE (left) == AOP_IMMD)
8939         {
8940           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8941         }
8942       else
8943         {
8944           /* we need to get it byte by byte */
8945           _startLazyDPSEvaluation ();
8946           if (AOP_TYPE (left) != AOP_DPTR)
8947             {
8948               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8949               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8950               if (options.model == MODEL_FLAT24)
8951                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8952             }
8953           else
8954             {
8955               /* We need to generate a load to DPTR indirect through DPTR. */
8956               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8957                 );
8958               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8959               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8960               if (options.model == MODEL_FLAT24)
8961                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8962               emitcode ("pop", "dph");
8963               emitcode ("pop", "dpl");
8964               dopi =0;
8965             }
8966           _endLazyDPSEvaluation ();
8967         }
8968     }
8969   /* so dptr know contains the address */
8970   aopOp (result, ic, FALSE, TRUE);
8971
8972   /* if bit then unpack */
8973   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8974     genUnpackBits (result, "dptr", FPOINTER);
8975   else
8976     {
8977       size = AOP_SIZE (result);
8978       offset = 0;
8979
8980       _startLazyDPSEvaluation ();
8981       while (size--)
8982         {
8983
8984           genSetDPTR (0);
8985           _flushLazyDPS ();
8986
8987           emitcode ("movx", "a,@dptr");
8988           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
8989             emitcode ("inc", "dptr");
8990
8991           aopPut (AOP (result), "a", offset++);
8992         }
8993       _endLazyDPSEvaluation ();
8994     }
8995   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
8996     aopPut ( AOP (left), "dpl", 0);
8997     aopPut ( AOP (left), "dph", 1);
8998     if (options.model == MODEL_FLAT24)
8999             aopPut ( AOP (left), "dpx", 2);
9000     pi->generated = 1;
9001   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9002              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9003       
9004       size = AOP_SIZE (result) - 1;
9005       while (size--) emitcode ("lcall","__decdptr");
9006   }
9007
9008   freeAsmop (left, NULL, ic, TRUE);
9009   freeAsmop (result, NULL, ic, TRUE);
9010 }
9011
9012 /*-----------------------------------------------------------------*/
9013 /* emitcodePointerGet - gget value from code space                  */
9014 /*-----------------------------------------------------------------*/
9015 static void
9016 emitcodePointerGet (operand * left,
9017                     operand * result, iCode * ic, iCode *pi)
9018 {
9019   int size, offset, dopi=1;
9020   sym_link *retype = getSpec (operandType (result));
9021
9022   aopOp (left, ic, FALSE, FALSE);
9023
9024   /* if the operand is already in dptr
9025      then we do nothing else we move the value to dptr */
9026   if (AOP_TYPE (left) != AOP_STR)
9027     {
9028       /* if this is remateriazable */
9029       if (AOP_TYPE (left) == AOP_IMMD)
9030         {
9031           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9032         }
9033       else
9034         {                       /* we need to get it byte by byte */
9035           _startLazyDPSEvaluation ();
9036           if (AOP_TYPE (left) != AOP_DPTR)
9037             {
9038               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9039               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9040               if (options.model == MODEL_FLAT24)
9041                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9042             }
9043           else
9044             {
9045               /* We need to generate a load to DPTR indirect through DPTR. */
9046               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9047                 );
9048               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9049               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9050               if (options.model == MODEL_FLAT24)
9051                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9052               emitcode ("pop", "dph");
9053               emitcode ("pop", "dpl");
9054               dopi=0;
9055             }
9056           _endLazyDPSEvaluation ();
9057         }
9058     }
9059   /* so dptr know contains the address */
9060   aopOp (result, ic, FALSE, TRUE);
9061
9062   /* if bit then unpack */
9063   if (IS_BITVAR (retype))
9064     genUnpackBits (result, "dptr", CPOINTER);
9065   else
9066     {
9067       size = AOP_SIZE (result);
9068       offset = 0;
9069
9070       _startLazyDPSEvaluation ();
9071       while (size--)
9072         {
9073           genSetDPTR (0);
9074           _flushLazyDPS ();
9075
9076           emitcode ("clr", "a");
9077           emitcode ("movc", "a,@a+dptr");
9078           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9079             emitcode ("inc", "dptr");
9080           aopPut (AOP (result), "a", offset++);
9081         }
9082       _endLazyDPSEvaluation ();
9083     }
9084   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9085       aopPut ( AOP (left), "dpl", 0);
9086       aopPut ( AOP (left), "dph", 1);
9087       if (options.model == MODEL_FLAT24)
9088           aopPut ( AOP (left), "dpx", 2);
9089       pi->generated = 1;
9090   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9091              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9092       
9093       size = AOP_SIZE (result) - 1;
9094       while (size--) emitcode ("lcall","__decdptr");
9095   }
9096   
9097   freeAsmop (left, NULL, ic, TRUE);
9098   freeAsmop (result, NULL, ic, TRUE);
9099 }
9100
9101 /*-----------------------------------------------------------------*/
9102 /* genGenPointerGet - gget value from generic pointer space        */
9103 /*-----------------------------------------------------------------*/
9104 static void
9105 genGenPointerGet (operand * left,
9106                   operand * result, iCode * ic, iCode * pi)
9107 {
9108   int size, offset;
9109   sym_link *retype = getSpec (operandType (result));
9110   sym_link *letype = getSpec (operandType (left));
9111
9112   D (emitcode (";", "genGenPointerGet "); );
9113
9114   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9115
9116   /* if the operand is already in dptr
9117      then we do nothing else we move the value to dptr */
9118   if (AOP_TYPE (left) != AOP_STR)
9119     {
9120       /* if this is remateriazable */
9121       if (AOP_TYPE (left) == AOP_IMMD)
9122         {
9123           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9124           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9125                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9126           else
9127                   emitcode ("mov", "b,#%d", pointerCode (retype));
9128         }
9129       else
9130         {                       /* we need to get it byte by byte */
9131           _startLazyDPSEvaluation ();
9132           if (AOP(left)->type==AOP_DPTR2) {
9133             char *l;
9134             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9135             genSetDPTR(0);
9136             _flushLazyDPS();
9137             emitcode ("mov", "dpl,%s", l);
9138             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9139             genSetDPTR(0);
9140             _flushLazyDPS();
9141             emitcode ("mov", "dph,%s", l);
9142             if (options.model == MODEL_FLAT24) {
9143               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9144               genSetDPTR(0);
9145               _flushLazyDPS();
9146               emitcode ("mov", "dpx,%s", l);
9147               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9148             } else {
9149               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9150             }
9151           } else {
9152             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9153             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9154             if (options.model == MODEL_FLAT24) {
9155               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9156               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9157             } else {
9158               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9159             }
9160           }
9161           _endLazyDPSEvaluation ();
9162         }
9163     }
9164   /* so dptr know contains the address */
9165   aopOp (result, ic, FALSE, TRUE);
9166
9167   /* if bit then unpack */
9168   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9169     genUnpackBits (result, "dptr", GPOINTER);
9170   else
9171     {
9172       size = AOP_SIZE (result);
9173       offset = 0;
9174
9175       while (size--)
9176         {
9177           emitcode ("lcall", "__gptrget");
9178           aopPut (AOP (result), "a", offset++);
9179           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9180             emitcode ("inc", "dptr");
9181         }
9182     }
9183
9184   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9185     aopPut ( AOP (left), "dpl", 0);
9186     aopPut ( AOP (left), "dph", 1);
9187     if (options.model == MODEL_FLAT24) {
9188         aopPut ( AOP (left), "dpx", 2);
9189         aopPut ( AOP (left), "b", 3);   
9190     } else  aopPut ( AOP (left), "b", 2);       
9191     pi->generated = 1;
9192   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9193              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9194       
9195       size = AOP_SIZE (result) - 1;
9196       while (size--) emitcode ("lcall","__decdptr");
9197   }
9198
9199   freeAsmop (left, NULL, ic, TRUE);
9200   freeAsmop (result, NULL, ic, TRUE);
9201 }
9202
9203 /*-----------------------------------------------------------------*/
9204 /* genPointerGet - generate code for pointer get                   */
9205 /*-----------------------------------------------------------------*/
9206 static void
9207 genPointerGet (iCode * ic, iCode *pi)
9208 {
9209   operand *left, *result;
9210   sym_link *type, *etype;
9211   int p_type;
9212
9213   D (emitcode (";", "genPointerGet ");
9214     );
9215
9216   left = IC_LEFT (ic);
9217   result = IC_RESULT (ic);
9218
9219   /* depending on the type of pointer we need to
9220      move it to the correct pointer register */
9221   type = operandType (left);
9222   etype = getSpec (type);
9223   /* if left is of type of pointer then it is simple */
9224   if (IS_PTR (type) && !IS_FUNC (type->next))
9225     p_type = DCL_TYPE (type);
9226   else
9227     {
9228       /* we have to go by the storage class */
9229       p_type = PTR_TYPE (SPEC_OCLS (etype));
9230     }
9231   /* special case when cast remat */
9232   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9233       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9234           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9235           type =   type = operandType (left);
9236           p_type = DCL_TYPE (type);
9237   }
9238   /* now that we have the pointer type we assign
9239      the pointer values */
9240   switch (p_type)
9241     {
9242
9243     case POINTER:
9244     case IPOINTER:
9245       genNearPointerGet (left, result, ic, pi);
9246       break;
9247
9248     case PPOINTER:
9249       genPagedPointerGet (left, result, ic, pi);
9250       break;
9251
9252     case FPOINTER:
9253       genFarPointerGet (left, result, ic, pi);
9254       break;
9255
9256     case CPOINTER:
9257       emitcodePointerGet (left, result, ic, pi);
9258       break;
9259
9260     case GPOINTER:
9261       genGenPointerGet (left, result, ic, pi);
9262       break;
9263     }
9264
9265 }
9266
9267 /*-----------------------------------------------------------------*/
9268 /* genPackBits - generates code for packed bit storage             */
9269 /*-----------------------------------------------------------------*/
9270 static void
9271 genPackBits (sym_link * etype,
9272              operand * right,
9273              char *rname, int p_type)
9274 {
9275   int shCount = 0;
9276   int offset = 0;
9277   int rLen = 0;
9278   int blen, bstr;
9279   char *l;
9280
9281   blen = SPEC_BLEN (etype);
9282   bstr = SPEC_BSTR (etype);
9283
9284   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9285   MOVA (l);
9286
9287   /* if the bit lenth is less than or    */
9288   /* it exactly fits a byte then         */
9289   if (SPEC_BLEN (etype) <= 8)
9290     {
9291       shCount = SPEC_BSTR (etype);
9292
9293       /* shift left acc */
9294       AccLsh (shCount);
9295
9296       if (SPEC_BLEN (etype) < 8)
9297         {                       /* if smaller than a byte */
9298
9299
9300           switch (p_type)
9301             {
9302             case POINTER:
9303               emitcode ("mov", "b,a");
9304               emitcode ("mov", "a,@%s", rname);
9305               break;
9306
9307             case FPOINTER:
9308               emitcode ("mov", "b,a");
9309               emitcode ("movx", "a,@dptr");
9310               break;
9311
9312             case GPOINTER:
9313               emitcode ("push", "b");
9314               emitcode ("push", "acc");
9315               emitcode ("lcall", "__gptrget");
9316               emitcode ("pop", "b");
9317               break;
9318             }
9319
9320           emitcode ("anl", "a,#!constbyte", (unsigned char)
9321                     ((unsigned char) (0xFF << (blen + bstr)) |
9322                      (unsigned char) (0xFF >> (8 - bstr))));
9323           emitcode ("orl", "a,b");
9324           if (p_type == GPOINTER)
9325             emitcode ("pop", "b");
9326         }
9327     }
9328
9329   switch (p_type)
9330     {
9331     case POINTER:
9332       emitcode ("mov", "@%s,a", rname);
9333       break;
9334
9335     case FPOINTER:
9336       emitcode ("movx", "@dptr,a");
9337       break;
9338
9339     case GPOINTER:
9340       emitcode ("lcall", "__gptrput");
9341       break;
9342     }
9343
9344   /* if we r done */
9345   if (SPEC_BLEN (etype) <= 8)
9346     return;
9347
9348   emitcode ("inc", "%s", rname);
9349   rLen = SPEC_BLEN (etype);
9350
9351   /* now generate for lengths greater than one byte */
9352   while (1)
9353     {
9354
9355       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9356
9357       rLen -= 8;
9358       if (rLen < 8)
9359         break;
9360
9361       switch (p_type)
9362         {
9363         case POINTER:
9364           if (*l == '@')
9365             {
9366               MOVA (l);
9367               emitcode ("mov", "@%s,a", rname);
9368             }
9369           else
9370             emitcode ("mov", "@%s,%s", rname, l);
9371           break;
9372
9373         case FPOINTER:
9374           MOVA (l);
9375           emitcode ("movx", "@dptr,a");
9376           break;
9377
9378         case GPOINTER:
9379           MOVA (l);
9380           emitcode ("lcall", "__gptrput");
9381           break;
9382         }
9383       emitcode ("inc", "%s", rname);
9384     }
9385
9386   MOVA (l);
9387
9388   /* last last was not complete */
9389   if (rLen)
9390     {
9391       /* save the byte & read byte */
9392       switch (p_type)
9393         {
9394         case POINTER:
9395           emitcode ("mov", "b,a");
9396           emitcode ("mov", "a,@%s", rname);
9397           break;
9398
9399         case FPOINTER:
9400           emitcode ("mov", "b,a");
9401           emitcode ("movx", "a,@dptr");
9402           break;
9403
9404         case GPOINTER:
9405           emitcode ("push", "b");
9406           emitcode ("push", "acc");
9407           emitcode ("lcall", "__gptrget");
9408           emitcode ("pop", "b");
9409           break;
9410         }
9411
9412       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9413       emitcode ("orl", "a,b");
9414     }
9415
9416   if (p_type == GPOINTER)
9417     emitcode ("pop", "b");
9418
9419   switch (p_type)
9420     {
9421
9422     case POINTER:
9423       emitcode ("mov", "@%s,a", rname);
9424       break;
9425
9426     case FPOINTER:
9427       emitcode ("movx", "@dptr,a");
9428       break;
9429
9430     case GPOINTER:
9431       emitcode ("lcall", "__gptrput");
9432       break;
9433     }
9434 }
9435 /*-----------------------------------------------------------------*/
9436 /* genDataPointerSet - remat pointer to data space                 */
9437 /*-----------------------------------------------------------------*/
9438 static void
9439 genDataPointerSet (operand * right,
9440                    operand * result,
9441                    iCode * ic)
9442 {
9443   int size, offset = 0;
9444   char *l, buffer[256];
9445
9446   aopOp (right, ic, FALSE, FALSE);
9447
9448   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9449   size = AOP_SIZE (right);
9450   while (size--)
9451     {
9452       if (offset)
9453         sprintf (buffer, "(%s + %d)", l + 1, offset);
9454       else
9455         sprintf (buffer, "%s", l + 1);
9456       emitcode ("mov", "%s,%s", buffer,
9457                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9458     }
9459
9460   freeAsmop (right, NULL, ic, TRUE);
9461   freeAsmop (result, NULL, ic, TRUE);
9462 }
9463
9464 /*-----------------------------------------------------------------*/
9465 /* genNearPointerSet - emitcode for near pointer put                */
9466 /*-----------------------------------------------------------------*/
9467 static void
9468 genNearPointerSet (operand * right,
9469                    operand * result,
9470                    iCode * ic,
9471                    iCode * pi)
9472 {
9473   asmop *aop = NULL;
9474   regs *preg = NULL;
9475   char *rname, *l;
9476   sym_link *retype, *letype;
9477   sym_link *ptype = operandType (result);
9478
9479   retype = getSpec (operandType (right));
9480   letype = getSpec (ptype);
9481
9482   aopOp (result, ic, FALSE, FALSE);
9483
9484   /* if the result is rematerializable &
9485      in data space & not a bit variable */
9486   if (AOP_TYPE (result) == AOP_IMMD &&
9487       DCL_TYPE (ptype) == POINTER &&
9488       !IS_BITVAR (retype) &&
9489       !IS_BITVAR (letype))
9490     {
9491       genDataPointerSet (right, result, ic);
9492       return;
9493     }
9494
9495   /* if the value is already in a pointer register
9496      then don't need anything more */
9497   if (!AOP_INPREG (AOP (result)))
9498     {
9499       /* otherwise get a free pointer register */
9500       aop = newAsmop (0);
9501       preg = getFreePtr (ic, &aop, FALSE);
9502       emitcode ("mov", "%s,%s",
9503                 preg->name,
9504                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9505       rname = preg->name;
9506     }
9507   else
9508     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9509
9510   aopOp (right, ic, FALSE, FALSE);
9511
9512   /* if bitfield then unpack the bits */
9513   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9514     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9515   else
9516     {
9517       /* we have can just get the values */
9518       int size = AOP_SIZE (right);
9519       int offset = 0;
9520
9521       while (size--)
9522         {
9523           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9524           if (*l == '@')
9525             {
9526               MOVA (l);
9527               emitcode ("mov", "@%s,a", rname);
9528             }
9529           else
9530             emitcode ("mov", "@%s,%s", rname, l);
9531           if (size || pi)
9532             emitcode ("inc", "%s", rname);
9533           offset++;
9534         }
9535     }
9536
9537   /* now some housekeeping stuff */
9538   if (aop)
9539     {
9540       /* we had to allocate for this iCode */
9541       if (pi) aopPut (AOP (result),rname,0);
9542       freeAsmop (NULL, aop, ic, TRUE);
9543     }
9544   else
9545     {
9546       /* we did not allocate which means left
9547          already in a pointer register, then
9548          if size > 0 && this could be used again
9549          we have to point it back to where it
9550          belongs */
9551       if (AOP_SIZE (right) > 1 &&
9552           !OP_SYMBOL (result)->remat &&
9553           (OP_SYMBOL (result)->liveTo > ic->seq ||
9554            ic->depth) &&
9555           !pi)
9556         {
9557           int size = AOP_SIZE (right) - 1;
9558           while (size--)
9559             emitcode ("dec", "%s", rname);
9560         }
9561     }
9562
9563   /* done */
9564   if (pi) pi->generated = 1;
9565   freeAsmop (result, NULL, ic, TRUE);
9566   freeAsmop (right, NULL, ic, TRUE);
9567
9568
9569 }
9570
9571 /*-----------------------------------------------------------------*/
9572 /* genPagedPointerSet - emitcode for Paged pointer put             */
9573 /*-----------------------------------------------------------------*/
9574 static void
9575 genPagedPointerSet (operand * right,
9576                     operand * result,
9577                     iCode * ic,
9578                     iCode *pi)
9579 {
9580   asmop *aop = NULL;
9581   regs *preg = NULL;
9582   char *rname, *l;
9583   sym_link *retype, *letype;
9584
9585   retype = getSpec (operandType (right));
9586   letype = getSpec (operandType (result));
9587
9588   aopOp (result, ic, FALSE, FALSE);
9589
9590   /* if the value is already in a pointer register
9591      then don't need anything more */
9592   if (!AOP_INPREG (AOP (result)))
9593     {
9594       /* otherwise get a free pointer register */
9595       aop = newAsmop (0);
9596       preg = getFreePtr (ic, &aop, FALSE);
9597       emitcode ("mov", "%s,%s",
9598                 preg->name,
9599                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9600       rname = preg->name;
9601     }
9602   else
9603     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9604
9605   aopOp (right, ic, FALSE, FALSE);
9606
9607   /* if bitfield then unpack the bits */
9608   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9609     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9610   else
9611     {
9612       /* we have can just get the values */
9613       int size = AOP_SIZE (right);
9614       int offset = 0;
9615
9616       while (size--)
9617         {
9618           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9619
9620           MOVA (l);
9621           emitcode ("movx", "@%s,a", rname);
9622
9623           if (size || pi)
9624             emitcode ("inc", "%s", rname);
9625
9626           offset++;
9627         }
9628     }
9629
9630   /* now some housekeeping stuff */
9631   if (aop)
9632     {
9633       if (pi) aopPut (AOP (result),rname,0);
9634       /* we had to allocate for this iCode */
9635       freeAsmop (NULL, aop, ic, TRUE);
9636     }
9637   else
9638     {
9639       /* we did not allocate which means left
9640          already in a pointer register, then
9641          if size > 0 && this could be used again
9642          we have to point it back to where it
9643          belongs */
9644       if (AOP_SIZE (right) > 1 &&
9645           !OP_SYMBOL (result)->remat &&
9646           (OP_SYMBOL (result)->liveTo > ic->seq ||
9647            ic->depth) &&
9648           !pi)
9649         {
9650           int size = AOP_SIZE (right) - 1;
9651           while (size--)
9652             emitcode ("dec", "%s", rname);
9653         }
9654     }
9655
9656   /* done */
9657   if (pi) pi->generated = 1;
9658   freeAsmop (result, NULL, ic, TRUE);
9659   freeAsmop (right, NULL, ic, TRUE);
9660
9661
9662 }
9663
9664 /*-----------------------------------------------------------------*/
9665 /* genFarPointerSet - set value from far space                     */
9666 /*-----------------------------------------------------------------*/
9667 static void
9668 genFarPointerSet (operand * right,
9669                   operand * result, iCode * ic, iCode *pi)
9670 {
9671   int size, offset, dopi=1;
9672   sym_link *retype = getSpec (operandType (right));
9673   sym_link *letype = getSpec (operandType (result));
9674
9675   aopOp (result, ic, FALSE, FALSE);
9676
9677   /* if the operand is already in dptr
9678      then we do nothing else we move the value to dptr */
9679   if (AOP_TYPE (result) != AOP_STR)
9680     {
9681       /* if this is remateriazable */
9682       if (AOP_TYPE (result) == AOP_IMMD)
9683         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9684       else
9685         {
9686           /* we need to get it byte by byte */
9687           _startLazyDPSEvaluation ();
9688           if (AOP_TYPE (result) != AOP_DPTR)
9689             {
9690               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9691               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9692               if (options.model == MODEL_FLAT24)
9693                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9694             }
9695           else
9696             {
9697               /* We need to generate a load to DPTR indirect through DPTR. */
9698               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9699                 );
9700               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9701               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9702               if (options.model == MODEL_FLAT24)
9703                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9704               emitcode ("pop", "dph");
9705               emitcode ("pop", "dpl");
9706               dopi=0;
9707             }
9708           _endLazyDPSEvaluation ();
9709         }
9710     }
9711   /* so dptr know contains the address */
9712   aopOp (right, ic, FALSE, TRUE);
9713
9714   /* if bit then unpack */
9715   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9716     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9717   else
9718     {
9719       size = AOP_SIZE (right);
9720       offset = 0;
9721
9722       _startLazyDPSEvaluation ();
9723       while (size--)
9724         {
9725           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9726           MOVA (l);
9727
9728           genSetDPTR (0);
9729           _flushLazyDPS ();
9730
9731           emitcode ("movx", "@dptr,a");
9732           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9733             emitcode ("inc", "dptr");
9734         }
9735       _endLazyDPSEvaluation ();
9736     }
9737
9738   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9739       aopPut (AOP(result),"dpl",0);
9740       aopPut (AOP(result),"dph",1);
9741       if (options.model == MODEL_FLAT24)
9742           aopPut (AOP(result),"dpx",2);
9743       pi->generated=1;
9744   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9745              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9746       
9747       size = AOP_SIZE (right) - 1;
9748       while (size--) emitcode ("lcall","__decdptr");
9749   }
9750   freeAsmop (result, NULL, ic, TRUE);
9751   freeAsmop (right, NULL, ic, TRUE);
9752 }
9753
9754 /*-----------------------------------------------------------------*/
9755 /* genGenPointerSet - set value from generic pointer space         */
9756 /*-----------------------------------------------------------------*/
9757 static void
9758 genGenPointerSet (operand * right,
9759                   operand * result, iCode * ic, iCode *pi)
9760 {
9761   int size, offset;
9762   sym_link *retype = getSpec (operandType (right));
9763   sym_link *letype = getSpec (operandType (result));
9764
9765   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9766
9767   /* if the operand is already in dptr
9768      then we do nothing else we move the value to dptr */
9769   if (AOP_TYPE (result) != AOP_STR)
9770     {
9771       _startLazyDPSEvaluation ();
9772       /* if this is remateriazable */
9773       if (AOP_TYPE (result) == AOP_IMMD)
9774         {
9775           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9776           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9777                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9778           else
9779                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9780         }
9781       else
9782         {                       /* we need to get it byte by byte */
9783           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9784           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9785           if (options.model == MODEL_FLAT24) {
9786             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9787             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9788           } else {
9789             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9790           }
9791         }
9792       _endLazyDPSEvaluation ();
9793     }
9794   /* so dptr know contains the address */
9795   aopOp (right, ic, FALSE, TRUE);
9796
9797   /* if bit then unpack */
9798   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9799     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9800   else
9801     {
9802       size = AOP_SIZE (right);
9803       offset = 0;
9804
9805       _startLazyDPSEvaluation ();
9806       while (size--)
9807         {
9808           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9809           MOVA (l);
9810
9811           genSetDPTR (0);
9812           _flushLazyDPS ();
9813
9814           emitcode ("lcall", "__gptrput");
9815           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9816             emitcode ("inc", "dptr");
9817         }
9818       _endLazyDPSEvaluation ();
9819     }
9820
9821   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9822       aopPut (AOP(result),"dpl",0);
9823       aopPut (AOP(result),"dph",1);
9824       if (options.model == MODEL_FLAT24) {
9825           aopPut (AOP(result),"dpx",2);
9826           aopPut (AOP(result),"b",3);
9827       } else {
9828           aopPut (AOP(result),"b",2);
9829       }
9830       pi->generated=1;
9831   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9832              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9833       
9834       size = AOP_SIZE (right) - 1;
9835       while (size--) emitcode ("lcall","__decdptr");
9836   }
9837   freeAsmop (result, NULL, ic, TRUE);
9838   freeAsmop (right, NULL, ic, TRUE);
9839 }
9840
9841 /*-----------------------------------------------------------------*/
9842 /* genPointerSet - stores the value into a pointer location        */
9843 /*-----------------------------------------------------------------*/
9844 static void
9845 genPointerSet (iCode * ic, iCode *pi)
9846 {
9847   operand *right, *result;
9848   sym_link *type, *etype;
9849   int p_type;
9850
9851   D (emitcode (";", "genPointerSet ");
9852     );
9853
9854   right = IC_RIGHT (ic);
9855   result = IC_RESULT (ic);
9856
9857   /* depending on the type of pointer we need to
9858      move it to the correct pointer register */
9859   type = operandType (result);
9860   etype = getSpec (type);
9861   /* if left is of type of pointer then it is simple */
9862   if (IS_PTR (type) && !IS_FUNC (type->next))
9863     {
9864       p_type = DCL_TYPE (type);
9865     }
9866   else
9867     {
9868       /* we have to go by the storage class */
9869       p_type = PTR_TYPE (SPEC_OCLS (etype));
9870     }
9871   /* special case when cast remat */
9872   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9873       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9874           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9875           type =   type = operandType (result);
9876           p_type = DCL_TYPE (type);
9877   }
9878
9879   /* now that we have the pointer type we assign
9880      the pointer values */
9881   switch (p_type)
9882     {
9883
9884     case POINTER:
9885     case IPOINTER:
9886       genNearPointerSet (right, result, ic, pi);
9887       break;
9888
9889     case PPOINTER:
9890       genPagedPointerSet (right, result, ic, pi);
9891       break;
9892
9893     case FPOINTER:
9894       genFarPointerSet (right, result, ic, pi);
9895       break;
9896
9897     case GPOINTER:
9898       genGenPointerSet (right, result, ic, pi);
9899       break;
9900     }
9901
9902 }
9903
9904 /*-----------------------------------------------------------------*/
9905 /* genIfx - generate code for Ifx statement                        */
9906 /*-----------------------------------------------------------------*/
9907 static void
9908 genIfx (iCode * ic, iCode * popIc)
9909 {
9910   operand *cond = IC_COND (ic);
9911   int isbit = 0;
9912
9913   D (emitcode (";", "genIfx "););
9914
9915   aopOp (cond, ic, FALSE, FALSE);
9916
9917   /* get the value into acc */
9918   if (AOP_TYPE (cond) != AOP_CRY)
9919     toBoolean (cond);
9920   else
9921     isbit = 1;
9922   /* the result is now in the accumulator */
9923   freeAsmop (cond, NULL, ic, TRUE);
9924
9925   /* if there was something to be popped then do it */
9926   if (popIc)
9927     genIpop (popIc);
9928
9929   /* if the condition is  a bit variable */
9930   if (isbit && IS_ITEMP (cond) &&
9931       SPIL_LOC (cond))
9932     genIfxJump (ic, SPIL_LOC (cond)->rname);
9933   else if (isbit && !IS_ITEMP (cond))
9934     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9935   else
9936     genIfxJump (ic, "a");
9937
9938   ic->generated = 1;
9939 }
9940
9941 /*-----------------------------------------------------------------*/
9942 /* genAddrOf - generates code for address of                       */
9943 /*-----------------------------------------------------------------*/
9944 static void
9945 genAddrOf (iCode * ic)
9946 {
9947   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9948   int size, offset;
9949
9950   D (emitcode (";", "genAddrOf ");
9951     );
9952
9953   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9954
9955   /* if the operand is on the stack then we
9956      need to get the stack offset of this
9957      variable */
9958   if (sym->onStack) {
9959       
9960       /* if 10 bit stack */
9961       if (options.stack10bit) {
9962           char buff[10];
9963           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
9964           /* if it has an offset then we need to compute it */
9965           emitcode ("subb", "a,#!constbyte",
9966                     -((sym->stack < 0) ?
9967                       ((short) (sym->stack - _G.nRegsSaved)) :
9968                       ((short) sym->stack)) & 0xff);
9969           emitcode ("mov","b,a");
9970           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
9971                                          ((short) (sym->stack - _G.nRegsSaved)) :
9972                                          ((short) sym->stack)) >> 8) & 0xff);
9973           if (sym->stack) {
9974               emitcode ("mov", "a,_bpx");
9975               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
9976                                              ((char) (sym->stack - _G.nRegsSaved)) :
9977                                              ((char) sym->stack )) & 0xff);
9978               emitcode ("mov", "b,a");
9979               emitcode ("mov", "a,_bpx+1");
9980               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
9981                                               ((short) (sym->stack - _G.nRegsSaved)) :
9982                                               ((short) sym->stack )) >> 8) & 0xff);
9983               aopPut (AOP (IC_RESULT (ic)), "b", 0);
9984               aopPut (AOP (IC_RESULT (ic)), "a", 1);
9985               aopPut (AOP (IC_RESULT (ic)), buff, 2);
9986           } else {
9987               /* we can just move _bp */
9988               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
9989               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
9990               aopPut (AOP (IC_RESULT (ic)), buff, 2);
9991           }       
9992       } else {
9993           /* if it has an offset then we need to compute it */
9994           if (sym->stack) {
9995               emitcode ("mov", "a,_bp");
9996               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
9997               aopPut (AOP (IC_RESULT (ic)), "a", 0);
9998           } else {
9999               /* we can just move _bp */
10000               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10001           }
10002           /* fill the result with zero */
10003           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10004           
10005           
10006           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10007               fprintf (stderr,
10008                        "*** warning: pointer to stack var truncated.\n");
10009           }
10010
10011           offset = 1;
10012           while (size--) {
10013               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10014           }      
10015       }
10016       goto release;
10017   }
10018
10019   /* object not on stack then we need the name */
10020   size = AOP_SIZE (IC_RESULT (ic));
10021   offset = 0;
10022
10023   while (size--)
10024     {
10025       char s[SDCC_NAME_MAX];
10026       if (offset) {
10027           switch (offset) {
10028           case 1:
10029               tsprintf(s,"!his",sym->rname);
10030               break;
10031           case 2:
10032               tsprintf(s,"!hihis",sym->rname);
10033               break;
10034           case 3:
10035               tsprintf(s,"!hihihis",sym->rname);
10036               break;
10037           default: /* should not need this (just in case) */
10038               sprintf (s, "#(%s >> %d)",
10039                        sym->rname,
10040                        offset * 8);
10041           }
10042       } else
10043           sprintf (s, "#%s", sym->rname);
10044       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10045     }
10046
10047 release:
10048   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10049
10050 }
10051
10052 /*-----------------------------------------------------------------*/
10053 /* genArrayInit - generates code for address of                       */
10054 /*-----------------------------------------------------------------*/
10055 static void
10056 genArrayInit (iCode * ic)
10057 {
10058     literalList *iLoop;
10059     int         ix, count;
10060     int         elementSize = 0, eIndex;
10061     unsigned    val, lastVal;
10062     sym_link    *type;
10063     operand     *left=IC_LEFT(ic);
10064     
10065     D (emitcode (";", "genArrayInit "););
10066
10067     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10068     
10069     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10070     {
10071         // Load immediate value into DPTR.
10072         emitcode("mov", "dptr, %s",
10073              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10074     }
10075     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10076     {
10077 #if 0
10078       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10079               "Unexpected operand to genArrayInit.\n");
10080       exit(1);
10081 #else
10082       // a regression because of SDCCcse.c:1.52
10083       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10084       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10085       if (options.model == MODEL_FLAT24)
10086         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10087 #endif
10088     }
10089     
10090     type = operandType(IC_LEFT(ic));
10091     
10092     if (type && type->next)
10093     {
10094         elementSize = getSize(type->next);
10095     }
10096     else
10097     {
10098         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10099                                 "can't determine element size in genArrayInit.\n");
10100         exit(1);
10101     }
10102     
10103     iLoop = IC_ARRAYILIST(ic);
10104     lastVal = 0xffff;
10105     
10106     while (iLoop)
10107     {
10108         bool firstpass = TRUE;
10109         
10110         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10111                  iLoop->count, (int)iLoop->literalValue, elementSize);
10112         
10113         ix = iLoop->count;
10114         
10115         while (ix)
10116         {
10117             symbol *tlbl = NULL;
10118             
10119             count = ix > 256 ? 256 : ix;
10120             
10121             if (count > 1)
10122             {
10123                 tlbl = newiTempLabel (NULL);
10124                 if (firstpass || (count & 0xff))
10125                 {
10126                     emitcode("mov", "b, #!constbyte", count & 0xff);
10127                 }
10128                 
10129                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10130             }
10131             
10132             firstpass = FALSE;
10133                 
10134             for (eIndex = 0; eIndex < elementSize; eIndex++)
10135             {
10136                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10137                 if (val != lastVal)
10138                 {
10139                     emitcode("mov", "a, #!constbyte", val);
10140                     lastVal = val;
10141                 }
10142                 
10143                 emitcode("movx", "@dptr, a");
10144                 emitcode("inc", "dptr");
10145             }
10146             
10147             if (count > 1)
10148             {
10149                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10150             }
10151             
10152             ix -= count;
10153         }
10154         
10155         iLoop = iLoop->next;
10156     }
10157     
10158     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10159 }
10160
10161 /*-----------------------------------------------------------------*/
10162 /* genFarFarAssign - assignment when both are in far space         */
10163 /*-----------------------------------------------------------------*/
10164 static void
10165 genFarFarAssign (operand * result, operand * right, iCode * ic)
10166 {
10167   int size = AOP_SIZE (right);
10168   int offset = 0;
10169   symbol *rSym = NULL;
10170
10171   if (size == 1)
10172   {
10173       /* quick & easy case. */
10174       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10175       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10176       freeAsmop (right, NULL, ic, FALSE);
10177       /* now assign DPTR to result */
10178       _G.accInUse++;
10179       aopOp(result, ic, FALSE, FALSE);
10180       _G.accInUse--;
10181       aopPut(AOP(result), "a", 0);
10182       freeAsmop(result, NULL, ic, FALSE);
10183       return;
10184   }
10185   
10186   /* See if we've got an underlying symbol to abuse. */
10187   if (IS_SYMOP(result) && OP_SYMBOL(result))
10188   {
10189       if (IS_TRUE_SYMOP(result))
10190       {
10191           rSym = OP_SYMBOL(result);
10192       }
10193       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10194       {
10195           rSym = OP_SYMBOL(result)->usl.spillLoc;
10196       }
10197   }
10198              
10199   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10200   {
10201       /* We can use the '390 auto-toggle feature to good effect here. */
10202       
10203       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10204       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
10205       emitcode ("mov", "dptr,#%s", rSym->rname); 
10206       /* DP2 = result, DP1 = right, DP1 is current. */
10207       while (size)
10208       {
10209           emitcode("movx", "a,@dptr");
10210           emitcode("movx", "@dptr,a");
10211           if (--size)
10212           {
10213                emitcode("inc", "dptr");
10214                emitcode("inc", "dptr");
10215           }
10216       }
10217       emitcode("mov", "dps, #0");
10218       freeAsmop (right, NULL, ic, FALSE);
10219 #if 0
10220 some alternative code for processors without auto-toggle
10221 no time to test now, so later well put in...kpb
10222         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10223         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
10224         emitcode ("mov", "dptr,#%s", rSym->rname); 
10225         /* DP2 = result, DP1 = right, DP1 is current. */
10226         while (size)
10227         {
10228           --size;
10229           emitcode("movx", "a,@dptr");
10230           if (size)
10231             emitcode("inc", "dptr");
10232           emitcode("inc", "dps");
10233           emitcode("movx", "@dptr,a");
10234           if (size)
10235             emitcode("inc", "dptr");
10236           emitcode("inc", "dps");
10237         }
10238         emitcode("mov", "dps, #0");
10239         freeAsmop (right, NULL, ic, FALSE);
10240 #endif
10241   }
10242   else
10243   {
10244       D (emitcode (";", "genFarFarAssign"););
10245       aopOp (result, ic, TRUE, TRUE);
10246
10247       _startLazyDPSEvaluation ();
10248       
10249       while (size--)
10250         {
10251           aopPut (AOP (result),
10252                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10253           offset++;
10254         }
10255       _endLazyDPSEvaluation ();
10256       freeAsmop (result, NULL, ic, FALSE);
10257       freeAsmop (right, NULL, ic, FALSE);
10258   }
10259 }
10260
10261 /*-----------------------------------------------------------------*/
10262 /* genAssign - generate code for assignment                        */
10263 /*-----------------------------------------------------------------*/
10264 static void
10265 genAssign (iCode * ic)
10266 {
10267   operand *result, *right;
10268   int size, offset;
10269   unsigned long lit = 0L;
10270
10271   D (emitcode (";", "genAssign ");
10272     );
10273
10274   result = IC_RESULT (ic);
10275   right = IC_RIGHT (ic);
10276
10277   /* if they are the same */
10278   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10279     return;
10280
10281   aopOp (right, ic, FALSE, FALSE);
10282
10283   emitcode (";", "genAssign: resultIsFar = %s",
10284             isOperandInFarSpace (result) ?
10285             "TRUE" : "FALSE");
10286
10287   /* special case both in far space */
10288   if ((AOP_TYPE (right) == AOP_DPTR ||
10289        AOP_TYPE (right) == AOP_DPTR2) &&
10290   /* IS_TRUE_SYMOP(result)       && */
10291       isOperandInFarSpace (result))
10292     {
10293       genFarFarAssign (result, right, ic);
10294       return;
10295     }
10296
10297   aopOp (result, ic, TRUE, FALSE);
10298
10299   /* if they are the same registers */
10300   if (sameRegs (AOP (right), AOP (result)))
10301     goto release;
10302
10303   /* if the result is a bit */
10304   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10305     {
10306       /* if the right size is a literal then
10307          we know what the value is */
10308       if (AOP_TYPE (right) == AOP_LIT)
10309         {
10310           if (((int) operandLitValue (right)))
10311             aopPut (AOP (result), one, 0);
10312           else
10313             aopPut (AOP (result), zero, 0);
10314           goto release;
10315         }
10316
10317       /* the right is also a bit variable */
10318       if (AOP_TYPE (right) == AOP_CRY)
10319         {
10320           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10321           aopPut (AOP (result), "c", 0);
10322           goto release;
10323         }
10324
10325       /* we need to or */
10326       toBoolean (right);
10327       aopPut (AOP (result), "a", 0);
10328       goto release;
10329     }
10330
10331   /* bit variables done */
10332   /* general case */
10333   size = AOP_SIZE (result);
10334   offset = 0;
10335   if (AOP_TYPE (right) == AOP_LIT)
10336     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10337
10338   if ((size > 1) &&
10339       (AOP_TYPE (result) != AOP_REG) &&
10340       (AOP_TYPE (right) == AOP_LIT) &&
10341       !IS_FLOAT (operandType (right)))
10342     {
10343       _startLazyDPSEvaluation ();
10344       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10345         {
10346           aopPut (AOP (result),
10347                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10348                   offset);
10349           offset++;
10350           size--;
10351         }
10352       /* And now fill the rest with zeros. */
10353       if (size)
10354         {
10355           emitcode ("clr", "a");
10356         }
10357       while (size--)
10358         {
10359           aopPut (AOP (result), "a", offset++);
10360         }
10361       _endLazyDPSEvaluation ();
10362     }
10363   else
10364     {
10365       _startLazyDPSEvaluation ();
10366       while (size--)
10367         {
10368           aopPut (AOP (result),
10369                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10370                   offset);
10371           offset++;
10372         }
10373       _endLazyDPSEvaluation ();
10374     }
10375
10376 release:
10377   freeAsmop (right, NULL, ic, FALSE);
10378   freeAsmop (result, NULL, ic, TRUE);
10379 }
10380
10381 /*-----------------------------------------------------------------*/
10382 /* genJumpTab - generates code for jump table                      */
10383 /*-----------------------------------------------------------------*/
10384 static void
10385 genJumpTab (iCode * ic)
10386 {
10387   symbol *jtab;
10388   char *l;
10389
10390   D (emitcode (";", "genJumpTab ");
10391     );
10392
10393   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10394   /* get the condition into accumulator */
10395   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10396   MOVA (l);
10397   /* multiply by four! */
10398   emitcode ("add", "a,acc");
10399   emitcode ("add", "a,acc");
10400   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10401
10402   jtab = newiTempLabel (NULL);
10403   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10404   emitcode ("jmp", "@a+dptr");
10405   emitcode ("", "!tlabeldef", jtab->key + 100);
10406   /* now generate the jump labels */
10407   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10408        jtab = setNextItem (IC_JTLABELS (ic)))
10409     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10410
10411 }
10412
10413 /*-----------------------------------------------------------------*/
10414 /* genCast - gen code for casting                                  */
10415 /*-----------------------------------------------------------------*/
10416 static void
10417 genCast (iCode * ic)
10418 {
10419   operand *result = IC_RESULT (ic);
10420   sym_link *ctype = operandType (IC_LEFT (ic));
10421   sym_link *rtype = operandType (IC_RIGHT (ic));
10422   operand *right = IC_RIGHT (ic);
10423   int size, offset;
10424
10425   D (emitcode (";", "genCast ");
10426     );
10427
10428   /* if they are equivalent then do nothing */
10429   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10430     return;
10431
10432   aopOp (right, ic, FALSE, FALSE);
10433   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10434
10435   /* if the result is a bit */
10436   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10437   if (IS_BITVAR(OP_SYMBOL(result)->type))
10438     {
10439       /* if the right size is a literal then
10440          we know what the value is */
10441       if (AOP_TYPE (right) == AOP_LIT)
10442         {
10443           if (((int) operandLitValue (right)))
10444             aopPut (AOP (result), one, 0);
10445           else
10446             aopPut (AOP (result), zero, 0);
10447
10448           goto release;
10449         }
10450
10451       /* the right is also a bit variable */
10452       if (AOP_TYPE (right) == AOP_CRY)
10453         {
10454           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10455           aopPut (AOP (result), "c", 0);
10456           goto release;
10457         }
10458
10459       /* we need to or */
10460       toBoolean (right);
10461       aopPut (AOP (result), "a", 0);
10462       goto release;
10463     }
10464
10465   /* if they are the same size : or less */
10466   if (AOP_SIZE (result) <= AOP_SIZE (right))
10467     {
10468
10469       /* if they are in the same place */
10470       if (sameRegs (AOP (right), AOP (result)))
10471         goto release;
10472
10473       /* if they in different places then copy */
10474       size = AOP_SIZE (result);
10475       offset = 0;
10476       _startLazyDPSEvaluation ();
10477       while (size--)
10478         {
10479           aopPut (AOP (result),
10480                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10481                   offset);
10482           offset++;
10483         }
10484       _endLazyDPSEvaluation ();
10485       goto release;
10486     }
10487
10488
10489   /* if the result is of type pointer */
10490   if (IS_PTR (ctype))
10491     {
10492
10493       int p_type;
10494       sym_link *type = operandType (right);
10495
10496       /* pointer to generic pointer */
10497       if (IS_GENPTR (ctype))
10498         {
10499           char *l = zero;
10500
10501           if (IS_PTR (type))
10502             {
10503               p_type = DCL_TYPE (type);
10504             }
10505           else
10506             {
10507 #if OLD_CAST_BEHAVIOR
10508               /* KV: we are converting a non-pointer type to
10509                * a generic pointer. This (ifdef'd out) code
10510                * says that the resulting generic pointer
10511                * should have the same class as the storage
10512                * location of the non-pointer variable.
10513                *
10514                * For example, converting an int (which happens
10515                * to be stored in DATA space) to a pointer results
10516                * in a DATA generic pointer; if the original int
10517                * in XDATA space, so will be the resulting pointer.
10518                *
10519                * I don't like that behavior, and thus this change:
10520                * all such conversions will be forced to XDATA and
10521                * throw a warning. If you want some non-XDATA
10522                * type, or you want to suppress the warning, you
10523                * must go through an intermediate cast, like so:
10524                *
10525                * char _generic *gp = (char _xdata *)(intVar);
10526                */
10527               sym_link *etype = getSpec (type);
10528
10529               /* we have to go by the storage class */
10530               if (SPEC_OCLS (etype) != generic)
10531                 {
10532                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10533                 }
10534               else
10535 #endif
10536                 {
10537                   /* Converting unknown class (i.e. register variable)
10538                    * to generic pointer. This is not good, but
10539                    * we'll make a guess (and throw a warning).
10540                    */
10541                   p_type = FPOINTER;
10542                   werror (W_INT_TO_GEN_PTR_CAST);
10543                 }
10544             }
10545
10546           /* the first two bytes are known */
10547           size = GPTRSIZE - 1;
10548           offset = 0;
10549           _startLazyDPSEvaluation ();
10550           while (size--)
10551             {
10552               aopPut (AOP (result),
10553                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10554                       offset);
10555               offset++;
10556             }
10557           _endLazyDPSEvaluation ();
10558
10559           /* the last byte depending on type */
10560           switch (p_type)
10561             {
10562             case IPOINTER:
10563             case POINTER:
10564               l = zero;
10565               break;
10566             case FPOINTER:
10567               l = one;
10568               break;
10569             case CPOINTER:
10570               l = "#0x02";
10571               break;
10572             case PPOINTER:
10573               l = "#0x03";
10574               break;
10575
10576             default:
10577               /* this should never happen */
10578               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10579                       "got unknown pointer type");
10580               exit (1);
10581             }
10582           aopPut (AOP (result), l, GPTRSIZE - 1);
10583           goto release;
10584         }
10585
10586       /* just copy the pointers */
10587       size = AOP_SIZE (result);
10588       offset = 0;
10589       _startLazyDPSEvaluation ();
10590       while (size--)
10591         {
10592           aopPut (AOP (result),
10593                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10594                   offset);
10595           offset++;
10596         }
10597       _endLazyDPSEvaluation ();
10598       goto release;
10599     }
10600
10601   /* so we now know that the size of destination is greater
10602      than the size of the source */
10603   /* we move to result for the size of source */
10604   size = AOP_SIZE (right);
10605   offset = 0;
10606   _startLazyDPSEvaluation ();
10607   while (size--)
10608     {
10609       aopPut (AOP (result),
10610               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10611               offset);
10612       offset++;
10613     }
10614   _endLazyDPSEvaluation ();
10615
10616   /* now depending on the sign of the source && destination */
10617   size = AOP_SIZE (result) - AOP_SIZE (right);
10618   /* if unsigned or not an integral type */
10619   /* also, if the source is a bit, we don't need to sign extend, because
10620    * it can't possibly have set the sign bit.
10621    */
10622   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10623     {
10624       while (size--)
10625         {
10626           aopPut (AOP (result), zero, offset++);
10627         }
10628     }
10629   else
10630     {
10631       /* we need to extend the sign :{ */
10632       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10633                         FALSE, FALSE, TRUE);
10634       MOVA (l);
10635       emitcode ("rlc", "a");
10636       emitcode ("subb", "a,acc");
10637       while (size--)
10638         aopPut (AOP (result), "a", offset++);
10639     }
10640
10641   /* we are done hurray !!!! */
10642
10643 release:
10644   freeAsmop (right, NULL, ic, TRUE);
10645   freeAsmop (result, NULL, ic, TRUE);
10646
10647 }
10648
10649 /*-----------------------------------------------------------------*/
10650 /* genDjnz - generate decrement & jump if not zero instrucion      */
10651 /*-----------------------------------------------------------------*/
10652 static int
10653 genDjnz (iCode * ic, iCode * ifx)
10654 {
10655   symbol *lbl, *lbl1;
10656   if (!ifx)
10657     return 0;
10658
10659   /* if the if condition has a false label
10660      then we cannot save */
10661   if (IC_FALSE (ifx))
10662     return 0;
10663
10664   /* if the minus is not of the form
10665      a = a - 1 */
10666   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10667       !IS_OP_LITERAL (IC_RIGHT (ic)))
10668     return 0;
10669
10670   if (operandLitValue (IC_RIGHT (ic)) != 1)
10671     return 0;
10672
10673   /* if the size of this greater than one then no
10674      saving */
10675   if (getSize (operandType (IC_RESULT (ic))) > 1)
10676     return 0;
10677
10678   /* otherwise we can save BIG */
10679   D(emitcode(";", "genDjnz"););
10680
10681   lbl = newiTempLabel (NULL);
10682   lbl1 = newiTempLabel (NULL);
10683
10684   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10685
10686   if (AOP_NEEDSACC(IC_RESULT(ic)))
10687   {
10688       /* If the result is accessed indirectly via
10689        * the accumulator, we must explicitly write
10690        * it back after the decrement.
10691        */
10692       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10693       
10694       if (strcmp(rByte, "a"))
10695       {
10696            /* Something is hopelessly wrong */
10697            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10698                    __FILE__, __LINE__);
10699            /* We can just give up; the generated code will be inefficient,
10700             * but what the hey.
10701             */
10702            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10703            return 0;
10704       }
10705       emitcode ("dec", "%s", rByte);
10706       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10707       emitcode ("jnz", "!tlabel", lbl->key + 100);
10708   }
10709   else if (IS_AOP_PREG (IC_RESULT (ic)))
10710     {
10711       emitcode ("dec", "%s",
10712                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10713       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10714       emitcode ("jnz", "!tlabel", lbl->key + 100);
10715     }
10716   else
10717     {
10718       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10719                 lbl->key + 100);
10720     }
10721   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10722   emitcode ("", "!tlabeldef", lbl->key + 100);
10723   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10724   emitcode ("", "!tlabeldef", lbl1->key + 100);
10725
10726   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10727   ifx->generated = 1;
10728   return 1;
10729 }
10730
10731 /*-----------------------------------------------------------------*/
10732 /* genReceive - generate code for a receive iCode                  */
10733 /*-----------------------------------------------------------------*/
10734 static void
10735 genReceive (iCode * ic)
10736 {
10737
10738   D (emitcode (";", "genReceive ");
10739     );
10740
10741   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10742       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10743        IS_TRUE_SYMOP (IC_RESULT (ic))))
10744     {
10745       int size = getSize (operandType (IC_RESULT (ic)));
10746       int offset = fReturnSizeDS390 - size;
10747       while (size--)
10748         {
10749           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10750                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10751           offset++;
10752         }
10753       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10754       size = AOP_SIZE (IC_RESULT (ic));
10755       offset = 0;
10756       while (size--)
10757         {
10758           emitcode ("pop", "acc");
10759           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10760         }
10761
10762     }
10763   else
10764     {
10765       _G.accInUse++;
10766       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10767       _G.accInUse--;
10768       assignResultValue (IC_RESULT (ic));
10769     }
10770
10771   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10772 }
10773
10774 /*-----------------------------------------------------------------*/
10775 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10776 /*-----------------------------------------------------------------*/
10777 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10778 {
10779     operand *from , *to , *count;
10780     symbol *lbl;
10781
10782     /* we know it has to be 3 parameters */
10783     assert (nparms == 3);
10784     
10785     to = parms[0];
10786     from = parms[1];
10787     count = parms[2];
10788
10789     aopOp (from, ic->next, FALSE, FALSE);
10790
10791     /* get from into DPTR1 */
10792     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10793     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10794     if (options.model == MODEL_FLAT24) {
10795         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10796     }
10797
10798     freeAsmop (from, NULL, ic, FALSE);
10799     aopOp (to, ic, FALSE, FALSE);
10800     /* get "to" into DPTR */
10801     /* if the operand is already in dptr
10802        then we do nothing else we move the value to dptr */
10803     if (AOP_TYPE (to) != AOP_STR) {
10804         /* if already in DPTR then we need to push */
10805         if (AOP_TYPE(to) == AOP_DPTR) {
10806             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10807             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10808             if (options.model == MODEL_FLAT24)
10809                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10810             emitcode ("pop", "dph");
10811             emitcode ("pop", "dpl");        
10812         } else {
10813             _startLazyDPSEvaluation ();
10814             /* if this is remateriazable */
10815             if (AOP_TYPE (to) == AOP_IMMD) {
10816                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10817             } else {                    /* we need to get it byte by byte */
10818                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10819                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10820                 if (options.model == MODEL_FLAT24) {
10821                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10822                 }
10823             }
10824             _endLazyDPSEvaluation ();
10825         }
10826     }
10827     freeAsmop (to, NULL, ic, FALSE);
10828
10829     aopOp (count, ic->next->next, FALSE,FALSE);
10830     lbl =newiTempLabel(NULL);
10831
10832     /* now for the actual copy */
10833     if (AOP_TYPE(count) == AOP_LIT && 
10834         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10835         emitcode (";","OH! JOY auto increment with djnz (very fast)");
10836         emitcode ("mov", "dps, #0x21");         /* Select DPTR2 & auto-toggle. */
10837         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10838         emitcode ("","!tlabeldef",lbl->key+100);
10839         if (fromc) {
10840             emitcode ("clr","a");
10841             emitcode ("movc", "a,@a+dptr");
10842         } else 
10843             emitcode ("movx", "a,@dptr");
10844         emitcode ("movx", "@dptr,a");
10845         emitcode ("inc", "dptr");
10846         emitcode ("inc", "dptr");
10847         emitcode ("djnz","b,!tlabel",lbl->key+100);
10848     } else {
10849         symbol *lbl1 = newiTempLabel(NULL);
10850         
10851         emitcode (";"," Auto increment but no djnz");
10852         emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10853         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10854         emitcode ("mov", "dps, #0x21");         /* Select DPTR2 & auto-toggle. */
10855         emitcode ("","!tlabeldef",lbl->key+100);
10856         if (fromc) {
10857             emitcode ("clr","a");
10858             emitcode ("movc", "a,@a+dptr");
10859         } else 
10860             emitcode ("movx", "a,@dptr");
10861         emitcode ("movx", "@dptr,a");
10862         emitcode ("inc", "dptr");
10863         emitcode ("inc", "dptr");
10864         emitcode ("mov","a,b");
10865         emitcode ("orl","a,ap");
10866         emitcode ("jz","!tlabel",lbl1->key+100);
10867         emitcode ("mov","a,ap");
10868         emitcode ("add","a,#0xFF");
10869         emitcode ("mov","ap,a");
10870         emitcode ("mov","a,b");
10871         emitcode ("addc","a,#0xFF");
10872         emitcode ("mov","b,a");
10873         emitcode ("sjmp","!tlabel",lbl->key+100);
10874         emitcode ("","!tlabeldef",lbl1->key+100);
10875     }
10876     emitcode ("mov", "dps, #0"); 
10877     freeAsmop (count, NULL, ic, FALSE);
10878
10879 }
10880
10881 /*-----------------------------------------------------------------*/
10882 /* genMemsetX - gencode for memSetX data                           */
10883 /*-----------------------------------------------------------------*/
10884 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10885 {
10886     operand *to , *val , *count;
10887     symbol *lbl;
10888     char *l;
10889     /* we know it has to be 3 parameters */
10890     assert (nparms == 3);
10891     
10892     to = parms[0];
10893     val = parms[1];
10894     count = parms[2];
10895
10896     aopOp (to, ic, FALSE, FALSE);
10897     /* get "to" into DPTR */
10898     /* if the operand is already in dptr
10899        then we do nothing else we move the value to dptr */
10900     if (AOP_TYPE (to) != AOP_STR) {
10901         /* if already in DPTR then we need to push */
10902         if (AOP_TYPE(to) == AOP_DPTR) {
10903             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10904             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10905             if (options.model == MODEL_FLAT24)
10906                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10907             emitcode ("pop", "dph");
10908             emitcode ("pop", "dpl");        
10909         } else {
10910             _startLazyDPSEvaluation ();
10911             /* if this is remateriazable */
10912             if (AOP_TYPE (to) == AOP_IMMD) {
10913                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10914             } else {                    /* we need to get it byte by byte */
10915                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10916                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10917                 if (options.model == MODEL_FLAT24) {
10918                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10919                 }
10920             }
10921             _endLazyDPSEvaluation ();
10922         }
10923     }
10924     freeAsmop (to, NULL, ic, FALSE);
10925
10926     aopOp (val, ic->next->next, FALSE,FALSE);
10927     aopOp (count, ic->next->next, FALSE,FALSE);    
10928     lbl =newiTempLabel(NULL);
10929     /* now for the actual copy */
10930     if (AOP_TYPE(count) == AOP_LIT && 
10931         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10932         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10933         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10934         MOVA(l);
10935         emitcode ("","!tlabeldef",lbl->key+100);
10936         emitcode ("movx", "@dptr,a");
10937         emitcode ("inc", "dptr");
10938         emitcode ("djnz","b,!tlabel",lbl->key+100);
10939     } else {
10940         symbol *lbl1 = newiTempLabel(NULL);
10941         
10942         emitcode ("mov","ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10943         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10944         emitcode ("","!tlabeldef",lbl->key+100);
10945         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
10946         MOVA(l);
10947         emitcode ("movx", "a,@dptr");
10948         emitcode ("inc", "dptr");
10949         emitcode ("mov","a,b");
10950         emitcode ("orl","a,ap");
10951         emitcode ("jz","!tlabel",lbl1->key+100);
10952         emitcode ("mov","a,ap");
10953         emitcode ("add","a,#0xFF");
10954         emitcode ("mov","ap,a");
10955         emitcode ("mov","a,b");
10956         emitcode ("addc","a,#0xFF");
10957         emitcode ("mov","b,a");
10958         emitcode ("sjmp","!tlabel",lbl->key+100);
10959         emitcode ("","!tlabeldef",lbl1->key+100);
10960     }
10961     freeAsmop (count, NULL, ic, FALSE);
10962 }
10963
10964 /*-----------------------------------------------------------------*/
10965 /* genBuiltIn - calls the appropriate function to  generating code */
10966 /* for a built in function                                         */
10967 /*-----------------------------------------------------------------*/
10968 static void genBuiltIn (iCode *ic)
10969 {
10970     operand *bi_parms[MAX_BUILTIN_ARGS];
10971     int nbi_parms;
10972     iCode *bi_iCode;
10973     symbol *bif;
10974
10975     /* get all the arguments for a built in function */
10976     bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
10977
10978     /* which function is it */
10979     bif = OP_SYMBOL(IC_LEFT(bi_iCode));
10980     if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
10981         genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
10982     } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
10983         genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
10984     } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
10985         genMemsetX(bi_iCode,nbi_parms,bi_parms);
10986     } else {
10987         werror(E_INTERNAL_ERROR,"unknown builtin function encountered\n");
10988         return ;
10989     }
10990     return ;    
10991 }
10992
10993 /*-----------------------------------------------------------------*/
10994 /* gen390Code - generate code for Dallas 390 based controllers     */
10995 /*-----------------------------------------------------------------*/
10996 void
10997 gen390Code (iCode * lic)
10998 {
10999   iCode *ic;
11000   int cln = 0;
11001
11002   lineHead = lineCurr = NULL;
11003
11004   if (options.model == MODEL_FLAT24) {
11005     fReturnSizeDS390 = 5;
11006     fReturn = fReturn24;
11007   } else {
11008     fReturnSizeDS390 = 4;
11009     fReturn = fReturn16;
11010     options.stack10bit=0;
11011   }
11012 #if 0
11013   //REMOVE ME!!!
11014   /* print the allocation information */
11015   if (allocInfo)
11016     printAllocInfo (currFunc, codeOutFile);
11017 #endif
11018   /* if debug information required */
11019   if (options.debug && currFunc)
11020     {
11021       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11022       _G.debugLine = 1;
11023       if (IS_STATIC (currFunc->etype))
11024         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11025       else
11026         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11027       _G.debugLine = 0;
11028     }
11029   /* stack pointer name */
11030   if (options.useXstack)
11031     spname = "_spx";
11032   else
11033     spname = "sp";
11034
11035
11036   for (ic = lic; ic; ic = ic->next)
11037     {
11038
11039       if (cln != ic->lineno)
11040         {
11041           if (options.debug)
11042             {
11043               _G.debugLine = 1;
11044               emitcode ("", "C$%s$%d$%d$%d ==.",
11045                         FileBaseName (ic->filename), ic->lineno,
11046                         ic->level, ic->block);
11047               _G.debugLine = 0;
11048             }
11049           emitcode (";", "%s %d", ic->filename, ic->lineno);
11050           cln = ic->lineno;
11051         }
11052       /* if the result is marked as
11053          spilt and rematerializable or code for
11054          this has already been generated then
11055          do nothing */
11056       if (resultRemat (ic) || ic->generated)
11057         continue;
11058
11059       /* depending on the operation */
11060       switch (ic->op)
11061         {
11062         case '!':
11063           genNot (ic);
11064           break;
11065
11066         case '~':
11067           genCpl (ic);
11068           break;
11069
11070         case UNARYMINUS:
11071           genUminus (ic);
11072           break;
11073
11074         case IPUSH:
11075           genIpush (ic);
11076           break;
11077
11078         case IPOP:
11079           /* IPOP happens only when trying to restore a
11080              spilt live range, if there is an ifx statement
11081              following this pop then the if statement might
11082              be using some of the registers being popped which
11083              would destory the contents of the register so
11084              we need to check for this condition and handle it */
11085           if (ic->next &&
11086               ic->next->op == IFX &&
11087               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11088             genIfx (ic->next, ic);
11089           else
11090             genIpop (ic);
11091           break;
11092
11093         case CALL:
11094           genCall (ic);
11095           break;
11096
11097         case PCALL:
11098           genPcall (ic);
11099           break;
11100
11101         case FUNCTION:
11102           genFunction (ic);
11103           break;
11104
11105         case ENDFUNCTION:
11106           genEndFunction (ic);
11107           break;
11108
11109         case RETURN:
11110           genRet (ic);
11111           break;
11112
11113         case LABEL:
11114           genLabel (ic);
11115           break;
11116
11117         case GOTO:
11118           genGoto (ic);
11119           break;
11120
11121         case '+':
11122           genPlus (ic);
11123           break;
11124
11125         case '-':
11126           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11127             genMinus (ic);
11128           break;
11129
11130         case '*':
11131           genMult (ic);
11132           break;
11133
11134         case '/':
11135           genDiv (ic);
11136           break;
11137
11138         case '%':
11139           genMod (ic);
11140           break;
11141
11142         case '>':
11143           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11144           break;
11145
11146         case '<':
11147           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11148           break;
11149
11150         case LE_OP:
11151         case GE_OP:
11152         case NE_OP:
11153
11154           /* note these two are xlated by algebraic equivalence
11155              during parsing SDCC.y */
11156           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11157                   "got '>=' or '<=' shouldn't have come here");
11158           break;
11159
11160         case EQ_OP:
11161           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11162           break;
11163
11164         case AND_OP:
11165           genAndOp (ic);
11166           break;
11167
11168         case OR_OP:
11169           genOrOp (ic);
11170           break;
11171
11172         case '^':
11173           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11174           break;
11175
11176         case '|':
11177           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11178           break;
11179
11180         case BITWISEAND:
11181           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11182           break;
11183
11184         case INLINEASM:
11185           genInline (ic);
11186           break;
11187
11188         case RRC:
11189           genRRC (ic);
11190           break;
11191
11192         case RLC:
11193           genRLC (ic);
11194           break;
11195
11196         case GETHBIT:
11197           genGetHbit (ic);
11198           break;
11199
11200         case LEFT_OP:
11201           genLeftShift (ic);
11202           break;
11203
11204         case RIGHT_OP:
11205           genRightShift (ic);
11206           break;
11207
11208         case GET_VALUE_AT_ADDRESS:
11209           genPointerGet (ic,hasInc(IC_LEFT(ic),ic));
11210           break;
11211
11212         case '=':
11213           if (POINTER_SET (ic))
11214             genPointerSet (ic,hasInc(IC_RESULT(ic),ic));
11215           else
11216             genAssign (ic);
11217           break;
11218
11219         case IFX:
11220           genIfx (ic, NULL);
11221           break;
11222
11223         case ADDRESS_OF:
11224           genAddrOf (ic);
11225           break;
11226
11227         case JUMPTABLE:
11228           genJumpTab (ic);
11229           break;
11230
11231         case CAST:
11232           genCast (ic);
11233           break;
11234
11235         case RECEIVE:
11236           genReceive (ic);
11237           break;
11238
11239         case SEND:
11240           if (ic->builtinSEND) genBuiltIn(ic);
11241           else addSet (&_G.sendSet, ic);
11242           break;
11243
11244         case ARRAYINIT:
11245             genArrayInit(ic);
11246             break;
11247             
11248         default:
11249           ic = ic;
11250         }
11251     }
11252
11253
11254   /* now we are ready to call the
11255      peep hole optimizer */
11256   if (!options.nopeep)
11257     peepHole (&lineHead);
11258
11259   /* now do the actual printing */
11260   printLine (lineHead, codeOutFile);
11261   return;
11262 }