Fixed numerous bitfield problems.
[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 #define BETTER_LITERAL_SHIFT
40
41 char *aopLiteral (value * val, int offset);
42 extern int allocInfo;
43
44 /* this is the down and dirty file with all kinds of
45    kludgy & hacky stuff. This is what it is all about
46    CODE GENERATION for a specific MCU . some of the
47    routines may be reusable, will have to see */
48
49 static char *zero = "#0";
50 static char *one = "#1";
51 static char *spname;
52
53 #define D(x) x
54
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
57
58 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
65 {"a", "b"};
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
69
70 static struct
71   {
72     short r0Pushed;
73     short r1Pushed;
74     short accInUse;
75     short bInUse;
76     short inLine;
77     short debugLine;
78     short nRegsSaved;
79     short dptrInUse;
80     short dptr1InUse;
81     set *sendSet;
82   }
83 _G;
84
85 static char *rb1regs[] = {
86     "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
87 };
88
89 static void saveRBank (int, iCode *, bool);
90
91 #define RESULTONSTACK(x) \
92                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
93                          IC_RESULT(x)->aop->type == AOP_STK )
94
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
97                 
98 #define CLRC    emitcode("clr","c")
99 #define SETC    emitcode("setb","c")
100
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG  "_ap"
104
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
107
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110  0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113  0x07, 0x03, 0x01, 0x00};
114
115 #define LSB     0
116 #define MSB16   1
117 #define MSB24   2
118 #define MSB32   3
119 #define PROTECT_SP      {if (options.protect_sp_update) {                       \
120                                 symbol *lbl = newiTempLabel(NULL);              \
121                                 emitcode ("setb","F1");                         \
122                                 emitcode ("jbc","EA,!tlabel",lbl->key+100);     \
123                                 emitcode ("clr","F1");                          \
124                                 emitcode ("","!tlabeldef",lbl->key+100);        \
125                         }}
126 #define UNPROTECT_SP    { if (options.protect_sp_update) {                      \
127                                 symbol *lbl = newiTempLabel(NULL);              \
128                                 emitcode ("jnb","F1,!tlabel",lbl->key+100);     \
129                                 emitcode ("setb","EA");                         \
130                                 emitcode ("","!tlabeldef",lbl->key+100);        \
131                         }}
132
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         {
150             SNPRINTF (lb, sizeof(lb), "%s\t", inst);
151         }
152         else
153         {
154             SNPRINTF (lb, sizeof(lb), "%s", inst);
155         }
156         
157         tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), 
158                    fmt, ap);
159     }
160     else
161     {
162         tvsprintf (lb, sizeof(lb), fmt, ap);
163     }
164     
165
166     while (isspace (*lbp))
167     {
168         lbp++;
169     }
170
171     if (lbp && *lbp)
172     {
173         lineCurr = (lineCurr ?
174                     connectLine (lineCurr, newLineNode (lb)) :
175                     (lineHead = newLineNode (lb)));
176     }
177     
178     lineCurr->isInline = _G.inLine;
179     lineCurr->isDebug = _G.debugLine;
180     va_end (ap);
181 }
182
183 //
184 // Move the passed value into A unless it is already there.
185 // 
186 static void
187 _movA(const char *s)
188 {
189     if (strcmp(s,"a") && strcmp(s,"acc"))
190     { 
191         emitcode("mov","a,%s",s);
192     } 
193 }
194
195 //
196 // Move the passed value into B unless it is already there.
197 // 
198 static void
199 _movB(const char *s)
200 {
201     if (strcmp(s,"b"))
202     { 
203         emitcode("mov","b,%s",s);
204     } 
205 }
206
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
210 static regs *
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
212 {
213   bool r0iu, r1iu;
214   bool r0ou, r1ou;
215
216   /* the logic: if r0 & r1 used in the instruction
217      then we are in trouble otherwise */
218
219   /* first check if r0 & r1 are used by this
220      instruction, in which case we are in trouble */
221   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
223   if (r0iu && r1iu) {
224       goto endOfWorld;
225     }
226
227   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
229
230   /* if no usage of r0 then return it */
231   if (!r0iu && !r0ou)
232     {
233       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234       (*aopp)->type = AOP_R0;
235
236       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
237     }
238
239   /* if no usage of r1 then return it */
240   if (!r1iu && !r1ou)
241     {
242       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243       (*aopp)->type = AOP_R1;
244
245       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
246     }
247
248   /* now we know they both have usage */
249   /* if r0 not used in this instruction */
250   if (!r0iu)
251     {
252       /* push it if not already pushed */
253       if (!_G.r0Pushed)
254         {
255           emitcode ("push", "%s",
256                     ds390_regWithIdx (R0_IDX)->dname);
257           _G.r0Pushed++;
258         }
259
260       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261       (*aopp)->type = AOP_R0;
262
263       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
264     }
265
266   /* if r1 not used then */
267
268   if (!r1iu)
269     {
270       /* push it if not already pushed */
271       if (!_G.r1Pushed)
272         {
273           emitcode ("push", "%s",
274                     ds390_regWithIdx (R1_IDX)->dname);
275           _G.r1Pushed++;
276         }
277
278       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279       (*aopp)->type = AOP_R1;
280       return ds390_regWithIdx (R1_IDX);
281     }
282
283 endOfWorld:
284   /* I said end of world but not quite end of world yet */
285   /* if this is a result then we can push it on the stack */
286   if (result)
287     {
288       (*aopp)->type = AOP_STK;
289       return NULL;
290     }
291
292   /* other wise this is true end of the world */
293   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294           "getFreePtr should never reach here");
295   exit (1);
296     
297   return NULL; // notreached, but makes compiler happy.
298 }
299
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp                                  */
302 /*-----------------------------------------------------------------*/
303 static asmop *
304 newAsmop (short type)
305 {
306   asmop *aop;
307
308   aop = Safe_calloc (1, sizeof (asmop));
309   aop->type = type;
310   return aop;
311 }
312
313 static int _currentDPS;         /* Current processor DPS. */
314 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
316
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
320 /* alternate DPTR (DPL1/DPH1/DPX1).          */
321 /*-----------------------------------------------------------------*/
322 static void
323 genSetDPTR (int n)
324 {
325
326   /* If we are doing lazy evaluation, simply note the desired
327    * change, but don't emit any code yet.
328    */
329   if (_lazyDPS)
330     {
331       _desiredDPS = n;
332       return;
333     }
334
335   if (!n)
336     {
337       emitcode ("mov", "dps,#0");
338     }
339   else
340     {
341       TR_DPTR("#1");
342       emitcode ("mov", "dps,#1");
343     }
344 }
345
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
348 /*                   */
349 /* Any code that operates on DPTR (NB: not on the individual     */
350 /* components, like DPH) *must* call _flushLazyDPS() before using  */
351 /* DPTR within a lazy DPS evaluation block.        */
352 /*                   */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
355 /* DPS evaluation block.             */
356 /*                   */
357 /* Also, _flushLazyDPS must be called before any flow control      */
358 /* operations that could potentially branch out of the block.    */
359 /*                         */
360 /* Lazy DPS evaluation is simply an optimization (though an      */
361 /* important one), so if in doubt, leave it out.       */
362 /*-----------------------------------------------------------------*/
363 static void
364 _startLazyDPSEvaluation (void)
365 {
366   _currentDPS = 0;
367   _desiredDPS = 0;
368 #ifdef BETTER_LITERAL_SHIFT  
369   _lazyDPS++;
370 #else
371   _lazyDPS = 1;
372 #endif  
373 }
374
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
378 /* block.                */
379 /*-----------------------------------------------------------------*/
380 static void
381 _flushLazyDPS (void)
382 {
383   if (!_lazyDPS)
384     {
385       /* nothing to do. */
386       return;
387     }
388
389   if (_desiredDPS != _currentDPS)
390     {
391       if (_desiredDPS)
392         {
393           emitcode ("inc", "dps");
394         }
395       else
396         {
397           emitcode ("dec", "dps");
398         }
399       _currentDPS = _desiredDPS;
400     }
401 }
402
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
405 /*                   */
406 /* Forces us back to the safe state (standard DPTR selected).    */
407 /*-----------------------------------------------------------------*/
408 static void
409 _endLazyDPSEvaluation (void)
410 {
411 #ifdef BETTER_LITERAL_SHIFT  
412   _lazyDPS--;
413 #else
414   _lazyDPS = 0;
415 #endif    
416   if (!_lazyDPS)
417   {
418     if (_currentDPS)
419     {
420       genSetDPTR (0);
421       _flushLazyDPS ();
422     }
423     _currentDPS = 0;
424     _desiredDPS = 0;
425   }
426 }
427
428
429
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type               */
432 /*-----------------------------------------------------------------*/
433 static int
434 pointerCode (sym_link * etype)
435 {
436
437   return PTR_TYPE (SPEC_OCLS (etype));
438
439 }
440
441 /*-----------------------------------------------------------------*/
442 /* aopForSym - for a true symbol                                   */
443 /*-----------------------------------------------------------------*/
444 static asmop *
445 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
446 {
447   asmop *aop;
448   memmap *space = SPEC_OCLS (sym->etype);
449
450   /* if already has one */
451   if (sym->aop)
452     return sym->aop;
453
454   /* assign depending on the storage class */
455   /* if it is on the stack or indirectly addressable */
456   /* space we need to assign either r0 or r1 to it   */
457   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
458     {
459       sym->aop = aop = newAsmop (0);
460       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
461       aop->size = getSize (sym->type);
462
463       /* now assign the address of the variable to
464          the pointer register */
465       if (aop->type != AOP_STK)
466         {
467
468           if (sym->onStack)
469             {
470               if (_G.accInUse)
471                 emitcode ("push", "acc");
472
473               if (_G.bInUse)
474                 emitcode ("push", "b");
475
476               emitcode ("mov", "a,_bp");
477               emitcode ("add", "a,#!constbyte",
478                         ((sym->stack < 0) ?
479                          ((char) (sym->stack - _G.nRegsSaved)) :
480                          ((char) sym->stack)) & 0xff);
481               emitcode ("mov", "%s,a",
482                         aop->aopu.aop_ptr->name);
483
484               if (_G.bInUse)
485                 emitcode ("pop", "b");
486
487               if (_G.accInUse)
488                 emitcode ("pop", "acc");
489             }
490           else
491             emitcode ("mov", "%s,#%s",
492                       aop->aopu.aop_ptr->name,
493                       sym->rname);
494           aop->paged = space->paged;
495         }
496       else
497         aop->aopu.aop_stk = sym->stack;
498       return aop;
499     }
500
501   if (sym->onStack && options.stack10bit)
502     {
503         short stack_val = -((sym->stack < 0) ?
504                             ((short) (sym->stack - _G.nRegsSaved)) :
505                             ((short) sym->stack)) ;
506         if (useDP2 && _G.dptr1InUse) {
507             emitcode ("push","dpl1");
508             emitcode ("push","dph1");
509             emitcode ("push","dpx1");
510         } else if (_G.dptrInUse ) {
511             emitcode ("push","dpl");
512             emitcode ("push","dph");
513             emitcode ("push","dpx");
514         }
515       /* It's on the 10 bit stack, which is located in
516        * far data space.
517        */           
518         if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
519             if (useDP2) {
520                 if (options.model == MODEL_FLAT24)
521                 {
522                     emitcode ("mov", "dpx1,#!constbyte",
523                               (options.stack_loc >> 16) & 0xff);
524                 }
525                 emitcode ("mov", "dph1,_bpx+1");
526                 
527                 emitcode ("mov", "dpl1,_bpx");
528                 emitcode ("mov","dps,#1");
529             } else {
530                 if (options.model == MODEL_FLAT24)
531                 {
532                     emitcode ("mov", "dpx,#!constbyte",
533                               (options.stack_loc >> 16) & 0xff);
534                 }
535                 emitcode ("mov", "dph,_bpx+1");
536                 emitcode ("mov", "dpl,_bpx");
537             }
538             stack_val = -stack_val;
539             while (stack_val--) {
540                 emitcode ("inc","dptr");
541             }
542             if (useDP2) {
543                 emitcode("mov","dps,#0");
544             }
545         }  else {
546             if (_G.accInUse)
547                 emitcode ("push", "acc");
548             
549             if (_G.bInUse)
550                 emitcode ("push", "b");
551         
552             emitcode ("mov", "a,_bpx");
553             emitcode ("clr","c");
554             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
555             emitcode ("mov","b,a");
556             emitcode ("mov","a,_bpx+1");
557             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
558             if (useDP2) {
559                 if (options.model == MODEL_FLAT24)
560                 {
561                     emitcode ("mov", "dpx1,#!constbyte",
562                               (options.stack_loc >> 16) & 0xff);
563                 }
564                 emitcode ("mov", "dph1,a");
565                 emitcode ("mov", "dpl1,b");
566             } else {
567                 if (options.model == MODEL_FLAT24)
568                 {
569                     emitcode ("mov", "dpx,#!constbyte",
570                               (options.stack_loc >> 16) & 0xff);
571                 }
572                 emitcode ("mov", "dph,a");
573                 emitcode ("mov", "dpl,b");
574             }
575             
576             if (_G.bInUse)
577                 emitcode ("pop", "b");
578             
579             if (_G.accInUse)
580                 emitcode ("pop", "acc");
581         }
582         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
583         aop->size = getSize (sym->type);
584         return aop;
585     }
586
587   /* if in bit space */
588   if (IN_BITSPACE (space))
589     {
590       sym->aop = aop = newAsmop (AOP_CRY);
591       aop->aopu.aop_dir = sym->rname;
592       aop->size = getSize (sym->type);
593       return aop;
594     }
595   /* if it is in direct space */
596   if (IN_DIRSPACE (space))
597     {
598       sym->aop = aop = newAsmop (AOP_DIR);
599       aop->aopu.aop_dir = sym->rname;
600       aop->size = getSize (sym->type);
601       return aop;
602     }
603
604   /* special case for a function */
605   if (IS_FUNC (sym->type))
606     {
607       sym->aop = aop = newAsmop (AOP_IMMD);
608       aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);   
609       aop->size = FPTRSIZE;
610       return aop;
611     }
612   
613   /* only remaining is far space */
614   /* in which case DPTR gets the address */
615   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
616   if (useDP2)
617     {
618       genSetDPTR (1);
619       _flushLazyDPS ();
620       emitcode ("mov", "dptr,#%s", sym->rname);
621       genSetDPTR (0);
622     }
623   else
624     {
625       emitcode ("mov", "dptr,#%s", sym->rname);
626     }
627   aop->size = getSize (sym->type);
628
629   /* if it is in code space */
630   if (IN_CODESPACE (space))
631     aop->code = 1;
632
633   return aop;
634 }
635
636 /*-----------------------------------------------------------------*/
637 /* aopForRemat - rematerialzes an object                           */
638 /*-----------------------------------------------------------------*/
639 static asmop *
640 aopForRemat (symbol * sym)
641 {
642   iCode *ic = sym->rematiCode;
643   asmop *aop = newAsmop (AOP_IMMD);
644   int ptr_type =0;
645   int val = 0;
646
647   for (;;)
648     {
649       if (ic->op == '+')
650         val += (int) operandLitValue (IC_RIGHT (ic));
651       else if (ic->op == '-')
652         val -= (int) operandLitValue (IC_RIGHT (ic));
653       else if (IS_CAST_ICODE(ic)) {
654               sym_link *from_type = operandType(IC_RIGHT(ic));
655               aop->aopu.aop_immd.from_cast_remat = 1;
656               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
657               ptr_type = DCL_TYPE(from_type);
658               if (ptr_type == IPOINTER) {
659                 // bug #481053
660                 ptr_type = POINTER;
661               }
662               continue ;
663       } else break;
664       
665       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
666     }
667
668   if (val)
669   {
670       SNPRINTF (buffer, sizeof(buffer),
671                 "(%s %c 0x%04x)",
672                 OP_SYMBOL (IC_LEFT (ic))->rname,
673                 val >= 0 ? '+' : '-',
674                 abs (val) & 0xffffff);
675   }
676   else 
677   {
678       if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
679       {
680           SNPRINTF(buffer, sizeof(buffer), 
681                    "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
682       }
683       else
684       {
685           strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
686       }
687   }
688
689   aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);  
690   /* set immd2 field if required */
691   if (aop->aopu.aop_immd.from_cast_remat) 
692   {
693       tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
694       aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
695   }
696
697   return aop;
698 }
699
700 /*-----------------------------------------------------------------*/
701 /* aopHasRegs - returns true if aop has regs between from-to       */
702 /*-----------------------------------------------------------------*/
703 static int aopHasRegs(asmop *aop, int from, int to)
704 {
705     int size =0;
706
707     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
708
709     for (; size < aop->size ; size++) {
710         int reg;
711         for (reg = from ; reg <= to ; reg++)
712             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
713     }
714     return 0;
715 }
716
717 /*-----------------------------------------------------------------*/
718 /* regsInCommon - two operands have some registers in common       */
719 /*-----------------------------------------------------------------*/
720 static bool
721 regsInCommon (operand * op1, operand * op2)
722 {
723   symbol *sym1, *sym2;
724   int i;
725
726   /* if they have registers in common */
727   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
728     return FALSE;
729
730   sym1 = OP_SYMBOL (op1);
731   sym2 = OP_SYMBOL (op2);
732
733   if (sym1->nRegs == 0 || sym2->nRegs == 0)
734     return FALSE;
735
736   for (i = 0; i < sym1->nRegs; i++)
737     {
738       int j;
739       if (!sym1->regs[i])
740         continue;
741
742       for (j = 0; j < sym2->nRegs; j++)
743         {
744           if (!sym2->regs[j])
745             continue;
746
747           if (sym2->regs[j] == sym1->regs[i])
748             return TRUE;
749         }
750     }
751
752   return FALSE;
753 }
754
755 /*-----------------------------------------------------------------*/
756 /* operandsEqu - equivalent                                        */
757 /*-----------------------------------------------------------------*/
758 static bool
759 operandsEqu (operand * op1, operand * op2)
760 {
761   symbol *sym1, *sym2;
762
763   /* if they not symbols */
764   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
765     return FALSE;
766
767   sym1 = OP_SYMBOL (op1);
768   sym2 = OP_SYMBOL (op2);
769
770   /* if both are itemps & one is spilt
771      and the other is not then false */
772   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
773       sym1->isspilt != sym2->isspilt)
774     return FALSE;
775
776   /* if they are the same */
777   if (sym1 == sym2)
778     return TRUE;
779
780   if (strcmp (sym1->rname, sym2->rname) == 0)
781     return TRUE;
782
783
784   /* if left is a tmp & right is not */
785   if (IS_ITEMP (op1) &&
786       !IS_ITEMP (op2) &&
787       sym1->isspilt &&
788       (sym1->usl.spillLoc == sym2))
789     return TRUE;
790
791   if (IS_ITEMP (op2) &&
792       !IS_ITEMP (op1) &&
793       sym2->isspilt &&
794       sym1->level > 0 &&
795       (sym2->usl.spillLoc == sym1))
796     return TRUE;
797
798   return FALSE;
799 }
800
801 /*-----------------------------------------------------------------*/
802 /* sameRegs - two asmops have the same registers                   */
803 /*-----------------------------------------------------------------*/
804 static bool
805 sameRegs (asmop * aop1, asmop * aop2)
806 {
807   int i;
808
809   if (aop1 == aop2)
810     {
811       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
812         {
813           return FALSE;
814         }
815       return TRUE;
816     }
817
818   if (aop1->type != AOP_REG ||
819       aop2->type != AOP_REG)
820     return FALSE;
821
822   if (aop1->size != aop2->size)
823     return FALSE;
824
825   for (i = 0; i < aop1->size; i++)
826     if (aop1->aopu.aop_reg[i] !=
827         aop2->aopu.aop_reg[i])
828       return FALSE;
829
830   return TRUE;
831 }
832
833 /*-----------------------------------------------------------------*/
834 /* aopOp - allocates an asmop for an operand  :                    */
835 /*-----------------------------------------------------------------*/
836 static void
837 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
838 {
839   asmop *aop;
840   symbol *sym;
841   int i;
842
843   if (!op)
844     return;
845
846   /* if this a literal */
847   if (IS_OP_LITERAL (op))
848     {
849       op->aop = aop = newAsmop (AOP_LIT);
850       aop->aopu.aop_lit = op->operand.valOperand;
851       aop->size = getSize (operandType (op));
852       return;
853     }
854
855   /* if already has a asmop then continue */
856   if (op->aop)
857     return;
858
859   /* if the underlying symbol has a aop */
860   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
861     {
862       op->aop = OP_SYMBOL (op)->aop;
863       return;
864     }
865
866   /* if this is a true symbol */
867   if (IS_TRUE_SYMOP (op))
868     {
869       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
870       return;
871     }
872
873   /* this is a temporary : this has
874      only four choices :
875      a) register
876      b) spillocation
877      c) rematerialize
878      d) conditional
879      e) can be a return use only */
880
881   sym = OP_SYMBOL (op);
882
883
884   /* if the type is a conditional */
885   if (sym->regType == REG_CND)
886     {
887       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
888       aop->size = 0;
889       return;
890     }
891
892   /* if it is spilt then two situations
893      a) is rematerialize
894      b) has a spill location */
895   if (sym->isspilt || sym->nRegs == 0)
896     {
897
898       /* rematerialize it NOW */
899       if (sym->remat)
900         {
901           sym->aop = op->aop = aop =
902             aopForRemat (sym);
903           aop->size = getSize (sym->type);
904           return;
905         }
906
907       if (sym->accuse)
908         {
909           int i;
910           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
911           aop->size = getSize (sym->type);
912           for (i = 0; i < 2; i++)
913             aop->aopu.aop_str[i] = accUse[i];
914           return;
915         }
916
917       if (sym->ruonly)
918         {
919           int i;
920
921           if (useDP2)
922             {
923               /* a AOP_STR uses DPTR, but DPTR is already in use;
924                * we're just hosed.
925                */
926                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
927             }
928
929           aop = op->aop = sym->aop = newAsmop (AOP_STR);
930           aop->size = getSize (sym->type);
931           for (i = 0; i < (int) fReturnSizeDS390; i++)
932             aop->aopu.aop_str[i] = fReturn[i];
933           return;
934         }
935       
936       if (sym->dptr) { /* has been allocated to a DPTRn */
937           aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
938           aop->size = getSize (sym->type);
939           aop->aopu.dptr = sym->dptr;
940           return ;
941       }
942       /* else spill location  */
943       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
944           /* force a new aop if sizes differ */
945           sym->usl.spillLoc->aop = NULL;
946       }
947       sym->aop = op->aop = aop =
948         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
949       aop->size = getSize (sym->type);
950       return;
951     }
952
953   /* must be in a register */
954   sym->aop = op->aop = aop = newAsmop (AOP_REG);
955   aop->size = sym->nRegs;
956   for (i = 0; i < sym->nRegs; i++)
957     aop->aopu.aop_reg[i] = sym->regs[i];
958 }
959
960 /*-----------------------------------------------------------------*/
961 /* freeAsmop - free up the asmop given to an operand               */
962 /*----------------------------------------------------------------*/
963 static void
964 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
965 {
966   asmop *aop;
967
968   if (!op)
969     aop = aaop;
970   else
971     aop = op->aop;
972
973   if (!aop)
974     return;
975
976   if (aop->freed)
977     goto dealloc;
978
979   aop->freed = 1;
980
981   /* depending on the asmop type only three cases need work AOP_RO
982      , AOP_R1 && AOP_STK */
983   switch (aop->type)
984     {
985     case AOP_R0:
986       if (_G.r0Pushed)
987         {
988           if (pop)
989             {
990               emitcode ("pop", "ar0");
991               _G.r0Pushed--;
992             }
993         }
994       bitVectUnSetBit (ic->rUsed, R0_IDX);
995       break;
996
997     case AOP_R1:
998       if (_G.r1Pushed)
999         {
1000           if (pop)
1001             {
1002               emitcode ("pop", "ar1");
1003               _G.r1Pushed--;
1004             }
1005         }
1006       bitVectUnSetBit (ic->rUsed, R1_IDX);
1007       break;
1008
1009     case AOP_STK:
1010       {
1011         int sz = aop->size;
1012         int stk = aop->aopu.aop_stk + aop->size;
1013         bitVectUnSetBit (ic->rUsed, R0_IDX);
1014         bitVectUnSetBit (ic->rUsed, R1_IDX);
1015
1016         getFreePtr (ic, &aop, FALSE);
1017
1018         if (options.stack10bit)
1019           {
1020             /* I'm not sure what to do here yet... */
1021             /* #STUB */
1022             fprintf (stderr,
1023                      "*** Warning: probably generating bad code for "
1024                      "10 bit stack mode.\n");
1025           }
1026
1027         if (stk)
1028           {
1029             emitcode ("mov", "a,_bp");
1030             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1031             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1032           }
1033         else
1034           {
1035             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1036           }
1037
1038         while (sz--)
1039           {
1040             emitcode ("pop", "acc");
1041             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1042             if (!sz)
1043               break;
1044             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1045           }
1046         op->aop = aop;
1047         freeAsmop (op, NULL, ic, TRUE);
1048         if (_G.r0Pushed)
1049           {
1050             emitcode ("pop", "ar0");
1051             _G.r0Pushed--;
1052           }
1053
1054         if (_G.r1Pushed)
1055           {
1056             emitcode ("pop", "ar1");
1057             _G.r1Pushed--;
1058           }
1059       }
1060     case AOP_DPTR2:
1061         if (_G.dptr1InUse) {
1062             emitcode ("pop","dpx1");
1063             emitcode ("pop","dph1");
1064             emitcode ("pop","dpl1");
1065         }
1066         break;
1067     case AOP_DPTR:
1068         if (_G.dptrInUse) {
1069             emitcode ("pop","dpx");
1070             emitcode ("pop","dph");
1071             emitcode ("pop","dpl");
1072         }
1073         break;
1074     }
1075 dealloc:
1076   /* all other cases just dealloc */
1077   if (op)
1078     {
1079       op->aop = NULL;
1080       if (IS_SYMOP (op))
1081         {
1082           OP_SYMBOL (op)->aop = NULL;
1083           /* if the symbol has a spill */
1084           if (SPIL_LOC (op))
1085             SPIL_LOC (op)->aop = NULL;
1086         }
1087     }
1088 }
1089
1090 #define DEFAULT_ACC_WARNING 0
1091 static int saveAccWarn = DEFAULT_ACC_WARNING;
1092
1093 /*-------------------------------------------------------------------*/
1094 /* aopGet - for fetching value of the aop                            */
1095 /*                                                                   */
1096 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1097 /* in the accumulator. Set it to the name of a free register         */
1098 /* if acc must be preserved; the register will be used to preserve   */
1099 /* acc temporarily and to return the result byte.                    */
1100 /*-------------------------------------------------------------------*/
1101
1102 static char *
1103 aopGet (asmop *aop,
1104         int   offset,
1105         bool  bit16,
1106         bool  dname,
1107         char  *saveAcc)
1108 {
1109   /* offset is greater than
1110      size then zero */
1111   if (offset > (aop->size - 1) &&
1112       aop->type != AOP_LIT)
1113     return zero;
1114
1115   /* depending on type */
1116   switch (aop->type)
1117     {
1118
1119     case AOP_R0:
1120     case AOP_R1:
1121       /* if we need to increment it */
1122       while (offset > aop->coff)
1123         {
1124           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1125           aop->coff++;
1126         }
1127
1128       while (offset < aop->coff)
1129         {
1130           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1131           aop->coff--;
1132         }
1133
1134       aop->coff = offset;
1135       if (aop->paged)
1136         {
1137           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1138           return (dname ? "acc" : "a");
1139         }
1140       SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1141       return Safe_strdup(buffer);       
1142
1143     case AOP_DPTRn:
1144         assert(offset <= 3);
1145         return dptrn[aop->aopu.dptr][offset];
1146
1147     case AOP_DPTR:
1148     case AOP_DPTR2:
1149
1150       if (aop->type == AOP_DPTR2)
1151         {
1152           genSetDPTR (1);
1153         }
1154         
1155       if (saveAcc)
1156         {
1157             TR_AP("#1");
1158 //          if (aop->type != AOP_DPTR2)
1159 //          {
1160 //              if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1161 //              emitcode(";", "spanky: saveAcc for DPTR");
1162 //          }
1163             
1164             emitcode ("xch", "a, %s", saveAcc);
1165         }
1166
1167       _flushLazyDPS ();
1168
1169       while (offset > aop->coff)
1170         {
1171           emitcode ("inc", "dptr");
1172           aop->coff++;
1173         }
1174
1175       while (offset < aop->coff)
1176         {
1177           emitcode ("lcall", "__decdptr");
1178           aop->coff--;
1179         }
1180
1181       aop->coff = offset;
1182       if (aop->code)
1183         {
1184           emitcode ("clr", "a");
1185           emitcode ("movc", "a,@a+dptr");
1186         }
1187       else
1188         {
1189           emitcode ("movx", "a,@dptr");
1190         }
1191
1192       if (aop->type == AOP_DPTR2)
1193         {
1194           genSetDPTR (0);
1195         }
1196         
1197         if (saveAcc)
1198         {
1199        TR_AP("#2");
1200               emitcode ("xch", "a, %s", saveAcc);
1201 //            if (strcmp(saveAcc, "_ap"))
1202 //            {
1203 //                emitcode(";", "spiffy: non _ap return from aopGet.");
1204 //            }
1205                   
1206               return saveAcc;
1207         }
1208       return (dname ? "acc" : "a");
1209
1210     case AOP_IMMD:
1211       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) 
1212       {
1213           SNPRINTF(buffer, sizeof(buffer), 
1214                    "%s",aop->aopu.aop_immd.aop_immd2);
1215       } 
1216       else if (bit16)
1217       {
1218          SNPRINTF(buffer, sizeof(buffer), 
1219                   "#%s", aop->aopu.aop_immd.aop_immd1);
1220       }
1221       else if (offset) 
1222       {
1223           switch (offset) {
1224           case 1:
1225               tsprintf(buffer, sizeof(buffer),
1226                        "#!his",aop->aopu.aop_immd.aop_immd1);
1227               break;
1228           case 2:
1229               tsprintf(buffer, sizeof(buffer), 
1230                        "#!hihis",aop->aopu.aop_immd.aop_immd1);
1231               break;
1232           case 3:
1233               tsprintf(buffer, sizeof(buffer),
1234                        "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1235               break;
1236           default: /* should not need this (just in case) */
1237               SNPRINTF (buffer, sizeof(buffer), 
1238                         "#(%s >> %d)",
1239                        aop->aopu.aop_immd.aop_immd1,
1240                        offset * 8);
1241           }
1242       }
1243       else
1244       {
1245         SNPRINTF (buffer, sizeof(buffer), 
1246                   "#%s", aop->aopu.aop_immd.aop_immd1);
1247       }
1248       return Safe_strdup(buffer);       
1249
1250     case AOP_DIR:
1251       if (offset)
1252       {
1253         SNPRINTF (buffer, sizeof(buffer),
1254                   "(%s + %d)",
1255                  aop->aopu.aop_dir,
1256                  offset);
1257       }
1258       else
1259       {
1260         SNPRINTF(buffer, sizeof(buffer), 
1261                  "%s", aop->aopu.aop_dir);
1262       }
1263
1264       return Safe_strdup(buffer);
1265
1266     case AOP_REG:
1267       if (dname)
1268         return aop->aopu.aop_reg[offset]->dname;
1269       else
1270         return aop->aopu.aop_reg[offset]->name;
1271
1272     case AOP_CRY:
1273       emitcode ("clr", "a");
1274       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1275       emitcode ("rlc", "a");
1276       return (dname ? "acc" : "a");
1277
1278     case AOP_ACC:
1279       if (!offset && dname)
1280         return "acc";
1281       return aop->aopu.aop_str[offset];
1282
1283     case AOP_LIT:
1284       return aopLiteral (aop->aopu.aop_lit, offset);
1285
1286     case AOP_STR:
1287       aop->coff = offset;
1288       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1289           dname)
1290         return "acc";
1291
1292       return aop->aopu.aop_str[offset];
1293
1294     }
1295
1296   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1297           "aopget got unsupported aop->type");
1298   exit (1);
1299     
1300   return NULL;  // not reached, but makes compiler happy.
1301 }
1302 /*-----------------------------------------------------------------*/
1303 /* aopPut - puts a string for a aop                                */
1304 /*-----------------------------------------------------------------*/
1305 static void
1306 aopPut (asmop * aop, char *s, int offset)
1307 {
1308   if (aop->size && offset > (aop->size - 1))
1309     {
1310       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1311               "aopPut got offset > aop->size");
1312       exit (1);
1313     }
1314
1315   /* will assign value to value */
1316   /* depending on where it is ofcourse */
1317   switch (aop->type)
1318     {
1319     case AOP_DIR:
1320         if (offset)
1321         {
1322             SNPRINTF (buffer, sizeof(buffer),
1323                       "(%s + %d)",
1324                       aop->aopu.aop_dir, offset);
1325         }
1326         else
1327         {
1328             SNPRINTF (buffer, sizeof(buffer), 
1329                      "%s", aop->aopu.aop_dir);
1330         }
1331         
1332
1333         if (strcmp (buffer, s))
1334         {
1335             emitcode ("mov", "%s,%s", buffer, s);
1336         }
1337       break;
1338
1339     case AOP_REG:
1340       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1341           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1342         {
1343           if (*s == '@' ||
1344               strcmp (s, "r0") == 0 ||
1345               strcmp (s, "r1") == 0 ||
1346               strcmp (s, "r2") == 0 ||
1347               strcmp (s, "r3") == 0 ||
1348               strcmp (s, "r4") == 0 ||
1349               strcmp (s, "r5") == 0 ||
1350               strcmp (s, "r6") == 0 ||
1351               strcmp (s, "r7") == 0)
1352             {
1353                 emitcode ("mov", "%s,%s",
1354                           aop->aopu.aop_reg[offset]->dname, s);
1355             }
1356             else
1357             {
1358                 emitcode ("mov", "%s,%s",
1359                           aop->aopu.aop_reg[offset]->name, s);
1360             }
1361         }
1362       break;
1363
1364     case AOP_DPTRn:
1365         emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1366         break;
1367
1368     case AOP_DPTR:
1369     case AOP_DPTR2:
1370
1371       if (aop->type == AOP_DPTR2)
1372         {
1373           genSetDPTR (1);
1374         }
1375       _flushLazyDPS ();
1376
1377       if (aop->code)
1378         {
1379           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1380                   "aopPut writting to code space");
1381           exit (1);
1382         }
1383
1384       while (offset > aop->coff)
1385         {
1386           aop->coff++;
1387           emitcode ("inc", "dptr");
1388         }
1389
1390       while (offset < aop->coff)
1391         {
1392           aop->coff--;
1393           emitcode ("lcall", "__decdptr");
1394         }
1395
1396       aop->coff = offset;
1397
1398       /* if not in accumulater */
1399       MOVA (s);
1400
1401       emitcode ("movx", "@dptr,a");
1402
1403       if (aop->type == AOP_DPTR2)
1404         {
1405           genSetDPTR (0);
1406         }
1407       break;
1408
1409     case AOP_R0:
1410     case AOP_R1:
1411       while (offset > aop->coff)
1412         {
1413           aop->coff++;
1414           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1415         }
1416       while (offset < aop->coff)
1417         {
1418           aop->coff--;
1419           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1420         }
1421       aop->coff = offset;
1422
1423       if (aop->paged)
1424         {
1425           MOVA (s);
1426           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1427
1428         }
1429       else if (*s == '@')
1430         {
1431           MOVA (s);
1432           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1433         }
1434       else if (strcmp (s, "r0") == 0 ||
1435                strcmp (s, "r1") == 0 ||
1436                strcmp (s, "r2") == 0 ||
1437                strcmp (s, "r3") == 0 ||
1438                strcmp (s, "r4") == 0 ||
1439                strcmp (s, "r5") == 0 ||
1440                strcmp (s, "r6") == 0 ||
1441                strcmp (s, "r7") == 0)
1442         {
1443           char buff[10];
1444           SNPRINTF(buff, sizeof(buff), 
1445                    "a%s", s);
1446           emitcode ("mov", "@%s,%s",
1447                     aop->aopu.aop_ptr->name, buff);
1448         }
1449         else
1450         {
1451             emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1452         }
1453       break;
1454
1455     case AOP_STK:
1456       if (strcmp (s, "a") == 0)
1457         emitcode ("push", "acc");
1458       else
1459         if (*s=='@') {
1460           MOVA(s);
1461           emitcode ("push", "acc");
1462         } else {
1463           emitcode ("push", s);
1464         }
1465
1466       break;
1467
1468     case AOP_CRY:
1469       /* if bit variable */
1470       if (!aop->aopu.aop_dir)
1471         {
1472           emitcode ("clr", "a");
1473           emitcode ("rlc", "a");
1474         }
1475       else
1476         {
1477           if (s == zero)
1478             emitcode ("clr", "%s", aop->aopu.aop_dir);
1479           else if (s == one)
1480             emitcode ("setb", "%s", aop->aopu.aop_dir);
1481           else if (!strcmp (s, "c"))
1482             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1483           else
1484             {
1485               if (strcmp (s, "a"))
1486                 {
1487                   MOVA (s);
1488                 }
1489               {
1490                 /* set C, if a >= 1 */
1491                 emitcode ("add", "a,#!constbyte",0xff);
1492                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1493               }
1494             }
1495         }
1496       break;
1497
1498     case AOP_STR:
1499       aop->coff = offset;
1500       if (strcmp (aop->aopu.aop_str[offset], s))
1501         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1502       break;
1503
1504     case AOP_ACC:
1505       aop->coff = offset;
1506       if (!offset && (strcmp (s, "acc") == 0))
1507         break;
1508
1509       if (strcmp (aop->aopu.aop_str[offset], s))
1510         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1511       break;
1512
1513     default:
1514       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1515               "aopPut got unsupported aop->type");
1516       exit (1);
1517     }
1518
1519 }
1520
1521
1522 /*--------------------------------------------------------------------*/
1523 /* reAdjustPreg - points a register back to where it should (coff==0) */
1524 /*--------------------------------------------------------------------*/
1525 static void
1526 reAdjustPreg (asmop * aop)
1527 {
1528   if ((aop->coff==0) || (aop->size <= 1)) {
1529     return;
1530   }
1531
1532   switch (aop->type)
1533     {
1534     case AOP_R0:
1535     case AOP_R1:
1536       while (aop->coff--)
1537         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1538       break;
1539     case AOP_DPTR:
1540     case AOP_DPTR2:
1541       if (aop->type == AOP_DPTR2)
1542         {
1543           genSetDPTR (1);
1544           _flushLazyDPS ();
1545         }
1546       while (aop->coff--)
1547         {
1548           emitcode ("lcall", "__decdptr");
1549         }
1550
1551       if (aop->type == AOP_DPTR2)
1552         {
1553           genSetDPTR (0);
1554         }
1555       break;
1556
1557     }
1558   aop->coff=0;
1559 }
1560
1561 #define AOP(op) op->aop
1562 #define AOP_TYPE(op) AOP(op)->type
1563 #define AOP_SIZE(op) AOP(op)->size
1564 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1565                        AOP_TYPE(x) == AOP_R0))
1566
1567 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1568                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1569                          AOP(x)->paged))
1570
1571 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1572                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1573                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1574 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1575 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1576 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1577
1578 // The following two macros can be used even if the aop has not yet been aopOp'd.
1579 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1580 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1581
1582 /* Workaround for DS80C390 bug: div ab may return bogus results
1583  * if A is accessed in instruction immediately before the div.
1584  *
1585  * Will be fixed in B4 rev of processor, Dallas claims.
1586  */
1587
1588 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1589     if (!AOP_NEEDSACC(RIGHT))         \
1590     {               \
1591       /* We can load A first, then B, since     \
1592        * B (the RIGHT operand) won't clobber A,   \
1593        * thus avoiding touching A right before the div. \
1594        */             \
1595       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1596       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);     \
1597       MOVA(L);            \
1598       L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1599       MOVB(L); \
1600     }               \
1601     else              \
1602     {               \
1603       /* Just stuff in a nop after loading A. */    \
1604       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1605       L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL);   \
1606       MOVA(L);            \
1607       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1608     }
1609
1610 /*-----------------------------------------------------------------*/
1611 /* genNotFloat - generates not for float operations              */
1612 /*-----------------------------------------------------------------*/
1613 static void
1614 genNotFloat (operand * op, operand * res)
1615 {
1616   int size, offset;
1617   symbol *tlbl;
1618
1619   D (emitcode (";", "genNotFloat "););
1620
1621   /* we will put 127 in the first byte of
1622      the result */
1623   aopPut (AOP (res), "#127", 0);
1624   size = AOP_SIZE (op) - 1;
1625   offset = 1;
1626
1627   _startLazyDPSEvaluation ();
1628   MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL));
1629
1630   while (size--)
1631     {
1632       emitcode ("orl", "a,%s",
1633                 aopGet (op->aop,
1634                         offset++, FALSE, FALSE,
1635                         DP2_RESULT_REG));
1636     }
1637   _endLazyDPSEvaluation ();
1638
1639   tlbl = newiTempLabel (NULL);
1640   aopPut (res->aop, one, 1);
1641   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1642   aopPut (res->aop, zero, 1);
1643   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1644
1645   size = res->aop->size - 2;
1646   offset = 2;
1647   /* put zeros in the rest */
1648   while (size--)
1649     aopPut (res->aop, zero, offset++);
1650 }
1651
1652 /*-----------------------------------------------------------------*/
1653 /* opIsGptr: returns non-zero if the passed operand is       */
1654 /* a generic pointer type.             */
1655 /*-----------------------------------------------------------------*/
1656 static int
1657 opIsGptr (operand * op)
1658 {
1659   sym_link *type = operandType (op);
1660
1661   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1662     {
1663       return 1;
1664     }
1665   return 0;
1666 }
1667
1668 /*-----------------------------------------------------------------*/
1669 /* getDataSize - get the operand data size                         */
1670 /*-----------------------------------------------------------------*/
1671 static int
1672 getDataSize (operand * op)
1673 {
1674   int size;
1675   size = AOP_SIZE (op);
1676   if (size == GPTRSIZE)
1677     {
1678       sym_link *type = operandType (op);
1679       if (IS_GENPTR (type))
1680         {
1681           /* generic pointer; arithmetic operations
1682            * should ignore the high byte (pointer type).
1683            */
1684           size--;
1685         }
1686     }
1687   return size;
1688 }
1689
1690 /*-----------------------------------------------------------------*/
1691 /* outAcc - output Acc                                             */
1692 /*-----------------------------------------------------------------*/
1693 static void
1694 outAcc (operand * result)
1695 {
1696   int size, offset;
1697   size = getDataSize (result);
1698   if (size)
1699     {
1700       aopPut (AOP (result), "a", 0);
1701       size--;
1702       offset = 1;
1703       /* unsigned or positive */
1704       while (size--)
1705         {
1706           aopPut (AOP (result), zero, offset++);
1707         }
1708     }
1709 }
1710
1711 /*-----------------------------------------------------------------*/
1712 /* outBitC - output a bit C                                        */
1713 /*-----------------------------------------------------------------*/
1714 static void
1715 outBitC (operand * result)
1716 {
1717   /* if the result is bit */
1718   if (AOP_TYPE (result) == AOP_CRY)
1719     {
1720       aopPut (AOP (result), "c", 0);
1721     }
1722   else
1723     {
1724       emitcode ("clr", "a");
1725       emitcode ("rlc", "a");
1726       outAcc (result);
1727     }
1728 }
1729
1730 /*-----------------------------------------------------------------*/
1731 /* toBoolean - emit code for orl a,operator(sizeop)                */
1732 /*-----------------------------------------------------------------*/
1733 static void
1734 toBoolean (operand * oper)
1735 {
1736   int   size = AOP_SIZE (oper) - 1;
1737   int   offset = 1;
1738   bool usedB = FALSE;
1739
1740   /* The generic part of a generic pointer should
1741    * not participate in it's truth value.
1742    *
1743    * i.e. 0x10000000 is zero.
1744    */
1745   if (opIsGptr (oper))
1746     {
1747       D (emitcode (";", "toBoolean: generic ptr special case."););
1748       size--;
1749     }
1750
1751   _startLazyDPSEvaluation ();
1752   if (AOP_NEEDSACC (oper) && size)
1753     {
1754       usedB = TRUE;
1755       if (_G.bInUse)
1756       {
1757           emitcode ("push", "b");
1758       }
1759       MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1760     }
1761   else
1762     {
1763       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1764     }
1765     
1766   while (size--)
1767     {
1768       if (usedB)
1769         {
1770           emitcode ("orl", "b,%s",
1771                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1772         }
1773       else
1774         {
1775           emitcode ("orl", "a,%s",
1776                     aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1777         }
1778     }
1779   _endLazyDPSEvaluation ();
1780
1781   if (usedB)
1782     {
1783       emitcode ("mov", "a,b");
1784       if (_G.bInUse)
1785       {
1786           emitcode ("pop", "b");
1787       }
1788         
1789     }
1790 }
1791
1792
1793 /*-----------------------------------------------------------------*/
1794 /* genNot - generate code for ! operation                          */
1795 /*-----------------------------------------------------------------*/
1796 static void
1797 genNot (iCode * ic)
1798 {
1799   symbol *tlbl;
1800   sym_link *optype = operandType (IC_LEFT (ic));
1801
1802   D (emitcode (";", "genNot "););
1803
1804   /* assign asmOps to operand & result */
1805   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1806   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1807
1808   /* if in bit space then a special case */
1809   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1810     {
1811       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1812       emitcode ("cpl", "c");
1813       outBitC (IC_RESULT (ic));
1814       goto release;
1815     }
1816
1817   /* if type float then do float */
1818   if (IS_FLOAT (optype))
1819     {
1820       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1821       goto release;
1822     }
1823
1824   toBoolean (IC_LEFT (ic));
1825
1826   tlbl = newiTempLabel (NULL);
1827   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1828   emitcode ("", "!tlabeldef", tlbl->key + 100);
1829   outBitC (IC_RESULT (ic));
1830
1831 release:
1832   /* release the aops */
1833   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1834   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1835 }
1836
1837
1838 /*-----------------------------------------------------------------*/
1839 /* genCpl - generate code for complement                           */
1840 /*-----------------------------------------------------------------*/
1841 static void
1842 genCpl (iCode * ic)
1843 {
1844   int offset = 0;
1845   int size;
1846   symbol *tlbl;
1847
1848   D (emitcode (";", "genCpl "););
1849
1850
1851   /* assign asmOps to operand & result */
1852   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1853   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1854
1855   /* special case if in bit space */
1856   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1857     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1858       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1859       emitcode ("cpl", "c");
1860       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1861       goto release;
1862     }
1863     tlbl=newiTempLabel(NULL);
1864     emitcode ("cjne", "%s,#0x01,%05d$", 
1865               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1866     emitcode ("", "%05d$:", tlbl->key+100);
1867     outBitC (IC_RESULT(ic));
1868     goto release;
1869   }
1870
1871   size = AOP_SIZE (IC_RESULT (ic));
1872   _startLazyDPSEvaluation ();
1873   while (size--)
1874     {
1875       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1876       emitcode ("cpl", "a");
1877       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1878     }
1879   _endLazyDPSEvaluation ();
1880
1881
1882 release:
1883   /* release the aops */
1884   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1885   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* genUminusFloat - unary minus for floating points                */
1890 /*-----------------------------------------------------------------*/
1891 static void
1892 genUminusFloat (operand * op, operand * result)
1893 {
1894   int size, offset = 0;
1895     
1896   D(emitcode (";", "genUminusFloat"););
1897   
1898   /* for this we just copy and then flip the bit */
1899     
1900   _startLazyDPSEvaluation ();
1901   size = AOP_SIZE (op) - 1;
1902
1903   while (size--)
1904   {
1905       aopPut (AOP (result),
1906               aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1907               offset);
1908       offset++;
1909     }
1910   
1911   MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1912
1913   emitcode ("cpl", "acc.7");
1914   aopPut (AOP (result), "a", offset);    
1915   _endLazyDPSEvaluation ();
1916 }
1917
1918 /*-----------------------------------------------------------------*/
1919 /* genUminus - unary minus code generation                         */
1920 /*-----------------------------------------------------------------*/
1921 static void
1922 genUminus (iCode * ic)
1923 {
1924   int offset, size;
1925   sym_link *optype;
1926
1927   D (emitcode (";", "genUminus "););
1928
1929   /* assign asmops */
1930   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1931   aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1932
1933   /* if both in bit space then special
1934      case */
1935   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1936       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1937     {
1938
1939       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1940       emitcode ("cpl", "c");
1941       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1942       goto release;
1943     }
1944
1945   optype = operandType (IC_LEFT (ic));
1946
1947   /* if float then do float stuff */
1948   if (IS_FLOAT (optype))
1949     {
1950       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1951       goto release;
1952     }
1953
1954   /* otherwise subtract from zero */
1955   size = AOP_SIZE (IC_LEFT (ic));
1956   offset = 0;
1957   _startLazyDPSEvaluation ();
1958   while (size--)
1959     {
1960       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1961       if (!strcmp (l, "a"))
1962         {
1963           if (offset == 0)
1964             SETC;
1965           emitcode ("cpl", "a");
1966           emitcode ("addc", "a,#0");
1967         }
1968       else
1969         {
1970           if (offset == 0)
1971             CLRC;
1972           emitcode ("clr", "a");
1973           emitcode ("subb", "a,%s", l);
1974         }
1975       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1976     }
1977   _endLazyDPSEvaluation ();
1978
1979   /* if any remaining bytes in the result */
1980   /* we just need to propagate the sign   */
1981   if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
1982     {
1983       emitcode ("rlc", "a");
1984       emitcode ("subb", "a,acc");
1985       while (size--)
1986         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1987     }
1988
1989 release:
1990   /* release the aops */
1991   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1992   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1993 }
1994
1995 /*-----------------------------------------------------------------*/
1996 /* savermask - saves registers in the mask                         */
1997 /*-----------------------------------------------------------------*/
1998 static void savermask(bitVect *rs_mask)
1999 {
2000     int i;
2001     if (options.useXstack) {
2002         if (bitVectBitValue (rs_mask, R0_IDX))
2003             emitcode ("mov", "b,r0");
2004         emitcode ("mov", "r0,%s", spname);
2005         for (i = 0; i < ds390_nRegs; i++) {
2006             if (bitVectBitValue (rs_mask, i)) {
2007                 if (i == R0_IDX)
2008                     emitcode ("mov", "a,b");
2009                 else
2010                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2011                 emitcode ("movx", "@r0,a");
2012                 emitcode ("inc", "r0");
2013             }
2014         }
2015         emitcode ("mov", "%s,r0", spname);
2016         if (bitVectBitValue (rs_mask, R0_IDX))
2017             emitcode ("mov", "r0,b");
2018     } else {
2019         for (i = 0; i < ds390_nRegs; i++) {
2020             if (bitVectBitValue (rs_mask, i))
2021                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2022         }
2023     }
2024 }
2025
2026 /*-----------------------------------------------------------------*/
2027 /* saveRegisters - will look for a call and save the registers     */
2028 /*-----------------------------------------------------------------*/
2029 static void
2030 saveRegisters (iCode * lic)
2031 {
2032   iCode *ic;
2033   bitVect *rsave;
2034
2035   /* look for call */
2036   for (ic = lic; ic; ic = ic->next)
2037     if (ic->op == CALL || ic->op == PCALL)
2038       break;
2039
2040   if (!ic)
2041     {
2042       fprintf (stderr, "found parameter push with no function call\n");
2043       return;
2044     }
2045
2046   /* if the registers have been saved already then
2047      do nothing */
2048   if (ic->regsSaved 
2049       || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2050     return ;
2051
2052   /* special case if DPTR alive across a function call then must save it 
2053      even though callee saves */
2054   if (IS_SYMOP(IC_LEFT(ic)) &&
2055       IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2056       int i;
2057       rsave = newBitVect(ic->rMask->size);
2058       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2059           if (bitVectBitValue(ic->rMask,i))
2060               rsave = bitVectSetBit(rsave,i);
2061       }
2062       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2063   } else {
2064     /* safe the registers in use at this time but skip the
2065        ones for the result */
2066     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2067                            ds390_rUmaskForOp (IC_RESULT(ic)));
2068   }
2069   ic->regsSaved = 1;
2070   savermask(rsave);
2071 }
2072
2073 /*-----------------------------------------------------------------*/
2074 /* usavermask - restore registers with mask                        */
2075 /*-----------------------------------------------------------------*/
2076 static void unsavermask(bitVect *rs_mask)
2077 {
2078     int i;
2079     if (options.useXstack) {
2080         emitcode ("mov", "r0,%s", spname);
2081         for (i = ds390_nRegs; i >= 0; i--) {
2082             if (bitVectBitValue (rs_mask, i)) {
2083                 emitcode ("dec", "r0");
2084                 emitcode ("movx", "a,@r0");
2085                 if (i == R0_IDX)
2086                     emitcode ("mov", "b,a");
2087                 else
2088                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2089             }       
2090         }
2091         emitcode ("mov", "%s,r0", spname);
2092         if (bitVectBitValue (rs_mask, R0_IDX))
2093             emitcode ("mov", "r0,b");
2094     } else {
2095         for (i = ds390_nRegs; i >= 0; i--) {
2096             if (bitVectBitValue (rs_mask, i))
2097                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2098         }
2099     }
2100 }
2101
2102 /*-----------------------------------------------------------------*/
2103 /* unsaveRegisters - pop the pushed registers                      */
2104 /*-----------------------------------------------------------------*/
2105 static void
2106 unsaveRegisters (iCode * ic)
2107 {
2108   bitVect *rsave;
2109
2110   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2111       int i;
2112       rsave = newBitVect(ic->rMask->size);
2113       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2114           if (bitVectBitValue(ic->rMask,i))
2115               rsave = bitVectSetBit(rsave,i);
2116       }
2117       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2118   } else {
2119     /* restore the registers in use at this time but skip the
2120        ones for the result */
2121     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
2122                            ds390_rUmaskForOp (IC_RESULT(ic)));
2123   }
2124   unsavermask(rsave);
2125 }
2126
2127
2128 /*-----------------------------------------------------------------*/
2129 /* pushSide -                */
2130 /*-----------------------------------------------------------------*/
2131 static void
2132 pushSide (operand * oper, int size)
2133 {
2134   int offset = 0;
2135   _startLazyDPSEvaluation ();
2136   while (size--)
2137     {
2138       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2139       if (AOP_TYPE (oper) != AOP_REG &&
2140           AOP_TYPE (oper) != AOP_DIR &&
2141           strcmp (l, "a"))
2142         {
2143           emitcode ("mov", "a,%s", l);
2144           emitcode ("push", "acc");
2145         }
2146       else
2147         emitcode ("push", "%s", l);
2148     }
2149   _endLazyDPSEvaluation ();
2150 }
2151
2152 /*-----------------------------------------------------------------*/
2153 /* assignResultValue -               */
2154 /*-----------------------------------------------------------------*/
2155 static void
2156 assignResultValue (operand * oper)
2157 {
2158   int offset = 0;
2159   int size = AOP_SIZE (oper);
2160   bool pushedAcc = FALSE;
2161
2162   if (size == fReturnSizeDS390)
2163   {
2164       /* I don't think this case can ever happen... */
2165       /* ACC is the last part of this. If writing the result
2166        * uses AC, we must preserve it.
2167        */
2168       if (AOP_NEEDSACC(oper))
2169       {
2170           emitcode(";", "assignResultValue special case for ACC.");
2171           emitcode("push", "acc");
2172           pushedAcc = TRUE;
2173           size--;
2174       }
2175   }
2176     
2177     
2178   _startLazyDPSEvaluation ();
2179   while (size--)
2180     {
2181       aopPut (AOP (oper), fReturn[offset], offset);
2182       offset++;
2183     }
2184   _endLazyDPSEvaluation ();
2185     
2186   if (pushedAcc)
2187     {
2188         emitcode("pop", "acc");
2189         aopPut(AOP(oper), "a", offset);
2190     }
2191 }
2192
2193
2194 /*-----------------------------------------------------------------*/
2195 /* genXpush - pushes onto the external stack                       */
2196 /*-----------------------------------------------------------------*/
2197 static void
2198 genXpush (iCode * ic)
2199 {
2200   asmop *aop = newAsmop (0);
2201   regs *r;
2202   int size, offset = 0;
2203
2204   D (emitcode (";", "genXpush ");
2205     );
2206
2207   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2208   r = getFreePtr (ic, &aop, FALSE);
2209
2210
2211   emitcode ("mov", "%s,_spx", r->name);
2212
2213   size = AOP_SIZE (IC_LEFT (ic));
2214   _startLazyDPSEvaluation ();
2215   while (size--)
2216     {
2217
2218       MOVA (aopGet (AOP (IC_LEFT (ic)),
2219                         offset++, FALSE, FALSE, NULL));
2220       emitcode ("movx", "@%s,a", r->name);
2221       emitcode ("inc", "%s", r->name);
2222
2223     }
2224   _endLazyDPSEvaluation ();
2225
2226
2227   emitcode ("mov", "_spx,%s", r->name);
2228
2229   freeAsmop (NULL, aop, ic, TRUE);
2230   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2231 }
2232
2233 /*-----------------------------------------------------------------*/
2234 /* genIpush - generate code for pushing this gets a little complex  */
2235 /*-----------------------------------------------------------------*/
2236 static void
2237 genIpush (iCode * ic)
2238 {
2239   int size, offset = 0;
2240   char *l;
2241
2242   D (emitcode (";", "genIpush ");
2243     );
2244
2245   /* if this is not a parm push : ie. it is spill push
2246      and spill push is always done on the local stack */
2247   if (!ic->parmPush)
2248     {
2249
2250       /* and the item is spilt then do nothing */
2251       if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2252         return;
2253
2254       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2255       size = AOP_SIZE (IC_LEFT (ic));
2256       /* push it on the stack */
2257       _startLazyDPSEvaluation ();
2258       while (size--)
2259         {
2260           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2261           if (*l == '#')
2262             {
2263               MOVA (l);
2264               l = "acc";
2265             }
2266           emitcode ("push", "%s", l);
2267         }
2268       _endLazyDPSEvaluation ();
2269       return;
2270     }
2271
2272   /* this is a paramter push: in this case we call
2273      the routine to find the call and save those
2274      registers that need to be saved */
2275   saveRegisters (ic);
2276
2277   /* if use external stack then call the external
2278      stack pushing routine */
2279   if (options.useXstack)
2280     {
2281       genXpush (ic);
2282       return;
2283     }
2284
2285   /* then do the push */
2286   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2287
2288   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2289   size = AOP_SIZE (IC_LEFT (ic));
2290
2291   _startLazyDPSEvaluation ();
2292   while (size--)
2293     {
2294       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2295       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2296           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2297           strcmp (l, "acc"))
2298         {
2299           emitcode ("mov", "a,%s", l);
2300           emitcode ("push", "acc");
2301         }
2302       else
2303         {
2304             emitcode ("push", "%s", l);
2305         }
2306     }
2307   _endLazyDPSEvaluation ();
2308
2309   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2310 }
2311
2312 /*-----------------------------------------------------------------*/
2313 /* genIpop - recover the registers: can happen only for spilling   */
2314 /*-----------------------------------------------------------------*/
2315 static void
2316 genIpop (iCode * ic)
2317 {
2318   int size, offset;
2319
2320   D (emitcode (";", "genIpop ");
2321     );
2322
2323
2324   /* if the temp was not pushed then */
2325   if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2326     return;
2327
2328   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2329   size = AOP_SIZE (IC_LEFT (ic));
2330   offset = (size - 1);
2331   _startLazyDPSEvaluation ();
2332   while (size--)
2333     {
2334       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2335                                      FALSE, TRUE, NULL));
2336     }
2337   _endLazyDPSEvaluation ();
2338
2339   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2340 }
2341
2342 /*-----------------------------------------------------------------*/
2343 /* unsaveRBank - restores the resgister bank from stack            */
2344 /*-----------------------------------------------------------------*/
2345 static void
2346 unsaveRBank (int bank, iCode * ic, bool popPsw)
2347 {
2348   int i;
2349   asmop *aop = NULL;
2350   regs *r = NULL;
2351
2352   if (options.useXstack)
2353   {
2354       if (!ic)
2355       {
2356           /* Assume r0 is available for use. */
2357           r = ds390_regWithIdx (R0_IDX);;          
2358       } 
2359       else
2360       {
2361           aop = newAsmop (0);
2362           r = getFreePtr (ic, &aop, FALSE);
2363       }
2364       emitcode ("mov", "%s,_spx", r->name);      
2365   }
2366   
2367   if (popPsw)
2368     {
2369       if (options.useXstack)
2370       {
2371           emitcode ("movx", "a,@%s", r->name);
2372           emitcode ("mov", "psw,a");
2373           emitcode ("dec", "%s", r->name);
2374         }
2375       else
2376       {
2377         emitcode ("pop", "psw");
2378       }
2379     }
2380
2381   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2382     {
2383       if (options.useXstack)
2384         {
2385           emitcode ("movx", "a,@%s", r->name);
2386           emitcode ("mov", "(%s+%d),a",
2387                     regs390[i].base, 8 * bank + regs390[i].offset);
2388           emitcode ("dec", "%s", r->name);
2389
2390         }
2391       else
2392         emitcode ("pop", "(%s+%d)",
2393                   regs390[i].base, 8 * bank + regs390[i].offset);
2394     }
2395
2396   if (options.useXstack)
2397     {
2398       emitcode ("mov", "_spx,%s", r->name);
2399     }
2400     
2401   if (aop)
2402   {
2403       freeAsmop (NULL, aop, ic, TRUE);  
2404   }    
2405 }
2406
2407 /*-----------------------------------------------------------------*/
2408 /* saveRBank - saves an entire register bank on the stack          */
2409 /*-----------------------------------------------------------------*/
2410 static void
2411 saveRBank (int bank, iCode * ic, bool pushPsw)
2412 {
2413   int i;
2414   asmop *aop = NULL;
2415   regs *r = NULL;
2416
2417   if (options.useXstack)
2418     {
2419         if (!ic)
2420         {
2421           /* Assume r0 is available for use. */
2422                   r = ds390_regWithIdx (R0_IDX);;
2423         }
2424         else
2425         {
2426           aop = newAsmop (0);
2427           r = getFreePtr (ic, &aop, FALSE);
2428         }
2429         emitcode ("mov", "%s,_spx", r->name);    
2430     }
2431
2432   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2433     {
2434       if (options.useXstack)
2435         {
2436           emitcode ("inc", "%s", r->name);
2437           emitcode ("mov", "a,(%s+%d)",
2438                     regs390[i].base, 8 * bank + regs390[i].offset);
2439           emitcode ("movx", "@%s,a", r->name);
2440         }
2441       else
2442         emitcode ("push", "(%s+%d)",
2443                   regs390[i].base, 8 * bank + regs390[i].offset);
2444     }
2445
2446   if (pushPsw)
2447     {
2448       if (options.useXstack)
2449         {
2450           emitcode ("mov", "a,psw");
2451           emitcode ("movx", "@%s,a", r->name);
2452           emitcode ("inc", "%s", r->name);
2453           emitcode ("mov", "_spx,%s", r->name);
2454         }
2455       else
2456       {
2457         emitcode ("push", "psw");
2458       }
2459
2460       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2461     }
2462   
2463   if (aop)
2464   {
2465        freeAsmop (NULL, aop, ic, TRUE);
2466   }    
2467     
2468   if (ic)
2469   {  
2470       ic->bankSaved = 1;
2471   }
2472 }
2473
2474 /*-----------------------------------------------------------------*/
2475 /* genSend - gen code for SEND                                     */
2476 /*-----------------------------------------------------------------*/
2477 static void genSend(set *sendSet)
2478 {
2479     iCode *sic;
2480     int sendCount = 0 ;
2481     static int rb1_count = 0;
2482
2483     for (sic = setFirstItem (sendSet); sic;
2484          sic = setNextItem (sendSet)) {     
2485         int size, offset = 0;
2486         
2487         size=getSize(operandType(IC_LEFT(sic)));
2488         D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2489         if (sendCount == 0) { /* first parameter */
2490             // we know that dpl(hxb) is the result, so
2491             rb1_count = 0 ;
2492             _startLazyDPSEvaluation ();
2493             if (size>1) {
2494                 aopOp (IC_LEFT (sic), sic, FALSE, 
2495                        (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2496             } else {
2497                 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2498             }
2499             while (size--) {
2500                 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2501                                   FALSE, FALSE, NULL);
2502                 if (strcmp (l, fReturn[offset])) {
2503                     emitcode ("mov", "%s,%s",
2504                               fReturn[offset],
2505                               l);
2506                 }
2507                 offset++;
2508             }
2509             _endLazyDPSEvaluation ();
2510             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2511             rb1_count =0;
2512         } else { /* if more parameter in registers */
2513             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2514             while (size--) {
2515                 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2516                                                                 FALSE, FALSE, NULL));
2517             }
2518             freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2519         }
2520         sendCount++;
2521     }
2522 }
2523
2524 static void
2525 adjustEsp(const char *reg)
2526 {
2527     emitcode ("anl","%s,#3", reg);
2528     if (TARGET_IS_DS400)
2529     {
2530         emitcode ("orl","%s,#!constbyte",
2531                   reg,
2532                   (options.stack_loc >> 8) & 0xff);
2533     }
2534 }
2535
2536 /*-----------------------------------------------------------------*/
2537 /* genCall - generates a call statement                            */
2538 /*-----------------------------------------------------------------*/
2539 static void
2540 genCall (iCode * ic)
2541 {
2542   sym_link *dtype;
2543   bool restoreBank = FALSE;
2544   bool swapBanks = FALSE;
2545
2546   D (emitcode (";", "genCall "););
2547
2548   /* if we are calling a not _naked function that is not using
2549      the same register bank then we need to save the
2550      destination registers on the stack */
2551   dtype = operandType (IC_LEFT (ic));
2552   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2553       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2554       IFFUNC_ISISR (currFunc->type))
2555   {
2556       if (!ic->bankSaved) 
2557       {
2558            /* This is unexpected; the bank should have been saved in
2559             * genFunction.
2560             */
2561            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2562            restoreBank = TRUE;
2563       }
2564       swapBanks = TRUE;
2565   }
2566   
2567     /* if caller saves & we have not saved then */
2568     if (!ic->regsSaved)
2569       saveRegisters (ic);
2570   
2571   /* if send set is not empty the assign */
2572   /* We've saved all the registers we care about;
2573   * therefore, we may clobber any register not used
2574   * in the calling convention (i.e. anything not in
2575   * fReturn.
2576   */
2577   if (_G.sendSet)
2578     {
2579         if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2580             genSend(reverseSet(_G.sendSet));
2581         } else {
2582             genSend(_G.sendSet);
2583         }
2584       _G.sendSet = NULL;
2585     }  
2586     
2587   if (swapBanks)
2588   {
2589         emitcode ("mov", "psw,#!constbyte", 
2590            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2591   }
2592
2593   /* make the call */
2594   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2595                             OP_SYMBOL (IC_LEFT (ic))->rname :
2596                             OP_SYMBOL (IC_LEFT (ic))->name));
2597
2598   if (swapBanks)
2599   {
2600        emitcode ("mov", "psw,#!constbyte", 
2601           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2602   }
2603
2604   /* if we need assign a result value */
2605   if ((IS_ITEMP (IC_RESULT (ic)) &&
2606        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2607         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2608         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2609       IS_TRUE_SYMOP (IC_RESULT (ic)))
2610     {
2611       if (isOperandInFarSpace (IC_RESULT (ic))
2612           && getSize (operandType (IC_RESULT (ic))) <= 2)
2613         {
2614           int size = getSize (operandType (IC_RESULT (ic)));
2615
2616           /* Special case for 1 or 2 byte return in far space. */
2617           MOVA (fReturn[0]);
2618           if (size > 1)
2619             {
2620               emitcode ("mov", "b,%s", fReturn[1]);
2621             }
2622
2623           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2624           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2625
2626           if (size > 1)
2627             {
2628               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2629             }
2630           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2631         }
2632       else
2633         {
2634           _G.accInUse++;
2635           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2636           _G.accInUse--;
2637
2638           assignResultValue (IC_RESULT (ic));
2639
2640           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2641         }
2642     }
2643
2644   /* adjust the stack for parameters if
2645      required */
2646   if (ic->parmBytes) {
2647       int i;
2648       if (options.stack10bit) {
2649           if (ic->parmBytes <= 10) {
2650               emitcode(";","stack adjustment for parms");
2651               for (i=0; i < ic->parmBytes ; i++) {
2652                   emitcode("pop","acc");
2653               }
2654           } else {            
2655               PROTECT_SP;
2656               emitcode ("clr","c");
2657               emitcode ("mov","a,sp");
2658               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2659               emitcode ("mov","sp,a");
2660               emitcode ("mov","a,esp");
2661               adjustEsp("a");
2662               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2663               emitcode ("mov","esp,a");   
2664               UNPROTECT_SP;
2665           }
2666       } else {
2667           if (ic->parmBytes > 3) {
2668               emitcode ("mov", "a,%s", spname);
2669               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2670               emitcode ("mov", "%s,a", spname);
2671           } else
2672               for (i = 0; i < ic->parmBytes; i++)
2673                   emitcode ("dec", "%s", spname);
2674       }
2675   }
2676
2677   /* if we hade saved some registers then unsave them */
2678   if (ic->regsSaved)
2679     unsaveRegisters (ic);
2680
2681   /* if register bank was saved then pop them */
2682   if (restoreBank)
2683     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2684 }
2685
2686 /*-----------------------------------------------------------------*/
2687 /* genPcall - generates a call by pointer statement                */
2688 /*-----------------------------------------------------------------*/
2689 static void
2690 genPcall (iCode * ic)
2691 {
2692   sym_link *dtype;
2693   symbol *rlbl = newiTempLabel (NULL);
2694   bool restoreBank=FALSE;
2695
2696   D (emitcode (";", "genPcall ");
2697     );
2698
2699
2700   /* if caller saves & we have not saved then */
2701   if (!ic->regsSaved)
2702     saveRegisters (ic);
2703
2704   /* if we are calling a function that is not using
2705      the same register bank then we need to save the
2706      destination registers on the stack */
2707   dtype = operandType (IC_LEFT (ic));
2708   if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2709       IFFUNC_ISISR (currFunc->type) &&
2710       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2711     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2712     restoreBank=TRUE;
2713   }
2714
2715   /* push the return address on to the stack */
2716   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2717   emitcode ("push", "acc");
2718   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2719   emitcode ("push", "acc");
2720
2721   if (options.model == MODEL_FLAT24)
2722     {
2723       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2724       emitcode ("push", "acc");
2725     }
2726
2727   /* now push the calling address */
2728   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2729
2730   pushSide (IC_LEFT (ic), FPTRSIZE);
2731
2732   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2733
2734   /* if send set is not empty the assign */
2735   if (_G.sendSet)
2736     {
2737         genSend(reverseSet(_G.sendSet));
2738         _G.sendSet = NULL;
2739     }
2740
2741   emitcode ("ret", "");
2742   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2743
2744
2745   /* if we need assign a result value */
2746   if ((IS_ITEMP (IC_RESULT (ic)) &&
2747        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2748         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2749       IS_TRUE_SYMOP (IC_RESULT (ic)))
2750     {
2751
2752       _G.accInUse++;
2753       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2754       _G.accInUse--;
2755
2756       assignResultValue (IC_RESULT (ic));
2757
2758       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2759     }
2760
2761   /* adjust the stack for parameters if
2762      required */
2763   if (ic->parmBytes)
2764     {
2765       int i;
2766       if (options.stack10bit) {
2767           if (ic->parmBytes <= 10) {
2768               emitcode(";","stack adjustment for parms");
2769               for (i=0; i < ic->parmBytes ; i++) {
2770                   emitcode("pop","acc");
2771               }
2772           } else {            
2773               PROTECT_SP;
2774               emitcode ("clr","c");
2775               emitcode ("mov","a,sp");
2776               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2777               emitcode ("mov","sp,a");
2778               emitcode ("mov","a,esp");
2779               adjustEsp("a");
2780               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2781               emitcode ("mov","esp,a");   
2782               UNPROTECT_SP;
2783           }
2784       } else {
2785           if (ic->parmBytes > 3) {
2786               emitcode ("mov", "a,%s", spname);
2787               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2788               emitcode ("mov", "%s,a", spname);
2789           }
2790           else
2791               for (i = 0; i < ic->parmBytes; i++)
2792                   emitcode ("dec", "%s", spname);
2793           
2794       }
2795     }
2796   /* if register bank was saved then unsave them */
2797   if (restoreBank)
2798     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2799   
2800   /* if we hade saved some registers then
2801      unsave them */
2802   if (ic->regsSaved)
2803     unsaveRegisters (ic);
2804
2805 }
2806
2807 /*-----------------------------------------------------------------*/
2808 /* resultRemat - result  is rematerializable                       */
2809 /*-----------------------------------------------------------------*/
2810 static int
2811 resultRemat (iCode * ic)
2812 {
2813   if (SKIP_IC (ic) || ic->op == IFX)
2814     return 0;
2815
2816   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2817     {
2818       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2819       if (sym->remat && !POINTER_SET (ic))
2820         return 1;
2821     }
2822
2823   return 0;
2824 }
2825
2826 #if defined(__BORLANDC__) || defined(_MSC_VER)
2827 #define STRCASECMP stricmp
2828 #else
2829 #define STRCASECMP strcasecmp
2830 #endif
2831
2832 /*-----------------------------------------------------------------*/
2833 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2834 /*-----------------------------------------------------------------*/
2835 static int
2836 regsCmp(void *p1, void *p2)
2837 {
2838   return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2839 }
2840
2841 static bool
2842 inExcludeList (char *s)
2843 {
2844   const char *p = setFirstItem(options.excludeRegsSet);
2845
2846   if (p == NULL || STRCASECMP(p, "none") == 0)
2847     return FALSE;
2848
2849
2850   return isinSetWith(options.excludeRegsSet, s, regsCmp);
2851 }
2852
2853 /*-----------------------------------------------------------------*/
2854 /* genFunction - generated code for function entry                 */
2855 /*-----------------------------------------------------------------*/
2856 static void
2857 genFunction (iCode * ic)
2858 {
2859   symbol *sym;
2860   sym_link *ftype;
2861   bool   switchedPSW = FALSE;
2862
2863   D (emitcode (";", "genFunction "););
2864
2865   _G.nRegsSaved = 0;
2866   /* create the function header */
2867   emitcode (";", "-----------------------------------------");
2868   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2869   emitcode (";", "-----------------------------------------");
2870
2871   emitcode ("", "%s:", sym->rname);
2872   ftype = operandType (IC_LEFT (ic));
2873
2874   if (IFFUNC_ISNAKED(ftype))
2875   {
2876       emitcode(";", "naked function: no prologue.");
2877       return;
2878   }
2879   
2880   if (options.stack_probe) 
2881       emitcode ("lcall","__stack_probe");
2882   /* if critical function then turn interrupts off */
2883   if (IFFUNC_ISCRITICAL (ftype))
2884     emitcode ("clr", "ea");
2885
2886   /* here we need to generate the equates for the
2887      register bank if required */
2888   if (FUNC_REGBANK (ftype) != rbank)
2889     {
2890       int i;
2891
2892       rbank = FUNC_REGBANK (ftype);
2893       for (i = 0; i < ds390_nRegs; i++)
2894         {
2895           if (regs390[i].print) {
2896               if (strcmp (regs390[i].base, "0") == 0)
2897                   emitcode ("", "%s !equ !constbyte",
2898                             regs390[i].dname,
2899                             8 * rbank + regs390[i].offset);
2900               else
2901                   emitcode ("", "%s !equ %s + !constbyte",
2902                             regs390[i].dname,
2903                             regs390[i].base,
2904                             8 * rbank + regs390[i].offset);
2905           }
2906         }
2907     }
2908
2909   /* if this is an interrupt service routine then
2910      save acc, b, dpl, dph  */
2911   if (IFFUNC_ISISR (sym->type))
2912       { /* is ISR */
2913       if (!inExcludeList ("acc"))
2914         emitcode ("push", "acc");
2915       if (!inExcludeList ("b"))
2916         emitcode ("push", "b");
2917       if (!inExcludeList ("dpl"))
2918         emitcode ("push", "dpl");
2919       if (!inExcludeList ("dph"))
2920         emitcode ("push", "dph");
2921       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2922         {
2923           emitcode ("push", "dpx");
2924           /* Make sure we're using standard DPTR */
2925           emitcode ("push", "dps");
2926           emitcode ("mov", "dps,#0");
2927           if (options.stack10bit)
2928             {
2929               /* This ISR could conceivably use DPTR2. Better save it. */
2930               emitcode ("push", "dpl1");
2931               emitcode ("push", "dph1");
2932               emitcode ("push", "dpx1");
2933               emitcode ("push",  DP2_RESULT_REG);
2934             }
2935         }
2936       /* if this isr has no bank i.e. is going to
2937          run with bank 0 , then we need to save more
2938          registers :-) */
2939       if (!FUNC_REGBANK (sym->type))
2940         {
2941             int i;
2942
2943           /* if this function does not call any other
2944              function then we can be economical and
2945              save only those registers that are used */
2946           if (!IFFUNC_HASFCALL(sym->type))
2947             {
2948
2949               /* if any registers used */
2950               if (sym->regsUsed)
2951                 {
2952                   /* save the registers used */
2953                   for (i = 0; i < sym->regsUsed->size; i++)
2954                     {
2955                       if (bitVectBitValue (sym->regsUsed, i) ||
2956                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2957                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2958                     }
2959                 }
2960
2961             }
2962           else
2963             {
2964               /* this function has  a function call cannot
2965                  determines register usage so we will have to push the
2966                  entire bank */
2967               saveRBank (0, ic, FALSE);
2968               if (options.parms_in_bank1) {
2969                   for (i=0; i < 8 ; i++ ) {
2970                       emitcode ("push","%s",rb1regs[i]);
2971                   }
2972               }
2973             }
2974         }
2975         else
2976         {
2977             /* This ISR uses a non-zero bank.
2978              *
2979              * We assume that the bank is available for our
2980              * exclusive use.
2981              *
2982              * However, if this ISR calls a function which uses some
2983              * other bank, we must save that bank entirely.
2984              */
2985             unsigned long banksToSave = 0;
2986             
2987             if (IFFUNC_HASFCALL(sym->type))
2988             {
2989
2990 #define MAX_REGISTER_BANKS 4
2991
2992                 iCode *i;
2993                 int ix;
2994
2995                 for (i = ic; i; i = i->next)
2996                 {
2997                     if (i->op == ENDFUNCTION)
2998                     {
2999                         /* we got to the end OK. */
3000                         break;
3001                     }
3002                     
3003                     if (i->op == CALL)
3004                     {
3005                         sym_link *dtype;
3006                         
3007                         dtype = operandType (IC_LEFT(i));
3008                         if (dtype 
3009                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3010                         {
3011                              /* Mark this bank for saving. */
3012                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3013                              {
3014                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3015                              }
3016                              else
3017                              {
3018                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
3019                              }
3020                              
3021                              /* And note that we don't need to do it in 
3022                               * genCall.
3023                               */
3024                              i->bankSaved = 1;
3025                         }
3026                     }
3027                     if (i->op == PCALL)
3028                     {
3029                         /* This is a mess; we have no idea what
3030                          * register bank the called function might
3031                          * use.
3032                          *
3033                          * The only thing I can think of to do is
3034                          * throw a warning and hope.
3035                          */
3036                         werror(W_FUNCPTR_IN_USING_ISR);   
3037                     }
3038                 }
3039
3040                 if (banksToSave && options.useXstack)
3041                 {
3042                     /* Since we aren't passing it an ic, 
3043                      * saveRBank will assume r0 is available to abuse.
3044                      *
3045                      * So switch to our (trashable) bank now, so
3046                      * the caller's R0 isn't trashed.
3047                      */
3048                     emitcode ("push", "psw");
3049                     emitcode ("mov", "psw,#!constbyte", 
3050                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3051                     switchedPSW = TRUE;
3052                 }
3053                 
3054                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3055                 {
3056                      if (banksToSave & (1 << ix))
3057                      {
3058                          saveRBank(ix, NULL, FALSE);
3059                      }
3060                 }
3061             }
3062             // TODO: this needs a closer look
3063             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3064         }
3065     }
3066   else
3067     {
3068       /* if callee-save to be used for this function
3069          then save the registers being used in this function */
3070       if (IFFUNC_CALLEESAVES(sym->type))
3071         {
3072           int i;
3073
3074           /* if any registers used */
3075           if (sym->regsUsed)
3076             {
3077               /* save the registers used */
3078               for (i = 0; i < sym->regsUsed->size; i++)
3079                 {
3080                   if (bitVectBitValue (sym->regsUsed, i) ||
3081                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3082                     {
3083                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3084                       _G.nRegsSaved++;
3085                     }
3086                 }
3087             }
3088         }
3089     }
3090
3091   /* set the register bank to the desired value */
3092   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3093    && !switchedPSW)
3094     {
3095       emitcode ("push", "psw");
3096       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3097     }
3098
3099   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3100        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3101       if (options.stack10bit) {
3102           emitcode ("push","_bpx");
3103           emitcode ("push","_bpx+1");
3104           emitcode ("mov","_bpx,%s",spname);
3105           emitcode ("mov","_bpx+1,esp");
3106           adjustEsp("_bpx+1");
3107       } else {
3108           if (options.useXstack) {
3109               emitcode ("mov", "r0,%s", spname);
3110               emitcode ("mov", "a,_bp");
3111               emitcode ("movx", "@r0,a");
3112               emitcode ("inc", "%s", spname);
3113           } else {
3114               /* set up the stack */
3115               emitcode ("push", "_bp"); /* save the callers stack  */
3116           }
3117           emitcode ("mov", "_bp,%s", spname);
3118       }
3119   }
3120
3121   /* adjust the stack for the function */
3122   if (sym->stack) {
3123       int i = sym->stack;
3124       if (options.stack10bit) {
3125           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);    
3126           assert (sym->recvSize <= 4);
3127           if (sym->stack <= 8) {
3128               while (i--) emitcode ("push","acc");
3129           } else {
3130               PROTECT_SP;
3131               emitcode ("mov","a,sp");
3132               emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3133               emitcode ("mov","sp,a");
3134               emitcode ("mov","a,esp");
3135               adjustEsp("a");
3136               emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3137               emitcode ("mov","esp,a");
3138               UNPROTECT_SP;
3139           }
3140       } else {
3141           if (i > 256)
3142               werror (W_STACK_OVERFLOW, sym->name);
3143           
3144           if (i > 3 && sym->recvSize < 4) {
3145               
3146               emitcode ("mov", "a,sp");
3147               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3148               emitcode ("mov", "sp,a");
3149               
3150           } else
3151               while (i--)
3152                   emitcode ("inc", "sp");
3153       }
3154   }
3155
3156   if (sym->xstack)
3157     {
3158
3159       emitcode ("mov", "a,_spx");
3160       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3161       emitcode ("mov", "_spx,a");
3162     }
3163
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* genEndFunction - generates epilogue for functions               */
3168 /*-----------------------------------------------------------------*/
3169 static void
3170 genEndFunction (iCode * ic)
3171 {
3172   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3173
3174   D (emitcode (";", "genEndFunction "););
3175
3176   if (IFFUNC_ISNAKED(sym->type))
3177   {
3178       emitcode(";", "naked function: no epilogue.");
3179       return;
3180   }
3181
3182   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3183        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3184
3185       if (options.stack10bit) {
3186           PROTECT_SP;     
3187           emitcode ("mov", "sp,_bpx", spname);
3188           emitcode ("mov", "esp,_bpx+1", spname);
3189           UNPROTECT_SP;
3190       } else {
3191           emitcode ("mov", "%s,_bp", spname);
3192       }
3193   }
3194
3195   /* if use external stack but some variables were
3196      added to the local stack then decrement the
3197      local stack */
3198   if (options.useXstack && sym->stack) {
3199       emitcode ("mov", "a,sp");
3200       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3201       emitcode ("mov", "sp,a");
3202   }
3203
3204
3205   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3206        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3207
3208       if (options.useXstack) {
3209           emitcode ("mov", "r0,%s", spname);
3210           emitcode ("movx", "a,@r0");
3211           emitcode ("mov", "_bp,a");
3212           emitcode ("dec", "%s", spname);
3213       } else {
3214           if (options.stack10bit) {
3215               emitcode ("pop", "_bpx+1");
3216               emitcode ("pop", "_bpx");
3217           } else {
3218               emitcode ("pop", "_bp");
3219           }
3220       }
3221   }
3222
3223   /* restore the register bank  */
3224   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3225   {
3226     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3227      || !options.useXstack)
3228     {
3229         /* Special case of ISR using non-zero bank with useXstack
3230          * is handled below.
3231          */
3232         emitcode ("pop", "psw");
3233     }
3234   } 
3235
3236   if (IFFUNC_ISISR (sym->type))
3237       { /* is ISR */  
3238
3239       /* now we need to restore the registers */
3240       /* if this isr has no bank i.e. is going to
3241          run with bank 0 , then we need to save more
3242          registers :-) */
3243       if (!FUNC_REGBANK (sym->type))
3244         {
3245             int i;
3246           /* if this function does not call any other
3247              function then we can be economical and
3248              save only those registers that are used */
3249           if (!IFFUNC_HASFCALL(sym->type))
3250             {
3251
3252               /* if any registers used */
3253               if (sym->regsUsed)
3254                 {
3255                   /* save the registers used */
3256                   for (i = sym->regsUsed->size; i >= 0; i--)
3257                     {
3258                       if (bitVectBitValue (sym->regsUsed, i) ||
3259                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3260                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3261                     }
3262                 }
3263
3264             }
3265           else
3266             {
3267               /* this function has  a function call cannot
3268                  determines register usage so we will have to pop the
3269                  entire bank */
3270               if (options.parms_in_bank1) {
3271                   for (i = 7 ; i >= 0 ; i-- ) {
3272                       emitcode ("pop","%s",rb1regs[i]);
3273                   }
3274               }
3275               unsaveRBank (0, ic, FALSE);
3276             }
3277         }
3278         else
3279         {
3280             /* This ISR uses a non-zero bank.
3281              *
3282              * Restore any register banks saved by genFunction
3283              * in reverse order.
3284              */
3285             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3286             int ix;
3287           
3288             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3289             {
3290                 if (savedBanks & (1 << ix))
3291                 {
3292                     unsaveRBank(ix, NULL, FALSE);
3293                 }
3294             }
3295             
3296             if (options.useXstack)
3297             {
3298                 /* Restore bank AFTER calling unsaveRBank,
3299                  * since it can trash r0.
3300                  */
3301                 emitcode ("pop", "psw");
3302             }
3303         }
3304
3305       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3306         {
3307           if (options.stack10bit)
3308             {
3309               emitcode ("pop", DP2_RESULT_REG);
3310               emitcode ("pop", "dpx1");
3311               emitcode ("pop", "dph1");
3312               emitcode ("pop", "dpl1");
3313             }
3314           emitcode ("pop", "dps");
3315           emitcode ("pop", "dpx");
3316         }
3317       if (!inExcludeList ("dph"))
3318         emitcode ("pop", "dph");
3319       if (!inExcludeList ("dpl"))
3320         emitcode ("pop", "dpl");
3321       if (!inExcludeList ("b"))
3322         emitcode ("pop", "b");
3323       if (!inExcludeList ("acc"))
3324         emitcode ("pop", "acc");
3325
3326       if (IFFUNC_ISCRITICAL (sym->type))
3327         emitcode ("setb", "ea");
3328
3329       /* if debug then send end of function */
3330       if (options.debug && currFunc) {
3331           _G.debugLine = 1;
3332           emitcode ("", "C$%s$%d$%d$%d ==.",
3333                     FileBaseName (ic->filename), currFunc->lastLine,
3334                     ic->level, ic->block);
3335           if (IS_STATIC (currFunc->etype))
3336             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3337           else
3338             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3339           _G.debugLine = 0;
3340         }
3341
3342       emitcode ("reti", "");
3343     }
3344   else
3345     {
3346       if (IFFUNC_ISCRITICAL (sym->type))
3347         emitcode ("setb", "ea");
3348
3349       if (IFFUNC_CALLEESAVES(sym->type))
3350         {
3351           int i;
3352
3353           /* if any registers used */
3354           if (sym->regsUsed)
3355             {
3356               /* save the registers used */
3357               for (i = sym->regsUsed->size; i >= 0; i--)
3358                 {
3359                   if (bitVectBitValue (sym->regsUsed, i) ||
3360                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3361                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3362                 }
3363             }
3364
3365         }
3366
3367       /* if debug then send end of function */
3368       if (options.debug && currFunc)
3369         {
3370           _G.debugLine = 1;
3371           emitcode ("", "C$%s$%d$%d$%d ==.",
3372                     FileBaseName (ic->filename), currFunc->lastLine,
3373                     ic->level, ic->block);
3374           if (IS_STATIC (currFunc->etype))
3375             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3376           else
3377             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3378           _G.debugLine = 0;
3379         }
3380
3381       emitcode ("ret", "");
3382     }
3383
3384 }
3385
3386 /*-----------------------------------------------------------------*/
3387 /* genJavaNativeRet - generate code for return JavaNative          */
3388 /*-----------------------------------------------------------------*/
3389 static void genJavaNativeRet(iCode *ic)
3390 {
3391     int i, size;
3392
3393     aopOp (IC_LEFT (ic), ic, FALSE, 
3394            AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3395     size = AOP_SIZE (IC_LEFT (ic));
3396
3397     assert (size <= 4);
3398
3399     /* it is assigned to GPR0-R3 then push them */
3400     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3401         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3402         for (i = 0 ; i < size ; i++ ) {
3403             emitcode ("push","%s",
3404                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3405         }
3406         for (i = (size-1) ; i >= 0 ; i--) {
3407             emitcode ("pop","a%s",javaRet[i]);
3408         }
3409     } else {
3410         for (i = 0 ; i < size ; i++) 
3411             emitcode ("mov","%s,%s",javaRet[i],
3412                       aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3413     }
3414     for (i = size ; i < 4 ; i++ )
3415             emitcode ("mov","%s,#0",javaRet[i]);
3416     return;
3417 }
3418
3419 /*-----------------------------------------------------------------*/
3420 /* genRet - generate code for return statement                     */
3421 /*-----------------------------------------------------------------*/
3422 static void
3423 genRet (iCode * ic)
3424 {
3425   int size, offset = 0, pushed = 0;
3426
3427   D (emitcode (";", "genRet "););
3428
3429   /* if we have no return value then
3430      just generate the "ret" */
3431   if (!IC_LEFT (ic))
3432     goto jumpret;
3433
3434   /* if this is a JavaNative function then return 
3435      value in different register */
3436   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3437       genJavaNativeRet(ic);
3438       goto jumpret;
3439   }
3440   /* we have something to return then
3441      move the return value into place */
3442   aopOp (IC_LEFT (ic), ic, FALSE, 
3443          (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3444   size = AOP_SIZE (IC_LEFT (ic));
3445
3446   _startLazyDPSEvaluation ();
3447   while (size--)
3448     {
3449       char *l;
3450       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3451         {
3452           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3453                       FALSE, TRUE, NULL);
3454           emitcode ("push", "%s", l);
3455           pushed++;
3456         }
3457       else
3458         {
3459           /* Since A is the last element of fReturn,
3460            * is is OK to clobber it in the aopGet.
3461            */
3462           l = aopGet (AOP (IC_LEFT (ic)), offset,
3463                       FALSE, FALSE, NULL);
3464           if (strcmp (fReturn[offset], l))
3465             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3466         }
3467     }
3468   _endLazyDPSEvaluation ();
3469
3470   if (pushed)
3471     {
3472       while (pushed)
3473         {
3474           pushed--;
3475           if (strcmp (fReturn[pushed], "a"))
3476             emitcode ("pop", fReturn[pushed]);
3477           else
3478             emitcode ("pop", "acc");
3479         }
3480     }
3481   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3482
3483 jumpret:
3484   /* generate a jump to the return label
3485      if the next is not the return statement */
3486   if (!(ic->next && ic->next->op == LABEL &&
3487         IC_LABEL (ic->next) == returnLabel))
3488
3489     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3490
3491 }
3492
3493 /*-----------------------------------------------------------------*/
3494 /* genLabel - generates a label                                    */
3495 /*-----------------------------------------------------------------*/
3496 static void
3497 genLabel (iCode * ic)
3498 {
3499   /* special case never generate */
3500   if (IC_LABEL (ic) == entryLabel)
3501     return;
3502
3503   D (emitcode (";", "genLabel ");
3504     );
3505
3506   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3507 }
3508
3509 /*-----------------------------------------------------------------*/
3510 /* genGoto - generates a ljmp                                      */
3511 /*-----------------------------------------------------------------*/
3512 static void
3513 genGoto (iCode * ic)
3514 {
3515   D (emitcode (";", "genGoto ");
3516     );
3517   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3518 }
3519
3520 /*-----------------------------------------------------------------*/
3521 /* findLabelBackwards: walks back through the iCode chain looking  */
3522 /* for the given label. Returns number of iCode instructions     */
3523 /* between that label and given ic.          */
3524 /* Returns zero if label not found.          */
3525 /*-----------------------------------------------------------------*/
3526 static int
3527 findLabelBackwards (iCode * ic, int key)
3528 {
3529   int count = 0;
3530
3531   while (ic->prev)
3532     {
3533       ic = ic->prev;
3534       count++;
3535
3536       /* If we have any pushes or pops, we cannot predict the distance.
3537          I don't like this at all, this should be dealt with in the 
3538          back-end */
3539       if (ic->op == IPUSH || ic->op == IPOP) {
3540         return 0;
3541       }
3542
3543       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3544         {
3545           /* printf("findLabelBackwards = %d\n", count); */
3546           return count;
3547         }
3548     }
3549
3550   return 0;
3551 }
3552
3553 /*-----------------------------------------------------------------*/
3554 /* genPlusIncr :- does addition with increment if possible         */
3555 /*-----------------------------------------------------------------*/
3556 static bool
3557 genPlusIncr (iCode * ic)
3558 {
3559   unsigned int icount;
3560   unsigned int size = getDataSize (IC_RESULT (ic));
3561
3562   /* will try to generate an increment */
3563   /* if the right side is not a literal
3564      we cannot */
3565   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3566     return FALSE;
3567
3568   /* if the literal value of the right hand side
3569      is greater than 4 then it is not worth it */
3570   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3571     return FALSE;
3572
3573   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3574       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3575       while (icount--) {
3576           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3577       }
3578       return TRUE;
3579   }
3580   /* if increment 16 bits in register */
3581   if (
3582        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3583        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3584        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3585        (size > 1) &&
3586        (icount == 1))
3587     {
3588       symbol  *tlbl;
3589       int     emitTlbl;
3590       int     labelRange;
3591       char    *l;
3592
3593       /* If the next instruction is a goto and the goto target
3594        * is <= 5 instructions previous to this, we can generate
3595        * jumps straight to that target.
3596        */
3597       if (ic->next && ic->next->op == GOTO
3598           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3599           && labelRange <= 5)
3600         {
3601           D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3602           tlbl = IC_LABEL (ic->next);
3603           emitTlbl = 0;
3604         }
3605       else
3606         {
3607           tlbl = newiTempLabel (NULL);
3608           emitTlbl = 1;
3609         }
3610         
3611       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3612       emitcode ("inc", "%s", l);
3613       
3614       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3615           IS_AOP_PREG (IC_RESULT (ic)))
3616       {   
3617         emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3618       }
3619       else
3620       {
3621           emitcode ("clr", "a");
3622           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3623       }
3624
3625       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL); 
3626       emitcode ("inc", "%s", l);
3627       if (size > 2)
3628         {
3629             if (!strcmp(l, "acc"))
3630             {
3631                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3632             }
3633             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3634                      IS_AOP_PREG (IC_RESULT (ic)))
3635             {
3636                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3637             }
3638             else
3639             {
3640                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3641             }
3642
3643             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3644             emitcode ("inc", "%s", l);
3645         }
3646       if (size > 3)
3647         {
3648             if (!strcmp(l, "acc"))
3649             {
3650                 emitcode("jnz", "!tlabel", tlbl->key + 100);
3651             }
3652             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3653                      IS_AOP_PREG (IC_RESULT (ic)))
3654             {
3655                 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3656             }
3657             else
3658             {
3659                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3660             }
3661
3662             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3663             emitcode ("inc", "%s", l);  }
3664
3665       if (emitTlbl)
3666         {
3667           emitcode ("", "!tlabeldef", tlbl->key + 100);
3668         }
3669       return TRUE;
3670     }
3671
3672   if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3673       !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 && 
3674       options.model == MODEL_FLAT24 ) {
3675
3676       switch (size) {
3677       case 3:
3678           emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3679       case 2:
3680           emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3681       case 1:
3682           emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3683           break;
3684       }
3685       while (icount--) emitcode ("inc","dptr");      
3686       return TRUE;
3687   }
3688
3689   if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3690       AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3691       icount <= 5 ) {
3692       emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3693       while (icount--) emitcode ("inc","dptr");
3694       emitcode ("mov","dps,#0");
3695       return TRUE;
3696   }
3697
3698   /* if the sizes are greater than 1 then we cannot */
3699   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3700       AOP_SIZE (IC_LEFT (ic)) > 1)
3701     return FALSE;
3702
3703   /* we can if the aops of the left & result match or
3704      if they are in registers and the registers are the
3705      same */
3706   if (
3707        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3708        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3709        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3710     {
3711
3712       if (icount > 3)
3713         {
3714           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3715           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3716           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3717         }
3718       else
3719         {
3720
3721           _startLazyDPSEvaluation ();
3722           while (icount--)
3723             {
3724               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3725             }
3726           _endLazyDPSEvaluation ();
3727         }
3728
3729       return TRUE;
3730     }
3731
3732   return FALSE;
3733 }
3734
3735 /*-----------------------------------------------------------------*/
3736 /* outBitAcc - output a bit in acc                                 */
3737 /*-----------------------------------------------------------------*/
3738 static void
3739 outBitAcc (operand * result)
3740 {
3741   symbol *tlbl = newiTempLabel (NULL);
3742   /* if the result is a bit */
3743   if (AOP_TYPE (result) == AOP_CRY)
3744     {
3745       aopPut (AOP (result), "a", 0);
3746     }
3747   else
3748     {
3749       emitcode ("jz", "!tlabel", tlbl->key + 100);
3750       emitcode ("mov", "a,%s", one);
3751       emitcode ("", "!tlabeldef", tlbl->key + 100);
3752       outAcc (result);
3753     }
3754 }
3755
3756 /*-----------------------------------------------------------------*/
3757 /* genPlusBits - generates code for addition of two bits           */
3758 /*-----------------------------------------------------------------*/
3759 static void
3760 genPlusBits (iCode * ic)
3761 {
3762   D (emitcode (";", "genPlusBits "););
3763     
3764   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3765     {
3766       symbol *lbl = newiTempLabel (NULL);
3767       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3768       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3769       emitcode ("cpl", "c");
3770       emitcode ("", "!tlabeldef", (lbl->key + 100));
3771       outBitC (IC_RESULT (ic));
3772     }
3773   else
3774     {
3775       emitcode ("clr", "a");
3776       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3777       emitcode ("rlc", "a");
3778       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3779       emitcode ("addc", "a,#0");
3780       outAcc (IC_RESULT (ic));
3781     }
3782 }
3783
3784 static void
3785 adjustArithmeticResult (iCode * ic)
3786 {
3787   if (opIsGptr (IC_RESULT (ic)) &&
3788       opIsGptr (IC_LEFT (ic)) &&
3789       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3790     {
3791       aopPut (AOP (IC_RESULT (ic)),
3792               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3793               GPTRSIZE - 1);
3794     }
3795
3796   if (opIsGptr (IC_RESULT (ic)) &&
3797       opIsGptr (IC_RIGHT (ic)) &&
3798       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3799     {
3800       aopPut (AOP (IC_RESULT (ic)),
3801             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3802               GPTRSIZE - 1);
3803     }
3804
3805   if (opIsGptr (IC_RESULT (ic)) &&
3806       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3807       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3808       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3809       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3810     {
3811       char buff[5];
3812       SNPRINTF (buff, sizeof(buff), 
3813                 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3814       aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3815     }
3816 }
3817
3818 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3819 // generates the result if possible. If result is generated, returns TRUE; otherwise
3820 // returns false and caller must deal with fact that result isn't aopOp'd.
3821 bool aopOp3(iCode * ic)
3822 {
3823     bool dp1InUse, dp2InUse;
3824     bool useDp2;
3825     
3826     // First, generate the right opcode. DPTR may be used if neither left nor result are
3827     // of type AOP_STR.
3828     
3829 //    D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3830 //             AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3831 //             AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3832 //             AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3833 //      );
3834 //    D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3835 //             AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3836 //             AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3837 //             AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3838 //      );
3839     
3840     // Right uses DPTR unless left or result is an AOP_STR; however,
3841     // if right is an AOP_STR, it must use DPTR regardless.
3842     if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3843      && !AOP_IS_STR(IC_RIGHT(ic)))
3844     {
3845         useDp2 = TRUE;
3846     }
3847     else
3848     {
3849         useDp2 = FALSE;
3850     }
3851         
3852     aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3853     
3854     // if the right used DPTR, left MUST use DPTR2.
3855     // if the right used DPTR2, left MUST use DPTR.
3856     // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3857     // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3858     // enabling us to assign DPTR to result.
3859      
3860     if (AOP_USESDPTR(IC_RIGHT(ic)))
3861     {
3862         useDp2 = TRUE;
3863     }
3864     else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3865     {
3866         useDp2 = FALSE;
3867     }
3868     else
3869     {
3870         if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3871         {
3872             useDp2 = TRUE;
3873         }
3874         else
3875         {
3876             useDp2 = FALSE;
3877         }
3878     }
3879
3880     aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3881     
3882     // We've op'd the left & right. So, if left or right are the same operand as result, 
3883     // we know aopOp will succeed, and we can just do it & bail.
3884     if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3885         isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3886     {
3887 //      D(emitcode(";", "aopOp3: (left | right) & result equal"););
3888         aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3889         return TRUE;
3890     }
3891     
3892     // Note which dptrs are currently in use.
3893     dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3894     dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3895     
3896     // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot 
3897     // generate it.
3898     if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3899     {
3900         return FALSE;
3901     }
3902     
3903     // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3904     if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3905     {
3906         return FALSE;
3907     }
3908     
3909     // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck    
3910     if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3911     {
3912         return FALSE;
3913     }
3914
3915     aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3916
3917     // Some sanity checking...
3918     if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3919     {
3920         fprintf(stderr,
3921                 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3922                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3923         emitcode(";", ">>> unexpected DPTR here.");
3924     }
3925     
3926     if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3927     {
3928         fprintf(stderr,
3929                 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3930                 __FILE__, __LINE__, ic->filename, ic->lineno);  
3931         emitcode(";", ">>> unexpected DPTR2 here.");
3932     }    
3933     
3934     return TRUE;
3935 }
3936
3937 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3938 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3939 // will be set TRUE. The caller must then handle the case specially, noting
3940 // that the IC_RESULT operand is not aopOp'd.
3941 // 
3942 #define AOP_OP_3_NOFATAL(ic, rc) \
3943             do { rc = !aopOp3(ic); } while (0)
3944
3945 // aopOp the left & right operands of an ic.
3946 #define AOP_OP_2(ic) \
3947     aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3948     aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3949
3950 // convienience macro.
3951 #define AOP_SET_LOCALS(ic) \
3952     left = IC_LEFT(ic); \
3953     right = IC_RIGHT(ic); \
3954     result = IC_RESULT(ic);
3955
3956
3957 // Given an integer value of pushedSize bytes on the stack,
3958 // adjust it to be resultSize bytes, either by discarding
3959 // the most significant bytes or by zero-padding.
3960 //
3961 // On exit from this macro, pushedSize will have been adjusted to
3962 // equal resultSize, and ACC may be trashed.
3963 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3964       /* If the pushed data is bigger than the result,          \
3965        * simply discard unused bytes. Icky, but works.          \
3966        */                                                       \
3967       while (pushedSize > resultSize)                           \
3968       {                                                         \
3969           D (emitcode (";", "discarding unused result byte."););\
3970           emitcode ("pop", "acc");                              \
3971           pushedSize--;                                         \
3972       }                                                         \
3973       if (pushedSize < resultSize)                              \
3974       {                                                         \
3975           emitcode ("clr", "a");                                \
3976           /* Conversly, we haven't pushed enough here.          \
3977            * just zero-pad, and all is well.                    \
3978            */                                                   \
3979           while (pushedSize < resultSize)                       \
3980           {                                                     \
3981               emitcode("push", "acc");                          \
3982               pushedSize++;                                     \
3983           }                                                     \
3984       }                                                         \
3985       assert(pushedSize == resultSize);
3986
3987 /*-----------------------------------------------------------------*/
3988 /* genPlus - generates code for addition                           */
3989 /*-----------------------------------------------------------------*/
3990 static void
3991 genPlus (iCode * ic)
3992 {
3993   int size, offset = 0;
3994   bool pushResult;
3995   int rSize;
3996
3997   D (emitcode (";", "genPlus "););
3998
3999   /* special cases :- */
4000   if ( AOP_IS_STR(IC_LEFT(ic)) &&
4001       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4002       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4003       size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4004       if (size <= 9) {
4005           while (size--) emitcode ("inc","dptr");
4006       } else {
4007           emitcode ("mov","a,dpl");
4008           emitcode ("add","a,#!constbyte",size & 0xff);
4009           emitcode ("mov","dpl,a");
4010           emitcode ("mov","a,dph");
4011           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4012           emitcode ("mov","dph,a");
4013           emitcode ("mov","a,dpx");
4014           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4015           emitcode ("mov","dpx,a");
4016       }
4017       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4018       return ;
4019   }
4020   if ( IS_SYMOP(IC_LEFT(ic)) && 
4021        OP_SYMBOL(IC_LEFT(ic))->remat &&
4022        isOperandInFarSpace(IC_RIGHT(ic))) {
4023       operand *op = IC_RIGHT(ic);
4024       IC_RIGHT(ic) = IC_LEFT(ic);
4025       IC_LEFT(ic) = op;
4026   }
4027                 
4028   AOP_OP_3_NOFATAL (ic, pushResult);
4029     
4030   if (pushResult)
4031     {
4032       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4033     }
4034
4035   if (!pushResult)
4036     {
4037       /* if literal, literal on the right or
4038          if left requires ACC or right is already
4039          in ACC */
4040       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4041        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4042           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4043         {
4044           operand *t = IC_RIGHT (ic);
4045           IC_RIGHT (ic) = IC_LEFT (ic);
4046           IC_LEFT (ic) = t;
4047           emitcode (";", "Swapped plus args.");
4048         }
4049
4050       /* if both left & right are in bit
4051          space */
4052       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4053           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4054         {
4055           genPlusBits (ic);
4056           goto release;
4057         }
4058
4059       /* if left in bit space & right literal */
4060       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4061           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4062         {
4063           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4064           /* if result in bit space */
4065           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4066             {
4067               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4068                 emitcode ("cpl", "c");
4069               outBitC (IC_RESULT (ic));
4070             }
4071           else
4072             {
4073               size = getDataSize (IC_RESULT (ic));
4074               _startLazyDPSEvaluation ();
4075               while (size--)
4076                 {
4077                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4078                   emitcode ("addc", "a,#0");
4079                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4080                 }
4081               _endLazyDPSEvaluation ();
4082             }
4083           goto release;
4084         }
4085
4086       /* if I can do an increment instead
4087          of add then GOOD for ME */
4088       if (genPlusIncr (ic) == TRUE)
4089         {
4090           emitcode (";", "did genPlusIncr");
4091           goto release;
4092         }
4093
4094     }
4095   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4096
4097   _startLazyDPSEvaluation ();
4098   while (size--)
4099     {
4100       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4101         {
4102           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4103           if (offset == 0)
4104             emitcode ("add", "a,%s",
4105                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4106           else
4107             emitcode ("addc", "a,%s",
4108                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4109         }
4110       else
4111         {
4112           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4113           {
4114               /* right is going to use ACC or we would have taken the
4115                * above branch.
4116                */
4117               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4118        TR_AP("#3");
4119               D(emitcode(";", "+ AOP_ACC special case."););
4120               emitcode("xch", "a, %s", DP2_RESULT_REG);
4121           }
4122           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4123           if (offset == 0)
4124           {
4125             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4126             {
4127          TR_AP("#4");
4128                 emitcode("add", "a, %s", DP2_RESULT_REG); 
4129             }
4130             else
4131             {
4132                 emitcode ("add", "a,%s",
4133                           aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4134                                   DP2_RESULT_REG));
4135             }
4136           }
4137           else
4138           {
4139             emitcode ("addc", "a,%s",
4140                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4141                           DP2_RESULT_REG));
4142           }
4143         }
4144       if (!pushResult)
4145         {
4146           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4147         }
4148       else
4149         {
4150           emitcode ("push", "acc");
4151         }
4152       offset++;
4153     }
4154   _endLazyDPSEvaluation ();
4155
4156   if (pushResult)
4157     {
4158       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4159
4160       size = getDataSize (IC_LEFT (ic));
4161       rSize = getDataSize (IC_RESULT (ic));
4162
4163       ADJUST_PUSHED_RESULT(size, rSize);
4164
4165       _startLazyDPSEvaluation ();
4166       while (size--)
4167         {
4168           emitcode ("pop", "acc");
4169           aopPut (AOP (IC_RESULT (ic)), "a", size);
4170         }
4171       _endLazyDPSEvaluation ();
4172     }
4173
4174   adjustArithmeticResult (ic);
4175
4176 release:
4177   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4178   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4179   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4180 }
4181
4182 /*-----------------------------------------------------------------*/
4183 /* genMinusDec :- does subtraction with deccrement if possible     */
4184 /*-----------------------------------------------------------------*/
4185 static bool
4186 genMinusDec (iCode * ic)
4187 {
4188   unsigned int icount;
4189   unsigned int size = getDataSize (IC_RESULT (ic));
4190
4191   /* will try to generate an increment */
4192   /* if the right side is not a literal
4193      we cannot */
4194   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4195     return FALSE;
4196
4197   /* if the literal value of the right hand side
4198      is greater than 4 then it is not worth it */
4199   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4200     return FALSE;
4201
4202   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4203       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4204       while (icount--) {
4205           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4206       }
4207       return TRUE;
4208   }
4209   /* if decrement 16 bits in register */
4210   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4211       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4212       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4213       (size > 1) &&
4214       (icount == 1))
4215     {
4216       symbol *tlbl;
4217       int    emitTlbl;
4218       int    labelRange;
4219       char   *l;
4220
4221       /* If the next instruction is a goto and the goto target
4222          * is <= 5 instructions previous to this, we can generate
4223          * jumps straight to that target.
4224        */
4225       if (ic->next && ic->next->op == GOTO
4226           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4227           && labelRange <= 5)
4228         {
4229           emitcode (";", "tail decrement optimized (range %d)", labelRange);
4230           tlbl = IC_LABEL (ic->next);
4231           emitTlbl = 0;
4232         }
4233       else
4234         {
4235           tlbl = newiTempLabel (NULL);
4236           emitTlbl = 1;
4237         }
4238
4239       l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4240       emitcode ("dec", "%s", l);
4241  
4242       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4243           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4244           IS_AOP_PREG (IC_RESULT (ic)))
4245       {     
4246           emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4247       }
4248       else
4249       {
4250           emitcode ("mov", "a,#!constbyte",0xff);
4251           emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4252       }
4253       l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4254       emitcode ("dec", "%s", l);
4255       if (size > 2)
4256         {
4257             if (!strcmp(l, "acc"))
4258             {
4259                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4260             }
4261             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4262                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4263                      IS_AOP_PREG (IC_RESULT (ic)))
4264             {       
4265                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4266             }
4267             else
4268             {
4269                 emitcode ("mov", "a,#!constbyte",0xff);
4270                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4271             }
4272             l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4273             emitcode ("dec", "%s", l);
4274         }
4275       if (size > 3)
4276         {
4277             if (!strcmp(l, "acc"))
4278             {
4279                 emitcode("jnz", "!tlabel", tlbl->key + 100);
4280             }
4281             else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4282                      AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4283                      IS_AOP_PREG (IC_RESULT (ic)))
4284             {       
4285                 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4286             }
4287             else
4288             {
4289                 emitcode ("mov", "a,#!constbyte",0xff);
4290                 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4291             }       
4292             l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4293             emitcode ("dec", "%s", l);
4294         }
4295       if (emitTlbl)
4296         {
4297           emitcode ("", "!tlabeldef", tlbl->key + 100);
4298         }
4299       return TRUE;
4300     }
4301
4302   /* if the sizes are greater than 1 then we cannot */
4303   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4304       AOP_SIZE (IC_LEFT (ic)) > 1)
4305     return FALSE;
4306
4307   /* we can if the aops of the left & result match or
4308      if they are in registers and the registers are the
4309      same */
4310   if (
4311        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4312        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4313        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4314     {
4315
4316       _startLazyDPSEvaluation ();
4317       while (icount--)
4318         {
4319           emitcode ("dec", "%s",
4320                     aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4321         }
4322       _endLazyDPSEvaluation ();
4323
4324       return TRUE;
4325     }
4326
4327   return FALSE;
4328 }
4329
4330 /*-----------------------------------------------------------------*/
4331 /* addSign - complete with sign                                    */
4332 /*-----------------------------------------------------------------*/
4333 static void
4334 addSign (operand * result, int offset, int sign)
4335 {
4336   int size = (getDataSize (result) - offset);
4337   if (size > 0)
4338     {
4339       _startLazyDPSEvaluation();
4340       if (sign)
4341         {
4342           emitcode ("rlc", "a");
4343           emitcode ("subb", "a,acc");
4344           while (size--)
4345           {
4346             aopPut (AOP (result), "a", offset++);
4347           }
4348         }
4349       else
4350       {
4351         while (size--)
4352         {
4353           aopPut (AOP (result), zero, offset++);
4354         }
4355       }
4356       _endLazyDPSEvaluation();
4357     }
4358 }
4359
4360 /*-----------------------------------------------------------------*/
4361 /* genMinusBits - generates code for subtraction  of two bits      */
4362 /*-----------------------------------------------------------------*/
4363 static void
4364 genMinusBits (iCode * ic)
4365 {
4366   symbol *lbl = newiTempLabel (NULL);
4367
4368   D (emitcode (";", "genMinusBits "););
4369
4370   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4371     {
4372       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4373       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4374       emitcode ("cpl", "c");
4375       emitcode ("", "!tlabeldef", (lbl->key + 100));
4376       outBitC (IC_RESULT (ic));
4377     }
4378   else
4379     {
4380       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4381       emitcode ("subb", "a,acc");
4382       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4383       emitcode ("inc", "a");
4384       emitcode ("", "!tlabeldef", (lbl->key + 100));
4385       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4386       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4387     }
4388 }
4389
4390 /*-----------------------------------------------------------------*/
4391 /* genMinus - generates code for subtraction                       */
4392 /*-----------------------------------------------------------------*/
4393 static void
4394 genMinus (iCode * ic)
4395 {
4396     int size, offset = 0;
4397     int rSize;
4398     long lit = 0L;
4399     bool pushResult;
4400
4401     D (emitcode (";", "genMinus "););
4402
4403     AOP_OP_3_NOFATAL(ic, pushResult);   
4404
4405     if (!pushResult)
4406     {
4407       /* special cases :- */
4408       /* if both left & right are in bit space */
4409       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4410           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4411         {
4412           genMinusBits (ic);
4413           goto release;
4414         }
4415
4416       /* if I can do an decrement instead
4417          of subtract then GOOD for ME */
4418       if (genMinusDec (ic) == TRUE)
4419         goto release;
4420
4421     }
4422
4423   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4424
4425   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4426     {
4427       CLRC;
4428     }
4429   else
4430     {
4431       lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4432       lit = -lit;
4433     }
4434
4435
4436   /* if literal, add a,#-lit, else normal subb */
4437   _startLazyDPSEvaluation ();
4438   while (size--) {
4439       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4440           if (AOP_USESDPTR(IC_RIGHT(ic))) {
4441               emitcode ("mov","b,%s",
4442                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4443               MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4444               emitcode ("subb","a,b");
4445           } else {
4446               MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4447               emitcode ("subb", "a,%s",
4448                         aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, 
4449                                 DP2_RESULT_REG));
4450           }
4451       } else {
4452           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4453           /* first add without previous c */
4454           if (!offset) {
4455               if (!size && lit==-1) {
4456                   emitcode ("dec", "a");
4457               } else {
4458                   emitcode ("add", "a,#!constbyte",
4459                             (unsigned int) (lit & 0x0FFL));
4460               }
4461           } else {
4462               emitcode ("addc", "a,#!constbyte",
4463                         (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4464           }
4465       }
4466       
4467       if (pushResult) {
4468           emitcode ("push", "acc");
4469       } else {
4470           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4471       }
4472       offset++;
4473   }
4474   _endLazyDPSEvaluation ();
4475   
4476   if (pushResult)
4477     {
4478       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4479
4480       size = getDataSize (IC_LEFT (ic));
4481       rSize = getDataSize (IC_RESULT (ic));
4482
4483       ADJUST_PUSHED_RESULT(size, rSize);
4484
4485       _startLazyDPSEvaluation ();
4486       while (size--)
4487         {
4488           emitcode ("pop", "acc");
4489           aopPut (AOP (IC_RESULT (ic)), "a", size);
4490         }
4491       _endLazyDPSEvaluation ();
4492     }
4493
4494   adjustArithmeticResult (ic);
4495
4496 release:
4497   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4499   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4500 }
4501
4502
4503 /*-----------------------------------------------------------------*/
4504 /* genMultbits :- multiplication of bits                           */
4505 /*-----------------------------------------------------------------*/
4506 static void
4507 genMultbits (operand * left,
4508              operand * right,
4509              operand * result,
4510              iCode   * ic)
4511 {
4512   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4513   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4514   aopOp(result, ic, TRUE, FALSE);
4515   outBitC (result);
4516 }
4517
4518
4519 /*-----------------------------------------------------------------*/
4520 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4521 /*-----------------------------------------------------------------*/
4522 static void
4523 genMultOneByte (operand * left,
4524                 operand * right,
4525                 operand * result,
4526                 iCode   * ic)
4527 {
4528   sym_link *opetype = operandType (result);
4529   symbol *lbl;
4530
4531
4532   /* (if two literals: the value is computed before) */
4533   /* if one literal, literal on the right */
4534   if (AOP_TYPE (left) == AOP_LIT)
4535     {
4536       operand *t = right;
4537       right = left;
4538       left = t;
4539       emitcode (";", "swapped left and right");
4540     }
4541
4542   if (SPEC_USIGN(opetype)
4543       // ignore the sign of left and right, what else can we do?
4544       || (SPEC_USIGN(operandType(left)) && 
4545           SPEC_USIGN(operandType(right)))) {
4546     // just an unsigned 8*8=8/16 multiply
4547     //emitcode (";","unsigned");
4548     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4549     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4550     emitcode ("mul", "ab");
4551    
4552     _G.accInUse++; _G.bInUse++;
4553     aopOp(result, ic, TRUE, FALSE);
4554       
4555       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4556       {
4557           // this should never happen
4558           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4559                    AOP_SIZE(result), __FILE__, lineno);
4560           exit (1);
4561       }      
4562       
4563     aopPut (AOP (result), "a", 0);
4564     _G.accInUse--; _G.bInUse--;
4565     if (AOP_SIZE(result)==2) 
4566     {
4567       aopPut (AOP (result), "b", 1);
4568     }
4569     return;
4570   }
4571
4572   // we have to do a signed multiply
4573
4574   emitcode (";", "signed");
4575   emitcode ("clr", "F0"); // reset sign flag
4576   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4577
4578   lbl=newiTempLabel(NULL);
4579   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4580   // left side is negative, 8-bit two's complement, this fails for -128
4581   emitcode ("setb", "F0"); // set sign flag
4582   emitcode ("cpl", "a");
4583   emitcode ("inc", "a");
4584
4585   emitcode ("", "!tlabeldef", lbl->key+100);
4586
4587   /* if literal */
4588   if (AOP_TYPE(right)==AOP_LIT) {
4589     signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4590     /* AND literal negative */
4591     if ((int) val < 0) {
4592       emitcode ("cpl", "F0"); // complement sign flag
4593       emitcode ("mov", "b,#!constbyte", -val);
4594     } else {
4595       emitcode ("mov", "b,#!constbyte", val);
4596     }
4597   } else {
4598     lbl=newiTempLabel(NULL);
4599     emitcode ("mov", "b,a");
4600     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4601     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4602     // right side is negative, 8-bit two's complement
4603     emitcode ("cpl", "F0"); // complement sign flag
4604     emitcode ("cpl", "a");
4605     emitcode ("inc", "a");
4606     emitcode ("", "!tlabeldef", lbl->key+100);
4607   }
4608   emitcode ("mul", "ab");
4609     
4610   _G.accInUse++;_G.bInUse++;
4611   aopOp(result, ic, TRUE, FALSE);
4612     
4613   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4614   {
4615     // this should never happen
4616       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4617                AOP_SIZE(result), __FILE__, lineno);
4618       exit (1);
4619   }    
4620     
4621   lbl=newiTempLabel(NULL);
4622   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4623   // only ONE op was negative, we have to do a 8/16-bit two's complement
4624   emitcode ("cpl", "a"); // lsb
4625   if (AOP_SIZE(result)==1) {
4626     emitcode ("inc", "a");
4627   } else {
4628     emitcode ("add", "a,#1");
4629     emitcode ("xch", "a,b");
4630     emitcode ("cpl", "a"); // msb
4631     emitcode ("addc", "a,#0");
4632     emitcode ("xch", "a,b");
4633   }
4634
4635   emitcode ("", "!tlabeldef", lbl->key+100);
4636   aopPut (AOP (result), "a", 0);
4637   _G.accInUse--;_G.bInUse--;
4638   if (AOP_SIZE(result)==2) {
4639     aopPut (AOP (result), "b", 1);
4640   }
4641 }
4642
4643 /*-----------------------------------------------------------------*/
4644 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4645 /*-----------------------------------------------------------------*/
4646 static void genMultTwoByte (operand *left, operand *right, 
4647                             operand *result, iCode *ic)
4648 {
4649         sym_link *retype = getSpec(operandType(right));
4650         sym_link *letype = getSpec(operandType(left));
4651         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4652         symbol *lbl;
4653
4654         if (AOP_TYPE (left) == AOP_LIT) {
4655                 operand *t = right;
4656                 right = left;
4657                 left = t;
4658         }
4659         /* save EA bit in F1 */
4660         lbl = newiTempLabel(NULL);
4661         emitcode ("setb","F1");
4662         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4663         emitcode ("clr","F1");
4664         emitcode("","!tlabeldef",lbl->key+100);
4665
4666         /* load up MB with right */
4667         if (!umult) {
4668                 emitcode("clr","F0");
4669                 if (AOP_TYPE(right) == AOP_LIT) {
4670                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4671                         if (val < 0) {
4672                                 emitcode("setb","F0");
4673                                 val = -val;
4674                         }
4675                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4676                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4677                 } else {
4678                         lbl = newiTempLabel(NULL);
4679                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4680                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4681                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4682                         emitcode ("xch", "a,b");
4683                         emitcode ("cpl","a");
4684                         emitcode ("add", "a,#1");
4685                         emitcode ("xch", "a,b");
4686                         emitcode ("cpl", "a"); // msb
4687                         emitcode ("addc", "a,#0");
4688                         emitcode ("setb","F0");
4689                         emitcode ("","!tlabeldef",lbl->key+100);
4690                         emitcode ("mov","mb,b");
4691                         emitcode ("mov","mb,a");
4692                 }
4693         } else {
4694                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4695                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4696         }
4697         /* load up MA with left */
4698         if (!umult) {
4699                 lbl = newiTempLabel(NULL);
4700                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4701                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4702                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4703                 emitcode ("xch", "a,b");
4704                 emitcode ("cpl","a");
4705                 emitcode ("add", "a,#1");
4706                 emitcode ("xch", "a,b");
4707                 emitcode ("cpl", "a"); // msb
4708                 emitcode ("addc","a,#0");
4709                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4710                 emitcode ("setb","F0");
4711                 emitcode ("","!tlabeldef",lbl->key+100);
4712                 emitcode ("mov","ma,b");
4713                 emitcode ("mov","ma,a");
4714         } else {
4715                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4716                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4717         }
4718         /* wait for multiplication to finish */
4719         lbl = newiTempLabel(NULL);
4720         emitcode("","!tlabeldef", lbl->key+100);
4721         emitcode("mov","a,mcnt1");
4722         emitcode("anl","a,#!constbyte",0x80);
4723         emitcode("jnz","!tlabel",lbl->key+100);
4724         
4725         freeAsmop (left, NULL, ic, TRUE);
4726         freeAsmop (right, NULL, ic,TRUE);
4727         aopOp(result, ic, TRUE, FALSE);
4728
4729         /* if unsigned then simple */   
4730         if (umult) {
4731                 emitcode ("mov","a,ma");
4732                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4733                 emitcode ("mov","a,ma");
4734                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4735                 aopPut(AOP(result),"ma",1);
4736                 aopPut(AOP(result),"ma",0);
4737         } else {
4738                 emitcode("push","ma");
4739                 emitcode("push","ma");
4740                 emitcode("push","ma");
4741                 MOVA("ma");
4742                 /* negate result if needed */
4743                 lbl = newiTempLabel(NULL);      
4744                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4745                 emitcode("cpl","a");
4746                 emitcode("add","a,#1");
4747                 emitcode("","!tlabeldef", lbl->key+100);
4748                 if (AOP_TYPE(result) == AOP_ACC)
4749                 {
4750                     D(emitcode(";", "ACC special case."););
4751                     /* We know result is the only live aop, and 
4752                      * it's obviously not a DPTR2, so AP is available.
4753                      */
4754                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4755                 }
4756                 else
4757                 {
4758                     aopPut(AOP(result),"a",0);
4759                 }
4760             
4761                 emitcode("pop","acc");
4762                 lbl = newiTempLabel(NULL);      
4763                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4764                 emitcode("cpl","a");
4765                 emitcode("addc","a,#0");
4766                 emitcode("","!tlabeldef", lbl->key+100);
4767                 aopPut(AOP(result),"a",1);
4768                 emitcode("pop","acc");
4769                 if (AOP_SIZE(result) >= 3) {
4770                         lbl = newiTempLabel(NULL);      
4771                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4772                         emitcode("cpl","a");
4773                         emitcode("addc","a,#0");                        
4774                         emitcode("","!tlabeldef", lbl->key+100);
4775                         aopPut(AOP(result),"a",2);
4776                 }
4777                 emitcode("pop","acc");
4778                 if (AOP_SIZE(result) >= 4) {
4779                         lbl = newiTempLabel(NULL);      
4780                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4781                         emitcode("cpl","a");
4782                         emitcode("addc","a,#0");                        
4783                         emitcode("","!tlabeldef", lbl->key+100);
4784                         aopPut(AOP(result),"a",3);
4785                 }
4786                 if (AOP_TYPE(result) == AOP_ACC)
4787                 {
4788                     /* We stashed the result away above. */
4789                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4790                 }           
4791                 
4792         }
4793         freeAsmop (result, NULL, ic, TRUE);
4794
4795         /* restore EA bit in F1 */
4796         lbl = newiTempLabel(NULL);
4797         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4798         emitcode ("setb","EA");
4799         emitcode("","!tlabeldef",lbl->key+100);
4800         return ;
4801 }
4802
4803 /*-----------------------------------------------------------------*/
4804 /* genMult - generates code for multiplication                     */
4805 /*-----------------------------------------------------------------*/
4806 static void
4807 genMult (iCode * ic)
4808 {
4809   operand *left = IC_LEFT (ic);
4810   operand *right = IC_RIGHT (ic);
4811   operand *result = IC_RESULT (ic);
4812
4813   D (emitcode (";", "genMult "););
4814
4815   /* assign the amsops */
4816   AOP_OP_2 (ic);
4817
4818   /* special cases first */
4819   /* both are bits */
4820   if (AOP_TYPE (left) == AOP_CRY &&
4821       AOP_TYPE (right) == AOP_CRY)
4822     {
4823       genMultbits (left, right, result, ic);
4824       goto release;
4825     }
4826
4827   /* if both are of size == 1 */
4828   if (AOP_SIZE (left) == 1 &&
4829       AOP_SIZE (right) == 1)
4830     {
4831       genMultOneByte (left, right, result, ic);
4832       goto release;
4833     }
4834
4835   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4836           /* use the ds390 ARITHMETIC accel UNIT */
4837           genMultTwoByte (left, right, result, ic);
4838           return ;
4839   }
4840   /* should have been converted to function call */
4841   assert (0);
4842
4843 release:
4844   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4845   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4846   freeAsmop (result, NULL, ic, TRUE);
4847 }
4848
4849 /*-----------------------------------------------------------------*/
4850 /* genDivbits :- division of bits                                  */
4851 /*-----------------------------------------------------------------*/
4852 static void
4853 genDivbits (operand * left,
4854             operand * right,
4855             operand * result,
4856             iCode   * ic)
4857 {
4858
4859   char *l;
4860
4861   /* the result must be bit */
4862   LOAD_AB_FOR_DIV (left, right, l);
4863   emitcode ("div", "ab");
4864   emitcode ("rrc", "a");
4865   aopOp(result, ic, TRUE, FALSE);
4866     
4867   aopPut (AOP (result), "c", 0);
4868 }
4869
4870 /*-----------------------------------------------------------------*/
4871 /* genDivOneByte : 8 bit division                                  */
4872 /*-----------------------------------------------------------------*/
4873 static void
4874 genDivOneByte (operand * left,
4875                operand * right,
4876                operand * result,
4877                iCode   * ic)
4878 {
4879   sym_link *opetype = operandType (result);
4880   char *l;
4881   symbol *lbl;
4882   int size, offset;
4883
4884   offset = 1;
4885   /* signed or unsigned */
4886   if (SPEC_USIGN (opetype))
4887     {
4888         /* unsigned is easy */
4889         LOAD_AB_FOR_DIV (left, right, l);
4890         emitcode ("div", "ab");
4891
4892         _G.accInUse++;
4893         aopOp(result, ic, TRUE, FALSE);
4894         aopPut (AOP (result), "a", 0);
4895         _G.accInUse--;
4896
4897         size = AOP_SIZE (result) - 1;
4898         
4899         while (size--)
4900         {
4901             aopPut (AOP (result), zero, offset++);
4902         }
4903       return;
4904     }
4905
4906   /* signed is a little bit more difficult */
4907
4908   /* save the signs of the operands */
4909   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4910   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4911   emitcode ("push", "acc");     /* save it on the stack */
4912
4913   /* now sign adjust for both left & right */
4914   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4915   lbl = newiTempLabel (NULL);
4916   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4917   emitcode ("cpl", "a");
4918   emitcode ("inc", "a");
4919   emitcode ("", "!tlabeldef", (lbl->key + 100));
4920   emitcode ("mov", "b,a");
4921
4922   /* sign adjust left side */
4923   MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4924
4925   lbl = newiTempLabel (NULL);
4926   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4927   emitcode ("cpl", "a");
4928   emitcode ("inc", "a");
4929   emitcode ("", "!tlabeldef", (lbl->key + 100));
4930
4931   /* now the division */
4932   emitcode ("nop", "; workaround for DS80C390 div bug.");
4933   emitcode ("div", "ab");
4934   /* we are interested in the lower order
4935      only */
4936   emitcode ("mov", "b,a");
4937   lbl = newiTempLabel (NULL);
4938   emitcode ("pop", "acc");
4939   /* if there was an over flow we don't
4940      adjust the sign of the result */
4941   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4942   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4943   CLRC;
4944   emitcode ("clr", "a");
4945   emitcode ("subb", "a,b");
4946   emitcode ("mov", "b,a");
4947   emitcode ("", "!tlabeldef", (lbl->key + 100));
4948
4949   /* now we are done */
4950   _G.accInUse++;     _G.bInUse++;
4951     aopOp(result, ic, TRUE, FALSE);
4952     
4953     aopPut (AOP (result), "b", 0);
4954     
4955     size = AOP_SIZE (result) - 1;
4956     
4957     if (size > 0)
4958     {
4959       emitcode ("mov", "c,b.7");
4960       emitcode ("subb", "a,acc");
4961     }
4962     while (size--)
4963     {
4964         aopPut (AOP (result), "a", offset++);
4965     }
4966     _G.accInUse--;     _G.bInUse--;
4967
4968 }
4969
4970 /*-----------------------------------------------------------------*/
4971 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4972 /*-----------------------------------------------------------------*/
4973 static void genDivTwoByte (operand *left, operand *right, 
4974                             operand *result, iCode *ic)
4975 {
4976         sym_link *retype = getSpec(operandType(right));
4977         sym_link *letype = getSpec(operandType(left));
4978         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4979         symbol *lbl;
4980
4981         /* save EA bit in F1 */
4982         lbl = newiTempLabel(NULL);
4983         emitcode ("setb","F1");
4984         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4985         emitcode ("clr","F1");
4986         emitcode("","!tlabeldef",lbl->key+100);
4987
4988         /* load up MA with left */
4989         if (!umult) {
4990                 emitcode("clr","F0");
4991                 lbl = newiTempLabel(NULL);
4992                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4993                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4994                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4995                 emitcode ("xch", "a,b");
4996                 emitcode ("cpl","a");
4997                 emitcode ("add", "a,#1");
4998                 emitcode ("xch", "a,b");
4999                 emitcode ("cpl", "a"); // msb
5000                 emitcode ("addc","a,#0");
5001                 emitcode ("setb","F0");
5002                 emitcode ("","!tlabeldef",lbl->key+100);
5003                 emitcode ("mov","ma,b");
5004                 emitcode ("mov","ma,a");
5005         } else {
5006                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5007                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5008         }
5009
5010         /* load up MB with right */
5011         if (!umult) {
5012                 if (AOP_TYPE(right) == AOP_LIT) {
5013                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5014                         if (val < 0) {
5015                                 lbl = newiTempLabel(NULL);
5016                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5017                                 emitcode("setb","F0");
5018                                 emitcode ("","!tlabeldef",lbl->key+100);
5019                                 val = -val;
5020                         } 
5021                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
5022                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5023                 } else {
5024                         lbl = newiTempLabel(NULL);
5025                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5026                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5027                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5028                         emitcode ("xch", "a,b");
5029                         emitcode ("cpl","a");
5030                         emitcode ("add", "a,#1");
5031                         emitcode ("xch", "a,b");
5032                         emitcode ("cpl", "a"); // msb
5033                         emitcode ("addc", "a,#0");
5034                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
5035                         emitcode ("setb","F0");
5036                         emitcode ("","!tlabeldef",lbl->key+100);
5037                         emitcode ("mov","mb,b");
5038                         emitcode ("mov","mb,a");
5039                 }
5040         } else {
5041                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5042                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5043         }
5044
5045         /* wait for multiplication to finish */
5046         lbl = newiTempLabel(NULL);
5047         emitcode("","!tlabeldef", lbl->key+100);
5048         emitcode("mov","a,mcnt1");
5049         emitcode("anl","a,#!constbyte",0x80);
5050         emitcode("jnz","!tlabel",lbl->key+100);
5051         
5052         freeAsmop (left, NULL, ic, TRUE);
5053         freeAsmop (right, NULL, ic,TRUE);
5054         aopOp(result, ic, TRUE, FALSE);
5055
5056         /* if unsigned then simple */   
5057         if (umult) {
5058                 aopPut(AOP(result),"ma",1);
5059                 aopPut(AOP(result),"ma",0);
5060         } else {
5061                 emitcode("push","ma");
5062                 MOVA("ma");
5063                 /* negate result if needed */
5064                 lbl = newiTempLabel(NULL);      
5065                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5066                 emitcode("cpl","a");
5067                 emitcode("add","a,#1");
5068                 emitcode("","!tlabeldef", lbl->key+100);
5069                 aopPut(AOP(result),"a",0);
5070                 emitcode("pop","acc");
5071                 lbl = newiTempLabel(NULL);      
5072                 emitcode("jnb","F0,!tlabel",lbl->key+100);
5073                 emitcode("cpl","a");
5074                 emitcode("addc","a,#0");
5075                 emitcode("","!tlabeldef", lbl->key+100);
5076                 aopPut(AOP(result),"a",1);
5077         }
5078         freeAsmop (result, NULL, ic, TRUE);
5079         /* restore EA bit in F1 */
5080         lbl = newiTempLabel(NULL);
5081         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5082         emitcode ("setb","EA");
5083         emitcode("","!tlabeldef",lbl->key+100);
5084         return ;
5085 }
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genDiv - generates code for division                            */
5089 /*-----------------------------------------------------------------*/
5090 static void
5091 genDiv (iCode * ic)
5092 {
5093   operand *left = IC_LEFT (ic);
5094   operand *right = IC_RIGHT (ic);
5095   operand *result = IC_RESULT (ic);
5096
5097   D (emitcode (";", "genDiv "););
5098
5099   /* assign the amsops */
5100   AOP_OP_2 (ic);
5101
5102   /* special cases first */
5103   /* both are bits */
5104   if (AOP_TYPE (left) == AOP_CRY &&
5105       AOP_TYPE (right) == AOP_CRY)
5106     {
5107       genDivbits (left, right, result, ic);
5108       goto release;
5109     }
5110
5111   /* if both are of size == 1 */
5112   if (AOP_SIZE (left) == 1 &&
5113       AOP_SIZE (right) == 1)
5114     {
5115       genDivOneByte (left, right, result, ic);
5116       goto release;
5117     }
5118
5119   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5120           /* use the ds390 ARITHMETIC accel UNIT */
5121           genDivTwoByte (left, right, result, ic);
5122           return ;
5123   }
5124   /* should have been converted to function call */
5125   assert (0);
5126 release:
5127   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5128   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5129   freeAsmop (result, NULL, ic, TRUE);
5130 }
5131
5132 /*-----------------------------------------------------------------*/
5133 /* genModbits :- modulus of bits                                   */
5134 /*-----------------------------------------------------------------*/
5135 static void
5136 genModbits (operand * left,
5137             operand * right,
5138             operand * result,
5139             iCode   * ic)
5140 {
5141
5142   char *l;
5143
5144   /* the result must be bit */
5145   LOAD_AB_FOR_DIV (left, right, l);
5146   emitcode ("div", "ab");
5147   emitcode ("mov", "a,b");
5148   emitcode ("rrc", "a");
5149   aopOp(result, ic, TRUE, FALSE);
5150   aopPut (AOP (result), "c", 0);
5151 }
5152
5153 /*-----------------------------------------------------------------*/
5154 /* genModOneByte : 8 bit modulus                                   */
5155 /*-----------------------------------------------------------------*/
5156 static void
5157 genModOneByte (operand * left,
5158                operand * right,
5159                operand * result,
5160                iCode   * ic)
5161 {
5162   sym_link *opetype = operandType (result);
5163   char *l;
5164   symbol *lbl;
5165
5166   /* signed or unsigned */
5167   if (SPEC_USIGN (opetype))
5168     {
5169       /* unsigned is easy */
5170       LOAD_AB_FOR_DIV (left, right, l);
5171       emitcode ("div", "ab");
5172       aopOp(result, ic, TRUE, FALSE);   
5173       aopPut (AOP (result), "b", 0);
5174       return;
5175     }
5176
5177   /* signed is a little bit more difficult */
5178
5179   /* save the signs of the operands */
5180   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5181
5182   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5183   emitcode ("push", "acc");     /* save it on the stack */
5184
5185   /* now sign adjust for both left & right */
5186   MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5187
5188   lbl = newiTempLabel (NULL);
5189   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5190   emitcode ("cpl", "a");
5191   emitcode ("inc", "a");
5192   emitcode ("", "!tlabeldef", (lbl->key + 100));
5193   emitcode ("mov", "b,a");
5194
5195   /* sign adjust left side */
5196   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5197
5198   lbl = newiTempLabel (NULL);
5199   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5200   emitcode ("cpl", "a");
5201   emitcode ("inc", "a");
5202   emitcode ("", "!tlabeldef", (lbl->key + 100));
5203
5204   /* now the multiplication */
5205   emitcode ("nop", "; workaround for DS80C390 div bug.");
5206   emitcode ("div", "ab");
5207   /* we are interested in the lower order
5208      only */
5209   lbl = newiTempLabel (NULL);
5210   emitcode ("pop", "acc");
5211   /* if there was an over flow we don't
5212      adjust the sign of the result */
5213   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5214   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5215   CLRC;
5216   emitcode ("clr", "a");
5217   emitcode ("subb", "a,b");
5218   emitcode ("mov", "b,a");
5219   emitcode ("", "!tlabeldef", (lbl->key + 100));
5220   
5221   _G.bInUse++;
5222   /* now we are done */
5223   aopOp(result, ic, TRUE, FALSE);    
5224   aopPut (AOP (result), "b", 0);
5225   _G.bInUse--;
5226
5227 }
5228
5229 /*-----------------------------------------------------------------*/
5230 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
5231 /*-----------------------------------------------------------------*/
5232 static void genModTwoByte (operand *left, operand *right, 
5233                             operand *result, iCode *ic)
5234 {
5235         sym_link *retype = getSpec(operandType(right));
5236         sym_link *letype = getSpec(operandType(left));
5237         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5238         symbol *lbl;
5239
5240         /* load up MA with left */
5241         /* save EA bit in F1 */
5242         lbl = newiTempLabel(NULL);
5243         emitcode ("setb","F1");
5244         emitcode ("jbc","EA,!tlabel",lbl->key+100);
5245         emitcode ("clr","F1");
5246         emitcode("","!tlabeldef",lbl->key+100);
5247
5248         if (!umult) {
5249                 lbl = newiTempLabel(NULL);
5250                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5251                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5252                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5253                 emitcode ("xch", "a,b");
5254                 emitcode ("cpl","a");
5255                 emitcode ("add", "a,#1");
5256                 emitcode ("xch", "a,b");
5257                 emitcode ("cpl", "a"); // msb
5258                 emitcode ("addc","a,#0");
5259                 emitcode ("","!tlabeldef",lbl->key+100);
5260                 emitcode ("mov","ma,b");
5261                 emitcode ("mov","ma,a");
5262         } else {
5263                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5264                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5265         }
5266
5267         /* load up MB with right */
5268         if (!umult) {
5269                 if (AOP_TYPE(right) == AOP_LIT) {
5270                         int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5271                         if (val < 0) {
5272                                 val = -val;
5273                         } 
5274                         emitcode ("mov","mb,#!constbyte",val & 0xff);
5275                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
5276                 } else {
5277                         lbl = newiTempLabel(NULL);
5278                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5279                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5280                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
5281                         emitcode ("xch", "a,b");
5282                         emitcode ("cpl","a");
5283                         emitcode ("add", "a,#1");
5284                         emitcode ("xch", "a,b");
5285                         emitcode ("cpl", "a"); // msb
5286                         emitcode ("addc", "a,#0");
5287                         emitcode ("","!tlabeldef",lbl->key+100);
5288                         emitcode ("mov","mb,b");
5289                         emitcode ("mov","mb,a");
5290                 }
5291         } else {
5292                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5293                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5294         }
5295
5296         /* wait for multiplication to finish */
5297         lbl = newiTempLabel(NULL);
5298         emitcode("","!tlabeldef", lbl->key+100);
5299         emitcode("mov","a,mcnt1");
5300         emitcode("anl","a,#!constbyte",0x80);
5301         emitcode("jnz","!tlabel",lbl->key+100);
5302         
5303         freeAsmop (left, NULL, ic, TRUE);
5304         freeAsmop (right, NULL, ic,TRUE);
5305         aopOp(result, ic, TRUE, FALSE);
5306
5307         aopPut(AOP(result),"mb",1);
5308         aopPut(AOP(result),"mb",0);
5309         freeAsmop (result, NULL, ic, TRUE);
5310
5311         /* restore EA bit in F1 */
5312         lbl = newiTempLabel(NULL);
5313         emitcode ("jnb","F1,!tlabel",lbl->key+100);
5314         emitcode ("setb","EA");
5315         emitcode("","!tlabeldef",lbl->key+100);
5316         return ;
5317 }
5318
5319 /*-----------------------------------------------------------------*/
5320 /* genMod - generates code for division                            */
5321 /*-----------------------------------------------------------------*/
5322 static void
5323 genMod (iCode * ic)
5324 {
5325   operand *left = IC_LEFT (ic);
5326   operand *right = IC_RIGHT (ic);
5327   operand *result = IC_RESULT (ic);
5328
5329   D (emitcode (";", "genMod "); );
5330
5331   /* assign the amsops */
5332   AOP_OP_2 (ic);
5333
5334   /* special cases first */
5335   /* both are bits */
5336   if (AOP_TYPE (left) == AOP_CRY &&
5337       AOP_TYPE (right) == AOP_CRY)
5338     {
5339       genModbits (left, right, result, ic);
5340       goto release;
5341     }
5342
5343   /* if both are of size == 1 */
5344   if (AOP_SIZE (left) == 1 &&
5345       AOP_SIZE (right) == 1)
5346     {
5347       genModOneByte (left, right, result, ic);
5348       goto release;
5349     }
5350
5351   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5352           /* use the ds390 ARITHMETIC accel UNIT */
5353           genModTwoByte (left, right, result, ic);
5354           return ;
5355   }
5356
5357   /* should have been converted to function call */
5358   assert (0);
5359
5360 release:
5361   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5363   freeAsmop (result, NULL, ic, TRUE);
5364 }
5365
5366 /*-----------------------------------------------------------------*/
5367 /* genIfxJump :- will create a jump depending on the ifx           */
5368 /*-----------------------------------------------------------------*/
5369 static void
5370 genIfxJump (iCode * ic, char *jval)
5371 {
5372   symbol *jlbl;
5373   symbol *tlbl = newiTempLabel (NULL);
5374   char *inst;
5375
5376   D (emitcode (";", "genIfxJump"););
5377
5378   /* if true label then we jump if condition
5379      supplied is true */
5380   if (IC_TRUE (ic))
5381     {
5382       jlbl = IC_TRUE (ic);
5383       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5384                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5385     }
5386   else
5387     {
5388       /* false label is present */
5389       jlbl = IC_FALSE (ic);
5390       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5391                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5392     }
5393   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5394     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5395   else
5396     emitcode (inst, "!tlabel", tlbl->key + 100);
5397   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5398   emitcode ("", "!tlabeldef", tlbl->key + 100);
5399
5400   /* mark the icode as generated */
5401   ic->generated = 1;
5402 }
5403
5404 /*-----------------------------------------------------------------*/
5405 /* genCmp :- greater or less than comparison                       */
5406 /*-----------------------------------------------------------------*/
5407 static void
5408 genCmp (operand * left, operand * right,
5409         iCode * ic, iCode * ifx, int sign)
5410 {
5411   int size, offset = 0;
5412   unsigned long lit = 0L;
5413   operand *result;
5414
5415   D (emitcode (";", "genCmp"););
5416
5417   result = IC_RESULT (ic);
5418
5419   /* if left & right are bit variables */
5420   if (AOP_TYPE (left) == AOP_CRY &&
5421       AOP_TYPE (right) == AOP_CRY)
5422     {
5423       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5424       emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5425     }
5426   else
5427     {
5428       /* subtract right from left if at the
5429          end the carry flag is set then we know that
5430          left is greater than right */
5431       size = max (AOP_SIZE (left), AOP_SIZE (right));
5432
5433       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5434       if ((size == 1) && !sign 
5435           && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5436         {
5437           symbol *lbl = newiTempLabel (NULL);
5438           emitcode ("cjne", "%s,%s,!tlabel",
5439                     aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5440                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5441                     lbl->key + 100);
5442           emitcode ("", "!tlabeldef", lbl->key + 100);
5443         }
5444       else
5445         {
5446           if (AOP_TYPE (right) == AOP_LIT)
5447             {
5448               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5449               /* optimize if(x < 0) or if(x >= 0) */
5450               if (lit == 0L)
5451                 {
5452                   if (!sign)
5453                     {
5454                       CLRC;
5455                     }
5456                   else
5457                     {
5458                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5459
5460                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5461                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5462
5463                       aopOp (result, ic, FALSE, FALSE);
5464
5465                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5466                         {
5467                           freeAsmop (result, NULL, ic, TRUE);
5468                           genIfxJump (ifx, "acc.7");
5469                           return;
5470                         }
5471                       else
5472                         {
5473                           emitcode ("rlc", "a");
5474                         }
5475                       goto release_freedLR;
5476                     }
5477                   goto release;
5478                 }
5479             }
5480           CLRC;
5481           while (size--)
5482             {
5483               // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5484               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5485               // emitcode (";", "genCmp #2");
5486               if (sign && (size == 0))
5487                 {
5488                   // emitcode (";", "genCmp #3");
5489                   emitcode ("xrl", "a,#!constbyte",0x80);
5490                   if (AOP_TYPE (right) == AOP_LIT)
5491                     {
5492                       unsigned long lit = (unsigned long)
5493                       floatFromVal (AOP (right)->aopu.aop_lit);
5494                       // emitcode (";", "genCmp #3.1");
5495                       emitcode ("subb", "a,#!constbyte",
5496                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5497                     }
5498                   else
5499                     {
5500                       // emitcode (";", "genCmp #3.2");
5501                       saveAccWarn = 0;  
5502                       MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5503                       saveAccWarn = DEFAULT_ACC_WARNING;
5504                       emitcode ("xrl", "b,#!constbyte",0x80);
5505                       emitcode ("subb", "a,b");
5506                     }
5507                 }
5508               else
5509                 {
5510                   const char *s;
5511
5512                   // emitcode (";", "genCmp #4");
5513                   saveAccWarn = 0;
5514                   s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5515                   saveAccWarn = DEFAULT_ACC_WARNING;
5516
5517                   emitcode ("subb", "a,%s", s);
5518                 }
5519             }
5520         }
5521     }
5522
5523 release:
5524 /* Don't need the left & right operands any more; do need the result. */
5525   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5526   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5527
5528   aopOp (result, ic, FALSE, FALSE);
5529
5530 release_freedLR:
5531
5532   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5533     {
5534       outBitC (result);
5535     }
5536   else
5537     {
5538       /* if the result is used in the next
5539          ifx conditional branch then generate
5540          code a little differently */
5541       if (ifx)
5542         {
5543           genIfxJump (ifx, "c");
5544         }
5545       else
5546         {
5547           outBitC (result);
5548         }
5549       /* leave the result in acc */
5550     }
5551   freeAsmop (result, NULL, ic, TRUE);
5552 }
5553
5554 /*-----------------------------------------------------------------*/
5555 /* genCmpGt :- greater than comparison                             */
5556 /*-----------------------------------------------------------------*/
5557 static void
5558 genCmpGt (iCode * ic, iCode * ifx)
5559 {
5560   operand *left, *right;
5561   sym_link *letype, *retype;
5562   int sign;
5563
5564   D (emitcode (";", "genCmpGt ");
5565     );
5566
5567   left = IC_LEFT (ic);
5568   right = IC_RIGHT (ic);
5569
5570   letype = getSpec (operandType (left));
5571   retype = getSpec (operandType (right));
5572   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5573
5574   /* assign the left & right amsops */
5575   AOP_OP_2 (ic);
5576
5577   genCmp (right, left, ic, ifx, sign);
5578 }
5579
5580 /*-----------------------------------------------------------------*/
5581 /* genCmpLt - less than comparisons                                */
5582 /*-----------------------------------------------------------------*/
5583 static void
5584 genCmpLt (iCode * ic, iCode * ifx)
5585 {
5586   operand *left, *right;
5587   sym_link *letype, *retype;
5588   int sign;
5589
5590   D (emitcode (";", "genCmpLt "););
5591
5592   left = IC_LEFT (ic);
5593   right = IC_RIGHT (ic);
5594
5595   letype = getSpec (operandType (left));
5596   retype = getSpec (operandType (right));
5597   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5598
5599   /* assign the left & right amsops */
5600   AOP_OP_2 (ic);
5601
5602   genCmp (left, right, ic, ifx, sign);
5603 }
5604
5605 /*-----------------------------------------------------------------*/
5606 /* gencjneshort - compare and jump if not equal                    */
5607 /*-----------------------------------------------------------------*/
5608 static void
5609 gencjneshort (operand * left, operand * right, symbol * lbl)
5610 {
5611   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5612   int offset = 0;
5613   unsigned long lit = 0L;
5614
5615   D (emitcode (";", "gencjneshort");
5616     );
5617
5618   /* if the left side is a literal or
5619      if the right is in a pointer register and left
5620      is not */
5621   if ((AOP_TYPE (left) == AOP_LIT) ||
5622       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5623     {
5624       operand *t = right;
5625       right = left;
5626       left = t;
5627     }
5628
5629   if (AOP_TYPE (right) == AOP_LIT)
5630     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5631
5632   if (opIsGptr (left) || opIsGptr (right))
5633     {
5634       /* We are comparing a generic pointer to something.
5635        * Exclude the generic type byte from the comparison.
5636        */
5637       size--;
5638       D (emitcode (";", "cjneshort: generic ptr special case."););
5639     }
5640
5641
5642   /* if the right side is a literal then anything goes */
5643   if (AOP_TYPE (right) == AOP_LIT &&
5644       AOP_TYPE (left) != AOP_DIR)
5645     {
5646       while (size--)
5647         {
5648           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5649           emitcode ("cjne", "a,%s,!tlabel",
5650                     aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5651                     lbl->key + 100);
5652           offset++;
5653         }
5654     }
5655
5656   /* if the right side is in a register or in direct space or
5657      if the left is a pointer register & right is not */
5658   else if (AOP_TYPE (right) == AOP_REG ||
5659            AOP_TYPE (right) == AOP_DIR ||
5660            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5661            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5662     {
5663       while (size--)
5664         {
5665           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5666           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5667               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5668             emitcode ("jnz", "!tlabel", lbl->key + 100);
5669           else
5670             emitcode ("cjne", "a,%s,!tlabel",
5671                       aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5672                       lbl->key + 100);
5673           offset++;
5674         }
5675     }
5676   else
5677     {
5678       /* right is a pointer reg need both a & b */
5679       while (size--)
5680         {
5681           MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5682           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5683           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5684           offset++;
5685         }
5686     }
5687 }
5688
5689 /*-----------------------------------------------------------------*/
5690 /* gencjne - compare and jump if not equal                         */
5691 /*-----------------------------------------------------------------*/
5692 static void
5693 gencjne (operand * left, operand * right, symbol * lbl)
5694 {
5695   symbol *tlbl = newiTempLabel (NULL);
5696
5697   D (emitcode (";", "gencjne");
5698     );
5699
5700   gencjneshort (left, right, lbl);
5701
5702   emitcode ("mov", "a,%s", one);
5703   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5704   emitcode ("", "!tlabeldef", lbl->key + 100);
5705   emitcode ("clr", "a");
5706   emitcode ("", "!tlabeldef", tlbl->key + 100);
5707 }
5708
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpEq - generates code for equal to                          */
5711 /*-----------------------------------------------------------------*/
5712 static void
5713 genCmpEq (iCode * ic, iCode * ifx)
5714 {
5715   operand *left, *right, *result;
5716
5717   D (emitcode (";", "genCmpEq ");
5718     );
5719
5720   AOP_OP_2 (ic);
5721   AOP_SET_LOCALS (ic);
5722
5723   /* if literal, literal on the right or
5724      if the right is in a pointer register and left
5725      is not */
5726   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5727       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5728     {
5729       operand *t = IC_RIGHT (ic);
5730       IC_RIGHT (ic) = IC_LEFT (ic);
5731       IC_LEFT (ic) = t;
5732     }
5733
5734   if (ifx &&                    /* !AOP_SIZE(result) */
5735       OP_SYMBOL (result) &&
5736       OP_SYMBOL (result)->regType == REG_CND)
5737     {
5738       symbol *tlbl;
5739       /* if they are both bit variables */
5740       if (AOP_TYPE (left) == AOP_CRY &&
5741           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5742         {
5743           if (AOP_TYPE (right) == AOP_LIT)
5744             {
5745               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5746               if (lit == 0L)
5747                 {
5748                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5749                   emitcode ("cpl", "c");
5750                 }
5751               else if (lit == 1L)
5752                 {
5753                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5754                 }
5755               else
5756                 {
5757                   emitcode ("clr", "c");
5758                 }
5759               /* AOP_TYPE(right) == AOP_CRY */
5760             }
5761           else
5762             {
5763               symbol *lbl = newiTempLabel (NULL);
5764               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5766               emitcode ("cpl", "c");
5767               emitcode ("", "!tlabeldef", (lbl->key + 100));
5768             }
5769           /* if true label then we jump if condition
5770              supplied is true */
5771           tlbl = newiTempLabel (NULL);
5772           if (IC_TRUE (ifx))
5773             {
5774               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5775               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5776             }
5777           else
5778             {
5779               emitcode ("jc", "!tlabel", tlbl->key + 100);
5780               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5781             }
5782           emitcode ("", "!tlabeldef", tlbl->key + 100);
5783         }
5784       else
5785         {
5786           tlbl = newiTempLabel (NULL);
5787           gencjneshort (left, right, tlbl);
5788           if (IC_TRUE (ifx))
5789             {
5790               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5791               emitcode ("", "!tlabeldef", tlbl->key + 100);
5792             }
5793           else
5794             {
5795               symbol *lbl = newiTempLabel (NULL);
5796               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5797               emitcode ("", "!tlabeldef", tlbl->key + 100);
5798               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5799               emitcode ("", "!tlabeldef", lbl->key + 100);
5800             }
5801         }
5802       /* mark the icode as generated */
5803       ifx->generated = 1;
5804
5805       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5806       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5807       return;
5808     }
5809
5810   /* if they are both bit variables */
5811   if (AOP_TYPE (left) == AOP_CRY &&
5812       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5813     {
5814       if (AOP_TYPE (right) == AOP_LIT)
5815         {
5816           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5817           if (lit == 0L)
5818             {
5819               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5820               emitcode ("cpl", "c");
5821             }
5822           else if (lit == 1L)
5823             {
5824               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5825             }
5826           else
5827             {
5828               emitcode ("clr", "c");
5829             }
5830           /* AOP_TYPE(right) == AOP_CRY */
5831         }
5832       else
5833         {
5834           symbol *lbl = newiTempLabel (NULL);
5835           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5836           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5837           emitcode ("cpl", "c");
5838           emitcode ("", "!tlabeldef", (lbl->key + 100));
5839         }
5840
5841       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5842       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5843
5844       aopOp (result, ic, TRUE, FALSE);
5845
5846       /* c = 1 if egal */
5847       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5848         {
5849           outBitC (result);
5850           goto release;
5851         }
5852       if (ifx)
5853         {
5854           genIfxJump (ifx, "c");
5855           goto release;
5856         }
5857       /* if the result is used in an arithmetic operation
5858          then put the result in place */
5859       outBitC (result);
5860     }
5861   else
5862     {
5863       gencjne (left, right, newiTempLabel (NULL));
5864
5865       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5866       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5867
5868       aopOp (result, ic, TRUE, FALSE);
5869
5870       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5871         {
5872           aopPut (AOP (result), "a", 0);
5873           goto release;
5874         }
5875       if (ifx)
5876         {
5877           genIfxJump (ifx, "a");
5878           goto release;
5879         }
5880       /* if the result is used in an arithmetic operation
5881          then put the result in place */
5882       if (AOP_TYPE (result) != AOP_CRY)
5883         outAcc (result);
5884       /* leave the result in acc */
5885     }
5886
5887 release:
5888   freeAsmop (result, NULL, ic, TRUE);
5889 }
5890
5891 /*-----------------------------------------------------------------*/
5892 /* ifxForOp - returns the icode containing the ifx for operand     */
5893 /*-----------------------------------------------------------------*/
5894 static iCode *
5895 ifxForOp (operand * op, iCode * ic)
5896 {
5897   /* if true symbol then needs to be assigned */
5898   if (IS_TRUE_SYMOP (op))
5899     return NULL;
5900
5901   /* if this has register type condition and
5902      the next instruction is ifx with the same operand
5903      and live to of the operand is upto the ifx only then */
5904   if (ic->next &&
5905       ic->next->op == IFX &&
5906       IC_COND (ic->next)->key == op->key &&
5907       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5908     return ic->next;
5909
5910   return NULL;
5911 }
5912 /*-----------------------------------------------------------------*/
5913 /* hasInc - operand is incremented before any other use            */
5914 /*-----------------------------------------------------------------*/
5915 static iCode *
5916 hasInc (operand *op, iCode *ic, int osize)
5917 {
5918   sym_link *type = operandType(op);
5919   sym_link *retype = getSpec (type);
5920   iCode *lic = ic->next;
5921   int isize ;
5922   
5923   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5924   if (!IS_SYMOP(op)) return NULL;
5925
5926   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5927   if (IS_AGGREGATE(type->next)) return NULL;
5928   if (osize != (isize = getSize(type->next))) return NULL;
5929
5930   while (lic) {
5931       /* if operand of the form op = op + <sizeof *op> */
5932       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5933           isOperandEqual(IC_RESULT(lic),op) && 
5934           isOperandLiteral(IC_RIGHT(lic)) &&
5935           operandLitValue(IC_RIGHT(lic)) == isize) {
5936           return lic;
5937       }
5938       /* if the operand used or deffed */
5939       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5940           return NULL;
5941       }
5942       /* if GOTO or IFX */
5943       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5944       lic = lic->next;
5945   }
5946   return NULL;
5947 }
5948
5949 /*-----------------------------------------------------------------*/
5950 /* genAndOp - for && operation                                     */
5951 /*-----------------------------------------------------------------*/
5952 static void
5953 genAndOp (iCode * ic)
5954 {
5955   operand *left, *right, *result;
5956   symbol *tlbl;
5957
5958   D (emitcode (";", "genAndOp "););
5959
5960   /* note here that && operations that are in an
5961      if statement are taken away by backPatchLabels
5962      only those used in arthmetic operations remain */
5963   AOP_OP_2 (ic);
5964   AOP_SET_LOCALS (ic);
5965
5966   /* if both are bit variables */
5967   if (AOP_TYPE (left) == AOP_CRY &&
5968       AOP_TYPE (right) == AOP_CRY)
5969     {
5970       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5971       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5972       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5973       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5974   
5975       aopOp (result,ic,FALSE, FALSE);
5976       outBitC (result);
5977     }
5978   else
5979     {
5980       tlbl = newiTempLabel (NULL);
5981       toBoolean (left);
5982       emitcode ("jz", "!tlabel", tlbl->key + 100);
5983       toBoolean (right);
5984       emitcode ("", "!tlabeldef", tlbl->key + 100);
5985       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5986       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5987   
5988       aopOp (result,ic,FALSE, FALSE);
5989       outBitAcc (result);
5990     }
5991     freeAsmop (result, NULL, ic, TRUE);
5992 }
5993
5994
5995 /*-----------------------------------------------------------------*/
5996 /* genOrOp - for || operation                                      */
5997 /*-----------------------------------------------------------------*/
5998 static void
5999 genOrOp (iCode * ic)
6000 {
6001   operand *left, *right, *result;
6002   symbol *tlbl;
6003
6004   D (emitcode (";", "genOrOp "););
6005
6006   /* note here that || operations that are in an
6007      if statement are taken away by backPatchLabels
6008      only those used in arthmetic operations remain */
6009   AOP_OP_2 (ic);
6010   AOP_SET_LOCALS (ic);
6011
6012   /* if both are bit variables */
6013   if (AOP_TYPE (left) == AOP_CRY &&
6014       AOP_TYPE (right) == AOP_CRY)
6015     {
6016       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6017       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6018       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6019       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6020   
6021       aopOp (result,ic,FALSE, FALSE);
6022       
6023       outBitC (result);
6024     }
6025   else
6026     {
6027       tlbl = newiTempLabel (NULL);
6028       toBoolean (left);
6029       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6030       toBoolean (right);
6031       emitcode ("", "!tlabeldef", tlbl->key + 100);
6032       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6033       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6034   
6035       aopOp (result,ic,FALSE, FALSE);
6036       
6037       outBitAcc (result);
6038     }
6039
6040   freeAsmop (result, NULL, ic, TRUE);
6041 }
6042
6043 /*-----------------------------------------------------------------*/
6044 /* isLiteralBit - test if lit == 2^n                               */
6045 /*-----------------------------------------------------------------*/
6046 static int
6047 isLiteralBit (unsigned long lit)
6048 {
6049   unsigned long pw[32] =
6050   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6051    0x100L, 0x200L, 0x400L, 0x800L,
6052    0x1000L, 0x2000L, 0x4000L, 0x8000L,
6053    0x10000L, 0x20000L, 0x40000L, 0x80000L,
6054    0x100000L, 0x200000L, 0x400000L, 0x800000L,
6055    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6056    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6057   int idx;
6058
6059   for (idx = 0; idx < 32; idx++)
6060     if (lit == pw[idx])
6061       return idx + 1;
6062   return 0;
6063 }
6064
6065 /*-----------------------------------------------------------------*/
6066 /* continueIfTrue -                                                */
6067 /*-----------------------------------------------------------------*/
6068 static void
6069 continueIfTrue (iCode * ic)
6070 {
6071   if (IC_TRUE (ic))
6072     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6073   ic->generated = 1;
6074 }
6075
6076 /*-----------------------------------------------------------------*/
6077 /* jmpIfTrue -                                                     */
6078 /*-----------------------------------------------------------------*/
6079 static void
6080 jumpIfTrue (iCode * ic)
6081 {
6082   if (!IC_TRUE (ic))
6083     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6084   ic->generated = 1;
6085 }
6086
6087 /*-----------------------------------------------------------------*/
6088 /* jmpTrueOrFalse -                                                */
6089 /*-----------------------------------------------------------------*/
6090 static void
6091 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6092 {
6093   // ugly but optimized by peephole
6094   if (IC_TRUE (ic))
6095     {
6096       symbol *nlbl = newiTempLabel (NULL);
6097       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6098       emitcode ("", "!tlabeldef", tlbl->key + 100);
6099       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6100       emitcode ("", "!tlabeldef", nlbl->key + 100);
6101     }
6102   else
6103     {
6104       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6105       emitcode ("", "!tlabeldef", tlbl->key + 100);
6106     }
6107   ic->generated = 1;
6108 }
6109
6110 // Generate code to perform a bit-wise logic operation
6111 // on two operands in far space (assumed to already have been 
6112 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6113 // in far space. This requires pushing the result on the stack
6114 // then popping it into the result.
6115 static void
6116 genFarFarLogicOp(iCode *ic, char *logicOp)
6117 {
6118       int size, resultSize, compSize;
6119       int offset = 0;
6120       
6121       TR_AP("#5");
6122       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6123       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
6124                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6125       
6126       _startLazyDPSEvaluation();
6127       for (size = compSize; (size--); offset++)
6128       {
6129           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6130           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6131           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6132           
6133           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6134           emitcode ("push", "acc");
6135       }
6136       _endLazyDPSEvaluation();
6137      
6138       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6139       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6140       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6141      
6142       resultSize = AOP_SIZE(IC_RESULT(ic));
6143
6144       ADJUST_PUSHED_RESULT(compSize, resultSize);
6145
6146       _startLazyDPSEvaluation();
6147       while (compSize--)
6148       {
6149           emitcode ("pop", "acc");
6150           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6151       }
6152       _endLazyDPSEvaluation();
6153       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6154 }
6155
6156
6157 /*-----------------------------------------------------------------*/
6158 /* genAnd  - code for and                                          */
6159 /*-----------------------------------------------------------------*/
6160 static void
6161 genAnd (iCode * ic, iCode * ifx)
6162 {
6163   operand *left, *right, *result;
6164   int size, offset = 0;
6165   unsigned long lit = 0L;
6166   int bytelit;
6167   char buff[10];
6168   bool pushResult;
6169
6170   D (emitcode (";", "genAnd "););
6171
6172   AOP_OP_3_NOFATAL (ic, pushResult);
6173   AOP_SET_LOCALS (ic);
6174
6175   if (pushResult)
6176   {
6177       genFarFarLogicOp(ic, "anl");
6178       return;
6179   }  
6180
6181 #ifdef DEBUG_TYPE
6182   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6183             AOP_TYPE (result),
6184             AOP_TYPE (left), AOP_TYPE (right));
6185   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6186             AOP_SIZE (result),
6187             AOP_SIZE (left), AOP_SIZE (right));
6188 #endif
6189
6190   /* if left is a literal & right is not then exchange them */
6191   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6192 #ifdef LOGIC_OPS_BROKEN      
6193     ||  AOP_NEEDSACC (left)
6194 #endif
6195     )
6196     {
6197       operand *tmp = right;
6198       right = left;
6199       left = tmp;
6200     }
6201
6202   /* if result = right then exchange them */
6203   if (sameRegs (AOP (result), AOP (right)))
6204     {
6205       operand *tmp = right;
6206       right = left;
6207       left = tmp;
6208     }
6209
6210   /* if right is bit then exchange them */
6211   if (AOP_TYPE (right) == AOP_CRY &&
6212       AOP_TYPE (left) != AOP_CRY)
6213     {
6214       operand *tmp = right;
6215       right = left;
6216       left = tmp;
6217     }
6218   if (AOP_TYPE (right) == AOP_LIT)
6219     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6220
6221   size = AOP_SIZE (result);
6222
6223   // if(bit & yy)
6224   // result = bit & yy;
6225   if (AOP_TYPE (left) == AOP_CRY)
6226     {
6227       // c = bit & literal;
6228       if (AOP_TYPE (right) == AOP_LIT)
6229         {
6230           if (lit & 1)
6231             {
6232               if (size && sameRegs (AOP (result), AOP (left)))
6233                 // no change
6234                 goto release;
6235               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6236             }
6237           else
6238             {
6239               // bit(result) = 0;
6240               if (size && (AOP_TYPE (result) == AOP_CRY))
6241                 {
6242                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6243                   goto release;
6244                 }
6245               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6246                 {
6247                   jumpIfTrue (ifx);
6248                   goto release;
6249                 }
6250               emitcode ("clr", "c");
6251             }
6252         }
6253       else
6254         {
6255           if (AOP_TYPE (right) == AOP_CRY)
6256             {
6257               // c = bit & bit;
6258               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6259               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6260             }
6261           else
6262             {
6263               // c = bit & val;
6264               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6265               // c = lsb
6266               emitcode ("rrc", "a");
6267               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6268             }
6269         }
6270       // bit = c
6271       // val = c
6272       if (size)
6273         outBitC (result);
6274       // if(bit & ...)
6275       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6276         genIfxJump (ifx, "c");
6277       goto release;
6278     }
6279
6280   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6281   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6282   if ((AOP_TYPE (right) == AOP_LIT) &&
6283       (AOP_TYPE (result) == AOP_CRY) &&
6284       (AOP_TYPE (left) != AOP_CRY))
6285     {
6286       int posbit = isLiteralBit (lit);
6287       /* left &  2^n */
6288       if (posbit)
6289         {
6290           posbit--;
6291           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6292           // bit = left & 2^n
6293           if (size)
6294             emitcode ("mov", "c,acc.%d", posbit & 0x07);
6295           // if(left &  2^n)
6296           else
6297             {
6298               if (ifx)
6299                 {
6300                   SNPRINTF (buff, sizeof(buff), 
6301                             "acc.%d", posbit & 0x07);
6302                   genIfxJump (ifx, buff);
6303                 }
6304               else 
6305                   {
6306                       emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6307                   }
6308               goto release;
6309             }
6310         }
6311       else
6312         {
6313           symbol *tlbl = newiTempLabel (NULL);
6314           int sizel = AOP_SIZE (left);
6315           if (size)
6316             emitcode ("setb", "c");
6317           while (sizel--)
6318             {
6319               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6320                 {
6321                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6322                   // byte ==  2^n ?
6323                   if ((posbit = isLiteralBit (bytelit)) != 0)
6324                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6325                   else
6326                     {
6327                       if (bytelit != 0x0FFL)
6328                         emitcode ("anl", "a,%s",
6329                           aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6330                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6331                     }
6332                 }
6333               offset++;
6334             }
6335           // bit = left & literal
6336           if (size)
6337             {
6338               emitcode ("clr", "c");
6339               emitcode ("", "!tlabeldef", tlbl->key + 100);
6340             }
6341           // if(left & literal)
6342           else
6343             {
6344               if (ifx)
6345                 jmpTrueOrFalse (ifx, tlbl);
6346               goto release;
6347             }
6348         }
6349       outBitC (result);
6350       goto release;
6351     }
6352
6353   /* if left is same as result */
6354   if (sameRegs (AOP (result), AOP (left)))
6355     {
6356       for (; size--; offset++)
6357         {
6358           if (AOP_TYPE (right) == AOP_LIT)
6359             {
6360               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6361                 continue;
6362               else if (bytelit == 0)
6363                 aopPut (AOP (result), zero, offset);
6364               else if (IS_AOP_PREG (result))
6365                 {
6366                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6367                   emitcode ("anl", "a,%s",
6368                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6369                   aopPut (AOP (result), "a", offset);
6370                 }
6371               else
6372                 emitcode ("anl", "%s,%s",
6373                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6374                           aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6375             }
6376           else
6377             {
6378               if (AOP_TYPE (left) == AOP_ACC)
6379                 emitcode ("anl", "a,%s",
6380                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6381               else
6382                 {
6383                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6384                   if (IS_AOP_PREG (result))
6385                     {
6386                       emitcode ("anl", "a,%s",
6387                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6388                       aopPut (AOP (result), "a", offset);
6389                     }
6390                   else
6391                     emitcode ("anl", "%s,a",
6392                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6393                 }
6394             }
6395         }
6396     }
6397   else
6398     {
6399       // left & result in different registers
6400       if (AOP_TYPE (result) == AOP_CRY)
6401         {
6402           // result = bit
6403           // if(size), result in bit
6404           // if(!size && ifx), conditional oper: if(left & right)
6405           symbol *tlbl = newiTempLabel (NULL);
6406           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6407           if (size)
6408             emitcode ("setb", "c");
6409           while (sizer--)
6410             {
6411               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6412                 emitcode ("anl", "a,%s",
6413                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6414               } else {
6415                 if (AOP_TYPE(left)==AOP_ACC) {
6416                   emitcode("mov", "b,a");
6417                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6418                   emitcode("anl", "a,b");
6419                 }else {
6420                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6421                   emitcode ("anl", "a,%s",
6422                             aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6423                 }
6424               }
6425               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6426               offset++;
6427             }
6428           if (size)
6429             {
6430               CLRC;
6431               emitcode ("", "!tlabeldef", tlbl->key + 100);
6432               outBitC (result);
6433             }
6434           else if (ifx)
6435             jmpTrueOrFalse (ifx, tlbl);
6436         }
6437       else
6438         {
6439           for (; (size--); offset++)
6440             {
6441               // normal case
6442               // result = left & right
6443               if (AOP_TYPE (right) == AOP_LIT)
6444                 {
6445                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6446                     {
6447                       aopPut (AOP (result),
6448                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6449                               offset);
6450                       continue;
6451                     }
6452                   else if (bytelit == 0)
6453                     {
6454                       aopPut (AOP (result), zero, offset);
6455                       continue;
6456                     }
6457                   D (emitcode (";", "better literal AND."););
6458                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6459                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6460                                                     FALSE, FALSE, DP2_RESULT_REG));
6461
6462                 }
6463               else
6464                 {
6465                   // faster than result <- left, anl result,right
6466                   // and better if result is SFR
6467                   if (AOP_TYPE (left) == AOP_ACC)
6468                     {
6469                       emitcode ("anl", "a,%s", 
6470                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6471                     }
6472                   else
6473                     {
6474                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6475                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6476                       {
6477                           emitcode("mov", "b,a");
6478                           rOp = "b";
6479                       }
6480                         
6481                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6482                       emitcode ("anl", "a,%s", rOp);
6483                     }                   
6484                 }
6485               aopPut (AOP (result), "a", offset);
6486             }
6487         }
6488     }
6489
6490 release:
6491   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6492   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6493   freeAsmop (result, NULL, ic, TRUE);
6494 }
6495
6496
6497 /*-----------------------------------------------------------------*/
6498 /* genOr  - code for or                                            */
6499 /*-----------------------------------------------------------------*/
6500 static void
6501 genOr (iCode * ic, iCode * ifx)
6502 {
6503   operand *left, *right, *result;
6504   int size, offset = 0;
6505   unsigned long lit = 0L;
6506   bool     pushResult;
6507
6508   D (emitcode (";", "genOr "););
6509
6510   AOP_OP_3_NOFATAL (ic, pushResult);
6511   AOP_SET_LOCALS (ic);
6512
6513   if (pushResult)
6514   {
6515       genFarFarLogicOp(ic, "orl");
6516       return;
6517   }
6518
6519
6520 #ifdef DEBUG_TYPE
6521   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6522             AOP_TYPE (result),
6523             AOP_TYPE (left), AOP_TYPE (right));
6524   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6525             AOP_SIZE (result),
6526             AOP_SIZE (left), AOP_SIZE (right));
6527 #endif
6528
6529   /* if left is a literal & right is not then exchange them */
6530   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6531 #ifdef LOGIC_OPS_BROKEN
6532    || AOP_NEEDSACC (left) // I think this is a net loss now.
6533 #endif      
6534       )
6535     {
6536       operand *tmp = right;
6537       right = left;
6538       left = tmp;
6539     }
6540
6541   /* if result = right then exchange them */
6542   if (sameRegs (AOP (result), AOP (right)))
6543     {
6544       operand *tmp = right;
6545       right = left;
6546       left = tmp;
6547     }
6548
6549   /* if right is bit then exchange them */
6550   if (AOP_TYPE (right) == AOP_CRY &&
6551       AOP_TYPE (left) != AOP_CRY)
6552     {
6553       operand *tmp = right;
6554       right = left;
6555       left = tmp;
6556     }
6557   if (AOP_TYPE (right) == AOP_LIT)
6558     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6559
6560   size = AOP_SIZE (result);
6561
6562   // if(bit | yy)
6563   // xx = bit | yy;
6564   if (AOP_TYPE (left) == AOP_CRY)
6565     {
6566       if (AOP_TYPE (right) == AOP_LIT)
6567         {
6568           // c = bit & literal;
6569           if (lit)
6570             {
6571               // lit != 0 => result = 1
6572               if (AOP_TYPE (result) == AOP_CRY)
6573                 {
6574                   if (size)
6575                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6576                   else if (ifx)
6577                     continueIfTrue (ifx);
6578                   goto release;
6579                 }
6580               emitcode ("setb", "c");
6581             }
6582           else
6583             {
6584               // lit == 0 => result = left
6585               if (size && sameRegs (AOP (result), AOP (left)))
6586                 goto release;
6587               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6588             }
6589         }
6590       else
6591         {
6592           if (AOP_TYPE (right) == AOP_CRY)
6593             {
6594               // c = bit | bit;
6595               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6596               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6597             }
6598           else
6599             {
6600               // c = bit | val;
6601               symbol *tlbl = newiTempLabel (NULL);
6602               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6603                 emitcode ("setb", "c");
6604               emitcode ("jb", "%s,!tlabel",
6605                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6606               toBoolean (right);
6607               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6608               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6609                 {
6610                   jmpTrueOrFalse (ifx, tlbl);
6611                   goto release;
6612                 }
6613               else
6614                 {
6615                   CLRC;
6616                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6617                 }
6618             }
6619         }
6620       // bit = c
6621       // val = c
6622       if (size)
6623         outBitC (result);
6624       // if(bit | ...)
6625       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626            genIfxJump (ifx, "c");
6627       goto release;
6628     }
6629
6630   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6631   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6632   if ((AOP_TYPE (right) == AOP_LIT) &&
6633       (AOP_TYPE (result) == AOP_CRY) &&
6634       (AOP_TYPE (left) != AOP_CRY))
6635     {
6636       if (lit)
6637         {
6638           // result = 1
6639           if (size)
6640             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6641           else
6642             continueIfTrue (ifx);
6643           goto release;
6644         }
6645       else
6646         {
6647           // lit = 0, result = boolean(left)
6648           if (size)
6649             emitcode ("setb", "c");
6650           toBoolean (right);
6651           if (size)
6652             {
6653               symbol *tlbl = newiTempLabel (NULL);
6654               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6655               CLRC;
6656               emitcode ("", "!tlabeldef", tlbl->key + 100);
6657             }
6658           else
6659             {
6660               genIfxJump (ifx, "a");
6661               goto release;
6662             }
6663         }
6664       outBitC (result);
6665       goto release;
6666     }
6667
6668   /* if left is same as result */
6669   if (sameRegs (AOP (result), AOP (left)))
6670     {
6671       for (; size--; offset++)
6672         {
6673           if (AOP_TYPE (right) == AOP_LIT)
6674             {
6675               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6676                 {
6677                   continue;
6678                 }
6679               else
6680                 {
6681                   if (IS_AOP_PREG (left))
6682                     {
6683                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6684                       emitcode ("orl", "a,%s",
6685                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6686                       aopPut (AOP (result), "a", offset);
6687                     }
6688                   else
6689                     {
6690                       emitcode ("orl", "%s,%s",
6691                                 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6692                                 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6693                     }
6694                 }
6695             }
6696           else
6697             {
6698               if (AOP_TYPE (left) == AOP_ACC)
6699                 {
6700                   emitcode ("orl", "a,%s",
6701                             aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6702                 }
6703               else
6704                 {
6705                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6706                   if (IS_AOP_PREG (left))
6707                     {
6708                       emitcode ("orl", "a,%s", 
6709                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6710                       aopPut (AOP (result), "a", offset);
6711                     }
6712                   else
6713                     {
6714                       emitcode ("orl", "%s,a",
6715                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6716                     }
6717                 }
6718             }
6719         }
6720     }
6721   else
6722     {
6723       // left & result in different registers
6724       if (AOP_TYPE (result) == AOP_CRY)
6725         {
6726           // result = bit
6727           // if(size), result in bit
6728           // if(!size && ifx), conditional oper: if(left | right)
6729           symbol *tlbl = newiTempLabel (NULL);
6730           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6731           if (size)
6732             emitcode ("setb", "c");
6733           while (sizer--)
6734             {
6735               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6736                 emitcode ("orl", "a,%s",
6737                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6738               } else {
6739                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6740                 emitcode ("orl", "a,%s",
6741                           aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6742               }
6743               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6744               offset++;
6745             }
6746           if (size)
6747             {
6748               CLRC;
6749               emitcode ("", "!tlabeldef", tlbl->key + 100);
6750               outBitC (result);
6751             }
6752           else if (ifx)
6753             jmpTrueOrFalse (ifx, tlbl);
6754         }
6755       else
6756         {
6757             _startLazyDPSEvaluation();
6758           for (; (size--); offset++)
6759             {
6760               // normal case
6761               // result = left & right
6762               if (AOP_TYPE (right) == AOP_LIT)
6763                 {
6764                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6765                     {
6766                       aopPut (AOP (result),
6767                            aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6768                               offset);
6769                       continue;
6770                     }
6771                   D (emitcode (";", "better literal OR."););
6772                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6773                   emitcode ("orl", "a, %s",
6774                             aopGet (AOP (right), offset,
6775                                     FALSE, FALSE, DP2_RESULT_REG));
6776
6777                 }
6778               else
6779                 {
6780                   // faster than result <- left, anl result,right
6781                   // and better if result is SFR
6782                   if (AOP_TYPE (left) == AOP_ACC)
6783                     {
6784                       emitcode ("orl", "a,%s",
6785                                 aopGet (AOP (right), offset,
6786                                         FALSE, FALSE, DP2_RESULT_REG));
6787                     }
6788                   else
6789                     {
6790                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6791                         
6792                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6793                       {
6794                           emitcode("mov", "b,a");
6795                           rOp = "b";
6796                       }
6797                         
6798                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6799                       emitcode ("orl", "a,%s", rOp);
6800                     }
6801                 }
6802               aopPut (AOP (result), "a", offset);
6803             }
6804             _endLazyDPSEvaluation();
6805         }
6806     }
6807
6808 release:
6809   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6810   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6811   freeAsmop (result, NULL, ic, TRUE);
6812 }
6813
6814 /*-----------------------------------------------------------------*/
6815 /* genXor - code for xclusive or                                   */
6816 /*-----------------------------------------------------------------*/
6817 static void
6818 genXor (iCode * ic, iCode * ifx)
6819 {
6820   operand *left, *right, *result;
6821   int size, offset = 0;
6822   unsigned long lit = 0L;
6823   bool pushResult;
6824
6825   D (emitcode (";", "genXor "););
6826
6827   AOP_OP_3_NOFATAL (ic, pushResult);
6828   AOP_SET_LOCALS (ic);
6829
6830   if (pushResult)
6831   {
6832       genFarFarLogicOp(ic, "xrl");
6833       return;
6834   }  
6835
6836 #ifdef DEBUG_TYPE
6837   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6838             AOP_TYPE (result),
6839             AOP_TYPE (left), AOP_TYPE (right));
6840   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6841             AOP_SIZE (result),
6842             AOP_SIZE (left), AOP_SIZE (right));
6843 #endif
6844
6845   /* if left is a literal & right is not ||
6846      if left needs acc & right does not */
6847   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6848 #ifdef LOGIC_OPS_BROKEN      
6849       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6850 #endif
6851      )
6852     {
6853       operand *tmp = right;
6854       right = left;
6855       left = tmp;
6856     }
6857
6858   /* if result = right then exchange them */
6859   if (sameRegs (AOP (result), AOP (right)))
6860     {
6861       operand *tmp = right;
6862       right = left;
6863       left = tmp;
6864     }
6865
6866   /* if right is bit then exchange them */
6867   if (AOP_TYPE (right) == AOP_CRY &&
6868       AOP_TYPE (left) != AOP_CRY)
6869     {
6870       operand *tmp = right;
6871       right = left;
6872       left = tmp;
6873     }
6874   if (AOP_TYPE (right) == AOP_LIT)
6875     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6876
6877   size = AOP_SIZE (result);
6878
6879   // if(bit ^ yy)
6880   // xx = bit ^ yy;
6881   if (AOP_TYPE (left) == AOP_CRY)
6882     {
6883       if (AOP_TYPE (right) == AOP_LIT)
6884         {
6885           // c = bit & literal;
6886           if (lit >> 1)
6887             {
6888               // lit>>1  != 0 => result = 1
6889               if (AOP_TYPE (result) == AOP_CRY)
6890                 {
6891                   if (size)
6892                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6893                   else if (ifx)
6894                     continueIfTrue (ifx);
6895                   goto release;
6896                 }
6897               emitcode ("setb", "c");
6898             }
6899           else
6900             {
6901               // lit == (0 or 1)
6902               if (lit == 0)
6903                 {
6904                   // lit == 0, result = left
6905                   if (size && sameRegs (AOP (result), AOP (left)))
6906                     goto release;
6907                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6908                 }
6909               else
6910                 {
6911                   // lit == 1, result = not(left)
6912                   if (size && sameRegs (AOP (result), AOP (left)))
6913                     {
6914                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6915                       goto release;
6916                     }
6917                   else
6918                     {
6919                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6920                       emitcode ("cpl", "c");
6921                     }
6922                 }
6923             }
6924
6925         }
6926       else
6927         {
6928           // right != literal
6929           symbol *tlbl = newiTempLabel (NULL);
6930           if (AOP_TYPE (right) == AOP_CRY)
6931             {
6932               // c = bit ^ bit;
6933               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6934             }
6935           else
6936             {
6937               int sizer = AOP_SIZE (right);
6938               // c = bit ^ val
6939               // if val>>1 != 0, result = 1
6940               emitcode ("setb", "c");
6941               while (sizer)
6942                 {
6943                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6944                   if (sizer == 1)
6945                     // test the msb of the lsb
6946                     emitcode ("anl", "a,#!constbyte",0xfe);
6947                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6948                   sizer--;
6949                 }
6950               // val = (0,1)
6951               emitcode ("rrc", "a");
6952             }
6953           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6954           emitcode ("cpl", "c");
6955           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6956         }
6957       // bit = c
6958       // val = c
6959       if (size)
6960         outBitC (result);
6961       // if(bit | ...)
6962       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6963         genIfxJump (ifx, "c");
6964       goto release;
6965     }
6966
6967   if (sameRegs (AOP (result), AOP (left)))
6968     {
6969       /* if left is same as result */
6970       for (; size--; offset++)
6971         {
6972           if (AOP_TYPE (right) == AOP_LIT)
6973             {
6974               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6975                 continue;
6976               else if (IS_AOP_PREG (left))
6977                 {
6978                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6979                   emitcode ("xrl", "a,%s",
6980                             aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6981                   aopPut (AOP (result), "a", offset);
6982                 }
6983               else
6984                 emitcode ("xrl", "%s,%s",
6985                           aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6986                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6987             }
6988           else
6989             {
6990               if (AOP_TYPE (left) == AOP_ACC)
6991                 emitcode ("xrl", "a,%s",
6992                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6993               else
6994                 {
6995                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6996                   if (IS_AOP_PREG (left))
6997                     {
6998                       emitcode ("xrl", "a,%s",
6999                                 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7000                       aopPut (AOP (result), "a", offset);
7001                     }
7002                   else
7003                     emitcode ("xrl", "%s,a",
7004                            aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7005                 }
7006             }
7007         }
7008     }
7009   else
7010     {
7011       // left & result in different registers
7012       if (AOP_TYPE (result) == AOP_CRY)
7013         {
7014           // result = bit
7015           // if(size), result in bit
7016           // if(!size && ifx), conditional oper: if(left ^ right)
7017           symbol *tlbl = newiTempLabel (NULL);
7018           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7019                   
7020           if (size)
7021             emitcode ("setb", "c");
7022           while (sizer--)
7023             {
7024               if ((AOP_TYPE (right) == AOP_LIT) &&
7025                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7026                 {
7027                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7028                 }
7029               else
7030                 {
7031                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7032                     emitcode ("xrl", "a,%s",
7033                               aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7034                   } else {
7035                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7036                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7037                       {
7038                           emitcode("mov", "b,a");
7039                           rOp = "b";
7040                       }
7041                         
7042                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7043                       emitcode ("xrl", "a,%s", rOp);                  
7044                   }
7045                 }
7046               emitcode ("jnz", "!tlabel", tlbl->key + 100);
7047               offset++;
7048             }
7049           if (size)
7050             {
7051               CLRC;
7052               emitcode ("", "!tlabeldef", tlbl->key + 100);
7053               outBitC (result);
7054             }
7055           else if (ifx)
7056             jmpTrueOrFalse (ifx, tlbl);
7057         }
7058       else
7059         {
7060         for (; (size--); offset++)
7061           {
7062             // normal case
7063             // result = left & right
7064             if (AOP_TYPE (right) == AOP_LIT)
7065               {
7066                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7067                   {
7068                     aopPut (AOP (result),
7069                             aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7070                             offset);
7071                     continue;
7072                   }
7073                 D (emitcode (";", "better literal XOR."););
7074                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7075                 emitcode ("xrl", "a, %s",
7076                           aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7077               }
7078             else
7079               {
7080                 // faster than result <- left, anl result,right
7081                 // and better if result is SFR
7082                 if (AOP_TYPE (left) == AOP_ACC)
7083                   {
7084                     emitcode ("xrl", "a,%s",
7085                               aopGet (AOP (right), offset,
7086                                       FALSE, FALSE, DP2_RESULT_REG));
7087                   }
7088                 else
7089                   {
7090                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7091                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7092                       {
7093                           emitcode("mov", "b,a");
7094                           rOp = "b";
7095                       }
7096                         
7097                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7098                       emitcode ("xrl", "a,%s", rOp);
7099                   }
7100               }
7101             aopPut (AOP (result), "a", offset);
7102           }
7103         }
7104         
7105     }
7106
7107 release:
7108   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7109   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7110   freeAsmop (result, NULL, ic, TRUE);
7111 }
7112
7113 /*-----------------------------------------------------------------*/
7114 /* genInline - write the inline code out                           */
7115 /*-----------------------------------------------------------------*/
7116 static void
7117 genInline (iCode * ic)
7118 {
7119   char *buffer, *bp, *bp1;
7120
7121   D (emitcode (";", "genInline "); );
7122
7123   _G.inLine += (!options.asmpeep);
7124
7125   buffer = Safe_strdup(IC_INLINE(ic));
7126   bp = buffer;
7127   bp1 = buffer;
7128
7129   /* emit each line as a code */
7130   while (*bp)
7131     {
7132       if (*bp == '\n')
7133         {
7134           *bp++ = '\0';
7135           emitcode (bp1, "");
7136           bp1 = bp;
7137         }
7138       else
7139         {
7140           if (*bp == ':')
7141             {
7142               bp++;
7143               *bp = '\0';
7144               bp++;
7145               emitcode (bp1, "");
7146               bp1 = bp;
7147             }
7148           else
7149             bp++;
7150         }
7151     }
7152   if (bp1 != bp)
7153     emitcode (bp1, "");
7154   /*     emitcode("",buffer); */
7155   _G.inLine -= (!options.asmpeep);
7156 }
7157
7158 /*-----------------------------------------------------------------*/
7159 /* genRRC - rotate right with carry                                */
7160 /*-----------------------------------------------------------------*/
7161 static void
7162 genRRC (iCode * ic)
7163 {
7164   operand *left, *result;
7165   int     size, offset;
7166
7167   D (emitcode (";", "genRRC "););
7168
7169   /* rotate right with carry */
7170   left = IC_LEFT (ic);
7171   result = IC_RESULT (ic);
7172   aopOp (left, ic, FALSE, FALSE);
7173   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7174
7175   /* move it to the result */
7176   size = AOP_SIZE (result);
7177   offset = size - 1;
7178   CLRC;
7179
7180   _startLazyDPSEvaluation ();
7181   while (size--)
7182     {
7183       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7184       emitcode ("rrc", "a");
7185       if (AOP_SIZE (result) > 1)
7186         aopPut (AOP (result), "a", offset--);
7187     }
7188   _endLazyDPSEvaluation ();
7189
7190   /* now we need to put the carry into the
7191      highest order byte of the result */
7192   if (AOP_SIZE (result) > 1)
7193     {
7194       MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7195     }
7196   emitcode ("mov", "acc.7,c");
7197   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7198   freeAsmop (left, NULL, ic, TRUE);
7199   freeAsmop (result, NULL, ic, TRUE);
7200 }
7201
7202 /*-----------------------------------------------------------------*/
7203 /* genRLC - generate code for rotate left with carry               */
7204 /*-----------------------------------------------------------------*/
7205 static void
7206 genRLC (iCode * ic)
7207 {
7208   operand *left, *result;
7209   int size, offset;
7210   char *l;
7211
7212   D (emitcode (";", "genRLC "););
7213
7214   /* rotate right with carry */
7215   left = IC_LEFT (ic);
7216   result = IC_RESULT (ic);
7217   aopOp (left, ic, FALSE, FALSE);
7218   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7219
7220   /* move it to the result */
7221   size = AOP_SIZE (result);
7222   offset = 0;
7223   if (size--)
7224     {
7225       l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7226       MOVA (l);
7227       emitcode ("add", "a,acc");
7228       if (AOP_SIZE (result) > 1)
7229         {
7230           aopPut (AOP (result), "a", offset++);
7231         }
7232
7233       _startLazyDPSEvaluation ();
7234       while (size--)
7235         {
7236           l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7237           MOVA (l);
7238           emitcode ("rlc", "a");
7239           if (AOP_SIZE (result) > 1)
7240             aopPut (AOP (result), "a", offset++);
7241         }
7242       _endLazyDPSEvaluation ();
7243     }
7244   /* now we need to put the carry into the
7245      highest order byte of the result */
7246   if (AOP_SIZE (result) > 1)
7247     {
7248       l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7249       MOVA (l);
7250     }
7251   emitcode ("mov", "acc.0,c");
7252   aopPut (AOP (result), "a", 0);
7253   freeAsmop (left, NULL, ic, TRUE);
7254   freeAsmop (result, NULL, ic, TRUE);
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* genGetHbit - generates code get highest order bit               */
7259 /*-----------------------------------------------------------------*/
7260 static void
7261 genGetHbit (iCode * ic)
7262 {
7263   operand *left, *result;
7264   left = IC_LEFT (ic);
7265   result = IC_RESULT (ic);
7266   aopOp (left, ic, FALSE, FALSE);
7267   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7268
7269   D (emitcode (";", "genGetHbit "););
7270
7271   /* get the highest order byte into a */
7272   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7273   if (AOP_TYPE (result) == AOP_CRY)
7274     {
7275       emitcode ("rlc", "a");
7276       outBitC (result);
7277     }
7278   else
7279     {
7280       emitcode ("rl", "a");
7281       emitcode ("anl", "a,#1");
7282       outAcc (result);
7283     }
7284
7285
7286   freeAsmop (left, NULL, ic, TRUE);
7287   freeAsmop (result, NULL, ic, TRUE);
7288 }
7289
7290 /*-----------------------------------------------------------------*/
7291 /* AccRol - rotate left accumulator by known count                 */
7292 /*-----------------------------------------------------------------*/
7293 static void
7294 AccRol (int shCount)
7295 {
7296   shCount &= 0x0007;            // shCount : 0..7
7297
7298   switch (shCount)
7299     {
7300     case 0:
7301       break;
7302     case 1:
7303       emitcode ("rl", "a");
7304       break;
7305     case 2:
7306       emitcode ("rl", "a");
7307       emitcode ("rl", "a");
7308       break;
7309     case 3:
7310       emitcode ("swap", "a");
7311       emitcode ("rr", "a");
7312       break;
7313     case 4:
7314       emitcode ("swap", "a");
7315       break;
7316     case 5:
7317       emitcode ("swap", "a");
7318       emitcode ("rl", "a");
7319       break;
7320     case 6:
7321       emitcode ("rr", "a");
7322       emitcode ("rr", "a");
7323       break;
7324     case 7:
7325       emitcode ("rr", "a");
7326       break;
7327     }
7328 }
7329
7330 /*-----------------------------------------------------------------*/
7331 /* AccLsh - left shift accumulator by known count                  */
7332 /*-----------------------------------------------------------------*/
7333 static void
7334 AccLsh (int shCount)
7335 {
7336   if (shCount != 0)
7337     {
7338       if (shCount == 1)
7339         emitcode ("add", "a,acc");
7340       else if (shCount == 2)
7341         {
7342           emitcode ("add", "a,acc");
7343           emitcode ("add", "a,acc");
7344         }
7345       else
7346         {
7347           /* rotate left accumulator */
7348           AccRol (shCount);
7349           /* and kill the lower order bits */
7350           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7351         }
7352     }
7353 }
7354
7355 /*-----------------------------------------------------------------*/
7356 /* AccRsh - right shift accumulator by known count                 */
7357 /*-----------------------------------------------------------------*/
7358 static void
7359 AccRsh (int shCount)
7360 {
7361   if (shCount != 0)
7362     {
7363       if (shCount == 1)
7364         {
7365           CLRC;
7366           emitcode ("rrc", "a");
7367         }
7368       else
7369         {
7370           /* rotate right accumulator */
7371           AccRol (8 - shCount);
7372           /* and kill the higher order bits */
7373           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7374         }
7375     }
7376 }
7377
7378 #ifdef BETTER_LITERAL_SHIFT
7379 /*-----------------------------------------------------------------*/
7380 /* AccSRsh - signed right shift accumulator by known count                 */
7381 /*-----------------------------------------------------------------*/
7382 static void
7383 AccSRsh (int shCount)
7384 {
7385   symbol *tlbl;
7386   if (shCount != 0)
7387     {
7388       if (shCount == 1)
7389         {
7390           emitcode ("mov", "c,acc.7");
7391           emitcode ("rrc", "a");
7392         }
7393       else if (shCount == 2)
7394         {
7395           emitcode ("mov", "c,acc.7");
7396           emitcode ("rrc", "a");
7397           emitcode ("mov", "c,acc.7");
7398           emitcode ("rrc", "a");
7399         }
7400       else
7401         {
7402           tlbl = newiTempLabel (NULL);
7403           /* rotate right accumulator */
7404           AccRol (8 - shCount);
7405           /* and kill the higher order bits */
7406           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7407           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7408           emitcode ("orl", "a,#!constbyte",
7409                     (unsigned char) ~SRMask[shCount]);
7410           emitcode ("", "!tlabeldef", tlbl->key + 100);
7411         }
7412     }
7413 }
7414 #endif
7415
7416 #ifdef BETTER_LITERAL_SHIFT
7417 /*-----------------------------------------------------------------*/
7418 /* shiftR1Left2Result - shift right one byte from left to result   */
7419 /*-----------------------------------------------------------------*/
7420 static void
7421 shiftR1Left2Result (operand * left, int offl,
7422                     operand * result, int offr,
7423                     int shCount, int sign)
7424 {
7425   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7426   /* shift right accumulator */
7427   if (sign)
7428     AccSRsh (shCount);
7429   else
7430     AccRsh (shCount);
7431   aopPut (AOP (result), "a", offr);
7432 }
7433 #endif
7434
7435 #ifdef BETTER_LITERAL_SHIFT
7436 /*-----------------------------------------------------------------*/
7437 /* shiftL1Left2Result - shift left one byte from left to result    */
7438 /*-----------------------------------------------------------------*/
7439 static void
7440 shiftL1Left2Result (operand * left, int offl,
7441                     operand * result, int offr, int shCount)
7442 {
7443   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7444   /* shift left accumulator */
7445   AccLsh (shCount);
7446   aopPut (AOP (result), "a", offr);
7447 }
7448 #endif
7449
7450 #ifdef BETTER_LITERAL_SHIFT
7451 /*-----------------------------------------------------------------*/
7452 /* movLeft2Result - move byte from left to result                  */
7453 /*-----------------------------------------------------------------*/
7454 static void
7455 movLeft2Result (operand * left, int offl,
7456                 operand * result, int offr, int sign)
7457 {
7458   char *l;
7459   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7460   {
7461       l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7462
7463       if (*l == '@' && (IS_AOP_PREG (result)))
7464       {
7465           emitcode ("mov", "a,%s", l);
7466           aopPut (AOP (result), "a", offr);
7467       }
7468       else
7469       {
7470           if (!sign)
7471           {
7472             aopPut (AOP (result), l, offr);
7473           }
7474           else
7475             {
7476               /* MSB sign in acc.7 ! */
7477               if (getDataSize (left) == offl + 1)
7478                 {
7479                   emitcode ("mov", "a,%s", l);
7480                   aopPut (AOP (result), "a", offr);
7481                 }
7482             }
7483       }
7484   }
7485 }
7486 #endif
7487
7488 #ifdef BETTER_LITERAL_SHIFT
7489 /*-----------------------------------------------------------------*/
7490 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7491 /*-----------------------------------------------------------------*/
7492 static void
7493 AccAXRrl1 (char *x)
7494 {
7495   emitcode ("rrc", "a");
7496   emitcode ("xch", "a,%s", x);
7497   emitcode ("rrc", "a");
7498   emitcode ("xch", "a,%s", x);
7499 }
7500 #endif
7501
7502 #ifdef BETTER_LITERAL_SHIFT
7503 //REMOVE ME!!!
7504 /*-----------------------------------------------------------------*/
7505 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7506 /*-----------------------------------------------------------------*/
7507 static void
7508 AccAXLrl1 (char *x)
7509 {
7510   emitcode ("xch", "a,%s", x);
7511   emitcode ("rlc", "a");
7512   emitcode ("xch", "a,%s", x);
7513   emitcode ("rlc", "a");
7514 }
7515 #endif
7516
7517 #ifdef BETTER_LITERAL_SHIFT
7518 /*-----------------------------------------------------------------*/
7519 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7520 /*-----------------------------------------------------------------*/
7521 static void
7522 AccAXLsh1 (char *x)
7523 {
7524   emitcode ("xch", "a,%s", x);
7525   emitcode ("add", "a,acc");
7526   emitcode ("xch", "a,%s", x);
7527   emitcode ("rlc", "a");
7528 }
7529 #endif
7530
7531 #ifdef BETTER_LITERAL_SHIFT
7532 /*-----------------------------------------------------------------*/
7533 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7534 /*-----------------------------------------------------------------*/
7535 static void
7536 AccAXLsh (char *x, int shCount)
7537 {
7538   switch (shCount)
7539     {
7540     case 0:
7541       break;
7542     case 1:
7543       AccAXLsh1 (x);
7544       break;
7545     case 2:
7546       AccAXLsh1 (x);
7547       AccAXLsh1 (x);
7548       break;
7549     case 3:
7550     case 4:
7551     case 5:                     // AAAAABBB:CCCCCDDD
7552
7553       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7554
7555       emitcode ("anl", "a,#!constbyte",
7556                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7557
7558       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7559
7560       AccRol (shCount);         // DDDCCCCC:BBB00000
7561
7562       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7563
7564       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7565
7566       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7567
7568       emitcode ("anl", "a,#!constbyte",
7569                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7570
7571       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7572
7573       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7574
7575       break;
7576     case 6:                     // AAAAAABB:CCCCCCDD
7577       emitcode ("anl", "a,#!constbyte",
7578                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7579       emitcode ("mov", "c,acc.0");      // c = B
7580       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7581 #if 0
7582       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7583       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7584 #else
7585       emitcode("rrc","a"); 
7586       emitcode("xch","a,%s", x); 
7587       emitcode("rrc","a"); 
7588       emitcode("mov","c,acc.0"); //<< get correct bit 
7589       emitcode("xch","a,%s", x); 
7590
7591       emitcode("rrc","a"); 
7592       emitcode("xch","a,%s", x); 
7593       emitcode("rrc","a"); 
7594       emitcode("xch","a,%s", x); 
7595 #endif
7596       break;
7597     case 7:                     // a:x <<= 7
7598
7599       emitcode ("anl", "a,#!constbyte",
7600                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7601
7602       emitcode ("mov", "c,acc.0");      // c = B
7603
7604       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7605
7606       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7607
7608       break;
7609     default:
7610       break;
7611     }
7612 }
7613 #endif
7614
7615 #ifdef BETTER_LITERAL_SHIFT
7616 //REMOVE ME!!!
7617 /*-----------------------------------------------------------------*/
7618 /* AccAXRsh - right shift a:x known count (0..7)                   */
7619 /*-----------------------------------------------------------------*/
7620 static void
7621 AccAXRsh (char *x, int shCount)
7622 {
7623   switch (shCount)
7624     {
7625     case 0:
7626       break;
7627     case 1:
7628       CLRC;
7629       AccAXRrl1 (x);            // 0->a:x
7630
7631       break;
7632     case 2:
7633       CLRC;
7634       AccAXRrl1 (x);            // 0->a:x
7635
7636       CLRC;
7637       AccAXRrl1 (x);            // 0->a:x
7638
7639       break;
7640     case 3:
7641     case 4:
7642     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7643
7644       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7645
7646       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7647
7648       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7649
7650       emitcode ("anl", "a,#!constbyte",
7651                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7652
7653       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7654
7655       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7656
7657       emitcode ("anl", "a,#!constbyte",
7658                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7659
7660       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7661
7662       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7663
7664       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7665
7666       break;
7667     case 6:                     // AABBBBBB:CCDDDDDD
7668
7669       emitcode ("mov", "c,acc.7");
7670       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7671
7672       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7673
7674       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7675
7676       emitcode ("anl", "a,#!constbyte",
7677                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7678
7679       break;
7680     case 7:                     // ABBBBBBB:CDDDDDDD
7681
7682       emitcode ("mov", "c,acc.7");      // c = A
7683
7684       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7685
7686       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7687
7688       emitcode ("anl", "a,#!constbyte",
7689                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7690
7691       break;
7692     default:
7693       break;
7694     }
7695 }
7696 #endif
7697
7698 #ifdef BETTER_LITERAL_SHIFT
7699 /*-----------------------------------------------------------------*/
7700 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7701 /*-----------------------------------------------------------------*/
7702 static void
7703 AccAXRshS (char *x, int shCount)
7704 {
7705   symbol *tlbl;
7706   switch (shCount)
7707     {
7708     case 0:
7709       break;
7710     case 1:
7711       emitcode ("mov", "c,acc.7");
7712       AccAXRrl1 (x);            // s->a:x
7713
7714       break;
7715     case 2:
7716       emitcode ("mov", "c,acc.7");
7717       AccAXRrl1 (x);            // s->a:x
7718
7719       emitcode ("mov", "c,acc.7");
7720       AccAXRrl1 (x);            // s->a:x
7721
7722       break;
7723     case 3:
7724     case 4:
7725     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7726
7727       tlbl = newiTempLabel (NULL);
7728       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7729
7730       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7731
7732       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7733
7734       emitcode ("anl", "a,#!constbyte",
7735                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7736
7737       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7738
7739       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7740
7741       emitcode ("anl", "a,#!constbyte",
7742                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7743
7744       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7745
7746       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7747
7748       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7749
7750       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7751       emitcode ("orl", "a,#!constbyte",
7752                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7753
7754       emitcode ("", "!tlabeldef", tlbl->key + 100);
7755       break;                    // SSSSAAAA:BBBCCCCC
7756
7757     case 6:                     // AABBBBBB:CCDDDDDD
7758
7759       tlbl = newiTempLabel (NULL);
7760       emitcode ("mov", "c,acc.7");
7761       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7762
7763       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7764
7765       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7766
7767       emitcode ("anl", "a,#!constbyte",
7768                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7769
7770       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7771       emitcode ("orl", "a,#!constbyte",
7772                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7773
7774       emitcode ("", "!tlabeldef", tlbl->key + 100);
7775       break;
7776     case 7:                     // ABBBBBBB:CDDDDDDD
7777
7778       tlbl = newiTempLabel (NULL);
7779       emitcode ("mov", "c,acc.7");      // c = A
7780
7781       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7782
7783       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7784
7785       emitcode ("anl", "a,#!constbyte",
7786                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7787
7788       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789       emitcode ("orl", "a,#!constbyte",
7790                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7791
7792       emitcode ("", "!tlabeldef", tlbl->key + 100);
7793       break;
7794     default:
7795       break;
7796     }
7797 }
7798 #endif
7799
7800 #ifdef BETTER_LITERAL_SHIFT
7801 static void
7802 _loadLeftIntoAx(char    **lsb, 
7803                 operand *left, 
7804                 operand *result,
7805                 int     offl,
7806                 int     offr)
7807 {
7808   // Get the initial value from left into a pair of registers.
7809   // MSB must be in A, LSB can be any register.
7810   //
7811   // If the result is held in registers, it is an optimization
7812   // if the LSB can be held in the register which will hold the,
7813   // result LSB since this saves us from having to copy it into
7814   // the result following AccAXLsh.
7815   //
7816   // If the result is addressed indirectly, this is not a gain.
7817   if (AOP_NEEDSACC(result))
7818   {
7819        char *leftByte;
7820        
7821        _startLazyDPSEvaluation();
7822       if (AOP_TYPE(left) == AOP_DPTR2)
7823        {
7824            // Get MSB in A.
7825            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7826            // get LSB in DP2_RESULT_REG.
7827            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7828            assert(!strcmp(leftByte, DP2_RESULT_REG));
7829        }
7830        else
7831        {
7832            // get LSB into DP2_RESULT_REG
7833            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7834            if (strcmp(leftByte, DP2_RESULT_REG))
7835            {
7836                TR_AP("#7");
7837                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7838            }
7839            // And MSB in A.
7840            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7841            assert(strcmp(leftByte, DP2_RESULT_REG));
7842            MOVA(leftByte);
7843        }
7844        _endLazyDPSEvaluation();
7845        *lsb = DP2_RESULT_REG;
7846   }
7847   else
7848   {
7849       if (sameRegs (AOP (result), AOP (left)) &&
7850         ((offl + MSB16) == offr))
7851       {
7852           /* don't crash result[offr] */
7853           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7854           emitcode ("xch", "a,%s", 
7855                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7856       }
7857       else
7858       {
7859           movLeft2Result (left, offl, result, offr, 0);
7860           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7861       }
7862       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7863       assert(strcmp(*lsb,"a"));      
7864   }
7865 }
7866
7867 static void
7868 _storeAxResults(char    *lsb,
7869                 operand *result,
7870                 int     offr)
7871 {
7872   _startLazyDPSEvaluation();
7873   if (AOP_NEEDSACC(result))
7874   {
7875       /* We have to explicitly update the result LSB.
7876        */
7877       emitcode("xch","a,%s", lsb);
7878       aopPut(AOP(result), "a", offr);
7879       emitcode("mov","a,%s", lsb);
7880   }
7881   if (getDataSize (result) > 1)
7882   {
7883       aopPut (AOP (result), "a", offr + MSB16);
7884   }
7885   _endLazyDPSEvaluation();
7886 }
7887
7888 /*-----------------------------------------------------------------*/
7889 /* shiftL2Left2Result - shift left two bytes from left to result   */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 shiftL2Left2Result (operand * left, int offl,
7893                     operand * result, int offr, int shCount)
7894 {
7895   char *lsb;
7896
7897   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7898   
7899   AccAXLsh (lsb, shCount);
7900   
7901   _storeAxResults(lsb, result, offr);
7902 }
7903 #endif
7904
7905 #ifdef BETTER_LITERAL_SHIFT
7906 /*-----------------------------------------------------------------*/
7907 /* shiftR2Left2Result - shift right two bytes from left to result  */
7908 /*-----------------------------------------------------------------*/
7909 static void
7910 shiftR2Left2Result (operand * left, int offl,
7911                     operand * result, int offr,
7912                     int shCount, int sign)
7913 {
7914   char *lsb;
7915   
7916   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7917   
7918   /* a:x >> shCount (x = lsb(result)) */
7919   if (sign)
7920   {
7921      AccAXRshS(lsb, shCount);
7922   }
7923   else
7924   {
7925     AccAXRsh(lsb, shCount);
7926   }
7927   
7928   _storeAxResults(lsb, result, offr);
7929 }
7930 #endif
7931
7932 /*-----------------------------------------------------------------*/
7933 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7934 /*-----------------------------------------------------------------*/
7935 static void
7936 shiftLLeftOrResult (operand * left, int offl,
7937                     operand * result, int offr, int shCount)
7938 {
7939   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7940   /* shift left accumulator */
7941   AccLsh (shCount);
7942   /* or with result */
7943   emitcode ("orl", "a,%s",
7944             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7945   /* back to result */
7946   aopPut (AOP (result), "a", offr);
7947 }
7948
7949 #if 0
7950 //REMOVE ME!!!
7951 /*-----------------------------------------------------------------*/
7952 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7953 /*-----------------------------------------------------------------*/
7954 static void
7955 shiftRLeftOrResult (operand * left, int offl,
7956                     operand * result, int offr, int shCount)
7957 {
7958   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7959   /* shift right accumulator */
7960   AccRsh (shCount);
7961   /* or with result */
7962   emitcode ("orl", "a,%s",
7963             aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7964   /* back to result */
7965   aopPut (AOP (result), "a", offr);
7966 }
7967 #endif
7968
7969 #ifdef BETTER_LITERAL_SHIFT
7970 /*-----------------------------------------------------------------*/
7971 /* genlshOne - left shift a one byte quantity by known count       */
7972 /*-----------------------------------------------------------------*/
7973 static void
7974 genlshOne (operand * result, operand * left, int shCount)
7975 {
7976   D (emitcode (";", "genlshOne "););
7977   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7978 }
7979 #endif
7980
7981 #ifdef BETTER_LITERAL_SHIFT
7982 /*-----------------------------------------------------------------*/
7983 /* genlshTwo - left shift two bytes by known amount != 0           */
7984 /*-----------------------------------------------------------------*/
7985 static void
7986 genlshTwo (operand * result, operand * left, int shCount)
7987 {
7988   int size;
7989
7990   D (emitcode (";", "genlshTwo "););
7991
7992   size = getDataSize (result);
7993
7994   /* if shCount >= 8 */
7995   if (shCount >= 8)
7996   {
7997       shCount -= 8;
7998
7999       _startLazyDPSEvaluation();
8000
8001       if (size > 1)
8002         {
8003           if (shCount)
8004           {
8005             _endLazyDPSEvaluation();
8006             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8007             aopPut (AOP (result), zero, LSB);       
8008           }
8009           else
8010           {
8011             movLeft2Result (left, LSB, result, MSB16, 0);
8012             aopPut (AOP (result), zero, LSB);
8013             _endLazyDPSEvaluation();
8014           }
8015         }
8016         else
8017         {
8018           aopPut (AOP (result), zero, LSB);
8019           _endLazyDPSEvaluation();
8020         }
8021   }
8022
8023   /*  1 <= shCount <= 7 */
8024   else
8025     {
8026       if (size == 1)
8027       {
8028         shiftL1Left2Result (left, LSB, result, LSB, shCount);
8029       }
8030       else
8031       {
8032         shiftL2Left2Result (left, LSB, result, LSB, shCount);
8033       }
8034     }
8035 }
8036 #endif
8037
8038 #if 0
8039 //REMOVE ME!!!
8040 /*-----------------------------------------------------------------*/
8041 /* shiftLLong - shift left one long from left to result            */
8042 /* offl = LSB or MSB16                                             */
8043 /*-----------------------------------------------------------------*/
8044 static void
8045 shiftLLong (operand * left, operand * result, int offr)
8046 {
8047   char *l;
8048   int size = AOP_SIZE (result);
8049
8050   if (size >= LSB + offr)
8051     {
8052       l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8053       MOVA (l);
8054       emitcode ("add", "a,acc");
8055       if (sameRegs (AOP (left), AOP (result)) &&
8056           size >= MSB16 + offr && offr != LSB)
8057         emitcode ("xch", "a,%s",
8058                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8059       else
8060         aopPut (AOP (result), "a", LSB + offr);
8061     }
8062
8063   if (size >= MSB16 + offr)
8064     {
8065       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8066         {
8067           MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8068         }
8069       emitcode ("rlc", "a");
8070       if (sameRegs (AOP (left), AOP (result)) &&
8071           size >= MSB24 + offr && offr != LSB)
8072         emitcode ("xch", "a,%s",
8073                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8074       else
8075         aopPut (AOP (result), "a", MSB16 + offr);
8076     }
8077
8078   if (size >= MSB24 + offr)
8079     {
8080       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8081         {
8082           MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8083         }
8084       emitcode ("rlc", "a");
8085       if (sameRegs (AOP (left), AOP (result)) &&
8086           size >= MSB32 + offr && offr != LSB)
8087         emitcode ("xch", "a,%s",
8088                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8089       else
8090         aopPut (AOP (result), "a", MSB24 + offr);
8091     }
8092
8093   if (size > MSB32 + offr)
8094     {
8095       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8096         {
8097           MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8098         }
8099       emitcode ("rlc", "a");
8100       aopPut (AOP (result), "a", MSB32 + offr);
8101     }
8102   if (offr != LSB)
8103     aopPut (AOP (result), zero, LSB);
8104 }
8105 #endif
8106
8107 #if 0
8108 //REMOVE ME!!!
8109 /*-----------------------------------------------------------------*/
8110 /* genlshFour - shift four byte by a known amount != 0             */
8111 /*-----------------------------------------------------------------*/
8112 static void
8113 genlshFour (operand * result, operand * left, int shCount)
8114 {
8115   int size;
8116
8117   D (emitcode (";", "genlshFour ");
8118     );
8119
8120   size = AOP_SIZE (result);
8121
8122   /* if shifting more that 3 bytes */
8123   if (shCount >= 24)
8124     {
8125       shCount -= 24;
8126       if (shCount)
8127         /* lowest order of left goes to the highest
8128            order of the destination */
8129         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8130       else
8131         movLeft2Result (left, LSB, result, MSB32, 0);
8132       aopPut (AOP (result), zero, LSB);
8133       aopPut (AOP (result), zero, MSB16);
8134       aopPut (AOP (result), zero, MSB24);
8135       return;
8136     }
8137
8138   /* more than two bytes */
8139   else if (shCount >= 16)
8140     {
8141       /* lower order two bytes goes to higher order two bytes */
8142       shCount -= 16;
8143       /* if some more remaining */
8144       if (shCount)
8145         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8146       else
8147         {
8148           movLeft2Result (left, MSB16, result, MSB32, 0);
8149           movLeft2Result (left, LSB, result, MSB24, 0);
8150         }
8151       aopPut (AOP (result), zero, MSB16);
8152       aopPut (AOP (result), zero, LSB);
8153       return;
8154     }
8155
8156   /* if more than 1 byte */
8157   else if (shCount >= 8)
8158     {
8159       /* lower order three bytes goes to higher order  three bytes */
8160       shCount -= 8;
8161       if (size == 2)
8162         {
8163           if (shCount)
8164             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8165           else
8166             movLeft2Result (left, LSB, result, MSB16, 0);
8167         }
8168       else
8169         {                       /* size = 4 */
8170           if (shCount == 0)
8171             {
8172               movLeft2Result (left, MSB24, result, MSB32, 0);
8173               movLeft2Result (left, MSB16, result, MSB24, 0);
8174               movLeft2Result (left, LSB, result, MSB16, 0);
8175               aopPut (AOP (result), zero, LSB);
8176             }
8177           else if (shCount == 1)
8178             shiftLLong (left, result, MSB16);
8179           else
8180             {
8181               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8182               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8183               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8184               aopPut (AOP (result), zero, LSB);
8185             }
8186         }
8187     }
8188
8189   /* 1 <= shCount <= 7 */
8190   else if (shCount <= 2)
8191     {
8192       shiftLLong (left, result, LSB);
8193       if (shCount == 2)
8194         shiftLLong (result, result, LSB);
8195     }
8196   /* 3 <= shCount <= 7, optimize */
8197   else
8198     {
8199       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8200       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8201       shiftL2Left2Result (left, LSB, result, LSB, shCount);
8202     }
8203 }
8204 #endif
8205
8206 #ifdef BETTER_LITERAL_SHIFT
8207 /*-----------------------------------------------------------------*/
8208 /* genLeftShiftLiteral - left shifting by known count              */
8209 /*-----------------------------------------------------------------*/
8210 static bool
8211 genLeftShiftLiteral (operand * left,
8212                      operand * right,
8213                      operand * result,
8214                      iCode * ic)
8215 {
8216   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8217   int size;
8218
8219   size = getSize (operandType (result));
8220
8221   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8222
8223   /* We only handle certain easy cases so far. */
8224   if ((shCount != 0)
8225    && (shCount < (size * 8))
8226    && (size != 1)
8227    && (size != 2))
8228   {
8229       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
8230       return FALSE;
8231   }
8232
8233   freeAsmop (right, NULL, ic, TRUE);
8234
8235   aopOp(left, ic, FALSE, FALSE);
8236   aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8237
8238 #if 0 // debug spew
8239   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8240   {
8241         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8242         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8243         {
8244            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8245         }
8246   }
8247   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8248   {
8249         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8250         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8251         {
8252            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8253         }       
8254   }  
8255 #endif
8256   
8257 #if VIEW_SIZE
8258   emitcode ("; shift left ", "result %d, left %d", size,
8259             AOP_SIZE (left));
8260 #endif
8261
8262   /* I suppose that the left size >= result size */
8263   if (shCount == 0)
8264   {
8265         _startLazyDPSEvaluation();
8266         while (size--)
8267         {
8268           movLeft2Result (left, size, result, size, 0);
8269         }
8270         _endLazyDPSEvaluation();
8271   }
8272   else if (shCount >= (size * 8))
8273   {
8274     _startLazyDPSEvaluation();
8275     while (size--)
8276     {
8277       aopPut (AOP (result), zero, size);
8278     }
8279     _endLazyDPSEvaluation();
8280   }
8281   else
8282   {
8283       switch (size)
8284         {
8285         case 1:
8286           genlshOne (result, left, shCount);
8287           break;
8288
8289         case 2:
8290           genlshTwo (result, left, shCount);
8291           break;
8292 #if 0
8293         case 4:
8294           genlshFour (result, left, shCount);
8295           break;
8296 #endif
8297         default:
8298           fprintf(stderr, "*** ack! mystery literal shift!\n");   
8299           break;
8300         }
8301     }
8302   freeAsmop (left, NULL, ic, TRUE);
8303   freeAsmop (result, NULL, ic, TRUE);
8304   return TRUE;
8305 }
8306 #endif
8307
8308 /*-----------------------------------------------------------------*/
8309 /* genLeftShift - generates code for left shifting                 */
8310 /*-----------------------------------------------------------------*/
8311 static void
8312 genLeftShift (iCode * ic)
8313 {
8314   operand *left, *right, *result;
8315   int size, offset;
8316   char *l;
8317   symbol *tlbl, *tlbl1;
8318
8319   D (emitcode (";", "genLeftShift "););
8320
8321   right = IC_RIGHT (ic);
8322   left = IC_LEFT (ic);
8323   result = IC_RESULT (ic);
8324
8325   aopOp (right, ic, FALSE, FALSE);
8326
8327
8328 #ifdef BETTER_LITERAL_SHIFT
8329   /* if the shift count is known then do it
8330      as efficiently as possible */
8331   if (AOP_TYPE (right) == AOP_LIT)
8332     {
8333       if (genLeftShiftLiteral (left, right, result, ic))
8334       {
8335         return;
8336       }
8337     }
8338 #endif
8339
8340   /* shift count is unknown then we have to form
8341      a loop get the loop count in B : Note: we take
8342      only the lower order byte since shifting
8343      more that 32 bits make no sense anyway, ( the
8344      largest size of an object can be only 32 bits ) */
8345
8346   if (AOP_TYPE (right) == AOP_LIT)
8347   {
8348       /* Really should be handled by genLeftShiftLiteral,
8349        * but since I'm too lazy to fix that today, at least we can make
8350        * some small improvement.
8351        */
8352        emitcode("mov", "b,#!constbyte",
8353                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8354   }
8355   else
8356   {
8357       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8358       emitcode ("inc", "b");
8359   }
8360   freeAsmop (right, NULL, ic, TRUE);
8361   aopOp (left, ic, FALSE, FALSE);
8362   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8363
8364   /* now move the left to the result if they are not the
8365      same */
8366   if (!sameRegs (AOP (left), AOP (result)) &&
8367       AOP_SIZE (result) > 1)
8368     {
8369
8370       size = AOP_SIZE (result);
8371       offset = 0;
8372       _startLazyDPSEvaluation ();
8373       while (size--)
8374         {
8375           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8376           if (*l == '@' && (IS_AOP_PREG (result)))
8377             {
8378
8379               emitcode ("mov", "a,%s", l);
8380               aopPut (AOP (result), "a", offset);
8381             }
8382           else
8383             aopPut (AOP (result), l, offset);
8384           offset++;
8385         }
8386       _endLazyDPSEvaluation ();
8387     }
8388
8389   tlbl = newiTempLabel (NULL);
8390   size = AOP_SIZE (result);
8391   offset = 0;
8392   tlbl1 = newiTempLabel (NULL);
8393
8394   /* if it is only one byte then */
8395   if (size == 1)
8396     {
8397       symbol *tlbl1 = newiTempLabel (NULL);
8398
8399       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8400       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8401       emitcode ("", "!tlabeldef", tlbl->key + 100);
8402       emitcode ("add", "a,acc");
8403       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8404       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8405       aopPut (AOP (result), "a", 0);
8406       goto release;
8407     }
8408
8409   reAdjustPreg (AOP (result));
8410
8411   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8412   emitcode ("", "!tlabeldef", tlbl->key + 100);
8413   MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8414   emitcode ("add", "a,acc");
8415   aopPut (AOP (result), "a", offset++);
8416   _startLazyDPSEvaluation ();
8417   while (--size)
8418     {
8419       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8420       emitcode ("rlc", "a");
8421       aopPut (AOP (result), "a", offset++);
8422     }
8423   _endLazyDPSEvaluation ();
8424   reAdjustPreg (AOP (result));
8425
8426   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8427   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8428 release:
8429   freeAsmop (left, NULL, ic, TRUE);
8430   freeAsmop (result, NULL, ic, TRUE);
8431 }
8432
8433 #ifdef BETTER_LITERAL_SHIFT
8434 /*-----------------------------------------------------------------*/
8435 /* genrshOne - right shift a one byte quantity by known count      */
8436 /*-----------------------------------------------------------------*/
8437 static void
8438 genrshOne (operand * result, operand * left,
8439            int shCount, int sign)
8440 {
8441   D (emitcode (";", "genrshOne"););
8442   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8443 }
8444 #endif
8445
8446 #ifdef BETTER_LITERAL_SHIFT
8447 /*-----------------------------------------------------------------*/
8448 /* genrshTwo - right shift two bytes by known amount != 0          */
8449 /*-----------------------------------------------------------------*/
8450 static void
8451 genrshTwo (operand * result, operand * left,
8452            int shCount, int sign)
8453 {
8454   D (emitcode (";", "genrshTwo"););
8455
8456   /* if shCount >= 8 */
8457   if (shCount >= 8)
8458     {
8459       shCount -= 8;
8460       _startLazyDPSEvaluation();
8461       if (shCount)
8462       {
8463         shiftR1Left2Result (left, MSB16, result, LSB,
8464                             shCount, sign);
8465       }                     
8466       else
8467       {
8468         movLeft2Result (left, MSB16, result, LSB, sign);
8469       }
8470       addSign (result, MSB16, sign);
8471       _endLazyDPSEvaluation();
8472     }
8473
8474   /*  1 <= shCount <= 7 */
8475   else
8476   {
8477     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8478   }
8479 }
8480 #endif
8481
8482 /*-----------------------------------------------------------------*/
8483 /* shiftRLong - shift right one long from left to result           */
8484 /* offl = LSB or MSB16                                             */
8485 /*-----------------------------------------------------------------*/
8486 static void
8487 shiftRLong (operand * left, int offl,
8488             operand * result, int sign)
8489 {
8490   int isSameRegs=sameRegs(AOP(left),AOP(result));
8491
8492   if (isSameRegs && offl>1) {
8493     // we are in big trouble, but this shouldn't happen
8494     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8495   }
8496
8497   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8498   
8499   if (offl==MSB16) {
8500     // shift is > 8
8501     if (sign) {
8502       emitcode ("rlc", "a");
8503       emitcode ("subb", "a,acc");
8504       emitcode ("xch", "a,%s",
8505                 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8506     } else {
8507       aopPut (AOP(result), zero, MSB32);
8508     }
8509   }
8510
8511   if (!sign) {
8512     emitcode ("clr", "c");
8513   } else {
8514     emitcode ("mov", "c,acc.7");
8515   }
8516
8517   emitcode ("rrc", "a");
8518
8519   if (isSameRegs && offl==MSB16) {
8520     emitcode ("xch",
8521               "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8522   } else {
8523     aopPut (AOP (result), "a", MSB32);
8524     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8525   }
8526
8527   emitcode ("rrc", "a");
8528   if (isSameRegs && offl==1) {
8529     emitcode ("xch", "a,%s",
8530               aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8531   } else {
8532     aopPut (AOP (result), "a", MSB24);
8533     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8534   }
8535   emitcode ("rrc", "a");
8536   aopPut (AOP (result), "a", MSB16 - offl);
8537
8538   if (offl == LSB)
8539     {
8540       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8541       emitcode ("rrc", "a");
8542       aopPut (AOP (result), "a", LSB);
8543     }
8544 }
8545
8546 /*-----------------------------------------------------------------*/
8547 /* genrshFour - shift four byte by a known amount != 0             */
8548 /*-----------------------------------------------------------------*/
8549 static void
8550 genrshFour (operand * result, operand * left,
8551             int shCount, int sign)
8552 {
8553   D (emitcode (";", "genrshFour"););
8554
8555   /* if shifting more that 3 bytes */
8556   if (shCount >= 24)
8557     {
8558       shCount -= 24;
8559       _startLazyDPSEvaluation();
8560       if (shCount)
8561         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8562       else
8563         movLeft2Result (left, MSB32, result, LSB, sign);
8564       addSign (result, MSB16, sign);
8565       _endLazyDPSEvaluation();
8566     }
8567   else if (shCount >= 16)
8568     {
8569       shCount -= 16;
8570       _startLazyDPSEvaluation();
8571       if (shCount)
8572         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8573       else
8574         {
8575           movLeft2Result (left, MSB24, result, LSB, 0);
8576           movLeft2Result (left, MSB32, result, MSB16, sign);
8577         }
8578       addSign (result, MSB24, sign);
8579       _endLazyDPSEvaluation();
8580     }
8581   else if (shCount >= 8)
8582     {
8583       shCount -= 8;
8584       _startLazyDPSEvaluation();
8585       if (shCount == 1)
8586         {
8587             shiftRLong (left, MSB16, result, sign);
8588         }
8589       else if (shCount == 0)
8590         {
8591           movLeft2Result (left, MSB16, result, LSB, 0);
8592           movLeft2Result (left, MSB24, result, MSB16, 0);
8593           movLeft2Result (left, MSB32, result, MSB24, sign);
8594           addSign (result, MSB32, sign);
8595         }
8596       else
8597         {
8598           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8599           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8600           /* the last shift is signed */
8601           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8602           addSign (result, MSB32, sign);
8603         }
8604         _endLazyDPSEvaluation();
8605     }
8606   else
8607     {   
8608         /* 1 <= shCount <= 7 */
8609       if (shCount <= 2)
8610         {
8611           shiftRLong (left, LSB, result, sign);
8612           if (shCount == 2)
8613             shiftRLong (result, LSB, result, sign);
8614         }
8615       else
8616         {
8617           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8618           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8619           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8620         }
8621     }
8622 }
8623
8624 #ifdef BETTER_LITERAL_SHIFT
8625 /*-----------------------------------------------------------------*/
8626 /* genRightShiftLiteral - right shifting by known count            */
8627 /*-----------------------------------------------------------------*/
8628 static bool
8629 genRightShiftLiteral (operand * left,
8630                       operand * right,
8631                       operand * result,
8632                       iCode * ic,
8633                       int sign)
8634 {
8635   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8636   int size;
8637
8638   size = getSize (operandType (result));
8639
8640   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8641
8642   /* We only handle certain easy cases so far. */
8643   if ((shCount != 0)
8644    && (shCount < (size * 8))
8645    && (size != 1)
8646    && (size != 2)
8647    && (size != 4))
8648   {
8649       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8650       return FALSE;
8651   }
8652
8653   freeAsmop (right, NULL, ic, TRUE);
8654
8655   aopOp (left, ic, FALSE, FALSE);
8656   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8657
8658 #if VIEW_SIZE
8659   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8660             AOP_SIZE (left));
8661 #endif
8662
8663   /* test the LEFT size !!! */
8664
8665   /* I suppose that the left size >= result size */
8666   if (shCount == 0)
8667   {
8668       size = getDataSize (result);
8669       _startLazyDPSEvaluation();
8670       while (size--)
8671       {
8672         movLeft2Result (left, size, result, size, 0);
8673       }
8674       _endLazyDPSEvaluation();
8675   }
8676   else if (shCount >= (size * 8))
8677     {
8678       if (sign)
8679       {
8680         /* get sign in acc.7 */
8681         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8682       }
8683       addSign (result, LSB, sign);
8684     }
8685   else
8686     {
8687       switch (size)
8688         {
8689         case 1:
8690           genrshOne (result, left, shCount, sign);
8691           break;
8692
8693         case 2:
8694           genrshTwo (result, left, shCount, sign);
8695           break;
8696 #if 1
8697         case 4:
8698           genrshFour (result, left, shCount, sign);
8699           break;
8700 #endif    
8701         default:
8702           break;
8703         }
8704     }
8705   freeAsmop (left, NULL, ic, TRUE);
8706   freeAsmop (result, NULL, ic, TRUE);
8707   
8708   return TRUE;
8709 }
8710 #endif
8711
8712 /*-----------------------------------------------------------------*/
8713 /* genSignedRightShift - right shift of signed number              */
8714 /*-----------------------------------------------------------------*/
8715 static void
8716 genSignedRightShift (iCode * ic)
8717 {
8718   operand *right, *left, *result;
8719   int size, offset;
8720   char *l;
8721   symbol *tlbl, *tlbl1;
8722
8723   D (emitcode (";", "genSignedRightShift "););
8724
8725   /* we do it the hard way put the shift count in b
8726      and loop thru preserving the sign */
8727
8728   right = IC_RIGHT (ic);
8729   left = IC_LEFT (ic);
8730   result = IC_RESULT (ic);
8731
8732   aopOp (right, ic, FALSE, FALSE);
8733
8734 #ifdef BETTER_LITERAL_SHIFT
8735   if (AOP_TYPE (right) == AOP_LIT)
8736     {
8737       if (genRightShiftLiteral (left, right, result, ic, 1))
8738       {
8739         return;
8740       }
8741     }
8742 #endif
8743   /* shift count is unknown then we have to form
8744      a loop get the loop count in B : Note: we take
8745      only the lower order byte since shifting
8746      more that 32 bits make no sense anyway, ( the
8747      largest size of an object can be only 32 bits ) */
8748
8749   if (AOP_TYPE (right) == AOP_LIT)
8750   {
8751       /* Really should be handled by genRightShiftLiteral,
8752        * but since I'm too lazy to fix that today, at least we can make
8753        * some small improvement.
8754        */
8755        emitcode("mov", "b,#!constbyte",
8756                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8757   }
8758   else
8759   {
8760         MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8761         emitcode ("inc", "b");
8762   }
8763   freeAsmop (right, NULL, ic, TRUE);
8764   aopOp (left, ic, FALSE, FALSE);
8765   aopOp (result, ic, FALSE, AOP_USESDPTR(left)); 
8766
8767   /* now move the left to the result if they are not the
8768      same */
8769   if (!sameRegs (AOP (left), AOP (result)) &&
8770       AOP_SIZE (result) > 1)
8771     {
8772
8773       size = AOP_SIZE (result);
8774       offset = 0;
8775       _startLazyDPSEvaluation ();
8776       while (size--)
8777         {
8778           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8779           if (*l == '@' && IS_AOP_PREG (result))
8780             {
8781
8782               emitcode ("mov", "a,%s", l);
8783               aopPut (AOP (result), "a", offset);
8784             }
8785           else
8786             aopPut (AOP (result), l, offset);
8787           offset++;
8788         }
8789       _endLazyDPSEvaluation ();
8790     }
8791
8792   /* mov the highest order bit to OVR */
8793   tlbl = newiTempLabel (NULL);
8794   tlbl1 = newiTempLabel (NULL);
8795
8796   size = AOP_SIZE (result);
8797   offset = size - 1;
8798   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8799   emitcode ("rlc", "a");
8800   emitcode ("mov", "ov,c");
8801   /* if it is only one byte then */
8802   if (size == 1)
8803     {
8804       MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8805       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8806       emitcode ("", "!tlabeldef", tlbl->key + 100);
8807       emitcode ("mov", "c,ov");
8808       emitcode ("rrc", "a");
8809       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8810       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8811       aopPut (AOP (result), "a", 0);
8812       goto release;
8813     }
8814
8815   reAdjustPreg (AOP (result));
8816   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8817   emitcode ("", "!tlabeldef", tlbl->key + 100);
8818   emitcode ("mov", "c,ov");
8819   _startLazyDPSEvaluation ();
8820   while (size--)
8821     {
8822       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8823       emitcode ("rrc", "a");
8824       aopPut (AOP (result), "a", offset--);
8825     }
8826   _endLazyDPSEvaluation ();
8827   reAdjustPreg (AOP (result));
8828   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8829   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8830
8831 release:
8832   freeAsmop (left, NULL, ic, TRUE);
8833   freeAsmop (result, NULL, ic, TRUE);
8834 }
8835
8836 /*-----------------------------------------------------------------*/
8837 /* genRightShift - generate code for right shifting                */
8838 /*-----------------------------------------------------------------*/
8839 static void
8840 genRightShift (iCode * ic)
8841 {
8842   operand *right, *left, *result;
8843   sym_link *retype;
8844   int size, offset;
8845   char *l;
8846   symbol *tlbl, *tlbl1;
8847
8848   D (emitcode (";", "genRightShift "););
8849
8850   /* if signed then we do it the hard way preserve the
8851      sign bit moving it inwards */
8852   retype = getSpec (operandType (IC_RESULT (ic)));
8853
8854   if (!SPEC_USIGN (retype))
8855     {
8856       genSignedRightShift (ic);
8857       return;
8858     }
8859
8860   /* signed & unsigned types are treated the same : i.e. the
8861      signed is NOT propagated inwards : quoting from the
8862      ANSI - standard : "for E1 >> E2, is equivalent to division
8863      by 2**E2 if unsigned or if it has a non-negative value,
8864      otherwise the result is implementation defined ", MY definition
8865      is that the sign does not get propagated */
8866
8867   right = IC_RIGHT (ic);
8868   left = IC_LEFT (ic);
8869   result = IC_RESULT (ic);
8870
8871   aopOp (right, ic, FALSE, FALSE);
8872
8873 #ifdef BETTER_LITERAL_SHIFT
8874   /* if the shift count is known then do it
8875      as efficiently as possible */
8876   if (AOP_TYPE (right) == AOP_LIT)
8877     {
8878       if (genRightShiftLiteral (left, right, result, ic, 0))
8879       {
8880         return;
8881       }
8882     }
8883 #endif
8884
8885   /* shift count is unknown then we have to form
8886      a loop get the loop count in B : Note: we take
8887      only the lower order byte since shifting
8888      more that 32 bits make no sense anyway, ( the
8889      largest size of an object can be only 32 bits ) */
8890   
8891   if (AOP_TYPE (right) == AOP_LIT)
8892   {
8893       /* Really should be handled by genRightShiftLiteral,
8894        * but since I'm too lazy to fix that today, at least we can make
8895        * some small improvement.
8896        */
8897        emitcode("mov", "b,#!constbyte",
8898                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8899   }
8900   else
8901   {
8902       MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8903       emitcode ("inc", "b");
8904   }
8905   freeAsmop (right, NULL, ic, TRUE);
8906   aopOp (left, ic, FALSE, FALSE);
8907   aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8908
8909   /* now move the left to the result if they are not the
8910      same */
8911   if (!sameRegs (AOP (left), AOP (result)) &&
8912       AOP_SIZE (result) > 1)
8913     {
8914
8915       size = AOP_SIZE (result);
8916       offset = 0;
8917       _startLazyDPSEvaluation ();
8918       while (size--)
8919         {
8920           l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8921           if (*l == '@' && IS_AOP_PREG (result))
8922             {
8923
8924               emitcode ("mov", "a,%s", l);
8925               aopPut (AOP (result), "a", offset);
8926             }
8927           else
8928             aopPut (AOP (result), l, offset);
8929           offset++;
8930         }
8931       _endLazyDPSEvaluation ();
8932     }
8933
8934   tlbl = newiTempLabel (NULL);
8935   tlbl1 = newiTempLabel (NULL);
8936   size = AOP_SIZE (result);
8937   offset = size - 1;
8938
8939   /* if it is only one byte then */
8940   if (size == 1)
8941     {
8942       MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8943       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8944       emitcode ("", "!tlabeldef", tlbl->key + 100);
8945       CLRC;
8946       emitcode ("rrc", "a");
8947       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8948       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8949       aopPut (AOP (result), "a", 0);
8950       goto release;
8951     }
8952
8953   reAdjustPreg (AOP (result));
8954   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8955   emitcode ("", "!tlabeldef", tlbl->key + 100);
8956   CLRC;
8957   _startLazyDPSEvaluation ();
8958   while (size--)
8959     {
8960       MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8961       emitcode ("rrc", "a");
8962       aopPut (AOP (result), "a", offset--);
8963     }
8964   _endLazyDPSEvaluation ();
8965   reAdjustPreg (AOP (result));
8966
8967   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8968   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8969
8970 release:
8971   freeAsmop (left, NULL, ic, TRUE);
8972   freeAsmop (result, NULL, ic, TRUE);
8973 }
8974
8975 /*-----------------------------------------------------------------*/
8976 /* genUnpackBits - generates code for unpacking bits               */
8977 /*-----------------------------------------------------------------*/
8978 static void
8979 genUnpackBits (operand * result, char *rname, int ptype)
8980 {
8981   int shCnt;
8982   int rlen = 0;
8983   sym_link *etype;
8984   int offset = 0;
8985   int rsize;
8986
8987   D (emitcode (";", "genUnpackBits "););
8988
8989   etype = getSpec (operandType (result));
8990   rsize = getSize (operandType (result));
8991
8992   /* read the first byte  */
8993   switch (ptype)
8994     {
8995
8996     case POINTER:
8997     case IPOINTER:
8998       emitcode ("mov", "a,@%s", rname);
8999       break;
9000
9001     case PPOINTER:
9002       emitcode ("movx", "a,@%s", rname);
9003       break;
9004
9005     case FPOINTER:
9006       emitcode ("movx", "a,@dptr");
9007       break;
9008
9009     case CPOINTER:
9010       emitcode ("clr", "a");
9011       emitcode ("movc", "a,@a+dptr");
9012       break;
9013
9014     case GPOINTER:
9015       emitcode ("lcall", "__gptrget");
9016       break;
9017     }
9018
9019   /* if we have bitdisplacement then it fits   */
9020   /* into this byte completely or if length is */
9021   /* less than a byte                          */
9022   if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8))
9023     {
9024
9025       /* shift right acc */
9026       AccRsh (shCnt);
9027
9028       emitcode ("anl", "a,#!constbyte",
9029                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
9030       aopPut (AOP (result), "a", offset++);
9031       goto finish;
9032     }
9033
9034   /* bit field did not fit in a byte  */
9035   rlen = SPEC_BLEN (etype);
9036   aopPut (AOP (result), "a", offset++);
9037
9038   while (1)
9039     {
9040
9041       switch (ptype)
9042         {
9043         case POINTER:
9044         case IPOINTER:
9045           emitcode ("inc", "%s", rname);
9046           emitcode ("mov", "a,@%s", rname);
9047           break;
9048
9049         case PPOINTER:
9050           emitcode ("inc", "%s", rname);
9051           emitcode ("movx", "a,@%s", rname);
9052           break;
9053
9054         case FPOINTER:
9055           emitcode ("inc", "dptr");
9056           emitcode ("movx", "a,@dptr");
9057           break;
9058
9059         case CPOINTER:
9060           emitcode ("clr", "a");
9061           emitcode ("inc", "dptr");
9062           emitcode ("movc", "a,@a+dptr");
9063           break;
9064
9065         case GPOINTER:
9066           emitcode ("inc", "dptr");
9067           emitcode ("lcall", "__gptrget");
9068           break;
9069         }
9070
9071       rlen -= 8;
9072       /* if we are done */
9073       if (rlen < 8)
9074         break;
9075
9076       aopPut (AOP (result), "a", offset++);
9077
9078     }
9079
9080   if (rlen)
9081     {
9082       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9083       aopPut (AOP (result), "a", offset++);
9084     }
9085
9086 finish:
9087   if (offset < rsize)
9088     {
9089       rsize -=offset;
9090       while (rsize--)
9091         aopPut (AOP (result), zero, offset++);
9092     }
9093 }
9094
9095
9096 /*-----------------------------------------------------------------*/
9097 /* genDataPointerGet - generates code when ptr offset is known     */
9098 /*-----------------------------------------------------------------*/
9099 static void
9100 genDataPointerGet (operand * left,
9101                    operand * result,
9102                    iCode * ic)
9103 {
9104   char *l;
9105   char buff[256];
9106   int size, offset = 0;
9107   aopOp (result, ic, TRUE, FALSE);
9108
9109   /* get the string representation of the name */
9110   l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9111   size = AOP_SIZE (result);
9112   _startLazyDPSEvaluation ();
9113   while (size--)
9114     {
9115         if (offset)
9116         {
9117             SNPRINTF (buff, sizeof(buff), 
9118                       "(%s + %d)", l + 1, offset);
9119         }
9120         else
9121         {
9122             SNPRINTF (buff, sizeof(buff), 
9123                       "%s", l + 1);
9124         }
9125       aopPut (AOP (result), buff, offset++);
9126     }
9127   _endLazyDPSEvaluation ();
9128
9129   freeAsmop (left, NULL, ic, TRUE);
9130   freeAsmop (result, NULL, ic, TRUE);
9131 }
9132
9133 /*-----------------------------------------------------------------*/
9134 /* genNearPointerGet - emitcode for near pointer fetch             */
9135 /*-----------------------------------------------------------------*/
9136 static void
9137 genNearPointerGet (operand * left,
9138                    operand * result,
9139                    iCode * ic,
9140                    iCode *pi)
9141 {
9142   asmop *aop = NULL;
9143   regs *preg;
9144   char *rname;
9145   sym_link *rtype, *retype, *letype;
9146   sym_link *ltype = operandType (left);
9147   char buff[80];
9148
9149   rtype = operandType (result);
9150   retype = getSpec (rtype);
9151   letype = getSpec (ltype);
9152
9153   aopOp (left, ic, FALSE, FALSE);
9154
9155   /* if left is rematerialisable and
9156      result is not bit variable type and
9157      the left is pointer to data space i.e
9158      lower 128 bytes of space */
9159   if (AOP_TYPE (left) == AOP_IMMD &&
9160       !IS_BITVAR (retype) &&
9161       !IS_BITVAR (letype) &&
9162       DCL_TYPE (ltype) == POINTER)
9163     {
9164       genDataPointerGet (left, result, ic);
9165       return;
9166     }
9167
9168   /* if the value is already in a pointer register
9169      then don't need anything more */
9170   if (!AOP_INPREG (AOP (left)))
9171     {
9172       /* otherwise get a free pointer register */
9173       aop = newAsmop (0);
9174       preg = getFreePtr (ic, &aop, FALSE);
9175       emitcode ("mov", "%s,%s",
9176                 preg->name,
9177                 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9178       rname = preg->name;
9179     }
9180   else
9181     rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9182
9183   freeAsmop (left, NULL, ic, TRUE);
9184   aopOp (result, ic, FALSE, FALSE);
9185
9186   /* if bitfield then unpack the bits */
9187   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9188     genUnpackBits (result, rname, POINTER);
9189   else
9190     {
9191       /* we have can just get the values */
9192       int size = AOP_SIZE (result);
9193       int offset = 0;
9194
9195       while (size--)
9196         {
9197           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9198             {
9199
9200               emitcode ("mov", "a,@%s", rname);
9201               aopPut (AOP (result), "a", offset);
9202             }
9203           else
9204             {
9205               SNPRINTF (buff, sizeof(buff), "@%s", rname);
9206               aopPut (AOP (result), buff, offset);
9207             }
9208           offset++;
9209           if (size || pi)
9210             {
9211                 emitcode ("inc", "%s", rname);
9212             }
9213         }
9214     }
9215
9216   /* now some housekeeping stuff */
9217   if (aop)
9218     {
9219       /* we had to allocate for this iCode */
9220       if (pi) { /* post increment present */
9221         aopPut(AOP ( left ),rname,0);
9222       }
9223       freeAsmop (NULL, aop, ic, TRUE);
9224     }
9225   else
9226     {
9227       /* we did not allocate which means left
9228          already in a pointer register, then
9229          if size > 0 && this could be used again
9230          we have to point it back to where it
9231          belongs */
9232       if (AOP_SIZE (result) > 1 &&
9233           !OP_SYMBOL (left)->remat &&
9234           (OP_SYMBOL (left)->liveTo > ic->seq ||
9235            ic->depth) &&
9236           !pi)
9237         {
9238           int size = AOP_SIZE (result) - 1;
9239           while (size--)
9240             emitcode ("dec", "%s", rname);
9241         }
9242     }
9243
9244   /* done */
9245   freeAsmop (result, NULL, ic, TRUE);
9246   if (pi) pi->generated = 1;
9247 }
9248
9249 /*-----------------------------------------------------------------*/
9250 /* genPagedPointerGet - emitcode for paged pointer fetch           */
9251 /*-----------------------------------------------------------------*/
9252 static void
9253 genPagedPointerGet (operand * left,
9254                     operand * result,
9255                     iCode * ic,
9256                     iCode * pi)
9257 {
9258   asmop *aop = NULL;
9259   regs *preg;
9260   char *rname;
9261   sym_link *rtype, *retype, *letype;
9262
9263   rtype = operandType (result);
9264   retype = getSpec (rtype);
9265   letype = getSpec (operandType (left));
9266   aopOp (left, ic, FALSE, FALSE);
9267
9268   /* if the value is already in a pointer register
9269      then don't need anything more */
9270   if (!AOP_INPREG (AOP (left)))
9271     {
9272       /* otherwise get a free pointer register */
9273       aop = newAsmop (0);
9274       preg = getFreePtr (ic, &aop, FALSE);
9275       emitcode ("mov", "%s,%s",
9276                 preg->name,
9277                 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9278       rname = preg->name;
9279     }
9280   else
9281     rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9282
9283   freeAsmop (left, NULL, ic, TRUE);
9284   aopOp (result, ic, FALSE, FALSE);
9285
9286   /* if bitfield then unpack the bits */
9287   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9288     genUnpackBits (result, rname, PPOINTER);
9289   else
9290     {
9291       /* we have can just get the values */
9292       int size = AOP_SIZE (result);
9293       int offset = 0;
9294
9295       while (size--)
9296         {
9297
9298           emitcode ("movx", "a,@%s", rname);
9299           aopPut (AOP (result), "a", offset);
9300
9301           offset++;
9302
9303           if (size || pi)
9304             emitcode ("inc", "%s", rname);
9305         }
9306     }
9307
9308   /* now some housekeeping stuff */
9309   if (aop)
9310     {
9311       /* we had to allocate for this iCode */
9312       if (pi) aopPut ( AOP (left), rname, 0);
9313       freeAsmop (NULL, aop, ic, TRUE);
9314     }
9315   else
9316     {
9317       /* we did not allocate which means left
9318          already in a pointer register, then
9319          if size > 0 && this could be used again
9320          we have to point it back to where it
9321          belongs */
9322       if (AOP_SIZE (result) > 1 &&
9323           !OP_SYMBOL (left)->remat &&
9324           (OP_SYMBOL (left)->liveTo > ic->seq ||
9325            ic->depth) &&
9326           !pi)
9327         {
9328           int size = AOP_SIZE (result) - 1;
9329           while (size--)
9330             emitcode ("dec", "%s", rname);
9331         }
9332     }
9333
9334   /* done */
9335   freeAsmop (result, NULL, ic, TRUE);
9336   if (pi) pi->generated = 1;
9337 }
9338
9339 /*-----------------------------------------------------------------*/
9340 /* genFarPointerGet - gget value from far space                    */
9341 /*-----------------------------------------------------------------*/
9342 static void
9343 genFarPointerGet (operand * left,
9344                   operand * result, iCode * ic, iCode *pi)
9345 {
9346     int size, offset, dopi=1;
9347   sym_link *retype = getSpec (operandType (result));
9348   sym_link *letype = getSpec (operandType (left));
9349   D (emitcode (";", "genFarPointerGet"););
9350
9351   aopOp (left, ic, FALSE, FALSE);
9352
9353   /* if the operand is already in dptr
9354      then we do nothing else we move the value to dptr */
9355   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9356     {
9357       /* if this is remateriazable */
9358       if (AOP_TYPE (left) == AOP_IMMD)
9359         {
9360           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9361         }
9362       else
9363         {
9364           /* we need to get it byte by byte */
9365           _startLazyDPSEvaluation ();
9366           if (AOP_TYPE (left) != AOP_DPTR)
9367             {
9368               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9369               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9370               if (options.model == MODEL_FLAT24)
9371                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9372             }
9373           else
9374             {
9375               /* We need to generate a load to DPTR indirect through DPTR. */
9376               D (emitcode (";", "genFarPointerGet -- indirection special case."););
9377               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9378               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9379               if (options.model == MODEL_FLAT24)
9380                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9381               emitcode ("pop", "dph");
9382               emitcode ("pop", "dpl");
9383               dopi =0;
9384             }
9385           _endLazyDPSEvaluation ();
9386         }
9387     }
9388   /* so dptr know contains the address */
9389   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9390
9391   /* if bit then unpack */
9392   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9393       if (AOP_INDPTRn(left)) {
9394           genSetDPTR(AOP(left)->aopu.dptr);
9395       }
9396       genUnpackBits (result, "dptr", FPOINTER);
9397       if (AOP_INDPTRn(left)) {
9398           genSetDPTR(0);
9399       }
9400   } else
9401     {
9402       size = AOP_SIZE (result);
9403       offset = 0;
9404
9405       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9406           while (size--) {
9407               genSetDPTR(AOP(left)->aopu.dptr);
9408               emitcode ("movx", "a,@dptr");
9409               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9410                   emitcode ("inc", "dptr");
9411               genSetDPTR (0);
9412               aopPut (AOP (result), "a", offset++);
9413           }
9414       } else {
9415           _startLazyDPSEvaluation ();
9416           while (size--) {
9417               if (AOP_INDPTRn(left)) {
9418                   genSetDPTR(AOP(left)->aopu.dptr);
9419               } else {
9420                   genSetDPTR (0);
9421               }
9422               _flushLazyDPS ();
9423               
9424               emitcode ("movx", "a,@dptr");
9425               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9426                   emitcode ("inc", "dptr");
9427               
9428               aopPut (AOP (result), "a", offset++);
9429           }
9430           _endLazyDPSEvaluation ();
9431       }
9432     }
9433   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9434       if (!AOP_INDPTRn(left)) {
9435           _startLazyDPSEvaluation ();
9436           aopPut ( AOP (left), "dpl", 0);
9437           aopPut ( AOP (left), "dph", 1);
9438           if (options.model == MODEL_FLAT24)
9439               aopPut ( AOP (left), "dpx", 2);
9440           _endLazyDPSEvaluation ();
9441       }
9442     pi->generated = 1;
9443   } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) && 
9444              AOP_SIZE(result) > 1 &&
9445              IS_SYMOP(left) &&
9446              (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9447       
9448       size = AOP_SIZE (result) - 1;
9449       if (AOP_INDPTRn(left)) {
9450           genSetDPTR(AOP(left)->aopu.dptr);
9451       }
9452       while (size--) emitcode ("lcall","__decdptr");
9453       if (AOP_INDPTRn(left)) {
9454           genSetDPTR(0);
9455       }
9456   }
9457
9458   freeAsmop (left, NULL, ic, TRUE);
9459   freeAsmop (result, NULL, ic, TRUE);
9460 }
9461
9462 /*-----------------------------------------------------------------*/
9463 /* genCodePointerGet - get value from code space                  */
9464 /*-----------------------------------------------------------------*/
9465 static void
9466 genCodePointerGet (operand * left,
9467                     operand * result, iCode * ic, iCode *pi)
9468 {
9469   int size, offset, dopi=1;
9470   sym_link *retype = getSpec (operandType (result));
9471
9472   aopOp (left, ic, FALSE, FALSE);
9473
9474   /* if the operand is already in dptr
9475      then we do nothing else we move the value to dptr */
9476   if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9477     {
9478       /* if this is remateriazable */
9479       if (AOP_TYPE (left) == AOP_IMMD)
9480         {
9481           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9482         }
9483       else
9484         {                       /* we need to get it byte by byte */
9485           _startLazyDPSEvaluation ();
9486           if (AOP_TYPE (left) != AOP_DPTR)
9487             {
9488               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9489               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9490               if (options.model == MODEL_FLAT24)
9491                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9492             }
9493           else
9494             {
9495               /* We need to generate a load to DPTR indirect through DPTR. */
9496               D (emitcode (";", "gencodePointerGet -- indirection special case."););
9497               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9498               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9499               if (options.model == MODEL_FLAT24)
9500                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9501               emitcode ("pop", "dph");
9502               emitcode ("pop", "dpl");
9503               dopi=0;
9504             }
9505           _endLazyDPSEvaluation ();
9506         }
9507     }
9508   /* so dptr know contains the address */
9509   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9510
9511   /* if bit then unpack */
9512   if (IS_BITVAR (retype)) {
9513       if (AOP_INDPTRn(left)) {
9514           genSetDPTR(AOP(left)->aopu.dptr);
9515       }
9516       genUnpackBits (result, "dptr", CPOINTER);
9517       if (AOP_INDPTRn(left)) {
9518           genSetDPTR(0);
9519       }
9520   } else
9521     {
9522       size = AOP_SIZE (result);
9523       offset = 0;
9524       if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9525           while (size--) {
9526               genSetDPTR(AOP(left)->aopu.dptr);
9527               emitcode ("clr", "a");
9528               emitcode ("movc", "a,@a+dptr");
9529               if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9530                   emitcode ("inc", "dptr");
9531               genSetDPTR (0);
9532               aopPut (AOP (result), "a", offset++);
9533           }
9534       } else {
9535           _startLazyDPSEvaluation ();
9536           while (size--)
9537               {
9538                   if (AOP_INDPTRn(left)) {
9539                       genSetDPTR(AOP(left)->aopu.dptr);
9540                   } else {
9541                       genSetDPTR (0);
9542                   }
9543                   _flushLazyDPS ();
9544                   
9545                   emitcode ("clr", "a");
9546                   emitcode ("movc", "a,@a+dptr");
9547                   if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9548                       emitcode ("inc", "dptr");
9549                   aopPut (AOP (result), "a", offset++);
9550               }
9551           _endLazyDPSEvaluation ();
9552       }
9553     }
9554   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9555       if (!AOP_INDPTRn(left)) {
9556           _startLazyDPSEvaluation ();
9557           
9558           aopPut ( AOP (left), "dpl", 0);
9559           aopPut ( AOP (left), "dph", 1);
9560           if (options.model == MODEL_FLAT24)
9561               aopPut ( AOP (left), "dpx", 2);
9562
9563           _endLazyDPSEvaluation ();
9564       }
9565       pi->generated = 1;
9566   } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) && 
9567              AOP_SIZE(result) > 1 &&
9568              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9569       
9570       size = AOP_SIZE (result) - 1;
9571       if (AOP_INDPTRn(left)) {
9572           genSetDPTR(AOP(left)->aopu.dptr);
9573       }
9574       while (size--) emitcode ("lcall","__decdptr");
9575       if (AOP_INDPTRn(left)) {
9576           genSetDPTR(0);
9577       }
9578   }
9579   
9580   freeAsmop (left, NULL, ic, TRUE);
9581   freeAsmop (result, NULL, ic, TRUE);
9582 }
9583
9584 /*-----------------------------------------------------------------*/
9585 /* genGenPointerGet - gget value from generic pointer space        */
9586 /*-----------------------------------------------------------------*/
9587 static void
9588 genGenPointerGet (operand * left,
9589                   operand * result, iCode * ic, iCode * pi)
9590 {
9591   int size, offset;
9592   sym_link *retype = getSpec (operandType (result));
9593   sym_link *letype = getSpec (operandType (left));
9594
9595   D (emitcode (";", "genGenPointerGet "); );
9596
9597   aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9598
9599   /* if the operand is already in dptr
9600      then we do nothing else we move the value to dptr */
9601   if (AOP_TYPE (left) != AOP_STR)
9602     {
9603       /* if this is remateriazable */
9604       if (AOP_TYPE (left) == AOP_IMMD)
9605         {
9606           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9607           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9608             {
9609                 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9610             }
9611             else
9612             {
9613                 emitcode ("mov", "b,#%d", pointerCode (retype));
9614             }
9615         }
9616       else
9617         {                       /* we need to get it byte by byte */
9618             _startLazyDPSEvaluation ();
9619             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9620             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9621             if (options.model == MODEL_FLAT24) {
9622                 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9623                 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9624             } else {
9625                 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9626             }
9627             _endLazyDPSEvaluation ();
9628         }
9629     }
9630
9631   /* so dptr-b now contains the address */
9632   _G.bInUse++;
9633   aopOp (result, ic, FALSE, TRUE);
9634   _G.bInUse--;
9635
9636   /* if bit then unpack */
9637   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9638   {
9639     genUnpackBits (result, "dptr", GPOINTER);
9640   }
9641   else
9642     {
9643         size = AOP_SIZE (result);
9644         offset = 0;
9645
9646         while (size--)
9647         {
9648             if (size)
9649             {
9650                 // Get two bytes at a time, results in _AP & A.
9651                 // dptr will be incremented ONCE by __gptrgetWord.
9652                 //
9653                 // Note: any change here must be coordinated
9654                 // with the implementation of __gptrgetWord
9655                 // in device/lib/_gptrget.c
9656                 emitcode ("lcall", "__gptrgetWord");
9657                 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9658                 aopPut (AOP (result), "a", offset++);
9659                 size--;
9660             }
9661             else
9662             {
9663                 // Only one byte to get.
9664                 emitcode ("lcall", "__gptrget");
9665                 aopPut (AOP (result), "a", offset++);
9666             }
9667             
9668             if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9669             {
9670                 emitcode ("inc", "dptr");
9671             }
9672         }
9673     }
9674
9675   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9676     _startLazyDPSEvaluation ();
9677       
9678     aopPut ( AOP (left), "dpl", 0);
9679     aopPut ( AOP (left), "dph", 1);
9680     if (options.model == MODEL_FLAT24) {
9681         aopPut ( AOP (left), "dpx", 2);
9682         aopPut ( AOP (left), "b", 3);   
9683     } else  aopPut ( AOP (left), "b", 2);       
9684     
9685     _endLazyDPSEvaluation ();
9686       
9687     pi->generated = 1;
9688   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9689              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9690       
9691       size = AOP_SIZE (result) - 1;
9692       while (size--) emitcode ("lcall","__decdptr");
9693   }
9694
9695   freeAsmop (left, NULL, ic, TRUE);
9696   freeAsmop (result, NULL, ic, TRUE);
9697 }
9698
9699 /*-----------------------------------------------------------------*/
9700 /* genPointerGet - generate code for pointer get                   */
9701 /*-----------------------------------------------------------------*/
9702 static void
9703 genPointerGet (iCode * ic, iCode *pi)
9704 {
9705   operand *left, *result;
9706   sym_link *type, *etype;
9707   int p_type;
9708
9709   D (emitcode (";", "genPointerGet ");
9710     );
9711
9712   left = IC_LEFT (ic);
9713   result = IC_RESULT (ic);
9714
9715   /* depending on the type of pointer we need to
9716      move it to the correct pointer register */
9717   type = operandType (left);
9718   etype = getSpec (type);
9719   /* if left is of type of pointer then it is simple */
9720   if (IS_PTR (type) && !IS_FUNC (type->next))
9721     p_type = DCL_TYPE (type);
9722   else
9723     {
9724       /* we have to go by the storage class */
9725       p_type = PTR_TYPE (SPEC_OCLS (etype));
9726     }
9727   /* special case when cast remat */
9728   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9729       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9730           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9731           type = operandType (left);
9732           p_type = DCL_TYPE (type);
9733   }
9734   /* now that we have the pointer type we assign
9735      the pointer values */
9736   switch (p_type)
9737     {
9738
9739     case POINTER:
9740     case IPOINTER:
9741       genNearPointerGet (left, result, ic, pi);
9742       break;
9743
9744     case PPOINTER:
9745       genPagedPointerGet (left, result, ic, pi);
9746       break;
9747
9748     case FPOINTER:
9749       genFarPointerGet (left, result, ic, pi);
9750       break;
9751
9752     case CPOINTER:
9753       genCodePointerGet (left, result, ic, pi);
9754       break;
9755
9756     case GPOINTER:
9757       genGenPointerGet (left, result, ic, pi);
9758       break;
9759     }
9760
9761 }
9762
9763 /*-----------------------------------------------------------------*/
9764 /* genPackBits - generates code for packed bit storage             */
9765 /*-----------------------------------------------------------------*/
9766 static void
9767 genPackBits (sym_link * etype,
9768              operand * right,
9769              char *rname, int p_type)
9770 {
9771   int shCount = 0;
9772   int offset = 0;
9773   int rLen;
9774   int blen, bstr;
9775   char *l;
9776
9777   blen = SPEC_BLEN (etype);
9778   bstr = SPEC_BSTR (etype);
9779
9780   MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9781
9782   /* if the bit lenth is less than or    */
9783   /* it exactly fits a byte then         */
9784   if (SPEC_BLEN (etype) <= 8)
9785     {
9786       unsigned char mask = ((unsigned char) (0xFF << (blen + bstr)) |
9787                             (unsigned char) (0xFF >> (8 - bstr)));
9788       shCount = SPEC_BSTR (etype);
9789       
9790       /* shift left acc */
9791       AccLsh (shCount);
9792
9793       if (SPEC_BLEN (etype) < 8)
9794         {                       /* if smaller than a byte */
9795
9796           emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9797
9798           switch (p_type)
9799             {
9800             case POINTER:
9801               emitcode ("mov", "b,a");
9802               emitcode ("mov", "a,@%s", rname);
9803               break;
9804
9805             case FPOINTER:
9806               emitcode ("mov", "b,a");
9807               emitcode ("movx", "a,@dptr");
9808               break;
9809
9810             case GPOINTER:
9811               emitcode ("push", "b");
9812               emitcode ("push", "acc");
9813               emitcode ("lcall", "__gptrget");
9814               emitcode ("pop", "b");
9815               break;
9816             }
9817
9818           emitcode ("anl", "a,#!constbyte", mask);
9819           emitcode ("orl", "a,b");
9820           if (p_type == GPOINTER)
9821             emitcode ("pop", "b");
9822         }
9823     }
9824
9825   switch (p_type)
9826     {
9827     case POINTER:
9828       emitcode ("mov", "@%s,a", rname);
9829       break;
9830
9831     case FPOINTER:
9832       emitcode ("movx", "@dptr,a");
9833       break;
9834
9835     case GPOINTER:
9836       emitcode ("lcall", "__gptrput");
9837       break;
9838     }
9839
9840   /* if we r done */
9841   if (SPEC_BLEN (etype) <= 8)
9842     return;
9843
9844   emitcode ("inc", "%s", rname);
9845   rLen = SPEC_BLEN (etype);
9846
9847   /* now generate for lengths greater than one byte */
9848   while (1)
9849     {
9850
9851       l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL);
9852
9853       rLen -= 8;
9854       if (rLen < 8)
9855         break;
9856
9857       switch (p_type)
9858         {
9859         case POINTER:
9860           if (*l == '@')
9861             {
9862               MOVA (l);
9863               emitcode ("mov", "@%s,a", rname);
9864             }
9865           else
9866             emitcode ("mov", "@%s,%s", rname, l);
9867           break;
9868
9869         case FPOINTER:
9870           MOVA (l);
9871           emitcode ("movx", "@dptr,a");
9872           break;
9873
9874         case GPOINTER:
9875           MOVA (l);
9876           emitcode ("lcall", "__gptrput");
9877           break;
9878         }
9879       emitcode ("inc", "%s", rname);
9880     }
9881
9882   MOVA (l);
9883
9884   /* last last was not complete */
9885   if (rLen)
9886     {
9887       emitcode ("anl", "a,#!constbyte",
9888                 (~(((unsigned char) -1 << rLen) & 0xff)) & 0xff);
9889
9890       /* save the byte & read byte */
9891       switch (p_type)
9892         {
9893         case POINTER:
9894           emitcode ("mov", "b,a");
9895           emitcode ("mov", "a,@%s", rname);
9896           break;
9897
9898         case FPOINTER:
9899           emitcode ("mov", "b,a");
9900           emitcode ("movx", "a,@dptr");
9901           break;
9902
9903         case GPOINTER:
9904           emitcode ("push", "b");
9905           emitcode ("push", "acc");
9906           emitcode ("lcall", "__gptrget");
9907           emitcode ("pop", "b");
9908           break;
9909         }
9910
9911       emitcode ("anl", "a,#!constbyte", (((unsigned char) -1 << rLen) & 0xff));
9912       emitcode ("orl", "a,b");
9913     }
9914
9915   if (p_type == GPOINTER)
9916     emitcode ("pop", "b");
9917
9918   switch (p_type)
9919     {
9920
9921     case POINTER:
9922       emitcode ("mov", "@%s,a", rname);
9923       break;
9924
9925     case FPOINTER:
9926       emitcode ("movx", "@dptr,a");
9927       break;
9928
9929     case GPOINTER:
9930       emitcode ("lcall", "__gptrput");
9931       break;
9932     }
9933 }
9934 /*-----------------------------------------------------------------*/
9935 /* genDataPointerSet - remat pointer to data space                 */
9936 /*-----------------------------------------------------------------*/
9937 static void
9938 genDataPointerSet (operand * right,
9939                    operand * result,
9940                    iCode * ic)
9941 {
9942   int size, offset = 0;
9943   char *l, buff[256];
9944
9945   aopOp (right, ic, FALSE, FALSE);
9946
9947   l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9948   size = AOP_SIZE (right);
9949   while (size--)
9950     {
9951       if (offset)
9952         {
9953             SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9954         }
9955       else
9956         {
9957             SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9958         }
9959         
9960       emitcode ("mov", "%s,%s", buff,
9961                 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9962     }
9963
9964   freeAsmop (right, NULL, ic, TRUE);
9965   freeAsmop (result, NULL, ic, TRUE);
9966 }
9967
9968 /*-----------------------------------------------------------------*/
9969 /* genNearPointerSet - emitcode for near pointer put                */
9970 /*-----------------------------------------------------------------*/
9971 static void
9972 genNearPointerSet (operand * right,
9973                    operand * result,
9974                    iCode * ic,
9975                    iCode * pi)
9976 {
9977   asmop *aop = NULL;
9978   char *rname, *l;
9979   sym_link *retype, *letype;
9980   sym_link *ptype = operandType (result);
9981
9982   retype = getSpec (operandType (right));
9983   letype = getSpec (ptype);
9984
9985   aopOp (result, ic, FALSE, FALSE);
9986
9987   /* if the result is rematerializable &
9988      in data space & not a bit variable */
9989   if (AOP_TYPE (result) == AOP_IMMD &&
9990       DCL_TYPE (ptype) == POINTER &&
9991       !IS_BITVAR (retype) &&
9992       !IS_BITVAR (letype))
9993     {
9994       genDataPointerSet (right, result, ic);
9995       return;
9996     }
9997
9998   /* if the value is already in a pointer register
9999      then don't need anything more */
10000   if (!AOP_INPREG (AOP (result)))
10001     {
10002       /* otherwise get a free pointer register */
10003       regs *preg;
10004         
10005       aop = newAsmop (0);
10006       preg = getFreePtr (ic, &aop, FALSE);
10007       emitcode ("mov", "%s,%s",
10008                 preg->name,
10009                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10010       rname = preg->name;
10011     }
10012   else
10013     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10014
10015   aopOp (right, ic, FALSE, FALSE);
10016
10017   /* if bitfield then unpack the bits */
10018   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10019     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10020   else
10021     {
10022       /* we have can just get the values */
10023       int size = AOP_SIZE (right);
10024       int offset = 0;
10025
10026       while (size--)
10027         {
10028           l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10029           if (*l == '@')
10030             {
10031               MOVA (l);
10032               emitcode ("mov", "@%s,a", rname);
10033             }
10034           else
10035             emitcode ("mov", "@%s,%s", rname, l);
10036           if (size || pi)
10037             emitcode ("inc", "%s", rname);
10038           offset++;
10039         }
10040     }
10041
10042   /* now some housekeeping stuff */
10043   if (aop)
10044     {
10045       /* we had to allocate for this iCode */
10046       if (pi) aopPut (AOP (result),rname,0);
10047       freeAsmop (NULL, aop, ic, TRUE);
10048     }
10049   else
10050     {
10051       /* we did not allocate which means left
10052          already in a pointer register, then
10053          if size > 0 && this could be used again
10054          we have to point it back to where it
10055          belongs */
10056       if (AOP_SIZE (right) > 1 &&
10057           !OP_SYMBOL (result)->remat &&
10058           (OP_SYMBOL (result)->liveTo > ic->seq ||
10059            ic->depth) &&
10060           !pi)
10061         {
10062           int size = AOP_SIZE (right) - 1;
10063           while (size--)
10064             emitcode ("dec", "%s", rname);
10065         }
10066     }
10067
10068   /* done */
10069   if (pi) pi->generated = 1;
10070   freeAsmop (result, NULL, ic, TRUE);
10071   freeAsmop (right, NULL, ic, TRUE);
10072
10073
10074 }
10075
10076 /*-----------------------------------------------------------------*/
10077 /* genPagedPointerSet - emitcode for Paged pointer put             */
10078 /*-----------------------------------------------------------------*/
10079 static void
10080 genPagedPointerSet (operand * right,
10081                     operand * result,
10082                     iCode * ic,
10083                     iCode *pi)
10084 {
10085   asmop *aop = NULL;
10086   char *rname;
10087   sym_link *retype, *letype;
10088
10089   retype = getSpec (operandType (right));
10090   letype = getSpec (operandType (result));
10091
10092   aopOp (result, ic, FALSE, FALSE);
10093
10094   /* if the value is already in a pointer register
10095      then don't need anything more */
10096   if (!AOP_INPREG (AOP (result)))
10097     {
10098       /* otherwise get a free pointer register */
10099       regs *preg;
10100         
10101       aop = newAsmop (0);
10102       preg = getFreePtr (ic, &aop, FALSE);
10103       emitcode ("mov", "%s,%s",
10104                 preg->name,
10105                 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10106       rname = preg->name;
10107     }
10108   else
10109     rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10110
10111   aopOp (right, ic, FALSE, FALSE);
10112
10113   /* if bitfield then unpack the bits */
10114   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10115     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10116   else
10117     {
10118       /* we have can just get the values */
10119       int size = AOP_SIZE (right);
10120       int offset = 0;
10121
10122       while (size--)
10123         {
10124           MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10125
10126           emitcode ("movx", "@%s,a", rname);
10127
10128           if (size || pi)
10129             emitcode ("inc", "%s", rname);
10130
10131           offset++;
10132         }
10133     }
10134
10135   /* now some housekeeping stuff */
10136   if (aop)
10137     {
10138       if (pi) aopPut (AOP (result),rname,0);
10139       /* we had to allocate for this iCode */
10140       freeAsmop (NULL, aop, ic, TRUE);
10141     }
10142   else
10143     {
10144       /* we did not allocate which means left
10145          already in a pointer register, then
10146          if size > 0 && this could be used again
10147          we have to point it back to where it
10148          belongs */
10149       if (AOP_SIZE (right) > 1 &&
10150           !OP_SYMBOL (result)->remat &&
10151           (OP_SYMBOL (result)->liveTo > ic->seq ||
10152            ic->depth) &&
10153           !pi)
10154         {
10155           int size = AOP_SIZE (right) - 1;
10156           while (size--)
10157             emitcode ("dec", "%s", rname);
10158         }
10159     }
10160
10161   /* done */
10162   if (pi) pi->generated = 1;
10163   freeAsmop (result, NULL, ic, TRUE);
10164   freeAsmop (right, NULL, ic, TRUE);
10165
10166
10167 }
10168
10169 /*-----------------------------------------------------------------*/
10170 /* genFarPointerSet - set value from far space                     */
10171 /*-----------------------------------------------------------------*/
10172 static void
10173 genFarPointerSet (operand * right,
10174                   operand * result, iCode * ic, iCode *pi)
10175 {
10176   int size, offset, dopi=1;
10177   sym_link *retype = getSpec (operandType (right));
10178   sym_link *letype = getSpec (operandType (result));
10179
10180   aopOp (result, ic, FALSE, FALSE);
10181
10182   /* if the operand is already in dptr
10183      then we do nothing else we move the value to dptr */
10184   if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10185     {
10186       /* if this is remateriazable */
10187       if (AOP_TYPE (result) == AOP_IMMD)
10188         emitcode ("mov", "dptr,%s", 
10189                   aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10190       else
10191         {
10192           /* we need to get it byte by byte */
10193           _startLazyDPSEvaluation ();
10194           if (AOP_TYPE (result) != AOP_DPTR)
10195             {
10196               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10197               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10198               if (options.model == MODEL_FLAT24)
10199                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10200             }
10201           else
10202             {
10203               /* We need to generate a load to DPTR indirect through DPTR. */
10204               D (emitcode (";", "genFarPointerSet -- indirection special case."););
10205                 
10206               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10207               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10208               if (options.model == MODEL_FLAT24)
10209                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10210               emitcode ("pop", "dph");
10211               emitcode ("pop", "dpl");
10212               dopi=0;
10213             }
10214           _endLazyDPSEvaluation ();
10215         }
10216     }
10217   /* so dptr know contains the address */
10218   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10219
10220   /* if bit then unpack */
10221   if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10222       if (AOP_INDPTRn(result)) {
10223           genSetDPTR(AOP(result)->aopu.dptr);
10224       }
10225       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10226       if (AOP_INDPTRn(result)) {
10227           genSetDPTR(0);
10228       }
10229   } else {
10230       size = AOP_SIZE (right);
10231       offset = 0;
10232       if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10233           while (size--) {
10234               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10235               
10236               genSetDPTR(AOP(result)->aopu.dptr);
10237               emitcode ("movx", "@dptr,a");
10238               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10239                   emitcode ("inc", "dptr");
10240               genSetDPTR (0);
10241           }
10242       } else {
10243           _startLazyDPSEvaluation ();
10244           while (size--) {
10245               MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10246               
10247               if (AOP_INDPTRn(result)) {
10248                   genSetDPTR(AOP(result)->aopu.dptr);
10249               } else {
10250                   genSetDPTR (0);
10251               }
10252               _flushLazyDPS ();
10253               
10254               emitcode ("movx", "@dptr,a");
10255               if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10256                   emitcode ("inc", "dptr");
10257           }
10258           _endLazyDPSEvaluation ();
10259       }
10260   }
10261   
10262   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10263       if (!AOP_INDPTRn(result)) {
10264           _startLazyDPSEvaluation ();
10265           
10266           aopPut (AOP(result),"dpl",0);
10267           aopPut (AOP(result),"dph",1);
10268           if (options.model == MODEL_FLAT24)
10269               aopPut (AOP(result),"dpx",2);
10270
10271           _endLazyDPSEvaluation ();
10272       }
10273       pi->generated=1;
10274   } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) && 
10275              AOP_SIZE(right) > 1 &&
10276              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10277       
10278       size = AOP_SIZE (right) - 1;
10279       if (AOP_INDPTRn(result)) {
10280           genSetDPTR(AOP(result)->aopu.dptr);
10281       } 
10282       while (size--) emitcode ("lcall","__decdptr");
10283       if (AOP_INDPTRn(result)) {
10284           genSetDPTR(0);
10285       }
10286   }
10287   freeAsmop (result, NULL, ic, TRUE);
10288   freeAsmop (right, NULL, ic, TRUE);
10289 }
10290
10291 /*-----------------------------------------------------------------*/
10292 /* genGenPointerSet - set value from generic pointer space         */
10293 /*-----------------------------------------------------------------*/
10294 static void
10295 genGenPointerSet (operand * right,
10296                   operand * result, iCode * ic, iCode *pi)
10297 {
10298   int size, offset;
10299   sym_link *retype = getSpec (operandType (right));
10300   sym_link *letype = getSpec (operandType (result));
10301
10302   aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10303
10304   /* if the operand is already in dptr
10305      then we do nothing else we move the value to dptr */
10306   if (AOP_TYPE (result) != AOP_STR)
10307     {
10308       _startLazyDPSEvaluation ();
10309       /* if this is remateriazable */
10310       if (AOP_TYPE (result) == AOP_IMMD)
10311         {
10312           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10313           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
10314           {
10315               MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10316           }
10317           else
10318           {
10319               emitcode ("mov", 
10320                         "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10321           }
10322         }
10323       else
10324         {                       /* we need to get it byte by byte */
10325           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10326           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10327           if (options.model == MODEL_FLAT24) {
10328             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10329             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10330           } else {
10331             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10332           }
10333         }
10334       _endLazyDPSEvaluation ();
10335     }
10336   /* so dptr + b now contains the address */
10337   _G.bInUse++;
10338   aopOp (right, ic, FALSE, TRUE);
10339   _G.bInUse--;
10340     
10341
10342   /* if bit then unpack */
10343   if (IS_BITVAR (retype) || IS_BITVAR (letype))
10344     {
10345         genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10346     }
10347   else
10348     {
10349         size = AOP_SIZE (right);
10350         offset = 0;
10351
10352         _startLazyDPSEvaluation ();
10353         while (size--)
10354         {
10355             if (size)
10356             {
10357                 // Set two bytes at a time, passed in _AP & A.
10358                 // dptr will be incremented ONCE by __gptrputWord.
10359                 //
10360                 // Note: any change here must be coordinated
10361                 // with the implementation of __gptrputWord
10362                 // in device/lib/_gptrput.c
10363                 emitcode("mov", "_ap, %s", 
10364                          aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10365                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10366                 
10367                 genSetDPTR (0);
10368                 _flushLazyDPS ();
10369                 emitcode ("lcall", "__gptrputWord");
10370                 size--;
10371             }
10372             else
10373             {
10374                 // Only one byte to put.
10375                 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10376
10377                 genSetDPTR (0);
10378                 _flushLazyDPS ();               
10379                 emitcode ("lcall", "__gptrput");
10380             }
10381             
10382             if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10383             {
10384                 emitcode ("inc", "dptr");
10385             }
10386         }
10387         _endLazyDPSEvaluation ();
10388     }
10389
10390   if (pi && AOP_TYPE (result) != AOP_IMMD) {
10391       _startLazyDPSEvaluation ();
10392       
10393       aopPut (AOP(result),"dpl",0);
10394       aopPut (AOP(result),"dph",1);
10395       if (options.model == MODEL_FLAT24) {
10396           aopPut (AOP(result),"dpx",2);
10397           aopPut (AOP(result),"b",3);
10398       } else {
10399           aopPut (AOP(result),"b",2);
10400       }
10401       _endLazyDPSEvaluation ();
10402       
10403       pi->generated=1;
10404   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10405              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10406       
10407       size = AOP_SIZE (right) - 1;
10408       while (size--) emitcode ("lcall","__decdptr");
10409   }
10410   freeAsmop (result, NULL, ic, TRUE);
10411   freeAsmop (right, NULL, ic, TRUE);
10412 }
10413
10414 /*-----------------------------------------------------------------*/
10415 /* genPointerSet - stores the value into a pointer location        */
10416 /*-----------------------------------------------------------------*/
10417 static void
10418 genPointerSet (iCode * ic, iCode *pi)
10419 {
10420   operand *right, *result;
10421   sym_link *type, *etype;
10422   int p_type;
10423
10424   D (emitcode (";", "genPointerSet "););
10425
10426   right = IC_RIGHT (ic);
10427   result = IC_RESULT (ic);
10428
10429   /* depending on the type of pointer we need to
10430      move it to the correct pointer register */
10431   type = operandType (result);
10432   etype = getSpec (type);
10433   /* if left is of type of pointer then it is simple */
10434   if (IS_PTR (type) && !IS_FUNC (type->next))
10435     {
10436       p_type = DCL_TYPE (type);
10437     }
10438   else
10439     {
10440       /* we have to go by the storage class */
10441       p_type = PTR_TYPE (SPEC_OCLS (etype));
10442     }
10443   /* special case when cast remat */
10444   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10445       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10446           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10447           type = operandType (result);
10448           p_type = DCL_TYPE (type);
10449   }
10450
10451   /* now that we have the pointer type we assign
10452      the pointer values */
10453   switch (p_type)
10454     {
10455
10456     case POINTER:
10457     case IPOINTER:
10458       genNearPointerSet (right, result, ic, pi);
10459       break;
10460
10461     case PPOINTER:
10462       genPagedPointerSet (right, result, ic, pi);
10463       break;
10464
10465     case FPOINTER:
10466       genFarPointerSet (right, result, ic, pi);
10467       break;
10468
10469     case GPOINTER:
10470       genGenPointerSet (right, result, ic, pi);
10471       break;
10472
10473     default:
10474       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10475               "genPointerSet: illegal pointer type");
10476     }
10477
10478 }
10479
10480 /*-----------------------------------------------------------------*/
10481 /* genIfx - generate code for Ifx statement                        */
10482 /*-----------------------------------------------------------------*/
10483 static void
10484 genIfx (iCode * ic, iCode * popIc)
10485 {
10486   operand *cond = IC_COND (ic);
10487   int isbit = 0;
10488
10489   D (emitcode (";", "genIfx "););
10490
10491   aopOp (cond, ic, FALSE, FALSE);
10492
10493   /* get the value into acc */
10494   if (AOP_TYPE (cond) != AOP_CRY)
10495     {
10496         toBoolean (cond);
10497     }
10498   else
10499     {
10500         isbit = 1;
10501     }
10502     
10503   /* the result is now in the accumulator */
10504   freeAsmop (cond, NULL, ic, TRUE);
10505
10506   /* if there was something to be popped then do it */
10507   if (popIc)
10508     genIpop (popIc);
10509
10510   /* if the condition is  a bit variable */
10511   if (isbit && IS_ITEMP (cond) &&
10512       SPIL_LOC (cond))
10513     {
10514         genIfxJump (ic, SPIL_LOC (cond)->rname);
10515     }
10516   else if (isbit && !IS_ITEMP (cond))
10517     {
10518         genIfxJump (ic, OP_SYMBOL (cond)->rname);
10519     }
10520   else
10521     {
10522         genIfxJump (ic, "a");
10523     }
10524
10525   ic->generated = 1;
10526 }
10527
10528 /*-----------------------------------------------------------------*/
10529 /* genAddrOf - generates code for address of                       */
10530 /*-----------------------------------------------------------------*/
10531 static void
10532 genAddrOf (iCode * ic)
10533 {
10534   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10535   int size, offset;
10536
10537   D (emitcode (";", "genAddrOf ");
10538     );
10539
10540   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10541
10542   /* if the operand is on the stack then we
10543      need to get the stack offset of this
10544      variable */
10545   if (sym->onStack) {
10546       
10547       /* if 10 bit stack */
10548       if (options.stack10bit) {
10549           char buff[10];
10550           int  offset;
10551           
10552           tsprintf(buff, sizeof(buff), 
10553                    "#!constbyte",(options.stack_loc >> 16) & 0xff);
10554           /* if it has an offset then we need to compute it */
10555 /*        emitcode ("subb", "a,#!constbyte", */
10556 /*                  -((sym->stack < 0) ? */
10557 /*                    ((short) (sym->stack - _G.nRegsSaved)) : */
10558 /*                    ((short) sym->stack)) & 0xff); */
10559 /*        emitcode ("mov","b,a"); */
10560 /*        emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10561 /*                                       ((short) (sym->stack - _G.nRegsSaved)) : */
10562 /*                                       ((short) sym->stack)) >> 8) & 0xff); */
10563           if (sym->stack) {
10564               emitcode ("mov", "a,_bpx");
10565               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10566                                              ((char) (sym->stack - _G.nRegsSaved)) :
10567                                              ((char) sym->stack )) & 0xff);
10568               emitcode ("mov", "b,a");
10569               emitcode ("mov", "a,_bpx+1");
10570               
10571               offset = (((sym->stack < 0) ? 
10572                          ((short) (sym->stack - _G.nRegsSaved)) :
10573                          ((short) sym->stack )) >> 8) & 0xff;
10574           
10575               emitcode ("addc","a,#!constbyte", offset);
10576
10577               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10578               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10579               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10580           } else {
10581               /* we can just move _bp */
10582               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10583               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10584               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10585           }       
10586       } else {
10587           /* if it has an offset then we need to compute it */
10588           if (sym->stack) {
10589               emitcode ("mov", "a,_bp");
10590               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10591               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10592           } else {
10593               /* we can just move _bp */
10594               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10595           }
10596           /* fill the result with zero */
10597           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10598           
10599           
10600           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10601               fprintf (stderr,
10602                        "*** warning: pointer to stack var truncated.\n");
10603           }
10604
10605           offset = 1;
10606           while (size--) {
10607               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10608           }      
10609       }
10610       goto release;
10611   }
10612
10613   /* object not on stack then we need the name */
10614   size = AOP_SIZE (IC_RESULT (ic));
10615   offset = 0;
10616
10617   while (size--)
10618     {
10619       char s[SDCC_NAME_MAX];
10620       if (offset) {
10621           switch (offset) {
10622           case 1:
10623               tsprintf(s, sizeof(s), "#!his",sym->rname);
10624               break;
10625           case 2:
10626               tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10627               break;
10628           case 3:
10629               tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10630               break;
10631           default: /* should not need this (just in case) */
10632               SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10633                        sym->rname,
10634                        offset * 8);
10635           }
10636       } 
10637       else
10638       {
10639           SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10640       }
10641         
10642       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10643     }
10644
10645 release:
10646   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10647
10648 }
10649
10650 #if 0 // obsolete, and buggy for != xdata
10651 /*-----------------------------------------------------------------*/
10652 /* genArrayInit - generates code for address of                       */
10653 /*-----------------------------------------------------------------*/
10654 static void
10655 genArrayInit (iCode * ic)
10656 {
10657     literalList *iLoop;
10658     int         ix, count;
10659     int         elementSize = 0, eIndex;
10660     unsigned    val, lastVal;
10661     sym_link    *type;
10662     operand     *left=IC_LEFT(ic);
10663     
10664     D (emitcode (";", "genArrayInit "););
10665
10666     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10667     
10668     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10669     {
10670         // Load immediate value into DPTR.
10671         emitcode("mov", "dptr, %s",
10672              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10673     }
10674     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10675     {
10676 #if 0
10677       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10678               "Unexpected operand to genArrayInit.\n");
10679       exit(1);
10680 #else
10681       // a regression because of SDCCcse.c:1.52
10682       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10683       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10684       if (options.model == MODEL_FLAT24)
10685         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10686 #endif
10687     }
10688     
10689     type = operandType(IC_LEFT(ic));
10690     
10691     if (type && type->next)
10692     {
10693         elementSize = getSize(type->next);
10694     }
10695     else
10696     {
10697         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10698                                 "can't determine element size in genArrayInit.\n");
10699         exit(1);
10700     }
10701     
10702     iLoop = IC_ARRAYILIST(ic);
10703     lastVal = 0xffff;
10704     
10705     while (iLoop)
10706     {
10707         bool firstpass = TRUE;
10708         
10709         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10710                  iLoop->count, (int)iLoop->literalValue, elementSize);
10711         
10712         ix = iLoop->count;
10713         
10714         while (ix)
10715         {
10716             symbol *tlbl = NULL;
10717             
10718             count = ix > 256 ? 256 : ix;
10719             
10720             if (count > 1)
10721             {
10722                 tlbl = newiTempLabel (NULL);
10723                 if (firstpass || (count & 0xff))
10724                 {
10725                     emitcode("mov", "b, #!constbyte", count & 0xff);
10726                 }
10727                 
10728                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10729             }
10730             
10731             firstpass = FALSE;
10732                 
10733             for (eIndex = 0; eIndex < elementSize; eIndex++)
10734             {
10735                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10736                 if (val != lastVal)
10737                 {
10738                     emitcode("mov", "a, #!constbyte", val);
10739                     lastVal = val;
10740                 }
10741                 
10742                 emitcode("movx", "@dptr, a");
10743                 emitcode("inc", "dptr");
10744             }
10745             
10746             if (count > 1)
10747             {
10748                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10749             }
10750             
10751             ix -= count;
10752         }
10753         
10754         iLoop = iLoop->next;
10755     }
10756     
10757     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10758 }
10759 #endif
10760
10761 /*-----------------------------------------------------------------*/
10762 /* genFarFarAssign - assignment when both are in far space         */
10763 /*-----------------------------------------------------------------*/
10764 static void
10765 genFarFarAssign (operand * result, operand * right, iCode * ic)
10766 {
10767   int size = AOP_SIZE (right);
10768   int offset = 0;
10769   symbol *rSym = NULL;
10770
10771   if (size == 1)
10772   {
10773       /* quick & easy case. */
10774       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10775       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10776       freeAsmop (right, NULL, ic, FALSE);
10777       /* now assign DPTR to result */
10778       _G.accInUse++;
10779       aopOp(result, ic, FALSE, FALSE);
10780       _G.accInUse--;
10781       aopPut(AOP(result), "a", 0);
10782       freeAsmop(result, NULL, ic, FALSE);
10783       return;
10784   }
10785   
10786   /* See if we've got an underlying symbol to abuse. */
10787   if (IS_SYMOP(result) && OP_SYMBOL(result))
10788   {
10789       if (IS_TRUE_SYMOP(result))
10790       {
10791           rSym = OP_SYMBOL(result);
10792       }
10793       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10794       {
10795           rSym = OP_SYMBOL(result)->usl.spillLoc;
10796       }
10797   }
10798              
10799   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10800   {
10801       /* We can use the '390 auto-toggle feature to good effect here. */
10802       
10803       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10804       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10805       emitcode ("mov", "dptr,#%s", rSym->rname); 
10806       /* DP2 = result, DP1 = right, DP1 is current. */
10807       while (size)
10808       {
10809           emitcode("movx", "a,@dptr");
10810           emitcode("movx", "@dptr,a");
10811           if (--size)
10812           {
10813                emitcode("inc", "dptr");
10814                emitcode("inc", "dptr");
10815           }
10816       }
10817       emitcode("mov", "dps,#0");
10818       freeAsmop (right, NULL, ic, FALSE);
10819 #if 0
10820 some alternative code for processors without auto-toggle
10821 no time to test now, so later well put in...kpb
10822         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10823         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10824         emitcode ("mov", "dptr,#%s", rSym->rname); 
10825         /* DP2 = result, DP1 = right, DP1 is current. */
10826         while (size)
10827         {
10828           --size;
10829           emitcode("movx", "a,@dptr");
10830           if (size)
10831             emitcode("inc", "dptr");
10832           emitcode("inc", "dps");
10833           emitcode("movx", "@dptr,a");
10834           if (size)
10835             emitcode("inc", "dptr");
10836           emitcode("inc", "dps");
10837         }
10838         emitcode("mov", "dps,#0");
10839         freeAsmop (right, NULL, ic, FALSE);
10840 #endif
10841   }
10842   else
10843   {
10844       D (emitcode (";", "genFarFarAssign"););
10845       aopOp (result, ic, TRUE, TRUE);
10846
10847       _startLazyDPSEvaluation ();
10848       
10849       while (size--)
10850         {
10851           aopPut (AOP (result),
10852                   aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10853           offset++;
10854         }
10855       _endLazyDPSEvaluation ();
10856       freeAsmop (result, NULL, ic, FALSE);
10857       freeAsmop (right, NULL, ic, FALSE);
10858   }
10859 }
10860
10861 /*-----------------------------------------------------------------*/
10862 /* genAssign - generate code for assignment                        */
10863 /*-----------------------------------------------------------------*/
10864 static void
10865 genAssign (iCode * ic)
10866 {
10867   operand *result, *right;
10868   int size, offset;
10869   unsigned long lit = 0L;
10870
10871   D (emitcode (";", "genAssign ");
10872     );
10873
10874   result = IC_RESULT (ic);
10875   right = IC_RIGHT (ic);
10876
10877   /* if they are the same */
10878   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10879     return;
10880
10881   aopOp (right, ic, FALSE, FALSE);
10882
10883   emitcode (";", "genAssign: resultIsFar = %s",
10884             isOperandInFarSpace (result) ?
10885             "TRUE" : "FALSE");
10886
10887   /* special case both in far space */
10888   if ((AOP_TYPE (right) == AOP_DPTR ||
10889        AOP_TYPE (right) == AOP_DPTR2) &&
10890   /* IS_TRUE_SYMOP(result)       && */
10891       isOperandInFarSpace (result))
10892     {
10893       genFarFarAssign (result, right, ic);
10894       return;
10895     }
10896
10897   aopOp (result, ic, TRUE, FALSE);
10898
10899   /* if they are the same registers */
10900   if (sameRegs (AOP (right), AOP (result)))
10901     goto release;
10902
10903   /* if the result is a bit */
10904   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10905     {
10906       /* if the right size is a literal then
10907          we know what the value is */
10908       if (AOP_TYPE (right) == AOP_LIT)
10909         {
10910           if (((int) operandLitValue (right)))
10911             aopPut (AOP (result), one, 0);
10912           else
10913             aopPut (AOP (result), zero, 0);
10914           goto release;
10915         }
10916
10917       /* the right is also a bit variable */
10918       if (AOP_TYPE (right) == AOP_CRY)
10919         {
10920           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10921           aopPut (AOP (result), "c", 0);
10922           goto release;
10923         }
10924
10925       /* we need to or */
10926       toBoolean (right);
10927       aopPut (AOP (result), "a", 0);
10928       goto release;
10929     }
10930
10931   /* bit variables done */
10932   /* general case */
10933   size = AOP_SIZE (result);
10934   offset = 0;
10935   if (AOP_TYPE (right) == AOP_LIT)
10936     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10937
10938   if ((size > 1) &&
10939       (AOP_TYPE (result) != AOP_REG) &&
10940       (AOP_TYPE (right) == AOP_LIT) &&
10941       !IS_FLOAT (operandType (right)))
10942     {
10943       _startLazyDPSEvaluation ();
10944       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10945         {
10946           aopPut (AOP (result),
10947                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10948                   offset);
10949           offset++;
10950           size--;
10951         }
10952       /* And now fill the rest with zeros. */
10953       if (size)
10954         {
10955           emitcode ("clr", "a");
10956         }
10957       while (size--)
10958         {
10959           aopPut (AOP (result), "a", offset++);
10960         }
10961       _endLazyDPSEvaluation ();
10962     }
10963   else
10964     {
10965       _startLazyDPSEvaluation ();
10966       while (size--)
10967         {
10968           aopPut (AOP (result),
10969                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10970                   offset);
10971           offset++;
10972         }
10973       _endLazyDPSEvaluation ();
10974     }
10975
10976 release:
10977   freeAsmop (right, NULL, ic, FALSE);
10978   freeAsmop (result, NULL, ic, TRUE);
10979 }
10980
10981 /*-----------------------------------------------------------------*/
10982 /* genJumpTab - generates code for jump table                      */
10983 /*-----------------------------------------------------------------*/
10984 static void
10985 genJumpTab (iCode * ic)
10986 {
10987   symbol *jtab;
10988   char *l;
10989
10990   D (emitcode (";", "genJumpTab ");
10991     );
10992
10993   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10994   /* get the condition into accumulator */
10995   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10996   MOVA (l);
10997   /* multiply by four! */
10998   emitcode ("add", "a,acc");
10999   emitcode ("add", "a,acc");
11000   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11001
11002   jtab = newiTempLabel (NULL);
11003   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11004   emitcode ("jmp", "@a+dptr");
11005   emitcode ("", "!tlabeldef", jtab->key + 100);
11006   /* now generate the jump labels */
11007   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11008        jtab = setNextItem (IC_JTLABELS (ic)))
11009     emitcode ("ljmp", "!tlabel", jtab->key + 100);
11010
11011 }
11012
11013 /*-----------------------------------------------------------------*/
11014 /* genCast - gen code for casting                                  */
11015 /*-----------------------------------------------------------------*/
11016 static void
11017 genCast (iCode * ic)
11018 {
11019   operand *result = IC_RESULT (ic);
11020   sym_link *ctype = operandType (IC_LEFT (ic));
11021   sym_link *rtype = operandType (IC_RIGHT (ic));
11022   operand *right = IC_RIGHT (ic);
11023   int size, offset;
11024
11025   D (emitcode (";", "genCast "););
11026
11027   /* if they are equivalent then do nothing */
11028   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11029     return;
11030
11031   aopOp (right, ic, FALSE, FALSE);
11032   aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11033
11034   /* if the result is a bit */
11035   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
11036   if (IS_BITVAR(OP_SYMBOL(result)->type))
11037     {
11038       /* if the right size is a literal then
11039          we know what the value is */
11040       if (AOP_TYPE (right) == AOP_LIT)
11041         {
11042           if (((int) operandLitValue (right)))
11043             aopPut (AOP (result), one, 0);
11044           else
11045             aopPut (AOP (result), zero, 0);
11046
11047           goto release;
11048         }
11049
11050       /* the right is also a bit variable */
11051       if (AOP_TYPE (right) == AOP_CRY)
11052         {
11053           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11054           aopPut (AOP (result), "c", 0);
11055           goto release;
11056         }
11057
11058       /* we need to or */
11059       toBoolean (right);
11060       aopPut (AOP (result), "a", 0);
11061       goto release;
11062     }
11063
11064   /* if they are the same size : or less */
11065   if (AOP_SIZE (result) <= AOP_SIZE (right))
11066     {
11067
11068       /* if they are in the same place */
11069       if (sameRegs (AOP (right), AOP (result)))
11070         goto release;
11071
11072       /* if they in different places then copy */
11073       size = AOP_SIZE (result);
11074       offset = 0;
11075       _startLazyDPSEvaluation ();
11076       while (size--)
11077         {
11078           aopPut (AOP (result),
11079                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11080                   offset);
11081           offset++;
11082         }
11083       _endLazyDPSEvaluation ();
11084       goto release;
11085     }
11086
11087
11088   /* if the result is of type pointer */
11089   if (IS_PTR (ctype))
11090     {
11091
11092       int p_type;
11093       sym_link *type = operandType (right);
11094
11095       /* pointer to generic pointer */
11096       if (IS_GENPTR (ctype))
11097         {
11098           if (IS_PTR (type))
11099             {
11100               p_type = DCL_TYPE (type);
11101             }
11102           else
11103             {
11104 #if OLD_CAST_BEHAVIOR
11105               /* KV: we are converting a non-pointer type to
11106                * a generic pointer. This (ifdef'd out) code
11107                * says that the resulting generic pointer
11108                * should have the same class as the storage
11109                * location of the non-pointer variable.
11110                *
11111                * For example, converting an int (which happens
11112                * to be stored in DATA space) to a pointer results
11113                * in a DATA generic pointer; if the original int
11114                * in XDATA space, so will be the resulting pointer.
11115                *
11116                * I don't like that behavior, and thus this change:
11117                * all such conversions will be forced to XDATA and
11118                * throw a warning. If you want some non-XDATA
11119                * type, or you want to suppress the warning, you
11120                * must go through an intermediate cast, like so:
11121                *
11122                * char _generic *gp = (char _xdata *)(intVar);
11123                */
11124               sym_link *etype = getSpec (type);
11125
11126               /* we have to go by the storage class */
11127               if (SPEC_OCLS (etype) != generic)
11128                 {
11129                   p_type = PTR_TYPE (SPEC_OCLS (etype));
11130                 }
11131               else
11132 #endif
11133                 {
11134                   /* Converting unknown class (i.e. register variable)
11135                    * to generic pointer. This is not good, but
11136                    * we'll make a guess (and throw a warning).
11137                    */
11138                   p_type = FPOINTER;
11139                   werror (W_INT_TO_GEN_PTR_CAST);
11140                 }
11141             }
11142
11143           /* the first two bytes are known */
11144           size = GPTRSIZE - 1;
11145           offset = 0;
11146           _startLazyDPSEvaluation ();
11147           while (size--)
11148             {
11149               aopPut (AOP (result),
11150                       aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11151                       offset);
11152               offset++;
11153             }
11154           _endLazyDPSEvaluation ();
11155
11156           /* the last byte depending on type */
11157             {
11158                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11159                 char gpValStr[10];
11160             
11161                 if (gpVal == -1)
11162                 {
11163                     // pointerTypeToGPByte will have bitched.
11164                     exit(1);
11165                 }
11166             
11167                 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11168                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11169             }
11170           goto release;
11171         }
11172
11173       /* just copy the pointers */
11174       size = AOP_SIZE (result);
11175       offset = 0;
11176       _startLazyDPSEvaluation ();
11177       while (size--)
11178         {
11179           aopPut (AOP (result),
11180                   aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11181                   offset);
11182           offset++;
11183         }
11184       _endLazyDPSEvaluation ();
11185       goto release;
11186     }
11187
11188   /* so we now know that the size of destination is greater
11189      than the size of the source */
11190   /* we move to result for the size of source */
11191   size = AOP_SIZE (right);
11192   offset = 0;
11193   _startLazyDPSEvaluation ();
11194   while (size--)
11195     {
11196       aopPut (AOP (result),
11197               aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11198               offset);
11199       offset++;
11200     }
11201   _endLazyDPSEvaluation ();
11202
11203   /* now depending on the sign of the source && destination */
11204   size = AOP_SIZE (result) - AOP_SIZE (right);
11205   /* if unsigned or not an integral type */
11206   /* also, if the source is a bit, we don't need to sign extend, because
11207    * it can't possibly have set the sign bit.
11208    */
11209   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11210     {
11211       while (size--)
11212         {
11213           aopPut (AOP (result), zero, offset++);
11214         }
11215     }
11216   else
11217     {
11218       /* we need to extend the sign :{ */
11219       MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11220                         FALSE, FALSE, NULL));
11221       emitcode ("rlc", "a");
11222       emitcode ("subb", "a,acc");
11223       while (size--)
11224         aopPut (AOP (result), "a", offset++);
11225     }
11226
11227   /* we are done hurray !!!! */
11228
11229 release:
11230   freeAsmop (right, NULL, ic, TRUE);
11231   freeAsmop (result, NULL, ic, TRUE);
11232
11233 }
11234
11235 /*-----------------------------------------------------------------*/
11236 /* genDjnz - generate decrement & jump if not zero instrucion      */
11237 /*-----------------------------------------------------------------*/
11238 static int
11239 genDjnz (iCode * ic, iCode * ifx)
11240 {
11241   symbol *lbl, *lbl1;
11242   if (!ifx)
11243     return 0;
11244
11245   /* if the if condition has a false label
11246      then we cannot save */
11247   if (IC_FALSE (ifx))
11248     return 0;
11249
11250   /* if the minus is not of the form
11251      a = a - 1 */
11252   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11253       !IS_OP_LITERAL (IC_RIGHT (ic)))
11254     return 0;
11255
11256   if (operandLitValue (IC_RIGHT (ic)) != 1)
11257     return 0;
11258
11259   /* if the size of this greater than one then no
11260      saving */
11261   if (getSize (operandType (IC_RESULT (ic))) > 1)
11262     return 0;
11263
11264   /* otherwise we can save BIG */
11265   D(emitcode(";", "genDjnz"););
11266
11267   lbl = newiTempLabel (NULL);
11268   lbl1 = newiTempLabel (NULL);
11269
11270   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11271
11272   if (AOP_NEEDSACC(IC_RESULT(ic)))
11273   {
11274       /* If the result is accessed indirectly via
11275        * the accumulator, we must explicitly write
11276        * it back after the decrement.
11277        */
11278       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11279       
11280       if (strcmp(rByte, "a"))
11281       {
11282            /* Something is hopelessly wrong */
11283            fprintf(stderr, "*** warning: internal error at %s:%d\n",
11284                    __FILE__, __LINE__);
11285            /* We can just give up; the generated code will be inefficient,
11286             * but what the hey.
11287             */
11288            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11289            return 0;
11290       }
11291       emitcode ("dec", "%s", rByte);
11292       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11293       emitcode ("jnz", "!tlabel", lbl->key + 100);
11294   }
11295   else if (IS_AOP_PREG (IC_RESULT (ic)))
11296     {
11297       emitcode ("dec", "%s",
11298                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11299       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11300       emitcode ("jnz", "!tlabel", lbl->key + 100);
11301     }
11302   else
11303     {
11304       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11305                 lbl->key + 100);
11306     }
11307   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11308   emitcode ("", "!tlabeldef", lbl->key + 100);
11309   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11310   emitcode ("", "!tlabeldef", lbl1->key + 100);
11311
11312   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11313   ifx->generated = 1;
11314   return 1;
11315 }
11316
11317 /*-----------------------------------------------------------------*/
11318 /* genReceive - generate code for a receive iCode                  */
11319 /*-----------------------------------------------------------------*/
11320 static void
11321 genReceive (iCode * ic)
11322 {
11323     int size = getSize (operandType (IC_RESULT (ic)));
11324     int offset = 0;
11325     int rb1off ;
11326     
11327     D (emitcode (";", "genReceive "););
11328
11329     if (ic->argreg == 1) 
11330     {
11331         /* first parameter */
11332         if (AOP_IS_STR(IC_RESULT(ic)))
11333         {
11334             /* Nothing to do: it's already in the proper place. */
11335             return;
11336         }
11337         else
11338         {
11339             bool useDp2;
11340             
11341             useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11342                 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11343                  IS_TRUE_SYMOP (IC_RESULT (ic)));
11344             
11345             _G.accInUse++;
11346             aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11347             _G.accInUse--; 
11348             
11349             /* Sanity checking... */
11350             if (AOP_USESDPTR(IC_RESULT(ic)))
11351             {
11352                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11353                         "genReceive got unexpected DPTR.");
11354             }
11355             assignResultValue (IC_RESULT (ic));
11356         }
11357     } 
11358     else 
11359     { 
11360         /* second receive onwards */
11361         /* this gets a little tricky since unused recevies will be
11362          eliminated, we have saved the reg in the type field . and
11363          we use that to figure out which register to use */
11364         aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11365         rb1off = ic->argreg;
11366         while (size--) 
11367         {
11368             aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11369         }
11370     }
11371     freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11372 }
11373
11374 /*-----------------------------------------------------------------*/
11375 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
11376 /*-----------------------------------------------------------------*/
11377 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11378 {
11379     operand *from , *to , *count;
11380     symbol *lbl;
11381     bitVect *rsave;
11382     int i;
11383
11384     /* we know it has to be 3 parameters */
11385     assert (nparms == 3);
11386     
11387     rsave = newBitVect(16);
11388     /* save DPTR if it needs to be saved */
11389     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11390             if (bitVectBitValue(ic->rMask,i))
11391                     rsave = bitVectSetBit(rsave,i);
11392     }
11393     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11394                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11395     savermask(rsave);
11396     
11397     to = parms[0];
11398     from = parms[1];
11399     count = parms[2];
11400
11401     aopOp (from, ic->next, FALSE, FALSE);
11402
11403     /* get from into DPTR1 */
11404     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11405     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11406     if (options.model == MODEL_FLAT24) {
11407         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11408     }
11409
11410     freeAsmop (from, NULL, ic, FALSE);
11411     aopOp (to, ic, FALSE, FALSE);
11412     /* get "to" into DPTR */
11413     /* if the operand is already in dptr
11414        then we do nothing else we move the value to dptr */
11415     if (AOP_TYPE (to) != AOP_STR) {
11416         /* if already in DPTR then we need to push */
11417         if (AOP_TYPE(to) == AOP_DPTR) {
11418             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11419             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11420             if (options.model == MODEL_FLAT24)
11421                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11422             emitcode ("pop", "dph");
11423             emitcode ("pop", "dpl");        
11424         } else {
11425             _startLazyDPSEvaluation ();
11426             /* if this is remateriazable */
11427             if (AOP_TYPE (to) == AOP_IMMD) {
11428                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11429             } else {                    /* we need to get it byte by byte */
11430                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11431                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11432                 if (options.model == MODEL_FLAT24) {
11433                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11434                 }
11435             }
11436             _endLazyDPSEvaluation ();
11437         }
11438     }
11439     freeAsmop (to, NULL, ic, FALSE);
11440     _G.dptrInUse = _G.dptr1InUse = 1;
11441     aopOp (count, ic->next->next, FALSE,FALSE);
11442     lbl =newiTempLabel(NULL);
11443
11444     /* now for the actual copy */
11445     if (AOP_TYPE(count) == AOP_LIT && 
11446         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11447         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11448         if (fromc) {
11449             emitcode ("lcall","__bi_memcpyc2x_s");
11450         } else {
11451             emitcode ("lcall","__bi_memcpyx2x_s");
11452         }
11453         freeAsmop (count, NULL, ic, FALSE);
11454     } else {
11455         symbol *lbl1 = newiTempLabel(NULL);
11456         
11457         emitcode (";"," Auto increment but no djnz");
11458         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11459         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11460         freeAsmop (count, NULL, ic, FALSE);
11461         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11462         emitcode ("","!tlabeldef",lbl->key+100);
11463         if (fromc) {
11464             emitcode ("clr","a");
11465             emitcode ("movc", "a,@a+dptr");
11466         } else 
11467             emitcode ("movx", "a,@dptr");
11468         emitcode ("movx", "@dptr,a");
11469         emitcode ("inc", "dptr");
11470         emitcode ("inc", "dptr");
11471         emitcode ("mov","a,b");
11472         emitcode ("orl","a,_ap");
11473         emitcode ("jz","!tlabel",lbl1->key+100);
11474         emitcode ("mov","a,_ap");
11475         emitcode ("add","a,#!constbyte",0xFF);
11476         emitcode ("mov","_ap,a");
11477         emitcode ("mov","a,b");
11478         emitcode ("addc","a,#!constbyte",0xFF);
11479         emitcode ("mov","b,a");
11480         emitcode ("sjmp","!tlabel",lbl->key+100);
11481         emitcode ("","!tlabeldef",lbl1->key+100);
11482     }
11483     emitcode ("mov", "dps,#0"); 
11484     _G.dptrInUse = _G.dptr1InUse = 0;
11485     unsavermask(rsave);
11486
11487 }
11488
11489 /*-----------------------------------------------------------------*/
11490 /* genMemcmpX2X - gen code for memcmp xdata to xdata               */
11491 /*-----------------------------------------------------------------*/
11492 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11493 {
11494     operand *from , *to , *count;
11495     symbol *lbl,*lbl2;
11496     bitVect *rsave;
11497     int i;
11498
11499     /* we know it has to be 3 parameters */
11500     assert (nparms == 3);
11501     
11502     rsave = newBitVect(16);
11503     /* save DPTR if it needs to be saved */
11504     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11505             if (bitVectBitValue(ic->rMask,i))
11506                     rsave = bitVectSetBit(rsave,i);
11507     }
11508     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11509                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11510     savermask(rsave);
11511     
11512     to = parms[0];
11513     from = parms[1];
11514     count = parms[2];
11515
11516     aopOp (from, ic->next, FALSE, FALSE);
11517
11518     /* get from into DPTR1 */
11519     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11520     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11521     if (options.model == MODEL_FLAT24) {
11522         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11523     }
11524
11525     freeAsmop (from, NULL, ic, FALSE);
11526     aopOp (to, ic, FALSE, FALSE);
11527     /* get "to" into DPTR */
11528     /* if the operand is already in dptr
11529        then we do nothing else we move the value to dptr */
11530     if (AOP_TYPE (to) != AOP_STR) {
11531         /* if already in DPTR then we need to push */
11532         if (AOP_TYPE(to) == AOP_DPTR) {
11533             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11534             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11535             if (options.model == MODEL_FLAT24)
11536                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11537             emitcode ("pop", "dph");
11538             emitcode ("pop", "dpl");        
11539         } else {
11540             _startLazyDPSEvaluation ();
11541             /* if this is remateriazable */
11542             if (AOP_TYPE (to) == AOP_IMMD) {
11543                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11544             } else {                    /* we need to get it byte by byte */
11545                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11546                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11547                 if (options.model == MODEL_FLAT24) {
11548                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11549                 }
11550             }
11551             _endLazyDPSEvaluation ();
11552         }
11553     }
11554     freeAsmop (to, NULL, ic, FALSE);
11555     _G.dptrInUse = _G.dptr1InUse = 1;
11556     aopOp (count, ic->next->next, FALSE,FALSE);
11557     lbl =newiTempLabel(NULL);
11558     lbl2 =newiTempLabel(NULL);
11559
11560     /* now for the actual compare */
11561     if (AOP_TYPE(count) == AOP_LIT && 
11562         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11563         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11564         if (fromc)
11565             emitcode("lcall","__bi_memcmpc2x_s");
11566         else
11567             emitcode("lcall","__bi_memcmpx2x_s");
11568         freeAsmop (count, NULL, ic, FALSE);
11569         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11570         aopPut(AOP(IC_RESULT(ic)),"a",0);
11571         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11572     } else {
11573         symbol *lbl1 = newiTempLabel(NULL);
11574
11575         emitcode("push","ar0");         
11576         emitcode (";"," Auto increment but no djnz");
11577         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11578         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11579         freeAsmop (count, NULL, ic, FALSE);
11580         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
11581         emitcode ("","!tlabeldef",lbl->key+100);
11582         if (fromc) {
11583             emitcode ("clr","a");
11584             emitcode ("movc", "a,@a+dptr");
11585         } else 
11586             emitcode ("movx", "a,@dptr");
11587         emitcode ("mov","r0,a");
11588         emitcode ("movx", "a,@dptr");
11589         emitcode ("clr","c");
11590         emitcode ("subb","a,r0");
11591         emitcode ("jnz","!tlabel",lbl2->key+100);
11592         emitcode ("inc", "dptr");
11593         emitcode ("inc", "dptr");
11594         emitcode ("mov","a,b");
11595         emitcode ("orl","a,_ap");
11596         emitcode ("jz","!tlabel",lbl1->key+100);
11597         emitcode ("mov","a,_ap");
11598         emitcode ("add","a,#!constbyte",0xFF);
11599         emitcode ("mov","_ap,a");
11600         emitcode ("mov","a,b");
11601         emitcode ("addc","a,#!constbyte",0xFF);
11602         emitcode ("mov","b,a");
11603         emitcode ("sjmp","!tlabel",lbl->key+100);
11604         emitcode ("","!tlabeldef",lbl1->key+100);
11605         emitcode ("clr","a");
11606         emitcode ("","!tlabeldef",lbl2->key+100);
11607         aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11608         aopPut(AOP(IC_RESULT(ic)),"a",0);
11609         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11610         emitcode("pop","ar0");
11611         emitcode ("mov", "dps,#0");      
11612     }
11613     _G.dptrInUse = _G.dptr1InUse = 0;
11614     unsavermask(rsave);
11615
11616 }
11617
11618 /*-----------------------------------------------------------------*/
11619 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11620 /* port, first parameter output area second parameter pointer to   */
11621 /* port third parameter count                                      */
11622 /*-----------------------------------------------------------------*/
11623 static void genInp( iCode *ic, int nparms, operand **parms)
11624 {
11625     operand *from , *to , *count;
11626     symbol *lbl;
11627     bitVect *rsave;
11628     int i;
11629
11630     /* we know it has to be 3 parameters */
11631     assert (nparms == 3);
11632     
11633     rsave = newBitVect(16);
11634     /* save DPTR if it needs to be saved */
11635     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11636             if (bitVectBitValue(ic->rMask,i))
11637                     rsave = bitVectSetBit(rsave,i);
11638     }
11639     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11640                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11641     savermask(rsave);
11642     
11643     to = parms[0];
11644     from = parms[1];
11645     count = parms[2];
11646
11647     aopOp (from, ic->next, FALSE, FALSE);
11648
11649     /* get from into DPTR1 */
11650     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11651     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11652     if (options.model == MODEL_FLAT24) {
11653         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11654     }
11655
11656     freeAsmop (from, NULL, ic, FALSE);
11657     aopOp (to, ic, FALSE, FALSE);
11658     /* get "to" into DPTR */
11659     /* if the operand is already in dptr
11660        then we do nothing else we move the value to dptr */
11661     if (AOP_TYPE (to) != AOP_STR) {
11662         /* if already in DPTR then we need to push */
11663         if (AOP_TYPE(to) == AOP_DPTR) {
11664             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11665             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11666             if (options.model == MODEL_FLAT24)
11667                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11668             emitcode ("pop", "dph");
11669             emitcode ("pop", "dpl");        
11670         } else {
11671             _startLazyDPSEvaluation ();
11672             /* if this is remateriazable */
11673             if (AOP_TYPE (to) == AOP_IMMD) {
11674                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11675             } else {                    /* we need to get it byte by byte */
11676                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11677                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11678                 if (options.model == MODEL_FLAT24) {
11679                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11680                 }
11681             }
11682             _endLazyDPSEvaluation ();
11683         }
11684     }
11685     freeAsmop (to, NULL, ic, FALSE);
11686
11687     _G.dptrInUse = _G.dptr1InUse = 1;
11688     aopOp (count, ic->next->next, FALSE,FALSE);
11689     lbl =newiTempLabel(NULL);
11690
11691     /* now for the actual copy */
11692     if (AOP_TYPE(count) == AOP_LIT && 
11693         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11694         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11695         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11696         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11697         freeAsmop (count, NULL, ic, FALSE);
11698         emitcode ("","!tlabeldef",lbl->key+100);
11699         emitcode ("movx", "a,@dptr");   /* read data from port */
11700         emitcode ("dec","dps");         /* switch to DPTR */
11701         emitcode ("movx", "@dptr,a");   /* save into location */
11702         emitcode ("inc", "dptr");       /* point to next area */
11703         emitcode ("inc","dps");         /* switch to DPTR2 */
11704         emitcode ("djnz","b,!tlabel",lbl->key+100);
11705     } else {
11706         symbol *lbl1 = newiTempLabel(NULL);
11707         
11708         emitcode (";"," Auto increment but no djnz");
11709         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11710         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11711         freeAsmop (count, NULL, ic, FALSE);
11712         emitcode ("mov", "dps,#!constbyte",0x1);        /* Select DPTR2 */
11713         emitcode ("","!tlabeldef",lbl->key+100);
11714         emitcode ("movx", "a,@dptr");
11715         emitcode ("dec","dps");         /* switch to DPTR */
11716         emitcode ("movx", "@dptr,a");
11717         emitcode ("inc", "dptr");
11718         emitcode ("inc","dps");         /* switch to DPTR2 */
11719 /*      emitcode ("djnz","b,!tlabel",lbl->key+100); */
11720 /*      emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11721         emitcode ("mov","a,b");
11722         emitcode ("orl","a,_ap");
11723         emitcode ("jz","!tlabel",lbl1->key+100);
11724         emitcode ("mov","a,_ap");
11725         emitcode ("add","a,#!constbyte",0xFF);
11726         emitcode ("mov","_ap,a");
11727         emitcode ("mov","a,b");
11728         emitcode ("addc","a,#!constbyte",0xFF);
11729         emitcode ("mov","b,a");
11730         emitcode ("sjmp","!tlabel",lbl->key+100);
11731         emitcode ("","!tlabeldef",lbl1->key+100);
11732     }
11733     emitcode ("mov", "dps,#0"); 
11734     _G.dptrInUse = _G.dptr1InUse = 0;
11735     unsavermask(rsave);
11736
11737 }
11738
11739 /*-----------------------------------------------------------------*/
11740 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11741 /* port, first parameter output area second parameter pointer to   */
11742 /* port third parameter count                                      */
11743 /*-----------------------------------------------------------------*/
11744 static void genOutp( iCode *ic, int nparms, operand **parms)
11745 {
11746     operand *from , *to , *count;
11747     symbol *lbl;
11748     bitVect *rsave;
11749     int i;
11750
11751     /* we know it has to be 3 parameters */
11752     assert (nparms == 3);
11753     
11754     rsave = newBitVect(16);
11755     /* save DPTR if it needs to be saved */
11756     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11757             if (bitVectBitValue(ic->rMask,i))
11758                     rsave = bitVectSetBit(rsave,i);
11759     }
11760     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11761                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11762     savermask(rsave);
11763     
11764     to = parms[0];
11765     from = parms[1];
11766     count = parms[2];
11767
11768     aopOp (from, ic->next, FALSE, FALSE);
11769
11770     /* get from into DPTR1 */
11771     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11772     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11773     if (options.model == MODEL_FLAT24) {
11774         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11775     }
11776
11777     freeAsmop (from, NULL, ic, FALSE);
11778     aopOp (to, ic, FALSE, FALSE);
11779     /* get "to" into DPTR */
11780     /* if the operand is already in dptr
11781        then we do nothing else we move the value to dptr */
11782     if (AOP_TYPE (to) != AOP_STR) {
11783         /* if already in DPTR then we need to push */
11784         if (AOP_TYPE(to) == AOP_DPTR) {
11785             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11786             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11787             if (options.model == MODEL_FLAT24)
11788                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11789             emitcode ("pop", "dph");
11790             emitcode ("pop", "dpl");        
11791         } else {
11792             _startLazyDPSEvaluation ();
11793             /* if this is remateriazable */
11794             if (AOP_TYPE (to) == AOP_IMMD) {
11795                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11796             } else {                    /* we need to get it byte by byte */
11797                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11798                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11799                 if (options.model == MODEL_FLAT24) {
11800                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11801                 }
11802             }
11803             _endLazyDPSEvaluation ();
11804         }
11805     }
11806     freeAsmop (to, NULL, ic, FALSE);
11807
11808     _G.dptrInUse = _G.dptr1InUse = 1;
11809     aopOp (count, ic->next->next, FALSE,FALSE);
11810     lbl =newiTempLabel(NULL);
11811
11812     /* now for the actual copy */
11813     if (AOP_TYPE(count) == AOP_LIT && 
11814         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11815         emitcode (";","OH  JOY auto increment with djnz (very fast)");
11816         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11817         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11818         emitcode ("","!tlabeldef",lbl->key+100);
11819         emitcode ("movx", "a,@dptr");   /* read data from port */
11820         emitcode ("inc","dps");         /* switch to DPTR2 */
11821         emitcode ("movx", "@dptr,a");   /* save into location */
11822         emitcode ("inc", "dptr");       /* point to next area */
11823         emitcode ("dec","dps");         /* switch to DPTR */
11824         emitcode ("djnz","b,!tlabel",lbl->key+100);
11825         freeAsmop (count, NULL, ic, FALSE);
11826     } else {
11827         symbol *lbl1 = newiTempLabel(NULL);
11828         
11829         emitcode (";"," Auto increment but no djnz");
11830         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11831         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11832         freeAsmop (count, NULL, ic, FALSE);
11833         emitcode ("mov", "dps,#!constbyte",0x0);        /* Select DPTR */
11834         emitcode ("","!tlabeldef",lbl->key+100);
11835         emitcode ("movx", "a,@dptr");
11836         emitcode ("inc", "dptr");
11837         emitcode ("inc","dps");         /* switch to DPTR2 */
11838         emitcode ("movx", "@dptr,a");
11839         emitcode ("dec","dps");         /* switch to DPTR */
11840         emitcode ("mov","a,b");
11841         emitcode ("orl","a,_ap");
11842         emitcode ("jz","!tlabel",lbl1->key+100);
11843         emitcode ("mov","a,_ap");
11844         emitcode ("add","a,#!constbyte",0xFF);
11845         emitcode ("mov","_ap,a");
11846         emitcode ("mov","a,b");
11847         emitcode ("addc","a,#!constbyte",0xFF);
11848         emitcode ("mov","b,a");
11849         emitcode ("sjmp","!tlabel",lbl->key+100);
11850         emitcode ("","!tlabeldef",lbl1->key+100);
11851     }
11852     emitcode ("mov", "dps,#0"); 
11853     _G.dptrInUse = _G.dptr1InUse = 0;
11854     unsavermask(rsave);
11855
11856 }
11857
11858 /*-----------------------------------------------------------------*/
11859 /* genSwapW - swap lower & high order bytes                        */
11860 /*-----------------------------------------------------------------*/
11861 static void genSwapW(iCode *ic, int nparms, operand **parms)
11862 {
11863     operand *dest;
11864     operand *src;
11865     assert (nparms==1);
11866
11867     src = parms[0];
11868     dest=IC_RESULT(ic);
11869
11870     assert(getSize(operandType(src))==2);
11871
11872     aopOp (src, ic, FALSE, FALSE);
11873     emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11874     _G.accInUse++;
11875     MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11876     _G.accInUse--;
11877     freeAsmop (src, NULL, ic, FALSE);
11878     
11879     aopOp (dest,ic, FALSE, FALSE);
11880     aopPut(AOP(dest),"b",0);
11881     aopPut(AOP(dest),"a",1);
11882     freeAsmop (dest, NULL, ic, FALSE);    
11883 }
11884
11885 /*-----------------------------------------------------------------*/
11886 /* genMemsetX - gencode for memSetX data                           */
11887 /*-----------------------------------------------------------------*/
11888 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11889 {
11890     operand *to , *val , *count;
11891     symbol *lbl;
11892     char *l;
11893     int i;
11894     bitVect *rsave;
11895
11896     /* we know it has to be 3 parameters */
11897     assert (nparms == 3);
11898     
11899     to = parms[0];
11900     val = parms[1];
11901     count = parms[2];
11902         
11903     /* save DPTR if it needs to be saved */
11904     rsave = newBitVect(16);
11905     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11906             if (bitVectBitValue(ic->rMask,i))
11907                     rsave = bitVectSetBit(rsave,i);
11908     }
11909     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11910                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
11911     savermask(rsave);
11912
11913     aopOp (to, ic, FALSE, FALSE);
11914     /* get "to" into DPTR */
11915     /* if the operand is already in dptr
11916        then we do nothing else we move the value to dptr */
11917     if (AOP_TYPE (to) != AOP_STR) {
11918         /* if already in DPTR then we need to push */
11919         if (AOP_TYPE(to) == AOP_DPTR) {
11920             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11921             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11922             if (options.model == MODEL_FLAT24)
11923                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11924             emitcode ("pop", "dph");
11925             emitcode ("pop", "dpl");        
11926         } else {
11927             _startLazyDPSEvaluation ();
11928             /* if this is remateriazable */
11929             if (AOP_TYPE (to) == AOP_IMMD) {
11930                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11931             } else {                    /* we need to get it byte by byte */
11932                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11933                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11934                 if (options.model == MODEL_FLAT24) {
11935                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11936                 }
11937             }
11938             _endLazyDPSEvaluation ();
11939         }
11940     }
11941     freeAsmop (to, NULL, ic, FALSE);
11942
11943     aopOp (val, ic->next->next, FALSE,FALSE);
11944     aopOp (count, ic->next->next, FALSE,FALSE);    
11945     lbl =newiTempLabel(NULL);
11946     /* now for the actual copy */
11947     if (AOP_TYPE(count) == AOP_LIT && 
11948         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11949         l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11950         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11951         MOVA(l);
11952         emitcode ("","!tlabeldef",lbl->key+100);
11953         emitcode ("movx", "@dptr,a");
11954         emitcode ("inc", "dptr");
11955         emitcode ("djnz","b,!tlabel",lbl->key+100);
11956     } else {
11957         symbol *lbl1 = newiTempLabel(NULL);
11958         
11959         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11960         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11961         emitcode ("","!tlabeldef",lbl->key+100);
11962         MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11963         emitcode ("movx", "@dptr,a");
11964         emitcode ("inc", "dptr");
11965         emitcode ("mov","a,b");
11966         emitcode ("orl","a,_ap");
11967         emitcode ("jz","!tlabel",lbl1->key+100);
11968         emitcode ("mov","a,_ap");
11969         emitcode ("add","a,#!constbyte",0xFF);
11970         emitcode ("mov","_ap,a");
11971         emitcode ("mov","a,b");
11972         emitcode ("addc","a,#!constbyte",0xFF);
11973         emitcode ("mov","b,a");
11974         emitcode ("sjmp","!tlabel",lbl->key+100);
11975         emitcode ("","!tlabeldef",lbl1->key+100);
11976     }
11977     freeAsmop (count, NULL, ic, FALSE);
11978     unsavermask(rsave);
11979 }
11980
11981 /*-----------------------------------------------------------------*/
11982 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11983 /*-----------------------------------------------------------------*/
11984 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11985 {
11986         bitVect *rsave ;
11987         operand *pnum, *result;
11988         int i;
11989     
11990         assert (nparms==1);
11991         /* save registers that need to be saved */
11992         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11993                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11994     
11995         pnum = parms[0]; 
11996         aopOp (pnum, ic, FALSE, FALSE);
11997         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11998         freeAsmop (pnum, NULL, ic, FALSE);
11999         emitcode ("lcall","NatLib_LoadPrimitive");
12000         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12001         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
12002             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12003                 for (i = (size-1) ; i >= 0 ; i-- ) {
12004                         emitcode ("push","a%s",javaRet[i]);
12005                 }
12006                 for (i=0; i < size ; i++ ) {
12007                         emitcode ("pop","a%s",
12008                                   aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12009                 }
12010         } else {
12011                 for (i = 0 ; i < size ; i++ ) {
12012                         aopPut(AOP(result),javaRet[i],i);
12013                 }
12014         }    
12015         freeAsmop (result, NULL, ic, FALSE);
12016         unsavermask(rsave);
12017 }
12018
12019 /*-----------------------------------------------------------------*/
12020 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
12021 /*-----------------------------------------------------------------*/
12022 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12023 {
12024         bitVect *rsave ;
12025         operand *pnum, *result;
12026         int size = 3;
12027         int i;
12028     
12029         assert (nparms==1);
12030         /* save registers that need to be saved */
12031         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12032                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12033     
12034         pnum = parms[0]; 
12035         aopOp (pnum, ic, FALSE, FALSE);
12036         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12037         freeAsmop (pnum, NULL, ic, FALSE);
12038         emitcode ("lcall","NatLib_LoadPointer");
12039         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12040         if (AOP_TYPE(result)!=AOP_STR) {
12041                 for (i = 0 ; i < size ; i++ ) {
12042                         aopPut(AOP(result),fReturn[i],i);
12043                 }
12044         }    
12045         freeAsmop (result, NULL, ic, FALSE);
12046         unsavermask(rsave);
12047 }
12048
12049 /*-----------------------------------------------------------------*/
12050 /* genNatLibInstallStateBlock -                                    */
12051 /*-----------------------------------------------------------------*/
12052 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
12053                                        operand **parms, const char *name)
12054 {
12055         bitVect *rsave ;
12056         operand *psb, *handle;
12057         assert (nparms==2);
12058
12059         /* save registers that need to be saved */
12060         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12061                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12062         psb = parms[0];
12063         handle = parms[1];
12064
12065         /* put pointer to state block into DPTR1 */
12066         aopOp (psb, ic, FALSE, FALSE);
12067         if (AOP_TYPE (psb) == AOP_IMMD) {
12068                 emitcode ("mov","dps,#1");
12069                 emitcode ("mov", "dptr,%s",
12070                           aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12071                 emitcode ("mov","dps,#0");
12072         } else {
12073                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12074                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12075                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12076         }
12077         freeAsmop (psb, NULL, ic, FALSE);
12078
12079         /* put libraryID into DPTR */
12080         emitcode ("mov","dptr,#LibraryID");
12081
12082         /* put handle into r3:r2 */
12083         aopOp (handle, ic, FALSE, FALSE);
12084         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12085                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12086                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12087                 emitcode ("pop","ar3");
12088                 emitcode ("pop","ar2");
12089         } else {        
12090                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));       
12091                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12092         }
12093         freeAsmop (psb, NULL, ic, FALSE);
12094
12095         /* make the call */
12096         emitcode ("lcall","NatLib_Install%sStateBlock",name);
12097
12098         /* put return value into place*/
12099         _G.accInUse++;
12100         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12101         _G.accInUse--;
12102         aopPut(AOP(IC_RESULT(ic)),"a",0);
12103         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12104         unsavermask(rsave);
12105 }
12106
12107 /*-----------------------------------------------------------------*/
12108 /* genNatLibRemoveStateBlock -                                     */
12109 /*-----------------------------------------------------------------*/
12110 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12111 {
12112         bitVect *rsave ;
12113
12114         assert(nparms==0);
12115
12116         /* save registers that need to be saved */
12117         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12118                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12119
12120         /* put libraryID into DPTR */
12121         emitcode ("mov","dptr,#LibraryID");
12122         /* make the call */
12123         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12124         unsavermask(rsave);
12125 }
12126
12127 /*-----------------------------------------------------------------*/
12128 /* genNatLibGetStateBlock -                                        */
12129 /*-----------------------------------------------------------------*/
12130 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12131                                    operand **parms,const char *name)
12132 {
12133         bitVect *rsave ;
12134         symbol *lbl = newiTempLabel(NULL);
12135         
12136         assert(nparms==0);
12137         /* save registers that need to be saved */
12138         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12139                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12140
12141         /* put libraryID into DPTR */
12142         emitcode ("mov","dptr,#LibraryID");
12143         /* make the call */
12144         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12145         emitcode ("jnz","!tlabel",lbl->key+100);
12146
12147         /* put return value into place */
12148         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12149         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12150                 emitcode ("push","ar3");
12151                 emitcode ("push","ar2");
12152                 emitcode ("pop","%s",
12153                           aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12154                 emitcode ("pop","%s",
12155                           aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12156         } else {
12157                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12158                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12159         }
12160         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12161         emitcode ("","!tlabeldef",lbl->key+100);
12162         unsavermask(rsave);
12163 }
12164
12165 /*-----------------------------------------------------------------*/
12166 /* genMMMalloc -                                                   */
12167 /*-----------------------------------------------------------------*/
12168 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12169                          int size, const char *name)
12170 {
12171         bitVect *rsave ;
12172         operand *bsize;
12173         symbol *rsym;
12174         symbol *lbl = newiTempLabel(NULL);
12175
12176         assert (nparms == 1);
12177         /* save registers that need to be saved */
12178         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12179                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12180         
12181         bsize=parms[0];
12182         aopOp (bsize,ic,FALSE,FALSE);
12183
12184         /* put the size in R4-R2 */
12185         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12186                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12187                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12188                 if (size==3) {
12189                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12190                         emitcode("pop","ar4");
12191                 }
12192                 emitcode("pop","ar3");
12193                 emitcode("pop","ar2");          
12194         } else {
12195                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12196                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12197                 if (size==3) {
12198                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12199                 }
12200         }
12201         freeAsmop (bsize, NULL, ic, FALSE);
12202
12203         /* make the call */
12204         emitcode ("lcall","MM_%s",name);
12205         emitcode ("jz","!tlabel",lbl->key+100);
12206         emitcode ("mov","r2,#!constbyte",0xff);
12207         emitcode ("mov","r3,#!constbyte",0xff);
12208         emitcode ("","!tlabeldef",lbl->key+100);
12209         /* we don't care about the pointer : we just save the handle */
12210         rsym = OP_SYMBOL(IC_RESULT(ic));
12211         if (rsym->liveFrom != rsym->liveTo) {
12212                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12213                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12214                         emitcode ("push","ar3");
12215                         emitcode ("push","ar2");
12216                         emitcode ("pop","%s",
12217                                   aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12218                         emitcode ("pop","%s",
12219                                   aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12220                 } else {
12221                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
12222                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
12223                 }
12224                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12225         }
12226         unsavermask(rsave);
12227 }
12228
12229 /*-----------------------------------------------------------------*/
12230 /* genMMDeref -                                                    */
12231 /*-----------------------------------------------------------------*/
12232 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12233 {
12234         bitVect *rsave ;
12235         operand *handle;
12236
12237         assert (nparms == 1);
12238         /* save registers that need to be saved */
12239         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12240                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12241         
12242         handle=parms[0];
12243         aopOp (handle,ic,FALSE,FALSE);
12244
12245         /* put the size in R4-R2 */
12246         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12247                 emitcode("push","%s",
12248                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12249                 emitcode("push","%s",
12250                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12251                 emitcode("pop","ar3");
12252                 emitcode("pop","ar2");          
12253         } else {
12254                 emitcode ("mov","r2,%s",
12255                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12256                 emitcode ("mov","r3,%s",
12257                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12258         }
12259         freeAsmop (handle, NULL, ic, FALSE);
12260
12261         /* make the call */
12262         emitcode ("lcall","MM_Deref");
12263         
12264         {
12265                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12266                 if (rsym->liveFrom != rsym->liveTo) {                   
12267                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12268                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12269                             _startLazyDPSEvaluation ();
12270                             
12271                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12272                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12273                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12274
12275                             _endLazyDPSEvaluation ();
12276                             
12277                         }
12278                 }
12279         }
12280         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12281         unsavermask(rsave);
12282 }
12283
12284 /*-----------------------------------------------------------------*/
12285 /* genMMUnrestrictedPersist -                                      */
12286 /*-----------------------------------------------------------------*/
12287 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12288 {
12289         bitVect *rsave ;
12290         operand *handle;
12291
12292         assert (nparms == 1);
12293         /* save registers that need to be saved */
12294         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12295                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12296         
12297         handle=parms[0];
12298         aopOp (handle,ic,FALSE,FALSE);
12299
12300         /* put the size in R3-R2 */
12301         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12302                 emitcode("push","%s",
12303                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12304                 emitcode("push","%s",
12305                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12306                 emitcode("pop","ar3");
12307                 emitcode("pop","ar2");          
12308         } else {
12309                 emitcode ("mov","r2,%s",
12310                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12311                 emitcode ("mov","r3,%s",
12312                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12313         }
12314         freeAsmop (handle, NULL, ic, FALSE);
12315
12316         /* make the call */
12317         emitcode ("lcall","MM_UnrestrictedPersist");
12318
12319         {
12320                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12321                 if (rsym->liveFrom != rsym->liveTo) {   
12322                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12323                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12324                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12325                 }
12326         }
12327         unsavermask(rsave);
12328 }
12329
12330 /*-----------------------------------------------------------------*/
12331 /* genSystemExecJavaProcess -                                      */
12332 /*-----------------------------------------------------------------*/
12333 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12334 {
12335         bitVect *rsave ;
12336         operand *handle, *pp;
12337
12338         assert (nparms==2);
12339         /* save registers that need to be saved */
12340         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12341                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12342         
12343         pp = parms[0];
12344         handle = parms[1];
12345         
12346         /* put the handle in R3-R2 */
12347         aopOp (handle,ic,FALSE,FALSE);
12348         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12349                 emitcode("push","%s",
12350                          aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12351                 emitcode("push","%s",
12352                          aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12353                 emitcode("pop","ar3");
12354                 emitcode("pop","ar2");          
12355         } else {
12356                 emitcode ("mov","r2,%s",
12357                           aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12358                 emitcode ("mov","r3,%s",
12359                           aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12360         }
12361         freeAsmop (handle, NULL, ic, FALSE);
12362         
12363         /* put pointer in DPTR */
12364         aopOp (pp,ic,FALSE,FALSE);
12365         if (AOP_TYPE(pp) == AOP_IMMD) {
12366                 emitcode ("mov", "dptr,%s",
12367                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12368         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12369                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12370                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12371                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12372         }
12373         freeAsmop (handle, NULL, ic, FALSE);
12374
12375         /* make the call */
12376         emitcode ("lcall","System_ExecJavaProcess");
12377         
12378         /* put result in place */
12379         {
12380                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12381                 if (rsym->liveFrom != rsym->liveTo) {   
12382                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12383                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12384                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12385                 }
12386         }
12387         
12388         unsavermask(rsave);
12389 }
12390
12391 /*-----------------------------------------------------------------*/
12392 /* genSystemRTCRegisters -                                         */
12393 /*-----------------------------------------------------------------*/
12394 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12395                                   char *name)
12396 {
12397         bitVect *rsave ;
12398         operand *pp;
12399
12400         assert (nparms==1);
12401         /* save registers that need to be saved */
12402         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12403                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12404         
12405         pp=parms[0];
12406         /* put pointer in DPTR */
12407         aopOp (pp,ic,FALSE,FALSE);
12408         if (AOP_TYPE (pp) == AOP_IMMD) {
12409                 emitcode ("mov","dps,#1");
12410                 emitcode ("mov", "dptr,%s", 
12411                           aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12412                 emitcode ("mov","dps,#0");
12413         } else {
12414                 emitcode ("mov","dpl1,%s",
12415                           aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12416                 emitcode ("mov","dph1,%s",
12417                           aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12418                 emitcode ("mov","dpx1,%s",
12419                           aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12420         }
12421         freeAsmop (pp, NULL, ic, FALSE);
12422
12423         /* make the call */
12424         emitcode ("lcall","System_%sRTCRegisters",name);
12425
12426         unsavermask(rsave);
12427 }
12428
12429 /*-----------------------------------------------------------------*/
12430 /* genSystemThreadSleep -                                          */
12431 /*-----------------------------------------------------------------*/
12432 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12433 {
12434         bitVect *rsave ;
12435         operand *to, *s;
12436
12437         assert (nparms==1);
12438         /* save registers that need to be saved */
12439         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12440                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
12441
12442         to = parms[0];
12443         aopOp(to,ic,FALSE,FALSE);
12444         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12445             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12446                 emitcode ("push","%s",
12447                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12448                 emitcode ("push","%s",
12449                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12450                 emitcode ("push","%s",
12451                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12452                 emitcode ("push","%s",
12453                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12454                 emitcode ("pop","ar3");
12455                 emitcode ("pop","ar2");
12456                 emitcode ("pop","ar1");
12457                 emitcode ("pop","ar0");
12458         } else {
12459                 emitcode ("mov","r0,%s",
12460                           aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12461                 emitcode ("mov","r1,%s",
12462                           aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12463                 emitcode ("mov","r2,%s",
12464                           aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12465                 emitcode ("mov","r3,%s",
12466                           aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12467         }
12468         freeAsmop (to, NULL, ic, FALSE);
12469
12470         /* suspend in acc */
12471         s = parms[1];
12472         aopOp(s,ic,FALSE,FALSE);
12473         emitcode ("mov","a,%s",
12474                   aopGet(AOP(s),0,FALSE,TRUE,NULL));
12475         freeAsmop (s, NULL, ic, FALSE);
12476
12477         /* make the call */
12478         emitcode ("lcall","System_%s",name);
12479
12480         unsavermask(rsave);
12481 }
12482
12483 /*-----------------------------------------------------------------*/
12484 /* genSystemThreadResume -                                         */
12485 /*-----------------------------------------------------------------*/
12486 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12487 {
12488         bitVect *rsave ;
12489         operand *tid,*pid;
12490
12491         assert (nparms==2);
12492         /* save registers that need to be saved */
12493         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12494                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12495         
12496         tid = parms[0];
12497         pid = parms[1];
12498         
12499         /* PID in R0 */
12500         aopOp(pid,ic,FALSE,FALSE);
12501         emitcode ("mov","r0,%s",
12502                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12503         freeAsmop (pid, NULL, ic, FALSE);
12504         
12505         /* tid into ACC */
12506         aopOp(tid,ic,FALSE,FALSE);
12507         emitcode ("mov","a,%s",
12508                   aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12509         freeAsmop (tid, NULL, ic, FALSE);
12510         
12511         emitcode ("lcall","System_ThreadResume");
12512
12513         /* put result into place */
12514         {
12515                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12516                 if (rsym->liveFrom != rsym->liveTo) {   
12517                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12518                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12519                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12520                 }
12521         }
12522         unsavermask(rsave);
12523 }
12524
12525 /*-----------------------------------------------------------------*/
12526 /* genSystemProcessResume -                                        */
12527 /*-----------------------------------------------------------------*/
12528 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12529 {
12530         bitVect *rsave ;
12531         operand *pid;
12532
12533         assert (nparms==1);
12534         /* save registers that need to be saved */
12535         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12536                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12537         
12538         pid = parms[0];
12539         
12540         /* pid into ACC */
12541         aopOp(pid,ic,FALSE,FALSE);
12542         emitcode ("mov","a,%s",
12543                   aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12544         freeAsmop (pid, NULL, ic, FALSE);
12545         
12546         emitcode ("lcall","System_ProcessResume");
12547
12548         unsavermask(rsave);
12549 }
12550
12551 /*-----------------------------------------------------------------*/
12552 /* genSystem -                                                     */
12553 /*-----------------------------------------------------------------*/
12554 static void genSystem (iCode *ic,int nparms,char *name)
12555 {
12556         assert(nparms == 0);
12557
12558         emitcode ("lcall","System_%s",name);
12559 }
12560
12561 /*-----------------------------------------------------------------*/
12562 /* genSystemPoll -                                                  */
12563 /*-----------------------------------------------------------------*/
12564 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12565 {
12566         bitVect *rsave ;
12567         operand *fp;
12568
12569         assert (nparms==1);
12570         /* save registers that need to be saved */
12571         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12572                                          ds390_rUmaskForOp (IC_RESULT(ic))));
12573
12574         fp = parms[0];
12575         aopOp (fp,ic,FALSE,FALSE);
12576         if (AOP_TYPE (fp) == AOP_IMMD) {
12577                 emitcode ("mov", "dptr,%s", 
12578                           aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12579         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12580                 emitcode ("mov","dpl,%s",
12581                           aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12582                 emitcode ("mov","dph,%s",
12583                           aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12584                 emitcode ("mov","dpx,%s",
12585                           aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12586         }
12587         freeAsmop (fp, NULL, ic, FALSE);
12588
12589         emitcode ("lcall","System_%sPoll",name);
12590
12591         /* put result into place */
12592         {
12593                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12594                 if (rsym->liveFrom != rsym->liveTo) {   
12595                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12596                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12597                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12598                 }
12599         }
12600         unsavermask(rsave);
12601 }
12602
12603 /*-----------------------------------------------------------------*/
12604 /* genSystemGetCurrentID -                                         */
12605 /*-----------------------------------------------------------------*/
12606 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12607 {
12608         assert (nparms==0);
12609
12610         emitcode ("lcall","System_GetCurrent%sId",name);
12611         /* put result into place */
12612         {
12613                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12614                 if (rsym->liveFrom != rsym->liveTo) {   
12615                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12616                         aopPut(AOP(IC_RESULT(ic)),"a",0);
12617                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12618                 }
12619         }
12620 }
12621
12622 /*-----------------------------------------------------------------*/
12623 /* genDummyRead - generate code for dummy read of volatiles        */
12624 /*-----------------------------------------------------------------*/
12625 static void
12626 genDummyRead (iCode * ic)
12627 {
12628   operand *right;
12629   int size, offset;
12630
12631   D(emitcode(";     genDummyRead",""));
12632
12633   right = IC_RIGHT (ic);
12634
12635   aopOp (right, ic, FALSE, FALSE);
12636
12637   /* if the result is a bit */
12638   if (AOP_TYPE (right) == AOP_CRY)
12639     {
12640       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12641       goto release;
12642     }
12643
12644   /* bit variables done */
12645   /* general case */
12646   size = AOP_SIZE (right);
12647   offset = 0;
12648   while (size--)
12649     {
12650       emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12651       offset++;
12652     }
12653
12654 release:
12655   freeAsmop (right, NULL, ic, TRUE);
12656 }
12657
12658 /*-----------------------------------------------------------------*/
12659 /* genBuiltIn - calls the appropriate function to  generating code */
12660 /* for a built in function                                         */
12661 /*-----------------------------------------------------------------*/
12662 static void genBuiltIn (iCode *ic)
12663 {
12664         operand *bi_parms[MAX_BUILTIN_ARGS];
12665         int nbi_parms;
12666         iCode *bi_iCode;
12667         symbol *bif;
12668
12669         /* get all the arguments for a built in function */
12670         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12671
12672         /* which function is it */
12673         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12674         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12675                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12676         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12677                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12678         } else  if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12679                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12680         } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12681                 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12682         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12683                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12684         } else if (strcmp(bif->name,"__builtin_inp")==0) {
12685                 genInp(bi_iCode,nbi_parms,bi_parms);
12686         } else if (strcmp(bif->name,"__builtin_outp")==0) {
12687                 genOutp(bi_iCode,nbi_parms,bi_parms);
12688         } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12689                 genSwapW(bi_iCode,nbi_parms,bi_parms);
12690                 /* JavaNative builtIns */               
12691         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12692                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12693         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12694                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12695         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12696                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12697         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12698                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12699         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12700                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12701         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12702                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12703         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12704                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12705         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12706                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12707         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12708                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12709         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12710                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12711         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12712                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12713         } else if (strcmp(bif->name,"MM_Malloc")==0) {
12714                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12715         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12716                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12717         } else if (strcmp(bif->name,"MM_Free")==0) {
12718                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12719         } else if (strcmp(bif->name,"MM_Deref")==0) {
12720                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12721         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12722                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12723         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12724                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12725         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12726                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12727         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12728                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12729         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12730                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12731         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12732                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12733         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12734                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12735         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12736                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12737         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12738                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12739         } else if (strcmp(bif->name,"System_SaveThread")==0) {
12740                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12741         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12742                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12743         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12744                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12745         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12746                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12747         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12748                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12749         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12750                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12751         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12752                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12753         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12754                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12755         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12756                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12757         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12758                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12759         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12760                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12761         } else {
12762                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12763                 return ;
12764         }
12765         return ;    
12766 }
12767
12768 /*-----------------------------------------------------------------*/
12769 /* gen390Code - generate code for Dallas 390 based controllers     */
12770 /*-----------------------------------------------------------------*/
12771 void
12772 gen390Code (iCode * lic)
12773 {
12774   iCode *ic;
12775   int cln = 0;
12776
12777   lineHead = lineCurr = NULL;
12778   dptrn[1][0] = "dpl1";
12779   dptrn[1][1] = "dph1";
12780   dptrn[1][2] = "dpx1";
12781   
12782   if (options.model == MODEL_FLAT24) {
12783     fReturnSizeDS390 = 5;
12784     fReturn = fReturn24;
12785   } else {
12786     fReturnSizeDS390 = 4;
12787     fReturn = fReturn16;
12788     options.stack10bit=0;
12789   }
12790 #if 1
12791   /* print the allocation information */
12792   if (allocInfo && currFunc)
12793     printAllocInfo (currFunc, codeOutFile);
12794 #endif
12795   /* if debug information required */
12796   if (options.debug && currFunc)
12797     {
12798       debugFile->writeFunction(currFunc);
12799       _G.debugLine = 1;
12800       if (IS_STATIC (currFunc->etype))
12801         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12802       else
12803         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12804       _G.debugLine = 0;
12805     }
12806   /* stack pointer name */
12807   if (options.useXstack)
12808     spname = "_spx";
12809   else
12810     spname = "sp";
12811
12812
12813   for (ic = lic; ic; ic = ic->next)
12814     {
12815
12816       if (ic->lineno && cln != ic->lineno)
12817         {
12818           if (options.debug)
12819             {
12820               _G.debugLine = 1;
12821               emitcode ("", "C$%s$%d$%d$%d ==.",
12822                         FileBaseName (ic->filename), ic->lineno,
12823                         ic->level, ic->block);
12824               _G.debugLine = 0;
12825             }
12826           if (!options.noCcodeInAsm) {
12827             emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
12828                       printCLine(ic->filename, ic->lineno));
12829           }
12830           cln = ic->lineno;
12831         }
12832       if (options.iCodeInAsm) {
12833         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12834       }
12835       /* if the result is marked as
12836          spilt and rematerializable or code for
12837          this has already been generated then
12838          do nothing */
12839       if (resultRemat (ic) || ic->generated)
12840         continue;
12841
12842       /* depending on the operation */
12843       switch (ic->op)
12844         {
12845         case '!':
12846           genNot (ic);
12847           break;
12848
12849         case '~':
12850           genCpl (ic);
12851           break;
12852
12853         case UNARYMINUS:
12854           genUminus (ic);
12855           break;
12856
12857         case IPUSH:
12858           genIpush (ic);
12859           break;
12860
12861         case IPOP:
12862           /* IPOP happens only when trying to restore a
12863              spilt live range, if there is an ifx statement
12864              following this pop then the if statement might
12865              be using some of the registers being popped which
12866              would destory the contents of the register so
12867              we need to check for this condition and handle it */
12868           if (ic->next &&
12869               ic->next->op == IFX &&
12870               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12871             genIfx (ic->next, ic);
12872           else
12873             genIpop (ic);
12874           break;
12875
12876         case CALL:
12877           genCall (ic);
12878           break;
12879
12880         case PCALL:
12881           genPcall (ic);
12882           break;
12883
12884         case FUNCTION:
12885           genFunction (ic);
12886           break;
12887
12888         case ENDFUNCTION:
12889           genEndFunction (ic);
12890           break;
12891
12892         case RETURN:
12893           genRet (ic);
12894           break;
12895
12896         case LABEL:
12897           genLabel (ic);
12898           break;
12899
12900         case GOTO:
12901           genGoto (ic);
12902           break;
12903
12904         case '+':
12905           genPlus (ic);
12906           break;
12907
12908         case '-':
12909           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12910             genMinus (ic);
12911           break;
12912
12913         case '*':
12914           genMult (ic);
12915           break;
12916
12917         case '/':
12918           genDiv (ic);
12919           break;
12920
12921         case '%':
12922           genMod (ic);
12923           break;
12924
12925         case '>':
12926           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12927           break;
12928
12929         case '<':
12930           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12931           break;
12932
12933         case LE_OP:
12934         case GE_OP:
12935         case NE_OP:
12936
12937           /* note these two are xlated by algebraic equivalence
12938              during parsing SDCC.y */
12939           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12940                   "got '>=' or '<=' shouldn't have come here");
12941           break;
12942
12943         case EQ_OP:
12944           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12945           break;
12946
12947         case AND_OP:
12948           genAndOp (ic);
12949           break;
12950
12951         case OR_OP:
12952           genOrOp (ic);
12953           break;
12954
12955         case '^':
12956           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12957           break;
12958
12959         case '|':
12960           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12961           break;
12962
12963         case BITWISEAND:
12964           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12965           break;
12966
12967         case INLINEASM:
12968           genInline (ic);
12969           break;
12970
12971         case RRC:
12972           genRRC (ic);
12973           break;
12974
12975         case RLC:
12976           genRLC (ic);
12977           break;
12978
12979         case GETHBIT:
12980           genGetHbit (ic);
12981           break;
12982
12983         case LEFT_OP:
12984           genLeftShift (ic);
12985           break;
12986
12987         case RIGHT_OP:
12988           genRightShift (ic);
12989           break;
12990
12991         case GET_VALUE_AT_ADDRESS:
12992           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12993           break;
12994
12995         case '=':
12996           if (POINTER_SET (ic))
12997             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
12998           else
12999             genAssign (ic);
13000           break;
13001
13002         case IFX:
13003           genIfx (ic, NULL);
13004           break;
13005
13006         case ADDRESS_OF:
13007           genAddrOf (ic);
13008           break;
13009
13010         case JUMPTABLE:
13011           genJumpTab (ic);
13012           break;
13013
13014         case CAST:
13015           genCast (ic);
13016           break;
13017
13018         case RECEIVE:
13019           genReceive (ic);
13020           break;
13021
13022         case SEND:
13023           if (ic->builtinSEND) genBuiltIn(ic);
13024           else addSet (&_G.sendSet, ic);
13025           break;
13026
13027         case DUMMY_READ_VOLATILE:
13028           genDummyRead (ic);
13029           break;
13030
13031 #if 0 // obsolete, and buggy for != xdata
13032         case ARRAYINIT:
13033             genArrayInit(ic);
13034             break;
13035 #endif
13036             
13037         default:
13038           ic = ic;
13039         }
13040     }
13041
13042
13043   /* now we are ready to call the
13044      peep hole optimizer */
13045   if (!options.nopeep)
13046     peepHole (&lineHead);
13047
13048   /* now do the actual printing */
13049   printLine (lineHead, codeOutFile);
13050   return;
13051 }